diff --git a/ecs-cli/integ/cmd/compose.go b/ecs-cli/integ/cmd/compose.go index 94015b464..43cfeb89d 100644 --- a/ecs-cli/integ/cmd/compose.go +++ b/ecs-cli/integ/cmd/compose.go @@ -85,6 +85,7 @@ func TestServiceUp(t *testing.T, p *Project) { "up", "--cluster-config", p.ConfigName, + "--create-log-groups", } cmd := integ.GetCommand(args) diff --git a/ecs-cli/modules/cli/local/create_app.go b/ecs-cli/modules/cli/local/create_app.go index b0b642059..5bbedeef9 100644 --- a/ecs-cli/modules/cli/local/create_app.go +++ b/ecs-cli/modules/cli/local/create_app.go @@ -18,12 +18,39 @@ package local import ( "fmt" + "github.com/aws/amazon-ecs-cli/ecs-cli/modules/commands/flags" "github.com/urfave/cli" ) +const ( + // taskDefinitionLabelType represents the type of option used to + // transform a task definition to a compose file e.g. remoteFile, localFile. + // taskDefinitionLabelValue represents the value of the option + // e.g. file path, arn, family. + taskDefinitionLabelType = "ecsLocalTaskDefType" + taskDefinitionLabelValue = "ecsLocalTaskDefVal" +) + +const ( + localTaskDefType = "localFile" + remoteTaskDefType = "remoteFile" +) + +const ( + ecsLocalDockerComposeFileName = "docker-compose.local.yml" +) + func Create(c *cli.Context) { // 1. read in task def (from file or arn) // 2. parse task def into go object // 3. write to docker-compose.local.yml file fmt.Println("foo") // placeholder } + +func validateOptions(c *cli.Context) error { + if (c.String(flags.TaskDefinitionFileFlag) != "") && (c.String(flags.TaskDefinitionTaskFlag) != "") { + return fmt.Errorf("%s and %s can not be used together", + flags.TaskDefinitionTaskFlag, flags.TaskDefinitionFileFlag) + } + return nil +} diff --git a/ecs-cli/modules/cli/local/down_app.go b/ecs-cli/modules/cli/local/down_app.go index 43ec7a040..096d4722d 100644 --- a/ecs-cli/modules/cli/local/down_app.go +++ b/ecs-cli/modules/cli/local/down_app.go @@ -14,6 +14,7 @@ package local import ( + "fmt" "os" "os/exec" "path/filepath" @@ -28,12 +29,6 @@ import ( "golang.org/x/net/context" ) -// TODO These labels should be defined part of the local.Create workflow. -// Refactor to import these constants instead of re-defining them here. -const ( - ecsLocalDockerComposeFileName = "docker-compose.local.yml" -) - // Down stops and removes running local ECS tasks. // If the user stops the last running task in the local network then also remove the network. func Down(c *cli.Context) error { @@ -42,8 +37,28 @@ func Down(c *cli.Context) error { network.Teardown(client) }() + if err := validateOptions(c); err != nil { + logrus.Fatal(err.Error()) + } + + if c.String(flags.TaskDefinitionFileFlag) != "" { + return downLocalContainersWithFilters(filters.NewArgs( + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelValue, + c.String(flags.TaskDefinitionFileFlag))), + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelType, localTaskDefType)), + )) + } + if c.String(flags.TaskDefinitionTaskFlag) != "" { + return downLocalContainersWithFilters(filters.NewArgs( + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelValue, + c.String(flags.TaskDefinitionTaskFlag))), + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelType, remoteTaskDefType)), + )) + } if c.Bool(flags.AllFlag) { - return downAllLocalContainers() + return downLocalContainersWithFilters(filters.NewArgs( + filters.Arg("label", taskDefinitionLabelValue), + )) } return downComposeLocalContainers() } @@ -65,19 +80,17 @@ func downComposeLocalContainers() error { return nil } -func downAllLocalContainers() error { +func downLocalContainersWithFilters(args filters.Args) error { ctx, cancel := context.WithTimeout(context.Background(), docker.TimeoutInS) defer cancel() client := docker.NewClient() containers, err := client.ContainerList(ctx, types.ContainerListOptions{ - Filters: filters.NewArgs( - filters.Arg("label", taskDefinitionLabelKey), - ), - All: true, + Filters: args, + All: true, }) if err != nil { - logrus.Fatalf("Failed to list containers with label=%s due to %v", taskDefinitionLabelKey, err) + logrus.Fatalf("Failed to list containers with filters %v due to %v", args, err) } if len(containers) == 0 { logrus.Warn("No running ECS local tasks found") diff --git a/ecs-cli/modules/cli/local/ps_app.go b/ecs-cli/modules/cli/local/ps_app.go index 9b252ab8d..78f56608a 100644 --- a/ecs-cli/modules/cli/local/ps_app.go +++ b/ecs-cli/modules/cli/local/ps_app.go @@ -31,15 +31,6 @@ import ( "golang.org/x/net/context" ) -// TODO These labels should be defined part of the local.Create workflow. -// Refactor to import these constants instead of re-defining them here. -// Docker object labels associated with containers created with "ecs-cli local". -const ( - // taskDefinitionLabelKey represents the value of the option used to - // transform a task definition to a compose file e.g. file path, arn, family. - taskDefinitionLabelKey = "ecsLocalTaskDefinition" -) - // Table formatting settings used by the Docker CLI. // See https://github.com/docker/cli/blob/0904fbfc77dbd4b6296c56e68be573b889d049e3/cli/command/formatter/formatter.go#L74 const ( @@ -63,18 +54,34 @@ const ( // If the --all flag is provided, then list all local ECS task containers. // If the --json flag is provided, then output the format as JSON instead. func Ps(c *cli.Context) { + if err := validateOptions(c); err != nil { + logrus.Fatal(err.Error()) + } containers := listContainers(c) displayContainers(c, containers) } func listContainers(c *cli.Context) []types.Container { - if !c.Bool(flags.AllFlag) { - return listLocalComposeContainers() + if c.String(flags.TaskDefinitionFileFlag) != "" { + return listContainersWithFilters(filters.NewArgs( + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelValue, + c.String(flags.TaskDefinitionFileFlag))), + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelType, localTaskDefType)), + )) + } + if c.String(flags.TaskDefinitionTaskFlag) != "" { + return listContainersWithFilters(filters.NewArgs( + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelValue, + c.String(flags.TaskDefinitionTaskFlag))), + filters.Arg("label", fmt.Sprintf("%s=%s", taskDefinitionLabelType, remoteTaskDefType)), + )) + } + if c.Bool(flags.AllFlag) { + return listContainersWithFilters(filters.NewArgs( + filters.Arg("label", taskDefinitionLabelValue), + )) } - // Task containers running locally all have a local label - return listContainersWithFilters(filters.NewArgs( - filters.Arg("label", taskDefinitionLabelKey), - )) + return listLocalComposeContainers() } func listLocalComposeContainers() []types.Container { @@ -144,7 +151,7 @@ func displayAsTable(containers []types.Container) { container.Status, prettifyPorts(container.Ports), prettifyNames(container.Names), - container.Labels[taskDefinitionLabelKey]) + container.Labels[taskDefinitionLabelValue]) fmt.Fprintln(w, row) } w.Flush() diff --git a/ecs-cli/modules/commands/flags/flags.go b/ecs-cli/modules/commands/flags/flags.go index af7892909..8ff3c10c6 100644 --- a/ecs-cli/modules/commands/flags/flags.go +++ b/ecs-cli/modules/commands/flags/flags.go @@ -150,6 +150,7 @@ const ( // Local TaskDefinitionFileFlag = "file" TaskDefinitionArnFlag = "arn" + TaskDefinitionTaskFlag = "task-def" LocalOutputFlag = "output" JsonFlag = "json" AllFlag = "all" diff --git a/ecs-cli/modules/commands/local/local_command.go b/ecs-cli/modules/commands/local/local_command.go index f468b4669..2ff1401d1 100644 --- a/ecs-cli/modules/commands/local/local_command.go +++ b/ecs-cli/modules/commands/local/local_command.go @@ -60,12 +60,20 @@ func upCommand() cli.Command { func downCommand() cli.Command { return cli.Command{ Name: "down", - Usage: "Stop and remove a running local ECS task.", + Usage: "Stop and remove a running ECS task container.", Action: local.Down, Flags: []cli.Flag{ cli.BoolFlag{ Name: flags.AllFlag, - Usage: "Stop and remove all running local ECS tasks.", + Usage: "Stops and removes all running containers", + }, + cli.StringFlag{ + Name: flags.TaskDefinitionTaskFlag, + Usage: "Stops and removes all running containers matching the task family or ARN", + }, + cli.StringFlag{ + Name: flags.TaskDefinitionFileFlag, + Usage: "Stops and removes all running containers matching the task definition file path", }, }, } @@ -81,6 +89,14 @@ func psCommand() cli.Command { Name: flags.AllFlag, Usage: "Lists all running local ECS tasks.", }, + cli.StringFlag{ + Name: flags.TaskDefinitionTaskFlag, + Usage: "Lists all running containers matching the task family or ARN", + }, + cli.StringFlag{ + Name: flags.TaskDefinitionFileFlag, + Usage: "Lists all running containers matching the task definition file path", + }, cli.BoolFlag{ Name: flags.JsonFlag, Usage: "Output in JSON format.",