mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-31 16:11:03 +01:00 
			
		
		
		
	Update protobuf definitions + support methods for the API
Add more logging Updated protos with new routes API
This commit is contained in:
		
							parent
							
								
									8170f5e693
								
							
						
					
					
						commit
						1b557ac1ea
					
				| @ -126,17 +126,31 @@ service HeadscaleService { | ||||
|     // --- Machine end --- | ||||
| 
 | ||||
|     // --- Route start --- | ||||
|     rpc GetMachineRoute(GetMachineRouteRequest) returns (GetMachineRouteResponse) { | ||||
|     rpc GetRoutes(GetRoutesRequest) returns (GetRoutesResponse) { | ||||
|         option (google.api.http) = { | ||||
|             get: "/api/v1/routes" | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     rpc EnableRoute(EnableRouteRequest) returns (EnableRouteResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/routes/{route_id}/enable" | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     rpc DisableRoute(DisableRouteRequest) returns (DisableRouteResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/routes/{route_id}/disable" | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     rpc GetMachineRoutes(GetMachineRoutesRequest) returns (GetMachineRoutesResponse) { | ||||
|         option (google.api.http) = { | ||||
|             get: "/api/v1/machine/{machine_id}/routes" | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     rpc EnableMachineRoutes(EnableMachineRoutesRequest) returns (EnableMachineRoutesResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/machine/{machine_id}/routes" | ||||
|         }; | ||||
|     } | ||||
|     // --- Route end --- | ||||
| 
 | ||||
|     // --- ApiKeys start --- | ||||
|  | ||||
| @ -2,24 +2,47 @@ syntax = "proto3"; | ||||
| package headscale.v1; | ||||
| option  go_package = "github.com/juanfont/headscale/gen/go/v1"; | ||||
| 
 | ||||
| message Routes { | ||||
|     repeated string advertised_routes = 1; | ||||
|     repeated string enabled_routes    = 2; | ||||
| import "google/protobuf/timestamp.proto"; | ||||
| import "headscale/v1/machine.proto"; | ||||
| 
 | ||||
| message Route { | ||||
|     uint64  id          = 1; | ||||
|     Machine machine     = 2; | ||||
|     string  prefix      = 3; | ||||
|     bool    advertised   = 4; | ||||
|     bool    enabled     = 5; | ||||
|     bool    is_primary  = 6; | ||||
| 
 | ||||
|     google.protobuf.Timestamp created_at = 7; | ||||
|     google.protobuf.Timestamp updated_at = 8; | ||||
|     google.protobuf.Timestamp deleted_at = 9; | ||||
| } | ||||
| 
 | ||||
| message GetMachineRouteRequest { | ||||
| message GetRoutesRequest { | ||||
| } | ||||
| 
 | ||||
| message GetRoutesResponse { | ||||
|     repeated Route routes = 1; | ||||
| } | ||||
| 
 | ||||
| message EnableRouteRequest { | ||||
|     uint64 route_id = 1; | ||||
| } | ||||
| 
 | ||||
| message EnableRouteResponse { | ||||
| } | ||||
| 
 | ||||
| message DisableRouteRequest { | ||||
|     uint64 route_id = 1; | ||||
| } | ||||
| 
 | ||||
| message DisableRouteResponse { | ||||
| } | ||||
| 
 | ||||
| message GetMachineRoutesRequest { | ||||
|     uint64 machine_id = 1; | ||||
| } | ||||
| 
 | ||||
| message GetMachineRouteResponse { | ||||
|     Routes routes = 1; | ||||
| } | ||||
| 
 | ||||
| message EnableMachineRoutesRequest { | ||||
|     uint64          machine_id = 1; | ||||
|     repeated string routes     = 2; | ||||
| } | ||||
| 
 | ||||
| message EnableMachineRoutesResponse { | ||||
|     Routes routes = 1; | ||||
| } | ||||
| message GetMachineRoutesResponse { | ||||
|     repeated Route routes = 1; | ||||
| } | ||||
							
								
								
									
										89
									
								
								routes.go
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								routes.go
									
									
									
									
									
								
							| @ -5,7 +5,9 @@ import ( | ||||
| 	"fmt" | ||||
| 	"net/netip" | ||||
| 
 | ||||
| 	v1 "github.com/juanfont/headscale/gen/go/headscale/v1" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"google.golang.org/protobuf/types/known/timestamppb" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
| 
 | ||||
| @ -49,6 +51,64 @@ func (rs Routes) toPrefixes() []netip.Prefix { | ||||
| 	return prefixes | ||||
| } | ||||
| 
 | ||||
| func (h *Headscale) GetRoutes() ([]Route, error) { | ||||
| 	var routes []Route | ||||
| 	err := h.db.Preload("Machine").Find(&routes).Error | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return routes, nil | ||||
| } | ||||
| 
 | ||||
| func (h *Headscale) GetMachineRoutes(m *Machine) ([]Route, error) { | ||||
| 	var routes []Route | ||||
| 	err := h.db. | ||||
| 		Preload("Machine"). | ||||
| 		Where("machine_id = ?", m.ID). | ||||
| 		Find(&routes).Error | ||||
| 	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return routes, nil | ||||
| } | ||||
| 
 | ||||
| func (h *Headscale) GetRoute(id uint64) (*Route, error) { | ||||
| 	var route Route | ||||
| 	err := h.db.Preload("Machine").First(&route, id).Error | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return &route, nil | ||||
| } | ||||
| 
 | ||||
| func (h *Headscale) EnableRoute(id uint64) error { | ||||
| 	route, err := h.GetRoute(id) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return h.EnableRoutes(&route.Machine, netip.Prefix(route.Prefix).String()) | ||||
| } | ||||
| 
 | ||||
| func (h *Headscale) DisableRoute(id uint64) error { | ||||
| 	route, err := h.GetRoute(id) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	route.Enabled = false | ||||
| 	route.IsPrimary = false | ||||
| 	err = h.db.Save(route).Error | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return h.handlePrimarySubnetFailover() | ||||
| } | ||||
| 
 | ||||
| // isUniquePrefix returns if there is another machine providing the same route already. | ||||
| func (h *Headscale) isUniquePrefix(route Route) bool { | ||||
| 	var count int64 | ||||
| @ -163,6 +223,10 @@ func (h *Headscale) handlePrimarySubnetFailover() error { | ||||
| 		if !route.IsPrimary { | ||||
| 			_, err := h.getPrimaryRoute(netip.Prefix(route.Prefix)) | ||||
| 			if h.isUniquePrefix(route) || errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 				log.Info(). | ||||
| 					Str("prefix", netip.Prefix(route.Prefix).String()). | ||||
| 					Str("machine", route.Machine.GivenName). | ||||
| 					Msg("Setting primary route") | ||||
| 				routes[pos].IsPrimary = true | ||||
| 				err := h.db.Save(&routes[pos]).Error | ||||
| 				if err != nil { | ||||
| @ -247,3 +311,28 @@ func (h *Headscale) handlePrimarySubnetFailover() error { | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (rs Routes) toProto() []*v1.Route { | ||||
| 	protoRoutes := []*v1.Route{} | ||||
| 
 | ||||
| 	for _, route := range rs { | ||||
| 		protoRoute := v1.Route{ | ||||
| 			Id:         uint64(route.ID), | ||||
| 			Machine:    route.Machine.toProto(), | ||||
| 			Prefix:     netip.Prefix(route.Prefix).String(), | ||||
| 			Advertised: route.Advertised, | ||||
| 			Enabled:    route.Enabled, | ||||
| 			IsPrimary:  route.IsPrimary, | ||||
| 			CreatedAt:  timestamppb.New(route.CreatedAt), | ||||
| 			UpdatedAt:  timestamppb.New(route.UpdatedAt), | ||||
| 		} | ||||
| 
 | ||||
| 		if route.DeletedAt.Valid { | ||||
| 			protoRoute.DeletedAt = timestamppb.New(route.DeletedAt.Time) | ||||
| 		} | ||||
| 
 | ||||
| 		protoRoutes = append(protoRoutes, &protoRoute) | ||||
| 	} | ||||
| 
 | ||||
| 	return protoRoutes | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user