package daemon import ( "cmp" "context" "fmt" "isle/bootstrap" "isle/nebula" "slices" "golang.org/x/exp/maps" ) // 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 } // GetHostsResult wraps the results from the GetHosts RPC method. type GetHostsResult struct { Hosts []bootstrap.Host } // RemoveHostRequest contains the arguments to the RemoveHost RPC method. // // All fields are required. type RemoveHostRequest struct { HostName nebula.HostName } // CreateHostRequest contains the arguments to the // CreateHost RPC method. // // All fields are required. type CreateHostRequest struct { HostName nebula.HostName Opts CreateHostOpts } // CreateHostResult wraps the results from the CreateHost RPC method. type CreateHostResult struct { JoiningBootstrap JoiningBootstrap } // CreateNebulaCertificateRequest contains the arguments to the // CreateNebulaCertificate RPC method. // // All fields are required. type CreateNebulaCertificateRequest struct { HostName nebula.HostName HostEncryptingPublicKey nebula.EncryptingPublicKey } // CreateNebulaCertificateResult wraps the results from the // CreateNebulaCertificate RPC method. type CreateNebulaCertificateResult struct { HostNebulaCertifcate nebula.Certificate } // RPC exposes all RPC methods which are available to be called over the RPC // interface. type RPC interface { // CreateNetwork passes through to the Daemon method of the same name. CreateNetwork( ctx context.Context, req CreateNetworkRequest, ) ( struct{}, error, ) // JoinNetwork passes through to the Daemon method of the same name. JoinNetwork( ctx context.Context, req JoiningBootstrap, ) ( struct{}, error, ) // GetHosts returns all hosts known to the network, sorted by their name. GetHosts( ctx context.Context, req struct{}, ) ( GetHostsResult, error, ) // GetGarageClientParams passes the call through to the Daemon method of the // same name. GetGarageClientParams( ctx context.Context, req struct{}, ) ( GarageClientParams, error, ) // GetNebulaCAPublicCredentials returns the CAPublicCredentials for the // network. GetNebulaCAPublicCredentials( ctx context.Context, req struct{}, ) ( nebula.CAPublicCredentials, error, ) // RemoveHost passes the call through to the Daemon method of the same name. RemoveHost( ctx context.Context, req RemoveHostRequest, ) ( struct{}, error, ) // CreateHost passes the call through to the Daemon method of the same name. CreateHost( ctx context.Context, req CreateHostRequest, ) ( CreateHostResult, error, ) // CreateNebulaCertificate passes the call through to the Daemon method of // the same name. CreateNebulaCertificate( ctx context.Context, req CreateNebulaCertificateRequest, ) ( CreateNebulaCertificateResult, error, ) } type rpcImpl struct { daemon Daemon } // NewRPC initializes and returns an RPC instance. func NewRPC(daemon Daemon) RPC { return &rpcImpl{daemon} } func (r *rpcImpl) CreateNetwork( ctx context.Context, req CreateNetworkRequest, ) ( struct{}, error, ) { return struct{}{}, r.daemon.CreateNetwork( ctx, req.Name, req.Domain, req.IPNet, req.HostName, ) } func (r *rpcImpl) JoinNetwork( ctx context.Context, req JoiningBootstrap, ) ( struct{}, error, ) { return struct{}{}, r.daemon.JoinNetwork(ctx, req) } func (r *rpcImpl) 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 } func (r *rpcImpl) GetGarageClientParams( ctx context.Context, req struct{}, ) ( GarageClientParams, error, ) { return r.daemon.GetGarageClientParams(ctx) } func (r *rpcImpl) 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 } func (r *rpcImpl) RemoveHost( ctx context.Context, req RemoveHostRequest, ) ( struct{}, error, ) { return struct{}{}, r.daemon.RemoveHost(ctx, req.HostName) } func (r *rpcImpl) CreateHost( ctx context.Context, req CreateHostRequest, ) ( CreateHostResult, error, ) { joiningBootstrap, err := r.daemon.CreateHost( ctx, req.HostName, req.Opts, ) if err != nil { return CreateHostResult{}, err } return CreateHostResult{JoiningBootstrap: joiningBootstrap}, nil } func (r *rpcImpl) CreateNebulaCertificate( ctx context.Context, req CreateNebulaCertificateRequest, ) ( CreateNebulaCertificateResult, error, ) { cert, err := r.daemon.CreateNebulaCertificate( ctx, req.HostName, req.HostEncryptingPublicKey, ) if err != nil { return CreateNebulaCertificateResult{}, err } return CreateNebulaCertificateResult{ HostNebulaCertifcate: cert, }, nil }