diff --git a/go.sum b/go.sum index 0810d88..5d110dc 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,7 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= @@ -139,6 +140,7 @@ github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= @@ -182,6 +184,7 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -332,6 +335,7 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOA gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= diff --git a/internal/docker/network.go b/internal/docker/network.go index 2b2aa87..7de0f12 100644 --- a/internal/docker/network.go +++ b/internal/docker/network.go @@ -2,6 +2,7 @@ package docker import ( "fmt" + "github.com/pulumi/pulumi-docker/sdk/v3/go/docker" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -15,7 +16,7 @@ type DockerNetworkConfig struct { } // CreateNetwork creates the forge platform's Docker network. -func CreateNetwork(ctx *pulumi.Context, c DockerNetworkConfig, label string) error { +func CreateNetwork(ctx *pulumi.Context, c DockerNetworkConfig) error { args := docker.NetworkArgs{ Name: c.Name, IpamDriver: c.Driver, @@ -26,9 +27,9 @@ func CreateNetwork(ctx *pulumi.Context, c DockerNetworkConfig, label string) err }, } - _, err := docker.NewNetwork(ctx, label, &args) + _, err := docker.NewNetwork(ctx, "docker_network", &args) if err != nil { - return fmt.Errorf("unable to create the docker network, %w", err) + return fmt.Errorf("unable to create the docker network...\n%w", err) } return nil diff --git a/internal/stacks/network/deploy.go b/internal/stacks/network/deploy.go new file mode 100644 index 0000000..537bd88 --- /dev/null +++ b/internal/stacks/network/deploy.go @@ -0,0 +1,25 @@ +package network + +import ( + "fmt" + + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" + "gitlab.com/dananglin/forge-platform/internal/docker" +) + +// DeployDockerNetworkStack returns a Pulumi run function +// that deploys the Docker network stack. +func DeployDockerNetworkStack(name, subnet, driver string) pulumi.RunFunc { + return func(ctx *pulumi.Context) error { + config := docker.DockerNetworkConfig{ + Name: pulumi.String(name), + Subnet: pulumi.String(subnet), + Driver: pulumi.String(driver), + } + + if err := docker.CreateNetwork(ctx, config); err != nil { + return fmt.Errorf("unable to deploy the Docker Network Stack...\n%w", err) + } + return nil + } +} diff --git a/internal/stacks/network/stack.go b/internal/stacks/network/stack.go new file mode 100644 index 0000000..7be5efc --- /dev/null +++ b/internal/stacks/network/stack.go @@ -0,0 +1,110 @@ +package network + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/pulumi/pulumi/sdk/v3/go/auto" + "github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy" + "github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview" + "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" +) + +const ( + actionPreview string = "preview" + actionUpdate string = "update" + actionDestroy string = "destroy" + + stack string = "dockerNetwork" +) + +// DockerNetworkStackArgs contains arguments for +// creating the DockerNetworkStack +type DockerNetworkStackArgs struct { + NetworkName string + Subnet string + NetworkDriver string +} + +// DockerNetworkStack is a stack for +// managing the Docker network. +type DockerNetworkStack struct { + Name string + Stack auto.Stack +} + +// NewDockerNetworkStack creates a new DockerNetworkStack value. +func NewDockerNetworkStack(ctx context.Context, project string, args DockerNetworkStackArgs, opts ...auto.LocalWorkspaceOption) (*DockerNetworkStack, error) { + + deployFunc := DeployDockerNetworkStack(args.NetworkName, args.Subnet, args.NetworkDriver) + + s, err := createOrSelectStack(ctx, project, stack, deployFunc, opts...) + if err != nil { + return nil, fmt.Errorf("unable to initialise stack (%s)...\n%w", stack, err) + } + + n := DockerNetworkStack{ + Name: stack, + Stack: s, + } + + return &n, nil +} + +// Process performs an action on the DockerNetworkStack. +func (n *DockerNetworkStack) Process(ctx context.Context, action string) error { + switch action { + case actionPreview: + stdoutStreamer := optpreview.ProgressStreams(os.Stdout) + _, err := n.Stack.Preview(ctx, stdoutStreamer) + if err != nil { + return fmt.Errorf("unable to preview the stack...\n%w", err) + } + case actionUpdate: + stdoutStreamer := optup.ProgressStreams(os.Stdout) + _, err := n.Stack.Up(ctx, stdoutStreamer) + if err != nil { + return fmt.Errorf("unable to update the stack...\n%w", err) + } + case actionDestroy: + stdoutStreamer := optdestroy.ProgressStreams(os.Stdout) + _, err := n.Stack.Destroy(ctx, stdoutStreamer) + if err != nil { + return fmt.Errorf("unable to destroy the stack...\n%w", err) + } + default: + return fmt.Errorf("unknown action '%s'", action) + } + + return nil +} + +func createOrSelectStack(ctx context.Context, project, stack string, deployFunc pulumi.RunFunc, opts ...auto.LocalWorkspaceOption) (auto.Stack, error) { + wd := filepath.Join(os.Getenv("HOME"), "Pulumi", "projects", project, "workspaces", stack) + + fmt.Printf("INFO: Ensuring that %s exists...\n", wd) + if err := os.MkdirAll(wd, 0750); err != nil { + return auto.Stack{}, fmt.Errorf("unable to ensure that the directory exists...\n%w", err) + } + + workDir := auto.WorkDir(wd) + + opts = append(opts, workDir) + + fmt.Printf("INFO: Creating/selecting stack (%s)...\n", stack) + s, err := auto.UpsertStackInlineSource(ctx, stack, project, deployFunc, opts...) + if err != nil { + return auto.Stack{}, fmt.Errorf("unable to create/select the stack...\n%w", err) + } + + fmt.Printf("INFO: Refreshing stack (%s)...\n", stack) + _, err = s.Refresh(ctx) + if err != nil { + return auto.Stack{}, fmt.Errorf("unable to refresh the stack...\n%w", err) + } + + return s, nil +}