From 3cda5cc564a040debbf8020757e5fa0809261994 Mon Sep 17 00:00:00 2001 From: Pasha Sviderski Date: Fri, 22 Aug 2025 15:58:21 +1000 Subject: [PATCH] chore: caddy client to get caddy config --- cmd/uncloud/caddy/deploy.go | 2 +- cmd/uncloud/machine/add.go | 2 +- cmd/uncloud/machine/init.go | 2 +- pkg/client/caddy.go | 8 ++++++- pkg/client/client.go | 2 ++ test/e2e/service_test.go | 46 ++++++++++++++++++++++++++++++++++--- 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/cmd/uncloud/caddy/deploy.go b/cmd/uncloud/caddy/deploy.go index f13580f5..5a790b90 100644 --- a/cmd/uncloud/caddy/deploy.go +++ b/cmd/uncloud/caddy/deploy.go @@ -91,7 +91,7 @@ func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { placement := api.Placement{ Machines: cli.ExpandCommaSeparatedValues(opts.machines), } - d, err := clusterClient.NewCaddyDeployment(opts.image, placement) + d, err := clusterClient.NewCaddyDeployment(opts.image, "", placement) if err != nil { return fmt.Errorf("create caddy deployment: %w", err) } diff --git a/cmd/uncloud/machine/add.go b/cmd/uncloud/machine/add.go index 7b9fec3d..3d95d08e 100644 --- a/cmd/uncloud/machine/add.go +++ b/cmd/uncloud/machine/add.go @@ -146,7 +146,7 @@ func add(ctx context.Context, uncli *cli.CLI, remoteMachine *cli.RemoteMachine, // TODO: scale the existing Caddy service to the new machine instead of running a new deployment // that may cause a small downtime. - d, err := clusterClient.NewCaddyDeployment(caddyImage, api.Placement{}) + d, err := clusterClient.NewCaddyDeployment(caddyImage, "", api.Placement{}) if err != nil { return fmt.Errorf("create caddy deployment: %w", err) } diff --git a/cmd/uncloud/machine/init.go b/cmd/uncloud/machine/init.go index 85ddd2bd..0a1679fc 100644 --- a/cmd/uncloud/machine/init.go +++ b/cmd/uncloud/machine/init.go @@ -147,7 +147,7 @@ func initCluster(ctx context.Context, uncli *cli.CLI, remoteMachine *cli.RemoteM } if !opts.noCaddy { - d, err := client.NewCaddyDeployment("", api.Placement{}) + d, err := client.NewCaddyDeployment("", "", api.Placement{}) if err != nil { return fmt.Errorf("create caddy deployment: %w", err) } diff --git a/pkg/client/caddy.go b/pkg/client/caddy.go index a81920fa..b4b7de98 100644 --- a/pkg/client/caddy.go +++ b/pkg/client/caddy.go @@ -23,7 +23,7 @@ var caddyImageTagRegex = regexp.MustCompile(`^2\.\d+\.\d+$`) // NewCaddyDeployment creates a new deployment for a Caddy reverse proxy service. // The service is deployed in global mode to all machines in the cluster. If the image is not provided, the latest // version of the official Caddy Docker image is used. -func (cli *Client) NewCaddyDeployment(image string, placement api.Placement) (*deploy.Deployment, error) { +func (cli *Client) NewCaddyDeployment(image, config string, placement api.Placement) (*deploy.Deployment, error) { if image == "" { latest, err := LatestCaddyImage() if err != nil { @@ -72,6 +72,12 @@ func (cli *Client) NewCaddyDeployment(image string, placement api.Placement) (*d }, } + if config != "" { + spec.Caddy = &api.CaddySpec{ + Config: config, + } + } + return cli.NewDeployment(spec, nil), nil } diff --git a/pkg/client/client.go b/pkg/client/client.go index ca805bae..108de3d3 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -23,6 +23,7 @@ type Client struct { // Methods such as Reset or Inspect are ambiguous in the context of a machine+cluster client. pb.MachineClient pb.ClusterClient + Caddy pb.CaddyClient // Docker is a namespaced client for the Docker service to distinguish Uncloud-specific service container operations // from generic Docker operations. Docker *docker.Client @@ -50,6 +51,7 @@ func New(ctx context.Context, connector Connector) (*Client, error) { c.MachineClient = pb.NewMachineClient(c.conn) c.ClusterClient = pb.NewClusterClient(c.conn) + c.Caddy = pb.NewCaddyClient(c.conn) c.Docker = docker.NewClient(c.conn) return c, nil } diff --git a/test/e2e/service_test.go b/test/e2e/service_test.go index 08f055a7..7d7ccfae 100644 --- a/test/e2e/service_test.go +++ b/test/e2e/service_test.go @@ -271,7 +271,7 @@ func TestDeployment(t *testing.T) { } }) - deployment, err := cli.NewCaddyDeployment("", api.Placement{}) + deployment, err := cli.NewCaddyDeployment("", "", api.Placement{}) require.NoError(t, err) _, err = deployment.Run(ctx) @@ -284,6 +284,12 @@ func TestDeployment(t *testing.T) { ctr := svc.Containers[0].Container assert.Regexp(t, `^caddy:2\.\d+\.\d+$`, ctr.Config.Image) + + config, err := cli.Caddy.GetConfig(ctx, nil) + require.NoError(t, err) + + assert.Contains(t, config.Caddyfile, "# This file is autogenerated by Uncloud") + assert.Contains(t, config.Caddyfile, "handle /.uncloud-verify") }) t.Run("caddy with machine placement", func(t *testing.T) { @@ -295,7 +301,7 @@ func TestDeployment(t *testing.T) { }) // Deploy to machine #0. - deployment, err := cli.NewCaddyDeployment("", api.Placement{ + deployment, err := cli.NewCaddyDeployment("", "", api.Placement{ Machines: []string{c.Machines[0].Name}, }) require.NoError(t, err) @@ -313,7 +319,7 @@ func TestDeployment(t *testing.T) { // initialContainerID := svc.Containers[0].Container.ID // Deploy to all machines without a placement constraint. - deployment, err = cli.NewCaddyDeployment(image, api.Placement{}) + deployment, err = cli.NewCaddyDeployment(image, "", api.Placement{}) require.NoError(t, err) _, err = deployment.Run(ctx) @@ -332,6 +338,40 @@ func TestDeployment(t *testing.T) { // assert.True(t, containers.Contains(initialContainerID), "Expected initial container to remain") }) + t.Run("caddy with custom config", func(t *testing.T) { + t.Cleanup(func() { + err := cli.RemoveService(ctx, client.CaddyServiceName) + if !errors.Is(err, api.ErrNotFound) { + require.NoError(t, err) + } + }) + + caddyfile := `{ + debug +} + +myapp.example.com { + reverse_proxy myapp:8000 +}` + deployment, err := cli.NewCaddyDeployment("", caddyfile, api.Placement{}) + require.NoError(t, err) + + _, err = deployment.Run(ctx) + require.NoError(t, err) + + svc, err := cli.InspectService(ctx, client.CaddyServiceName) + require.NoError(t, err) + assertServiceMatchesSpec(t, svc, deployment.Spec) + + config, err := cli.Caddy.GetConfig(ctx, nil) + require.NoError(t, err) + + assert.Contains(t, config.Caddyfile, "# This file is autogenerated by Uncloud") + assert.Contains(t, config.Caddyfile, "handle /.uncloud-verify") + assert.Contains(t, config.Caddyfile, caddyfile, + "Expected user-defined global Caddy config to be included in the Caddyfile") + }) + t.Run("replicated", func(t *testing.T) { t.Parallel()