package daemon import ( "cmp" "context" "fmt" "isle/admin" "isle/bootstrap" "isle/nebula" "net/netip" "slices" "golang.org/x/exp/maps" ) // RPC exposes all RPC methods which are available to be called over the RPC // interface. type RPC struct { daemon Daemon } // NewRPC initializes and returns an RPC instance. func NewRPC(daemon Daemon) *RPC { return &RPC{daemon} } // CreateNetworkRequest contains the arguments to the CreateNetwork RPC method. // // All fields are required. type CreateNetworkRequest struct { // Human-readable name of the network. Name string // Primary domain name that network services are served under. Domain string // An IP subnet, in CIDR form, which will be the overall range of possible // IPs in the network. The first IP in this network range will become this // first host's IP. IPNet nebula.IPNet // The name of this first host in the network. HostName nebula.HostName } // CreateNetwork passes through to the Daemon method of the same name. func (r *RPC) CreateNetwork( ctx context.Context, req CreateNetworkRequest, ) ( admin.Admin, error, ) { return r.daemon.CreateNetwork( ctx, req.Name, req.Domain, req.IPNet, req.HostName, ) } // JoinNetwork passes through to the Daemon method of the same name. func (r *RPC) JoinNetwork( ctx context.Context, req bootstrap.Bootstrap, ) ( struct{}, error, ) { return struct{}{}, r.daemon.JoinNetwork(ctx, req) } // GetHostsResult wraps the results from the GetHosts RPC method. type GetHostsResult struct { Hosts []bootstrap.Host } // GetHosts returns all hosts known to the network, sorted by their name. func (r *RPC) GetHosts( ctx context.Context, req struct{}, ) ( GetHostsResult, error, ) { b, err := r.daemon.GetBootstrap(ctx) if err != nil { return GetHostsResult{}, fmt.Errorf("retrieving bootstrap: %w", err) } hosts := maps.Values(b.Hosts) slices.SortFunc(hosts, func(a, b bootstrap.Host) int { return cmp.Compare(a.Name, b.Name) }) return GetHostsResult{hosts}, nil } // GetGarageClientParams passes the call through to the Daemon method of the // same name. func (r *RPC) GetGarageClientParams( ctx context.Context, req struct{}, ) ( GarageClientParams, error, ) { return r.daemon.GetGarageClientParams(ctx) } // GetNebulaCAPublicCredentials returns the CAPublicCredentials for the network. func (r *RPC) GetNebulaCAPublicCredentials( ctx context.Context, req struct{}, ) ( nebula.CAPublicCredentials, error, ) { b, err := r.daemon.GetBootstrap(ctx) if err != nil { return nebula.CAPublicCredentials{}, fmt.Errorf( "retrieving bootstrap: %w", err, ) } return b.CAPublicCredentials, nil } // RemoveHostRequest contains the arguments to the RemoveHost RPC method. // // All fields are required. type RemoveHostRequest struct { HostName nebula.HostName } // RemoveHost passes the call through to the Daemon method of the same name. func (r *RPC) RemoveHost(ctx context.Context, req RemoveHostRequest) (struct{}, error) { return struct{}{}, r.daemon.RemoveHost(ctx, req.HostName) } // CreateHostRequest contains the arguments to the // CreateHost RPC method. // // All fields are required. type CreateHostRequest struct { CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage HostName nebula.HostName IP netip.Addr } // CreateHostResult wraps the results from the CreateHost RPC method. type CreateHostResult struct { HostBootstrap bootstrap.Bootstrap } // CreateHost passes the call through to the Daemon method of the // same name. func (r *RPC) CreateHost( ctx context.Context, req CreateHostRequest, ) ( CreateHostResult, error, ) { hostBootstrap, err := r.daemon.CreateHost( ctx, req.CASigningPrivateKey, req.HostName, req.IP, ) if err != nil { return CreateHostResult{}, err } return CreateHostResult{HostBootstrap: hostBootstrap}, nil } // CreateNebulaCertificateRequest contains the arguments to the // CreateNebulaCertificate RPC method. // // All fields are required. type CreateNebulaCertificateRequest struct { CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage HostName nebula.HostName HostEncryptingPublicKey nebula.EncryptingPublicKey } // CreateNebulaCertificateResult wraps the results from the // CreateNebulaCertificate RPC method. type CreateNebulaCertificateResult struct { HostNebulaCertifcate nebula.Certificate } // CreateNebulaCertificate passes the call through to the Daemon method of the // same name. func (r *RPC) CreateNebulaCertificate( ctx context.Context, req CreateNebulaCertificateRequest, ) ( CreateNebulaCertificateResult, error, ) { cert, err := r.daemon.CreateNebulaCertificate( ctx, req.CASigningPrivateKey, req.HostName, req.HostEncryptingPublicKey, ) if err != nil { return CreateNebulaCertificateResult{}, err } return CreateNebulaCertificateResult{ HostNebulaCertifcate: cert, }, nil }