Prechádzať zdrojové kódy

Add setup command to define a docker context for ecs-plugin

Signed-off-by: Guillaume Lours <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
Guillaume Lours 5 rokov pred
rodič
commit
aa8587095f

+ 5 - 10
ecs/cmd/commands/compose.go

@@ -6,16 +6,11 @@ import (
 
 	"github.com/docker/ecs-plugin/pkg/amazon"
 	"github.com/docker/ecs-plugin/pkg/compose"
+	"github.com/docker/ecs-plugin/pkg/docker"
 	"github.com/spf13/cobra"
 )
 
-type ClusterOptions struct {
-	Profile string
-	Region  string
-	Cluster string
-}
-
-func ComposeCommand(clusteropts *ClusterOptions) *cobra.Command {
+func ComposeCommand(clusteropts *docker.AwsContext) *cobra.Command {
 	cmd := &cobra.Command{
 		Use: "compose",
 	}
@@ -41,7 +36,7 @@ func (o upOptions) LoadBalancerArn() *string {
 	return &o.loadBalancerArn
 }
 
-func ConvertCommand(clusteropts *ClusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
+func ConvertCommand(clusteropts *docker.AwsContext, projectOpts *compose.ProjectOptions) *cobra.Command {
 	cmd := &cobra.Command{
 		Use: "convert",
 		RunE: compose.WithProject(projectOpts, func(project *compose.Project, args []string) error {
@@ -66,7 +61,7 @@ func ConvertCommand(clusteropts *ClusterOptions, projectOpts *compose.ProjectOpt
 	return cmd
 }
 
-func UpCommand(clusteropts *ClusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
+func UpCommand(clusteropts *docker.AwsContext, projectOpts *compose.ProjectOptions) *cobra.Command {
 	opts := upOptions{}
 	cmd := &cobra.Command{
 		Use: "up",
@@ -86,7 +81,7 @@ type downOptions struct {
 	DeleteCluster bool
 }
 
-func DownCommand(clusteropts *ClusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
+func DownCommand(clusteropts *docker.AwsContext, projectOpts *compose.ProjectOptions) *cobra.Command {
 	opts := downOptions{}
 	cmd := &cobra.Command{
 		Use: "down",

+ 5 - 5
ecs/cmd/commands/secret.go

@@ -22,7 +22,7 @@ type deleteSecretOptions struct {
 	recover bool
 }
 
-func SecretCommand(clusteropts *ClusterOptions) *cobra.Command {
+func SecretCommand(clusteropts *docker.AwsContext) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "secret",
 		Short: "Manages secrets",
@@ -37,7 +37,7 @@ func SecretCommand(clusteropts *ClusterOptions) *cobra.Command {
 	return cmd
 }
 
-func CreateSecret(clusteropts *ClusterOptions) *cobra.Command {
+func CreateSecret(clusteropts *docker.AwsContext) *cobra.Command {
 	//opts := createSecretOptions{}
 	cmd := &cobra.Command{
 		Use:   "create NAME SECRET",
@@ -60,7 +60,7 @@ func CreateSecret(clusteropts *ClusterOptions) *cobra.Command {
 	return cmd
 }
 
-func InspectSecret(clusteropts *ClusterOptions) *cobra.Command {
+func InspectSecret(clusteropts *docker.AwsContext) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "inspect ID",
 		Short: "Displays secret details",
@@ -88,7 +88,7 @@ func InspectSecret(clusteropts *ClusterOptions) *cobra.Command {
 	return cmd
 }
 
-func ListSecrets(clusteropts *ClusterOptions) *cobra.Command {
+func ListSecrets(clusteropts *docker.AwsContext) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "list",
 		Aliases: []string{"ls"},
@@ -110,7 +110,7 @@ func ListSecrets(clusteropts *ClusterOptions) *cobra.Command {
 	return cmd
 }
 
-func DeleteSecret(clusteropts *ClusterOptions) *cobra.Command {
+func DeleteSecret(clusteropts *docker.AwsContext) *cobra.Command {
 	opts := deleteSecretOptions{}
 	cmd := &cobra.Command{
 		Use:     "delete NAME",

+ 33 - 0
ecs/cmd/commands/setup.go

@@ -0,0 +1,33 @@
+package commands
+
+import (
+	"github.com/docker/cli/cli-plugins/plugin"
+	contextStore "github.com/docker/ecs-plugin/pkg/docker"
+	"github.com/spf13/cobra"
+)
+
+func SetupCommand() *cobra.Command {
+	var opts contextStore.AwsContext
+	var name string
+	cmd := &cobra.Command{
+		Use:   "setup",
+		Short: "",
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			//Override the root command PersistentPreRun
+			//We just need to initialize the top parent command
+			return plugin.PersistentPreRunE(cmd, args)
+		},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return contextStore.NewContext(name, &opts)
+		},
+	}
+	cmd.Flags().StringVarP(&name, "name", "n", "aws", "Context Name")
+	cmd.Flags().StringVarP(&opts.Profile, "profile", "p", "", "AWS Profile")
+	cmd.Flags().StringVarP(&opts.Cluster, "cluster", "c", "", "ECS cluster")
+	cmd.Flags().StringVarP(&opts.Region, "region", "r", "", "AWS region")
+
+	cmd.MarkFlagRequired("profile")
+	cmd.MarkFlagRequired("cluster")
+	cmd.MarkFlagRequired("region")
+	return cmd
+}

+ 14 - 7
ecs/cmd/main/main.go

@@ -7,6 +7,7 @@ import (
 	"github.com/docker/cli/cli-plugins/plugin"
 	"github.com/docker/cli/cli/command"
 	commands "github.com/docker/ecs-plugin/cmd/commands"
+	"github.com/docker/ecs-plugin/pkg/docker"
 	"github.com/spf13/cobra"
 )
 
@@ -26,23 +27,29 @@ func main() {
 
 // NewRootCmd returns the base root command.
 func NewRootCmd(name string, dockerCli command.Cli) *cobra.Command {
-	var opts commands.ClusterOptions
+	var opts *docker.AwsContext
 
 	cmd := &cobra.Command{
 		Short:       "Docker ECS",
 		Long:        `run multi-container applications on Amazon ECS.`,
 		Use:         name,
 		Annotations: map[string]string{"experimentalCLI": "true"},
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			err := plugin.PersistentPreRunE(cmd, args)
+			if err != nil {
+				return err
+			}
+			contextName := dockerCli.CurrentContext()
+			opts, err = docker.CheckAwsContextExists(contextName)
+			return err
+		},
 	}
 	cmd.AddCommand(
 		VersionCommand(),
-		commands.ComposeCommand(&opts),
-		commands.SecretCommand(&opts),
+		commands.ComposeCommand(opts),
+		commands.SecretCommand(opts),
+		commands.SetupCommand(),
 	)
-	cmd.Flags().StringVarP(&opts.Profile, "profile", "p", "default", "AWS Profile")
-	cmd.Flags().StringVarP(&opts.Cluster, "cluster", "c", "default", "ECS cluster")
-	cmd.Flags().StringVarP(&opts.Region, "region", "r", "", "AWS region")
-
 	return cmd
 }
 

+ 1 - 0
ecs/go.mod

@@ -35,6 +35,7 @@ require (
 	github.com/lib/pq v1.3.0 // indirect
 	github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
 	github.com/miekg/pkcs11 v1.0.3 // indirect
+	github.com/mitchellh/mapstructure v1.2.2
 	github.com/morikuni/aec v1.0.0 // indirect
 	github.com/onsi/ginkgo v1.11.0 // indirect
 	github.com/opencontainers/image-spec v1.0.1 // indirect

+ 63 - 0
ecs/pkg/docker/contextStore.go

@@ -0,0 +1,63 @@
+package docker
+
+import (
+	"fmt"
+
+	cliconfig "github.com/docker/cli/cli/config"
+	"github.com/docker/cli/cli/context/store"
+	"github.com/mitchellh/mapstructure"
+)
+
+const contextType = "aws"
+
+type TypeContext struct {
+	Type string
+}
+
+func getter() interface{} {
+	return &TypeContext{}
+}
+
+type AwsContext struct {
+	Profile string
+	Cluster string
+	Region  string
+}
+
+func NewContext(name string, awsContext *AwsContext) error {
+	contextStore := initContextStore()
+	endpoints := map[string]interface{}{
+		"aws":    awsContext,
+		"docker": awsContext,
+	}
+
+	metadata := store.Metadata{
+		Name:      name,
+		Endpoints: endpoints,
+		Metadata:  TypeContext{Type: contextType},
+	}
+	return contextStore.CreateOrUpdate(metadata)
+}
+
+func initContextStore() store.Store {
+	config := store.NewConfig(getter)
+	return store.New(cliconfig.ContextStoreDir(), config)
+}
+
+func CheckAwsContextExists(contextName string) (*AwsContext, error) {
+	contextStore := initContextStore()
+	metadata, err := contextStore.GetMetadata(contextName)
+	if err != nil {
+		return nil, err
+	}
+	endpoint := metadata.Endpoints["aws"]
+	awsContext := AwsContext{}
+	err = mapstructure.Decode(endpoint, &awsContext)
+	if err != nil {
+		return nil, err
+	}
+	if awsContext == (AwsContext{}) {
+		return nil, fmt.Errorf("can't use \"%s\" with ECS command because it is not an AWS context", contextName)
+	}
+	return &awsContext, nil
+}