From 69d3a511d64298aaca413ccb8ff38f7ab0c6cc14 Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Mon, 3 Mar 2025 19:12:21 +1000 Subject: [PATCH] feat(dns): reserve cluster domain when initialising cluster by default + update dns records --- cmd/uncloud/caddy/deploy.go | 12 ++++++-- cmd/uncloud/machine/init.go | 59 +++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/cmd/uncloud/caddy/deploy.go b/cmd/uncloud/caddy/deploy.go index 357684e3..1b9a41a9 100644 --- a/cmd/uncloud/caddy/deploy.go +++ b/cmd/uncloud/caddy/deploy.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "github.com/charmbracelet/huh" + "github.com/docker/cli/cli/streams" "github.com/docker/compose/v2/pkg/progress" "github.com/spf13/cobra" "maps" @@ -173,7 +174,11 @@ func deploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { } fmt.Println() - if _, err = clusterClient.GetDomain(ctx); err != nil { + return UpdateDomainRecords(ctx, clusterClient, uncli.ProgressOut()) +} + +func UpdateDomainRecords(ctx context.Context, clusterClient *client.Client, progressOut *streams.Out) error { + if _, err := clusterClient.GetDomain(ctx); err != nil { if errors.Is(err, client.ErrNotFound) { fmt.Println("Skipping DNS records update as no cluster domain is reserved (see 'uc dns').") return nil @@ -185,10 +190,11 @@ func deploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { // TODO: split the method into two: one to get the records and one to update them to ask for update confirmation. var records []*pb.DNSRecord - err = progress.RunWithTitle(ctx, func(ctx context.Context) error { + err := progress.RunWithTitle(ctx, func(ctx context.Context) error { + var err error records, err = clusterClient.CreateIngressRecords(ctx, client.CaddyServiceName) return err - }, uncli.ProgressOut(), "Verifying internet access to caddy service") + }, progressOut, "Verifying internet access to caddy service") if err != nil { if errors.Is(err, client.ErrNoReachableMachines) { fmt.Println() diff --git a/cmd/uncloud/machine/init.go b/cmd/uncloud/machine/init.go index e53efb3a..b2cb4289 100644 --- a/cmd/uncloud/machine/init.go +++ b/cmd/uncloud/machine/init.go @@ -6,18 +6,23 @@ import ( "github.com/docker/compose/v2/pkg/progress" "github.com/spf13/cobra" "net/netip" + "uncloud/cmd/uncloud/caddy" + "uncloud/cmd/uncloud/dns" "uncloud/internal/cli" "uncloud/internal/cli/config" + "uncloud/internal/machine/api/pb" "uncloud/internal/machine/cluster" ) type initOptions struct { - name string - network string - noCaddy bool - publicIP string - sshKey string - cluster string + dnsEndpoint string + name string + network string + noCaddy bool + noDNS bool + publicIP string + sshKey string + cluster string } func NewInitCommand() *cobra.Command { @@ -47,6 +52,8 @@ func NewInitCommand() *cobra.Command { return initCluster(cmd.Context(), uncli, remoteMachine, opts) }, } + cmd.Flags().StringVar(&opts.dnsEndpoint, "dns-endpoint", dns.DefaultUncloudDNSAPIEndpoint, + "API endpoint for the Uncloud DNS service.") cmd.Flags().StringVarP( &opts.name, "name", "n", "", "Assign a name to the machine.", @@ -59,6 +66,10 @@ func NewInitCommand() *cobra.Command { &opts.noCaddy, "no-caddy", false, "Don't deploy Caddy reverse proxy service to the machine.", ) + cmd.Flags().BoolVar( + &opts.noDNS, "no-dns", false, + "Don't reserve a cluster domain in Uncloud DNS.", + ) cmd.Flags().StringVar( &opts.publicIP, "public-ip", "auto", "Public IP address of the machine for ingress configuration. Use 'auto' for automatic detection, "+ @@ -102,7 +113,7 @@ func initCluster(ctx context.Context, uncli *cli.CLI, remoteMachine *cli.RemoteM } defer client.Close() - if opts.noCaddy { + if opts.noCaddy && opts.noDNS { return nil } @@ -111,15 +122,33 @@ func initCluster(ctx context.Context, uncli *cli.CLI, remoteMachine *cli.RemoteM // after cluster initialisation, we keep the user informed during this wait. fmt.Println("Waiting for the machine to be ready...") - d, err := client.NewCaddyDeployment("", nil) - if err != nil { - return fmt.Errorf("create caddy deployment: %w", err) + if !opts.noDNS { + domain, err := client.ReserveDomain(ctx, &pb.ReserveDomainRequest{Endpoint: opts.dnsEndpoint}) + if err != nil { + return fmt.Errorf("reserve cluster domain in Uncloud DNS: %w", err) + } + fmt.Printf("Reserved cluster domain: %s\n", domain.Name) } - return progress.RunWithTitle(ctx, func(ctx context.Context) error { - if _, err = d.Run(ctx); err != nil { - return fmt.Errorf("deploy caddy: %w", err) + if !opts.noCaddy { + d, err := client.NewCaddyDeployment("", nil) + if err != nil { + return fmt.Errorf("create caddy deployment: %w", err) } - return nil - }, uncli.ProgressOut(), fmt.Sprintf("Deploying service %s", d.Spec.Name)) + + err = progress.RunWithTitle(ctx, func(ctx context.Context) error { + if _, err = d.Run(ctx); err != nil { + return fmt.Errorf("deploy caddy: %w", err) + } + return nil + }, uncli.ProgressOut(), fmt.Sprintf("Deploying service %s", d.Spec.Name)) + if err != nil { + return err + } + + fmt.Println() + return caddy.UpdateDomainRecords(ctx, client, uncli.ProgressOut()) + } + + return nil }