From 2a761272a0a09184afce0f74bd783824164df5f7 Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Sun, 11 Jul 2021 13:32:01 +0100 Subject: [PATCH] feat: create a shared volume The shared volume will be used by each container to share their specific traefik dynamic configuration to allow Traefik to dynamically configure the backend. --- .gitignore | 1 + internal/config/config.go | 20 +++++++----- internal/config/config_test.go | 3 ++ internal/config/testdata/config-valid.json | 3 ++ internal/docker/container.go | 2 +- internal/docker/image.go | 2 +- internal/docker/volume.go | 36 ++++++++++++++++++++++ internal/stacks/docker.go | 29 +++++++++++------ 8 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 internal/docker/volume.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f9c99b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +helix diff --git a/internal/config/config.go b/internal/config/config.go index dc80893..4130b6d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -6,28 +6,34 @@ import ( "io/ioutil" ) +// Config is the whole configuration for the forge platform deployment. type Config struct { ProjectName string `json:"project"` Docker DockerConfig `json:"docker"` Services ServicesConfig `json:"services"` } -// DockerConfig contains the configuration for -// docker specific components. +// DockerConfig contains the configuration for docker specific components. type DockerConfig struct { - Network DockerNetworkConfig `json:"network"` + Network DockerNetworkConfig `json:"network"` + SharedVolume DockerSharedVolumeConfig `json:"sharedVolume"` } -// DockerNetworkStackArgs contains arguments for -// creating the DockerNetworkStack +// DockerNetworkConfig contains configuration for creating the docker network. + type DockerNetworkConfig struct { Name string `json:"name"` Subnet string `json:"subnet"` Driver string `json:"driver"` } -// Services contains a list of -// services and their configuration +// DockerSharedVolumeConfig contains configuration +// for creating the shared volume. +type DockerSharedVolumeConfig struct { + Name string `json:"name"` +} + +// Services contains a list of services and their configuration. type ServicesConfig struct { Traefik TraefikConfig `json:"traefik"` } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index d83bc8f..04c0619 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -23,6 +23,9 @@ func TestValidConfig(t *testing.T) { Subnet: "172.17.1.0/24", Driver: "default", }, + SharedVolume: DockerSharedVolumeConfig{ + Name: "shared-volume", + }, }, Services: ServicesConfig{ Traefik: TraefikConfig{ diff --git a/internal/config/testdata/config-valid.json b/internal/config/testdata/config-valid.json index a353b0a..d932b43 100644 --- a/internal/config/testdata/config-valid.json +++ b/internal/config/testdata/config-valid.json @@ -5,6 +5,9 @@ "subnet": "172.17.1.0/24", "name": "forge-platform-test-netwwork", "driver": "default" + }, + "sharedVolume": { + "name": "shared-volume" } }, "services": { diff --git a/internal/docker/container.go b/internal/docker/container.go index a301988..ef8f5b2 100644 --- a/internal/docker/container.go +++ b/internal/docker/container.go @@ -27,7 +27,7 @@ type DockerVolumeMount struct { MountPath pulumi.StringInput } -func CreateDockerContainer(ctx *pulumi.Context, c DockerContainerInput) error { +func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error { // all containers will mount the host's timezone and localtime files // to ensure the correct time is synced. volumes := []docker.ContainerVolumeInput{ diff --git a/internal/docker/image.go b/internal/docker/image.go index f7a9b85..091e3c6 100644 --- a/internal/docker/image.go +++ b/internal/docker/image.go @@ -25,7 +25,7 @@ type DockerImageOutput struct { } // CreateDockerImage creates a local Docker image. -func CreateDockerImage(ctx *pulumi.Context, c DockerImageInput) (DockerImageOutput, error) { +func CreateImage(ctx *pulumi.Context, c DockerImageInput) (DockerImageOutput, error) { var output DockerImageOutput args := docker.ImageArgs{ diff --git a/internal/docker/volume.go b/internal/docker/volume.go new file mode 100644 index 0000000..13f2590 --- /dev/null +++ b/internal/docker/volume.go @@ -0,0 +1,36 @@ +package docker + +import ( + "fmt" + + "github.com/pulumi/pulumi-docker/sdk/v3/go/docker" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" +) + +type DockerVolumeInput struct { + Name pulumi.StringInput + UniqueLabel string +} + +type DockerVolumeOutput struct { + Name pulumi.StringOutput +} + +func CreateVolume(ctx *pulumi.Context, input DockerVolumeInput) (DockerVolumeOutput, error) { + var output DockerVolumeOutput + + args := docker.VolumeArgs{ + Name: input.Name, + } + + volume, err := docker.NewVolume(ctx, input.UniqueLabel, &args) + if err != nil { + return output, fmt.Errorf("unable to create the %s volume...\n%v", input.UniqueLabel, err) + } + + output = DockerVolumeOutput{ + Name: volume.Name, + } + + return output, nil +} diff --git a/internal/stacks/docker.go b/internal/stacks/docker.go index ec67b70..645d3b9 100644 --- a/internal/stacks/docker.go +++ b/internal/stacks/docker.go @@ -31,7 +31,7 @@ var templateTraefikStaticConfig string // newContainerStack creates the ContainerStack value. func newDockerStack(ctx context.Context, project, stack string, c config.Config) (*DockerStack, error) { - deployFunc := deployDockerStack(project, c.Docker.Network, c.Services) + deployFunc := deployDockerStack(project, c.Docker, c.Services) s, err := createOrSelectStack(ctx, project, stack, deployFunc) if err != nil { @@ -78,18 +78,29 @@ func (c *DockerStack) Destroy(ctx context.Context) error { // deployDockerStack returns a Pulumi run function // that is used to deploy the docker stack. -func deployDockerStack(project string, network config.DockerNetworkConfig, services config.ServicesConfig) pulumi.RunFunc { +func deployDockerStack(project string, dockerConfig config.DockerConfig, services config.ServicesConfig) pulumi.RunFunc { return func(ctx *pulumi.Context) error { // TODO: Create the provider when we start playing with remote hosts // Create the docker network - config := docker.DockerNetworkConfig{ - Name: pulumi.String(network.Name), - Subnet: pulumi.String(network.Subnet), - Driver: pulumi.String(network.Driver), + networkConfig := docker.DockerNetworkConfig{ + Name: pulumi.String(dockerConfig.Network.Name), + Subnet: pulumi.String(dockerConfig.Network.Subnet), + Driver: pulumi.String(dockerConfig.Network.Driver), } - network, err := docker.CreateNetwork(ctx, config) + network, err := docker.CreateNetwork(ctx, networkConfig) + if err != nil { + return err + } + + // Create the shared volume + sharedVolumeInput := docker.DockerVolumeInput{ + Name: pulumi.String(dockerConfig.SharedVolume.Name), + UniqueLabel: "shared", + } + + _, err = docker.CreateVolume(ctx, sharedVolumeInput) if err != nil { return err } @@ -122,7 +133,7 @@ func deployDockerStack(project string, network config.DockerNetworkConfig, servi UniqueLabel: "traefik-image", } - traefikImage, err := docker.CreateDockerImage(ctx, c) + traefikImage, err := docker.CreateImage(ctx, c) if err != nil { return err } @@ -135,7 +146,7 @@ func deployDockerStack(project string, network config.DockerNetworkConfig, servi UniqueLabel: "traefik-container", } - if err = docker.CreateDockerContainer(ctx, traefikContainerInput); err != nil { + if err = docker.CreateContainer(ctx, traefikContainerInput); err != nil { return err }