Repository: docker/compose-cli
Pull request #718 (2020-10-02 13:00:53)

delete CapacityProvider before we invoke DeleteStack
**What I did**
this is a workaround for CloudFormation issue to manage CapacityProvider <-> Cluster reverse dependency
`compose down` on ECS first delete the CapacityProvider and AutoscalingGroup (if present) by imperative API call then run `DeleteStack`. This prevent Cluster deletion by CloudFormation to fail


**Related issue**
https://github.com/docker/docker_aws/issues/43

/test-ecs

**(not mandatory) A picture of a cute animal, if possible in relation with what you did**
![image](https://user-images.githubusercontent.com/132757/94925750-063fab80-04c0-11eb-9a90-78ada28cf93e.png)




Patch:
diff --git a/Makefile b/Makefile
index ef5205fc..6eca2482 100644
--- a/Makefile
+++ b/Makefile
@@ -96,8 +96,6 @@ validate-go-mod: ## Validate go.mod and go.sum are up-to-date
 
 validate: validate-go-mod validate-headers ## Validate sources
 
-pre-commit: all lint validate test e2e-local
-
 help: ## Show help
 	@echo Please specify a build target. The choices are:
 	@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
diff --git a/aci/convert/container.go b/aci/convert/container.go
index 7982f646..f2456039 100644
--- a/aci/convert/container.go
+++ b/aci/convert/container.go
@@ -46,7 +46,6 @@ func ContainerToComposeProject(r containers.ContainerConfig) (types.Project, err
 			{
 				Name:        r.ID,
 				Image:       r.Image,
-				Command:     r.Command,
 				Ports:       ports,
 				Labels:      r.Labels,
 				Volumes:     serviceConfigVolumes,
diff --git a/aci/convert/convert.go b/aci/convert/convert.go
index 236e5696..b2fd1973 100644
--- a/aci/convert/convert.go
+++ b/aci/convert/convert.go
@@ -374,7 +374,6 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
 		Name: to.StringPtr(s.Name),
 		ContainerProperties: &containerinstance.ContainerProperties{
 			Image:                to.StringPtr(s.Image),
-			Command:              to.StringSlicePtr(s.Command),
 			EnvironmentVariables: getEnvVariables(s.Environment),
 			Resources: &containerinstance.ResourceRequirements{
 				Limits: &containerinstance.ResourceLimits{
diff --git a/aci/convert/registry_credentials.go b/aci/convert/registry_credentials.go
index 8919fb53..e2fa66e7 100644
--- a/aci/convert/registry_credentials.go
+++ b/aci/convert/registry_credentials.go
@@ -39,10 +39,11 @@ import (
 	"github.com/docker/compose-cli/aci/login"
 )
 
+// Specific username from ACR docs : https://github.com/Azure/acr/blob/master/docs/AAD-OAuth.md#getting-credentials-programatically
 const (
-	// Specific username from ACR docs : https://github.com/Azure/acr/blob/master/docs/AAD-OAuth.md#getting-credentials-programatically
-	tokenUsername = "00000000-0000-0000-0000-000000000000"
-	dockerHub     = "index.docker.io"
+	tokenUsername     = "00000000-0000-0000-0000-000000000000"
+	dockerHub         = "index.docker.io"
+	acrRegistrySuffix = ".azurecr.io"
 )
 
 type registryHelper interface {
@@ -127,7 +128,7 @@ func getUsedRegistries(project compose.Project) (map[string]bool, []string) {
 			registry = dockerHub
 		} else if !strings.Contains(registry, ".") {
 			registry = dockerHub
-		} else if strings.HasSuffix(registry, login.AcrRegistrySuffix) {
+		} else if strings.HasSuffix(registry, acrRegistrySuffix) {
 			acrRegistries = append(acrRegistries, registry)
 		}
 		usedRegistries[registry] = true
diff --git a/aci/login/helper.go b/aci/login/helper.go
index 4d20624a..5242f5b5 100644
--- a/aci/login/helper.go
+++ b/aci/login/helper.go
@@ -49,7 +49,7 @@ type azureAPIHelper struct{}
 
 func (helper azureAPIHelper) getDeviceCodeFlowToken() (adal.Token, error) {
 	deviceconfig := auth.NewDeviceFlowConfig(clientID, "common")
-	deviceconfig.Resource = azureManagementURL
+	deviceconfig.Resource = "https://management.core.windows.net/"
 	spToken, err := deviceconfig.ServicePrincipalToken()
 	if err != nil {
 		return adal.Token{}, err
diff --git a/aci/login/login.go b/aci/login/login.go
index 9c99bcb8..05e297ae 100644
--- a/aci/login/login.go
+++ b/aci/login/login.go
@@ -38,18 +38,12 @@ import (
 
 //go login process, derived from code sample provided by MS at https://github.com/devigned/go-az-cli-stuff
 const (
-	// AcrRegistrySuffix suffix for ACR registry images
-	AcrRegistrySuffix         = ".azurecr.io"
-	activeDirectoryURL        = "https://login.microsoftonline.com"
-	azureManagementURL        = "https://management.core.windows.net/"
-	azureResouceManagementURL = "https://management.azure.com/"
-	authorizeFormat           = activeDirectoryURL + "/organizations/oauth2/v2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s&prompt=select_account&response_mode=query&scope=%s"
-	tokenEndpoint             = activeDirectoryURL + "/%s/oauth2/v2.0/token"
-	getTenantURL              = azureResouceManagementURL + "tenants?api-version=2019-11-01"
-
+	authorizeFormat = "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s&prompt=select_account&response_mode=query&scope=%s"
+	tokenEndpoint   = "https://login.microsoftonline.com/%s/oauth2/v2.0/token"
+	getTenantURL    = "https://management.azure.com/tenants?api-version=2019-11-01"
 	// scopes for a multi-tenant app works for openid, email, other common scopes, but fails when trying to add a token
 	// v1 scope like "https://management.azure.com/.default" for ARM access
-	scopes   = "offline_access " + azureResouceManagementURL + ".default"
+	scopes   = "offline_access https://management.azure.com/.default"
 	clientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" // Azure CLI client id
 )
 
diff --git a/api/containers/api.go b/api/containers/api.go
index 7cc29099..e9772d6b 100644
--- a/api/containers/api.go
+++ b/api/containers/api.go
@@ -79,8 +79,6 @@ type ContainerConfig struct {
 	ID string
 	// Image specifies the iamge reference used for a container
 	Image string
-	// Command are the arguments passed to the container's entrypoint
-	Command []string
 	// Ports provide a list of published ports
 	Ports []Port
 	// Labels set labels to the container
diff --git a/cli/cmd/login/login.go b/cli/cmd/login/login.go
index 78cc0a99..0b2ae2e9 100644
--- a/cli/cmd/login/login.go
+++ b/cli/cmd/login/login.go
@@ -19,12 +19,14 @@ package login
 import (
 	"context"
 	"fmt"
+	"strings"
+
+	"github.com/docker/compose-cli/cli/cmd/mobyflags"
 
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
 	"github.com/docker/compose-cli/api/client"
-	"github.com/docker/compose-cli/cli/cmd/mobyflags"
 	"github.com/docker/compose-cli/cli/mobycli"
 	"github.com/docker/compose-cli/errdefs"
 )
@@ -50,6 +52,10 @@ func Command() *cobra.Command {
 }
 
 func runLogin(cmd *cobra.Command, args []string) error {
+	if len(args) == 1 && !strings.Contains(args[0], ".") {
+		backend := args[0]
+		return errors.New("unknown backend type for cloud login: " + backend)
+	}
 	mobycli.Exec(cmd.Root())
 	return nil
 }
diff --git a/cli/cmd/run/run.go b/cli/cmd/run/run.go
index e1088475..0c1559b3 100644
--- a/cli/cmd/run/run.go
+++ b/cli/cmd/run/run.go
@@ -38,15 +38,11 @@ func Command(contextType string) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "run",
 		Short: "Run a container",
-		Args:  cobra.MinimumNArgs(1),
+		Args:  cobra.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
-			if len(args) > 1 {
-				opts.Command = args[1:]
-			}
 			return runRun(cmd.Context(), args[0], opts)
 		},
 	}
-	cmd.Flags().SetInterspersed(false)
 
 	cmd.Flags().StringArrayVarP(&opts.Publish, "publish", "p", []string{}, "Publish a container's port(s). [HOST_PORT:]CONTAINER_PORT")
 	cmd.Flags().StringVar(&opts.Name, "name", "", "Assign a name to the container")
@@ -56,7 +52,6 @@ func Command(contextType string) *cobra.Command {
 	cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
 	cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
 	cmd.Flags().StringArrayVarP(&opts.Environment, "env", "e", []string{}, "Set environment variables")
-	cmd.Flags().StringArrayVar(&opts.EnvironmentFiles, "envFile", []string{}, "Path to environment files to be translated as environment variables")
 	cmd.Flags().StringVarP(&opts.RestartPolicyCondition, "restart", "", containers.RestartPolicyNone, "Restart policy to apply when a container exits")
 
 	if contextType == store.AciContextType {
diff --git a/cli/main.go b/cli/main.go
index 9ea9404f..54b0df55 100644
--- a/cli/main.go
+++ b/cli/main.go
@@ -224,9 +224,13 @@ func exit(root *cobra.Command, ctx string, err error, ctype string) {
 		os.Exit(errdefs.ExitCodeLoginRequired)
 	}
 	if errors.Is(err, errdefs.ErrNotImplemented) {
-		name := metrics.GetCommand(os.Args[1:], root.PersistentFlags())
+		cmd, _, _ := root.Traverse(os.Args[1:])
+		name := cmd.Name()
+		parent := cmd.Parent()
+		if parent != nil && parent.Parent() != nil {
+			name = parent.Name() + " " + name
+		}
 		fmt.Fprintf(os.Stderr, "Command %q not available in current context (%s)\n", name, ctx)
-
 		os.Exit(1)
 	}
 
diff --git a/cli/options/run/opts.go b/cli/options/run/opts.go
index 9a3130aa..9cdd2ebe 100644
--- a/cli/options/run/opts.go
+++ b/cli/options/run/opts.go
@@ -21,8 +21,6 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/docker/cli/opts"
-
 	"github.com/docker/compose-cli/utils"
 
 	"github.com/docker/docker/pkg/namesgenerator"
@@ -35,7 +33,6 @@ import (
 // Opts contain run command options
 type Opts struct {
 	Name                   string
-	Command                []string
 	Publish                []string
 	Labels                 []string
 	Volumes                []string
@@ -43,7 +40,6 @@ type Opts struct {
 	Memory                 formatter.MemBytes
 	Detach                 bool
 	Environment            []string
-	EnvironmentFiles       []string
 	RestartPolicyCondition string
 	DomainName             string
 }
@@ -69,25 +65,15 @@ func (r *Opts) ToContainerConfig(image string) (containers.ContainerConfig, erro
 		return containers.ContainerConfig{}, err
 	}
 
-	envVars := r.Environment
-	for _, f := range r.EnvironmentFiles {
-		vars, err := opts.ParseEnvFile(f)
-		if err != nil {
-			return containers.ContainerConfig{}, err
-		}
-		envVars = append(envVars, vars...)
-	}
-
 	return containers.ContainerConfig{
 		ID:                     r.Name,
 		Image:                  image,
-		Command:                r.Command,
 		Ports:                  publish,
 		Labels:                 labels,
 		Volumes:                r.Volumes,
 		MemLimit:               r.Memory,
 		CPULimit:               r.Cpus,
-		Environment:            envVars,
+		Environment:            r.Environment,
 		RestartPolicyCondition: restartPolicy,
 		DomainName:             r.DomainName,
 	}, nil
diff --git a/docs/aci-interation.md b/docs/aci-interation.md
deleted file mode 100644
index 5a03a9c3..00000000
--- a/docs/aci-interation.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Features
-
-## Login
-
-You can log into Azure with the `docker login azure` command. This will open a Web browser to complete the login process. If the Docker CLI cannot open a browser, it will fall back to the [Azure device code flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code) and let you connect yourself.
-Note that the [Azure command line](https://docs.microsoft.com/en-us/cli/azure/) login is separated from the Docker CLI Azure login.
-
-## Docker contexts
-
-The Docker ACI integration is performed through the use of Docker contexts. You can create a context of type ACI, and then using this context you will be able to run classic Docker commands (like `docker run`) against ACI.
-Creating an ACI context requires an Azure subscription, a resource group and a region. 
-
-Before creating a context, you will need to `docker login azure` first so that the Docker CLI can find your Azure subscription.
-
-To create an ACI context, `docker context create aci` will prompt you for the relevant information, with the option to either create a new resource group or use an existing one.
-With a context created, you can either issue single commands against ACI, specifying the context name in the command line, like `docker --context acicontext run nginx`, or switch context so that all subsequent commands will be issued to ACI: `docker context use acicontext`.
-
-**Note:** You can have multiple ACI contexts associated each with different resource groups. This can be useful as it will act as namespaces for your containers. Actions on your containers will be restricted to your current context and resource group.
-
-## Single container
-
-You can start a single container on ACI with the `docker run` command. 
-The container is started in a container group, in the region and resource group associated with the ACI context.
-
-You can then list existing containers with `docker ps`. This will show the status of the container, if it exposes ports, and the container's public IP address or domain name.
-You can view a container's logs with the `docker logs` command.
-
-Running containers can be stopped with `docker stop` (`docker kill` will have the same effect). Stopped containers can be restarted with `docker start`.
- 
-**Note:** The semantics of restarting a container on ACI are different to those when using a moby type context for local development. On ACI, the container will be reset to its initial state and started on a new node. This includes the container's filesystem so all state that is not stored in a volume will be lost on restart.
-
-Containers can be removed using `docker rm`. Removing a running container will require using the `--force` flag, or stopping the container with `docker stop` before removing.   
-
-## Compose applications
-
-You can start Compose applications with the `docker compose up` command.
-All containers in the same Compose application are started in the same container group. Service discovery between the containers works using the service name specified in the Compose file.
-Name resolution is achieved by writing service names in the `/etc/hosts` file that is shared automatically by all containers in the container group.
-
-Containers started as part of Compose applications will be displayed along with single containers when using `docker ps`. 
-Their container ID will be of the format: `<COMPOSE-PROJECT>_<SERVICE>`. 
-These containers cannot be stopped, started or removed independently since they are all part of the same ACI container group. You can view each container's logs with `docker logs`.
-You can list deployed Compose applications with `docker compose ls`. This will list only compose applications, not single containers started with `docker run`.
-You can remove a Compose application with `docker compose down`.
-
-## Exposing ports
-
-Single containers and Compose applications can optionally expose ports. For single containers this is done using the `--publish` flag of the `docker run` command and for Compose applications this is done in the Compose file.
- 
-**Note:** ACI does not allow port mapping (i.e.: changing port number while exposing port), so the source and target ports must be the same when deploying to ACI.
-
-**Note:** All containers in the same Compose application are deployed in the same ACI container group. Containers in the same Compose application cannot expose the same port when deployed to ACI.
-
-By default, when exposing ports for your application, a random public IP address is associated with the container group supporting the deployed application (single container or Compose application).
-This IP address can be obtained when listing containers with `docker ps` or using `docker inspect`.    
-
-### DNS label name
-
-In addition to exposing ports on a random IP address, you can specify a DNS label name to expose your application on an FQDN of the form: `<NAME>.region.azurecontainer.io`.
-This name can be set with the `--domain` flag when performing a `docker run` or using the `domain` field in the Compose file when performing a `docker compose up`.
-**Note:** The domain of a Compose application can only be set once, if you specify `domain` for several services, the value must be identical.
-
-## Volumes
-
-Single containers and Compose applications can use volumes. In ACI, volumes are implemented as Azure file shares in Azure storage accounts.
-To use a volume when running a single container, specify a storage account and file share name like this: 
-
-```console
-docker run -v <STORAGE-ACCOUNT>/<FILE-SHARE>:/target/path[:ro]
-```
-  
-To specify more than one volume, just use the `-v` option as many times as required.
-Compose application volumes are specified in the _volumes_ section of the Compose file and attached to a service as follows:
-
-```yaml
-services:
-    myservice:
-        image: nginx
-        volumes:
-        - mydata:/mount/testvolumes
-
-volumes:
-  mydata:
-    driver: azure_file
-    driver_opts:
-      share_name: myfileshare
-      storage_account_name: mystorageaccount
-```
-
-**Note:** The volume short syntax in Compose files cannot be used as it is aimed at volume definition for local bind mounts. Using the volume driver and driver option syntax in Compose files makes the volume definition a lot more clear.
-
-In both cases, when deploying the containers, the Docker CLI will use your Azure login to fetch the key to the storage account, and provide this key with the container deployment information, so that the container can access the volume.
-Volumes can be used from any file share in any storage account you have access to with your Azure login. You can specify `rw` (read/write) or `ro` (read only) when mounting the volume (`rw` is the default).
-
-ACI volumes can be managed with the `volume` subcommand. This includes `docker volume ls`, `docker volume create`, and `docker volume rm`. 
-Creating a volume requires a storage account name and a volume name. The storage account is created using default options if it does not exist, using the region associated with your ACI context.  
-If the storage account name already exists (and you have access to it), a file share is created with default values, using this existing storage account. Volume creation fails if the file share already exists.
-
-Listing volumes will list all file shares you have access using your Azure login, in any storage account. You can use existing file shares as volumes, even if they have not been created through the Docker CLI.
-
-When using `docker volume rm`, the command will remove the specified file share from the specified storage account. If this storage account has no more file shares, and if the storage account was created by the Docker CLI, then the storage account will also be deleted.
-
-## Resource usage definition
-
-You can specify CPU and memory limits for your containers.
-For single containers, use `docker run --cpu 2 --memory 2G`. 
-In Compose files, you can use the service resource limits:
-
-```yaml
-services:
-  redis:
-    image: redis:alpine
-    deploy:
-      resources:
-        limits:
-          cpus: '0.50'
-          memory: 50M
-```
-
-In this general example, the _redis_ service is constrained to use no more than 50M of memory (50 MB) and 0.50 (50% of a single core) of available processing time (CPU).
-
-## Environment variables
-
-When using `docker run`, environment variables can be passed to ACI containers using the `--env` flag.
-Form compose applications, environment variables can be specified in the compose file with the `environment` or `env-file` service field, or with the `--environment` command line flag.
-
-## Private Docker Hub images and using the Azure Container Registry
-
-You can deploy private images to ACI that are hosted by any container registry. You need to `docker login` to the relevant registry before running `docker run` or `docker compose up`. The Docker CLI will fetch your registry login for the deployed images and send the credentials along with the image deployment information to ACI.
-In the case of the Azure Container Registry, the command line will try to automatically log you into ACR from your Azure login. You don't need to manually login to the ACR registry first, if your Azure login has access to the ACR.
diff --git a/ecs/architecture.md b/ecs/architecture.md
index 113c4350..f8561671 100644
--- a/ecs/architecture.md
+++ b/ecs/architecture.md
@@ -8,49 +8,38 @@ This document describes the mapping between compose application model and AWS co
 This diagram shows compose model and on same line AWS components that get created as equivalent resources
 
 ```
-+----------+                                +-------------+                              +-------------------+
-| Project  |  . . . . . . . . . . . . . .   | Cluster     |    . . . . . . .             | LoadBalancer      |
-+-+--------+                                +-------------+                              +-------------------+
++----------+                                +-------------+                          +-------------------+
+| Project  |                                | Cluster     |                          | LoadBalancer      |
++-+--------+                                +-------------+                          +-------------------+
   |
-  |    +----------+                         +-------------++-------------------+         +-------------------+  
-  +----+ Service  |   . . . . . . . . . .   | Service     || TaskDefinition    |         | TargetGroup       |  
-  |    +--+-------+                         +-------------++-------------------+-+       +-------------------+  
-  |       |                                                  | TaskRole          |                          
-  |       |                                                  +-------------------+-+                         
-  |       |  x-aws-role, x-aws-policies     . . . . . . . .    | TaskExecutionRole |                        
-  |       |                                                    +-------------------+                        
-  |       |  +---------+
-  |       +--+ Deploy  |
-  |       |  +---------+                    +-------------------+
-  |       |  x-aws-autoscale  . . . . . .   | ScalableTarget    |
-  |       |                                 +-------------------+---+
-  |       |                                     | ScalingPolicy     |
-  |       |                                     +-------------------+-+
-  |       |                                       | AutoScalingRole   |
-  |       |                                       +-------------------+
+  |    +----------+                         +-------------+ +----------------+       +-------------------+
+  +----+ Service  |                         | Service     | | TaskDefinition |       | TargetGroup       |
+  |    +--+-------+                         +-------------+ +----------------+       +-------------------+
+  |       |                                                 +----------------+
+  |       |  x-aws-role, x-aws-policies                     | TaskRole       |
+  |       |                                                 +----------------+
+  |       |  +---------+                    +-------------+                          +-------------------+
+  |       +--+ Ports   |                    | IngressRule |                          | Listener          |
+  |       |  +---------+                    +-------------+                          +-------------------+
   |       |
-  |       |  +---------+                    +-------------+                              +-------------------+
-  |       +--+ Ports   |   . . . . . . .    | IngressRule +-----+                        | Listener          |
-  |       |  +---------+                    +-------------+     |                        +-------------------+
-  |       |                                                     |
   |       |  +---------+                    +---------------+ +------------------+
-  |       +--+ Secrets |   . . . . . . .    | InitContainer | |TaskExecutionRole |
+  |       +--+ Secrets |                    | InitContainer | |TaskExecutionRole |
   |       |  +---------+                    +---------------+ +------------+-----+
-  |       |                                                     |          |
-  |       |  +---------+                                        |          |
-  |       +--+ Volumes |                                        |          |
-  |       |  +---------+                                        |          |
-  |       |                                                     |          |
-  |       |  +---------------+                                  |          |         +-------------------+
-  |       +--+ DeviceRequest |  . . . . . . . . . . . . .  . .  | . . . .  | . . .   | CapacityProvider  |
-  |          +---------------+                                  |          |         +-------------------+--------+
-  |                                                             |          |                | AutoscalingGroup    |
-  |   +------------+                        +---------------+   |          |                +---------------------+
-  +---+ Networks   |   . . . . . . . . .    | SecurityGroup +---+          |                | LaunchConfiguration |
-  |   +------------+                        +---------------+              |                +---------------------+
+  |       |                                                                |
+  |       |  +---------+                                                   |
+  |       +--+ Volumes |                                                   |
+  |       |  +---------+                                                   |
+  |       |                                                                |
+  |       |  +---------------+                                             |         +------------------------------------------+
+  |       +--+ DeviceRequest |                                             |         | CapacityProvider  || AutoscalingGroup    |
+  |          +---------------+                                             |         +------------------------------------------+
+  |                                                                        |                              | LaunchConfiguration |
+  |   +------------+                        +---------------+              |                              +---------------------+
+  +---+ Networks   |                        | SecurityGroup |              |
+  |   +------------+                        +---------------+              |
   |                                                                        |
   |   +------------+                        +---------------+              |
-  +---+ Secret     |   . . . . . . . . .    | Secret        +--------------+
+  +---+ Secret     |                        | Secret        +--------------+
       +------------+                        +---------------+
 ```
 
@@ -74,6 +63,6 @@ A `TaskExecutionRole` is also created per service, and is updated to grant acces
 Services using a GPU (`DeviceRequest`) get the `Cluster` extended with an EC2 `CapacityProvider`, using an `AutoscalingGroup` to manage
 EC2 resources allocation based on a `LaunchConfiguration`. The latter uses ECS recommended AMI and machine type for GPU.
 
-Service to declare `deploy.x-aws-autoscaling` get a `ScalingPolicy` created targeting specified the configured CPU usage metric
+
 
 
diff --git a/ecs/autoscaling.go b/ecs/autoscaling.go
deleted file mode 100644
index 7a40938d..00000000
--- a/ecs/autoscaling.go
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-   Copyright 2020 Docker Compose CLI authors
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package ecs
-
-import (
-	"fmt"
-
-	applicationautoscaling2 "github.com/aws/aws-sdk-go/service/applicationautoscaling"
-	"github.com/awslabs/goformation/v4/cloudformation"
-	"github.com/awslabs/goformation/v4/cloudformation/applicationautoscaling"
-	"github.com/awslabs/goformation/v4/cloudformation/iam"
-	"github.com/compose-spec/compose-go/types"
-)
-
-func (b *ecsAPIService) createAutoscalingPolicy(project *types.Project, resources awsResources, template *cloudformation.Template, service types.ServiceConfig) {
-	if service.Deploy == nil {
-		return
-	}
-	v, ok := service.Deploy.Extensions[extensionAutoScaling]
-	if !ok {
-		return
-	}
-
-	role := fmt.Sprintf("%sAutoScalingRole", normalizeResourceName(service.Name))
-	template.Resources[role] = &iam.Role{
-		AssumeRolePolicyDocument: ausocalingAssumeRolePolicyDocument,
-		Path:                     "/",
-		Policies: []iam.Role_Policy{
-			{
-				PolicyDocument: &PolicyDocument{
-					Statement: []PolicyStatement{
-						{
-							Effect: "Allow",
-							Action: []string{
-								actionAutoScaling,
-								actionDescribeService,
-								actionUpdateService,
-								actionGetMetrics,
-							},
-							Resource: []string{cloudformation.Ref(serviceResourceName(service.Name))},
-						},
-					},
-				},
-				PolicyName: "service-autoscaling",
-			},
-		},
-		Tags: serviceTags(project, service),
-	}
-
-	// Why isn't this just the service ARN ?????
-	resourceID := cloudformation.Join("/", []string{"service", resources.cluster, cloudformation.GetAtt(serviceResourceName(service.Name), "Name")})
-
-	target := fmt.Sprintf("%sScalableTarget", normalizeResourceName(service.Name))
-	template.Resources[target] = &applicationautoscaling.ScalableTarget{
-		MaxCapacity:                10,
-		MinCapacity:                0,
-		ResourceId:                 resourceID,
-		RoleARN:                    cloudformation.GetAtt(role, "Arn"),
-		ScalableDimension:          applicationautoscaling2.ScalableDimensionEcsServiceDesiredCount,
-		ServiceNamespace:           applicationautoscaling2.ServiceNamespaceEcs,
-		AWSCloudFormationDependsOn: []string{serviceResourceName(service.Name)},
-	}
-
-	policy := fmt.Sprintf("%sScalingPolicy", normalizeResourceName(service.Name))
-	template.Resources[policy] = &applicationautoscaling.ScalingPolicy{
-		PolicyType:                     "TargetTrackingScaling",
-		PolicyName:                     policy,
-		ScalingTargetId:                cloudformation.Ref(target),
-		StepScalingPolicyConfiguration: nil,
-		TargetTrackingScalingPolicyConfiguration: &applicationautoscaling.ScalingPolicy_TargetTrackingScalingPolicyConfiguration{
-			PredefinedMetricSpecification: &applicationautoscaling.ScalingPolicy_PredefinedMetricSpecification{
-				PredefinedMetricType: applicationautoscaling2.MetricTypeEcsserviceAverageCpuutilization,
-			},
-			ScaleOutCooldown: 60,
-			ScaleInCooldown:  60,
-			TargetValue:      float64(v.(int)),
-		},
-	}
-}
diff --git a/ecs/aws.go b/ecs/aws.go
new file mode 100644
index 00000000..a4b69255
--- /dev/null
+++ b/ecs/aws.go
@@ -0,0 +1,22 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package ecs
+
+const (
+	awsTypeCapacityProvider = "AWS::ECS::CapacityProvider"
+	awsTypeAutoscalingGroup = "AWS::AutoScaling::AutoScalingGroup"
+)
diff --git a/ecs/awsResources.go b/ecs/awsResources.go
index 829fc6bb..2ba44e5e 100644
--- a/ecs/awsResources.go
+++ b/ecs/awsResources.go
@@ -189,6 +189,7 @@ func (b *ecsAPIService) ensureNetworks(r *awsResources, project *types.Project,
 		securityGroup := networkResourceName(name)
 		template.Resources[securityGroup] = &ec2.SecurityGroup{
 			GroupDescription: fmt.Sprintf("%s Security Group for %s network", project.Name, name),
+			GroupName:        securityGroup,
 			VpcId:            r.vpc,
 			Tags:             networkTags(project, net),
 		}
diff --git a/ecs/cloudformation.go b/ecs/cloudformation.go
index b9f7c61c..0b9cb93e 100644
--- a/ecs/cloudformation.go
+++ b/ecs/cloudformation.go
@@ -91,7 +91,7 @@ func (b *ecsAPIService) convert(project *types.Project, resources awsResources)
 
 	for _, service := range project.Services {
 		taskExecutionRole := b.createTaskExecutionRole(project, service, template)
-		taskRole := b.createTaskRole(project, service, template)
+		taskRole := b.createTaskRole(service, template)
 
 		definition, err := b.createTaskExecution(project, service)
 		if err != nil {
@@ -183,8 +183,6 @@ func (b *ecsAPIService) convert(project *types.Project, resources awsResources)
 			Tags:               serviceTags(project, service),
 			TaskDefinition:     cloudformation.Ref(normalizeResourceName(taskDefinition)),
 		}
-
-		b.createAutoscalingPolicy(project, resources, template, service)
 	}
 	return template, nil
 }
@@ -365,12 +363,11 @@ func (b *ecsAPIService) createTaskExecutionRole(project *types.Project, service
 			ecsTaskExecutionPolicy,
 			ecrReadOnlyPolicy,
 		},
-		Tags: serviceTags(project, service),
 	}
 	return taskExecutionRole
 }
 
-func (b *ecsAPIService) createTaskRole(project *types.Project, service types.ServiceConfig, template *cloudformation.Template) string {
+func (b *ecsAPIService) createTaskRole(service types.ServiceConfig, template *cloudformation.Template) string {
 	taskRole := fmt.Sprintf("%sTaskRole", normalizeResourceName(service.Name))
 	rolePolicies := []iam.Role_Policy{}
 	if roles, ok := service.Extensions[extensionRole]; ok {
@@ -391,7 +388,6 @@ func (b *ecsAPIService) createTaskRole(project *types.Project, service types.Ser
 		AssumeRolePolicyDocument: ecsTaskAssumeRolePolicyDocument,
 		Policies:                 rolePolicies,
 		ManagedPolicyArns:        managedPolicies,
-		Tags:                     serviceTags(project, service),
 	}
 	return taskRole
 }
diff --git a/ecs/down.go b/ecs/down.go
index 914f680d..10dca809 100644
--- a/ecs/down.go
+++ b/ecs/down.go
@@ -18,12 +18,58 @@ package ecs
 
 import (
 	"context"
+
+	"github.com/docker/compose-cli/progress"
 )
 
 func (b *ecsAPIService) Down(ctx context.Context, project string) error {
-	err := b.SDK.DeleteStack(ctx, project)
+	resources, err := b.SDK.ListStackResources(ctx, project)
+	if err != nil {
+		return err
+	}
+
+	err = resources.apply(awsTypeCapacityProvider, delete(ctx, b.SDK.DeleteCapacityProvider))
+	if err != nil {
+		return err
+	}
+
+	err = resources.apply(awsTypeAutoscalingGroup, delete(ctx, b.SDK.DeleteAutoscalingGroup))
+	if err != nil {
+		return err
+	}
+
+	previousEvents, err := b.previousStackEvents(ctx, project)
 	if err != nil {
 		return err
 	}
-	return b.WaitStackCompletion(ctx, project, stackDelete)
+
+	err = b.SDK.DeleteStack(ctx, project)
+	if err != nil {
+		return err
+	}
+	return b.WaitStackCompletion(ctx, project, stackDelete, previousEvents...)
+}
+
+func (b *ecsAPIService) previousStackEvents(ctx context.Context, project string) ([]string, error) {
+	events, err := b.SDK.DescribeStackEvents(ctx, project)
+	if err != nil {
+		return nil, err
+	}
+	var previousEvents []string
+	for _, e := range events {
+		previousEvents = append(previousEvents, *e.EventId)
+	}
+	return previousEvents, nil
+}
+
+func delete(ctx context.Context, delete func(ctx context.Context, arn string) error) func(r stackResource) error {
+	return func(r stackResource) error {
+		w := progress.ContextWriter(ctx)
+		w.Event(progress.Event{
+			ID:         r.LogicalID,
+			Status:     progress.Working,
+			StatusText: "DELETE_IN_PROGRESS",
+		})
+		return delete(ctx, r.ARN)
+	}
 }
diff --git a/ecs/iam.go b/ecs/iam.go
index 5b061172..3a517482 100644
--- a/ecs/iam.go
+++ b/ecs/iam.go
@@ -21,35 +21,35 @@ const (
 	ecrReadOnlyPolicy      = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
 	ecsEC2InstanceRole     = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
 
-	actionGetSecretValue  = "secretsmanager:GetSecretValue"
-	actionGetParameters   = "ssm:GetParameters"
-	actionDecrypt         = "kms:Decrypt"
-	actionAutoScaling     = "application-autoscaling:*"
-	actionGetMetrics      = "cloudwatch:GetMetricStatistics"
-	actionDescribeService = "ecs:DescribeServices"
-	actionUpdateService   = "ecs:UpdateService"
+	actionGetSecretValue = "secretsmanager:GetSecretValue"
+	actionGetParameters  = "ssm:GetParameters"
+	actionDecrypt        = "kms:Decrypt"
 )
 
-var (
-	ecsTaskAssumeRolePolicyDocument     = policyDocument("ecs-tasks.amazonaws.com")
-	ec2InstanceAssumeRolePolicyDocument = policyDocument("ec2.amazonaws.com")
-	ausocalingAssumeRolePolicyDocument  = policyDocument("application-autoscaling.amazonaws.com")
-)
-
-func policyDocument(service string) PolicyDocument {
-	return PolicyDocument{
-		Version: "2012-10-17", // https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html
-		Statement: []PolicyStatement{
-			{
-				Effect: "Allow",
-				Principal: PolicyPrincipal{
-					Service: service,
-				},
-				Action: []string{"sts:AssumeRole"},
+var ecsTaskAssumeRolePolicyDocument = PolicyDocument{
+	Version: "2012-10-17", // https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html
+	Statement: []PolicyStatement{
+		{
+			Effect: "Allow",
+			Principal: PolicyPrincipal{
+				Service: "ecs-tasks.amazonaws.com",
 			},
+			Action: []string{"sts:AssumeRole"},
 		},
-	}
+	},
+}
 
+var ec2InstanceAssumeRolePolicyDocument = PolicyDocument{
+	Version: "2012-10-17", // https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html
+	Statement: []PolicyStatement{
+		{
+			Effect: "Allow",
+			Principal: PolicyPrincipal{
+				Service: "ec2.amazonaws.com",
+			},
+			Action: []string{"sts:AssumeRole"},
+		},
+	},
 }
 
 // PolicyDocument describes an IAM policy document
diff --git a/ecs/sdk.go b/ecs/sdk.go
index 0670a718..e1cef4c9 100644
--- a/ecs/sdk.go
+++ b/ecs/sdk.go
@@ -32,6 +32,8 @@ import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/autoscaling"
+	"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
 	"github.com/aws/aws-sdk-go/service/cloudformation"
 	"github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface"
 	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
@@ -48,6 +50,7 @@ import (
 	"github.com/aws/aws-sdk-go/service/iam/iamiface"
 	"github.com/aws/aws-sdk-go/service/secretsmanager"
 	"github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface"
+	"github.com/hashicorp/go-multierror"
 	"github.com/sirupsen/logrus"
 )
 
@@ -61,6 +64,7 @@ type sdk struct {
 	CF  cloudformationiface.CloudFormationAPI
 	SM  secretsmanageriface.SecretsManagerAPI
 	SSM ssmiface.SSMAPI
+	AG  autoscalingiface.AutoScalingAPI
 }
 
 func newSDK(sess *session.Session) sdk {
@@ -77,6 +81,7 @@ func newSDK(sess *session.Session) sdk {
 		CF:  cloudformation.New(sess),
 		SM:  secretsmanager.New(sess),
 		SSM: ssm.New(sess),
+		AG:  autoscaling.New(sess),
 	}
 }
 
@@ -364,7 +369,24 @@ type stackResource struct {
 	Status    string
 }
 
-func (s sdk) ListStackResources(ctx context.Context, name string) ([]stackResource, error) {
+type stackResourceFn func(r stackResource) error
+
+type stackResources []stackResource
+
+func (resources stackResources) apply(awsType string, fn stackResourceFn) error {
+	var errs *multierror.Error
+	for _, r := range resources {
+		if r.Type == awsType {
+			err := fn(r)
+			if err != nil {
+				errs = multierror.Append(err)
+			}
+		}
+	}
+	return errs.ErrorOrNil()
+}
+
+func (s sdk) ListStackResources(ctx context.Context, name string) (stackResources, error) {
 	// FIXME handle pagination
 	res, err := s.CF.ListStackResourcesWithContext(ctx, &cloudformation.ListStackResourcesInput{
 		StackName: aws.String(name),
@@ -373,7 +395,7 @@ func (s sdk) ListStackResources(ctx context.Context, name string) ([]stackResour
 		return nil, err
 	}
 
-	resources := []stackResource{}
+	resources := stackResources{}
 	for _, r := range res.StackResourceSummaries {
 		resources = append(resources, stackResource{
 			LogicalID: aws.StringValue(r.LogicalResourceId),
@@ -714,3 +736,18 @@ func (s sdk) SecurityGroupExists(ctx context.Context, sg string) (bool, error) {
 	}
 	return len(desc.SecurityGroups) > 0, nil
 }
+
+func (s sdk) DeleteCapacityProvider(ctx context.Context, arn string) error {
+	_, err := s.ECS.DeleteCapacityProvider(&ecs.DeleteCapacityProviderInput{
+		CapacityProvider: aws.String(arn),
+	})
+	return err
+}
+
+func (s sdk) DeleteAutoscalingGroup(ctx context.Context, arn string) error {
+	_, err := s.AG.DeleteAutoScalingGroup(&autoscaling.DeleteAutoScalingGroupInput{
+		AutoScalingGroupName: aws.String(arn),
+		ForceDelete:          aws.Bool(true),
+	})
+	return err
+}
diff --git a/ecs/volumes.go b/ecs/volumes.go
index f4f80bf4..d3f24621 100644
--- a/ecs/volumes.go
+++ b/ecs/volumes.go
@@ -42,7 +42,7 @@ func (b *ecsAPIService) createNFSmountIngress(securityGroups []string, project *
 				}
 				break
 			}
-			name := fmt.Sprintf("%sNFSMount%s", normalizeResourceName(s.Name), n)
+			name := fmt.Sprintf("%sNFSMount%s", s.Name, n)
 			template.Resources[name] = &ec2.SecurityGroupIngress{
 				Description:           fmt.Sprintf("Allow NFS mount for %s on %s", s.Name, n),
 				GroupId:               target,
diff --git a/ecs/wait.go b/ecs/wait.go
index 27ccef4b..7413a4fe 100644
--- a/ecs/wait.go
+++ b/ecs/wait.go
@@ -28,8 +28,12 @@ import (
 	"github.com/aws/aws-sdk-go/aws"
 )
 
-func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, operation int) error { //nolint:gocyclo
+func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, operation int, ignored ...string) error { //nolint:gocyclo
 	knownEvents := map[string]struct{}{}
+	for _, id := range ignored {
+		knownEvents[id] = struct{}{}
+	}
+
 	// progress writer
 	w := progress.ContextWriter(ctx)
 	// Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
@@ -78,7 +82,6 @@ func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, op
 			case "CREATE_COMPLETE":
 				if operation == stackCreate {
 					progressStatus = progress.Done
-
 				}
 			case "UPDATE_COMPLETE":
 				if operation == stackUpdate {
diff --git a/ecs/x.go b/ecs/x.go
index 6968ba99..9b93436c 100644
--- a/ecs/x.go
+++ b/ecs/x.go
@@ -29,5 +29,4 @@ const (
 	extensionRetention       = "x-aws-logs_retention"
 	extensionRole            = "x-aws-role"
 	extensionManagedPolicies = "x-aws-policies"
-	extensionAutoScaling     = "x-aws-autoscaling"
 )
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 05892cd4..7de8a2bb 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -78,7 +78,7 @@ const (
 
 // Track sends the tracking analytics to Docker Desktop
 func Track(context string, args []string, flags *flag.FlagSet, status string) {
-	command := GetCommand(args, flags)
+	command := getCommand(args, flags)
 	if command != "" {
 		c := NewClient()
 		c.Send(Command{
@@ -90,8 +90,7 @@ func Track(context string, args []string, flags *flag.FlagSet, status string) {
 	}
 }
 
-// GetCommand get the invoked command
-func GetCommand(args []string, flags *flag.FlagSet) string {
+func getCommand(args []string, flags *flag.FlagSet) string {
 	command := ""
 	strippedArgs := stripFlags(args, flags)
 
diff --git a/protos/containers/v1/containers.pb.go b/protos/containers/v1/containers.pb.go
index 75704f9a..aa4940be 100644
--- a/protos/containers/v1/containers.pb.go
+++ b/protos/containers/v1/containers.pb.go
@@ -737,8 +737,6 @@ type RunRequest struct {
 	MemoryLimit            uint64            `protobuf:"varint,6,opt,name=memory_limit,json=memoryLimit,proto3" json:"memory_limit,omitempty"`
 	CpuLimit               uint64            `protobuf:"varint,7,opt,name=cpu_limit,json=cpuLimit,proto3" json:"cpu_limit,omitempty"`
 	RestartPolicyCondition string            `protobuf:"bytes,8,opt,name=restart_policy_condition,json=restartPolicyCondition,proto3" json:"restart_policy_condition,omitempty"`
-	Command                []string          `protobuf:"bytes,9,rep,name=command,proto3" json:"command,omitempty"`
-	Environment            []string          `protobuf:"bytes,10,rep,name=environment,proto3" json:"environment,omitempty"`
 }
 
 func (x *RunRequest) Reset() {
@@ -829,20 +827,6 @@ func (x *RunRequest) GetRestartPolicyCondition() string {
 	return ""
 }
 
-func (x *RunRequest) GetCommand() []string {
-	if x != nil {
-		return x.Command
-	}
-	return nil
-}
-
-func (x *RunRequest) GetEnvironment() []string {
-	if x != nil {
-		return x.Environment
-	}
-	return nil
-}
-
 type RunResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1281,7 +1265,7 @@ var file_protos_containers_v1_containers_proto_rawDesc = []byte{
 	0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61,
 	0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x22,
 	0x0e, 0x0a, 0x0c, 0x4b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
-	0xd3, 0x03, 0x0a, 0x0a, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
+	0x97, 0x03, 0x0a, 0x0a, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
 	0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14,
 	0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69,
 	0x6d, 0x61, 0x67, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20,
@@ -1302,110 +1286,106 @@ var file_protos_containers_v1_containers_proto_rawDesc = []byte{
 	0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f,
 	0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
 	0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50,
-	0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18,
-	0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, 0x76, 0x69,
-	0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x65,
-	0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61,
-	0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x0d, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x0b, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x1b,
-	0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61,
-	0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12,
-	0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e,
-	0x76, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03,
-	0x74, 0x74, 0x79, 0x22, 0x26, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x4c,
-	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c,
-	0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x5e, 0x0a, 0x0c,
-	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0a,
-	0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70,
-	0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
-	0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x48, 0x0a, 0x0b,
-	0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63,
-	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16,
-	0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
-	0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x22, 0x24, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0xf2, 0x07, 0x0a,
-	0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, 0x04, 0x4c,
-	0x69, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
-	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
-	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
-	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
-	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72,
-	0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
-	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65,
+	0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x39,
+	0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+	0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+	0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x0d, 0x0a, 0x0b, 0x52, 0x75, 0x6e,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x0b, 0x45, 0x78, 0x65,
+	0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12,
+	0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61,
+	0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
+	0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x08, 0x52, 0x03, 0x74, 0x74, 0x79, 0x22, 0x26, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75,
+	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22,
+	0x1f, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10,
+	0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c,
+	0x22, 0x5e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x4e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65,
 	0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e,
-	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70,
-	0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70,
-	0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
-	0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e,
-	0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x4b, 0x69, 0x6c, 0x6c, 0x12, 0x30, 0x2e,
-	0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
-	0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x68, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e,
+	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61,
+	0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73,
+	0x22, 0x48, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
+	0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x08, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x22, 0x24, 0x0a, 0x0c, 0x4c, 0x6f,
+	0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x32, 0xf2, 0x07, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12,
+	0x6b, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f,
+	0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+	0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e,
 	0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04,
-	0x45, 0x78, 0x65, 0x63, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x05,
+	0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
+	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64,
+	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+	0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53,
+	0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04,
+	0x53, 0x74, 0x6f, 0x70, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65,
 	0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e,
-	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52,
+	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52,
 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63,
 	0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63,
-	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65,
-	0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x04, 0x4c, 0x6f, 0x67,
-	0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
+	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f,
+	0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x4b, 0x69, 0x6c,
+	0x6c, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
 	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
 	0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
-	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65,
-	0x74, 0x65, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e,
-	0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63,
+	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x6c, 0x6c, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x2f, 0x2e,
+	0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x6b, 0x0a, 0x04, 0x45, 0x78, 0x65, 0x63, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64,
+	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+	0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45,
+	0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a,
+	0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
+	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f,
+	0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+	0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f,
+	0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x06,
+	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63,
 	0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63,
 	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c,
-	0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x07, 0x49,
-	0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63,
-	0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63,
-	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73,
-	0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f,
-	0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
-	0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x2d, 0x63,
-	0x6c, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x33,
+	0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x74, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
+	0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+	0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+	0x73, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/protos/containers/v1/containers.proto b/protos/containers/v1/containers.proto
index 154f3a4f..c2cb2f14 100644
--- a/protos/containers/v1/containers.proto
+++ b/protos/containers/v1/containers.proto
@@ -103,8 +103,6 @@ message RunRequest {
 	uint64 memory_limit = 6;
 	uint64 cpu_limit = 7;
 	string restart_policy_condition = 8;
-	repeated string command = 9;
-	repeated string environment = 10; 
 }
 
 message RunResponse {
diff --git a/server/proxy/containers.go b/server/proxy/containers.go
index b3e74962..ff3e0962 100644
--- a/server/proxy/containers.go
+++ b/server/proxy/containers.go
@@ -153,13 +153,11 @@ func grpcContainerToContainerConfig(request *containersv1.RunRequest) containers
 	return containers.ContainerConfig{
 		ID:                     request.GetId(),
 		Image:                  request.GetImage(),
-		Command:                request.GetCommand(),
 		Ports:                  ports,
 		Labels:                 request.GetLabels(),
 		Volumes:                request.GetVolumes(),
 		MemLimit:               formatter.MemBytes(request.GetMemoryLimit()),
 		CPULimit:               float64(request.GetCpuLimit()),
 		RestartPolicyCondition: request.RestartPolicyCondition,
-		Environment:            request.Environment,
 	}
 }


Test patch:
diff --git a/aci/convert/container_test.go b/aci/convert/container_test.go
index 49f01895..6bb63e4a 100644
--- a/aci/convert/container_test.go
+++ b/aci/convert/container_test.go
@@ -29,14 +29,12 @@ import (
 func TestConvertContainerEnvironment(t *testing.T) {
 	container := containers.ContainerConfig{
 		ID:          "container1",
-		Command:     []string{"echo", "Hello!"},
 		Environment: []string{"key1=value1", "key2", "key3=value3"},
 	}
 	project, err := ContainerToComposeProject(container)
 	assert.NilError(t, err)
 	service1 := project.Services[0]
 	assert.Equal(t, service1.Name, container.ID)
-	assert.DeepEqual(t, []string(service1.Command), container.Command)
 	assert.DeepEqual(t, service1.Environment, types.MappingWithEquals{
 		"key1": to.StringPtr("value1"),
 		"key2": nil,
diff --git a/cli/cmd/run/run_test.go b/cli/cmd/run/run_test.go
index 789fe400..78b23c54 100644
--- a/cli/cmd/run/run_test.go
+++ b/cli/cmd/run/run_test.go
@@ -23,8 +23,6 @@ import (
 
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/golden"
-
-	"github.com/docker/compose-cli/cli/options/run"
 )
 
 func TestHelp(t *testing.T) {
@@ -42,24 +40,3 @@ func TestHelpNoDomainFlag(t *testing.T) {
 	_ = c.Help()
 	assert.Assert(t, !strings.Contains(b.String(), "domainname"))
 }
-
-func TestRunEnvironmentFiles(t *testing.T) {
-	runOpts := run.Opts{
-		Environment: []string{
-			"VAR=1",
-		},
-		EnvironmentFiles: []string{
-			"testdata/runtest1.env",
-			"testdata/runtest2.env",
-		},
-	}
-	containerConfig, err := runOpts.ToContainerConfig("test")
-	assert.NilError(t, err)
-	assert.DeepEqual(t, containerConfig.Environment, []string{
-		"VAR=1",
-		"FIRST_VAR=\"firstValue\"",
-		"SECOND_VAR=secondValue",
-		"THIRD_VAR=2",
-		"FOURTH_VAR=fourthValue",
-	})
-}
diff --git a/cli/cmd/run/testdata/run-help.golden b/cli/cmd/run/testdata/run-help.golden
index 71692ccd..178c63b0 100644
--- a/cli/cmd/run/testdata/run-help.golden
+++ b/cli/cmd/run/testdata/run-help.golden
@@ -8,7 +8,6 @@ Flags:
   -d, --detach                Run container in background and print container ID
       --domainname string     Container NIS domain name
   -e, --env stringArray       Set environment variables
-      --envFile stringArray   Path to environment files to be translated as environment variables
   -l, --label stringArray     Set meta data on a container
   -m, --memory bytes          Memory limit
       --name string           Assign a name to the container
diff --git a/cli/cmd/run/testdata/runtest1.env b/cli/cmd/run/testdata/runtest1.env
deleted file mode 100644
index 495661e3..00000000
--- a/cli/cmd/run/testdata/runtest1.env
+++ /dev/null
@@ -1,2 +0,0 @@
-FIRST_VAR="firstValue"
-SECOND_VAR=secondValue
diff --git a/cli/cmd/run/testdata/runtest2.env b/cli/cmd/run/testdata/runtest2.env
deleted file mode 100644
index d6182fbf..00000000
--- a/cli/cmd/run/testdata/runtest2.env
+++ /dev/null
@@ -1,2 +0,0 @@
-THIRD_VAR=2
-FOURTH_VAR=fourthValue
diff --git a/ecs/autoscaling_test.go b/ecs/autoscaling_test.go
deleted file mode 100644
index 1a411614..00000000
--- a/ecs/autoscaling_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-   Copyright 2020 Docker Compose CLI authors
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package ecs
-
-import (
-	"testing"
-
-	autoscaling "github.com/awslabs/goformation/v4/cloudformation/applicationautoscaling"
-	"gotest.tools/v3/assert"
-)
-
-func TestAutoScaling(t *testing.T) {
-	template := convertYaml(t, `
-services:
-  foo:
-    image: hello_world
-    deploy:
-      x-aws-autoscaling: 75
-`)
-	target := template.Resources["FooScalableTarget"].(*autoscaling.ScalableTarget)
-	assert.Check(t, target != nil)
-	policy := template.Resources["FooScalingPolicy"].(*autoscaling.ScalingPolicy)
-	if policy == nil || policy.TargetTrackingScalingPolicyConfiguration == nil {
-		t.Fail()
-	}
-	assert.Check(t, policy.TargetTrackingScalingPolicyConfiguration.TargetValue == float64(75))
-}
diff --git a/ecs/testdata/simple/simple-cloudformation-conversion.golden b/ecs/testdata/simple/simple-cloudformation-conversion.golden
index 07200659..56ec12f0 100644
--- a/ecs/testdata/simple/simple-cloudformation-conversion.golden
+++ b/ecs/testdata/simple/simple-cloudformation-conversion.golden
@@ -37,6 +37,7 @@
     "DefaultNetwork": {
       "Properties": {
         "GroupDescription": "TestSimpleConvert Security Group for default network",
+        "GroupName": "DefaultNetwork",
         "Tags": [
           {
             "Key": "com.docker.compose.project",
@@ -300,16 +301,6 @@
         "ManagedPolicyArns": [
           "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
           "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
-        ],
-        "Tags": [
-          {
-            "Key": "com.docker.compose.project",
-            "Value": "TestSimpleConvert"
-          },
-          {
-            "Key": "com.docker.compose.service",
-            "Value": "simple"
-          }
         ]
       },
       "Type": "AWS::IAM::Role"
diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go
index cb79f9a5..d2fbc236 100644
--- a/metrics/metrics_test.go
+++ b/metrics/metrics_test.go
@@ -25,7 +25,7 @@ import (
 
 func TestFlag(t *testing.T) {
 	root := &cobra.Command{}
-	root.PersistentFlags().BoolP("debug", "D", false, "debug")
+	root.PersistentFlags().BoolP("debug", "d", false, "debug")
 	root.PersistentFlags().String("str", "str", "str")
 
 	testCases := []struct {
@@ -40,7 +40,7 @@ func TestFlag(t *testing.T) {
 		},
 		{
 			name:     "with short flags",
-			args:     []string{"-D", "run"},
+			args:     []string{"-d", "run"},
 			expected: "run",
 		},
 		{
@@ -133,26 +133,11 @@ func TestFlag(t *testing.T) {
 			args:     []string{"create", "--rm", "test"},
 			expected: "create",
 		},
-		{
-			name:     "compose up -f xxx",
-			args:     []string{"compose", "up", "-f", "titi.yaml"},
-			expected: "compose up",
-		},
-		{
-			name:     "compose -f xxx up",
-			args:     []string{"compose", "-f", "titi.yaml", "up"},
-			expected: "compose up",
-		},
-		{
-			name:     "-D compose -f xxx up",
-			args:     []string{"--debug", "compose", "-f", "titi.yaml", "up"},
-			expected: "compose up",
-		},
 	}
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := GetCommand(testCase.args, root.PersistentFlags())
+			result := getCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
@@ -225,7 +210,7 @@ func TestEcs(t *testing.T) {
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := GetCommand(testCase.args, root.PersistentFlags())
+			result := getCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
@@ -273,7 +258,7 @@ func TestScan(t *testing.T) {
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := GetCommand(testCase.args, root.PersistentFlags())
+			result := getCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
diff --git a/server/proxy/containers_test.go b/server/proxy/containers_test.go
index e738523f..2fa0f84b 100644
--- a/server/proxy/containers_test.go
+++ b/server/proxy/containers_test.go
@@ -46,7 +46,6 @@ func TestGrpcContainerToContainerConfig(t *testing.T) {
 		},
 		MemoryLimit: 41,
 		CpuLimit:    42,
-		Environment: []string{"PROTOVAR=VALUE"},
 	}
 
 	cc := grpcContainerToContainerConfig(r)
@@ -66,5 +65,4 @@ func TestGrpcContainerToContainerConfig(t *testing.T) {
 	assert.DeepEqual(t, cc.Labels, map[string]string{
 		"mykey": "mylabel",
 	})
-	assert.DeepEqual(t, cc.Environment, []string{"PROTOVAR=VALUE"})
 }
diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go
index 193a7d5f..6d6444ec 100644
--- a/tests/aci-e2e/e2e-aci_test.go
+++ b/tests/aci-e2e/e2e-aci_test.go
@@ -20,6 +20,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"net/http"
 	"net/url"
 	"os"
@@ -30,6 +31,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/docker/compose-cli/aci/convert"
+
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	"gotest.tools/v3/icmd"
@@ -40,7 +43,6 @@ import (
 	"github.com/Azure/go-autorest/autorest/to"
 
 	"github.com/docker/compose-cli/aci"
-	"github.com/docker/compose-cli/aci/convert"
 	"github.com/docker/compose-cli/aci/login"
 	"github.com/docker/compose-cli/api/containers"
 	"github.com/docker/compose-cli/context/store"
@@ -250,8 +252,12 @@ func TestContainerRunVolume(t *testing.T) {
 	})
 
 	t.Run("http get", func(t *testing.T) {
-		output := HTTPGetWithRetry(t, endpoint, http.StatusOK, 2*time.Second, 20*time.Second)
-		assert.Assert(t, strings.Contains(output, testFileContent), "Actual content: "+output)
+		r, err := HTTPGetWithRetry(endpoint, 3)
+		assert.NilError(t, err)
+		assert.Equal(t, r.StatusCode, http.StatusOK)
+		b, err := ioutil.ReadAll(r.Body)
+		assert.NilError(t, err)
+		assert.Assert(t, strings.Contains(string(b), testFileContent), "Actual content: "+string(b))
 	})
 
 	t.Run("logs", func(t *testing.T) {
@@ -357,9 +363,9 @@ func TestContainerRunAttached(t *testing.T) {
 			"--restart", "on-failure",
 			"--memory", "0.1G", "--cpus", "0.1",
 			"-p", "80:80",
+			"nginx",
 			"--domainname",
 			dnsLabelName,
-			"nginx",
 		)
 		followLogsProcess = icmd.StartCmd(cmd)
 
@@ -493,12 +499,17 @@ func TestComposeUpUpdate(t *testing.T) {
 		assert.Assert(t, is.Len(containerInspect.Ports, 1))
 		endpoint := fmt.Sprintf("http://%s:%d", containerInspect.Ports[0].HostIP, containerInspect.Ports[0].HostPort)
 
-		output := HTTPGetWithRetry(t, endpoint+"/words/noun", http.StatusOK, 2*time.Second, 20*time.Second)
-
-		assert.Assert(t, strings.Contains(output, `"word":`))
+		r, err := HTTPGetWithRetry(endpoint+"/words/noun", 3)
+		assert.NilError(t, err)
+		assert.Equal(t, r.StatusCode, http.StatusOK)
+		b, err := ioutil.ReadAll(r.Body)
+		assert.NilError(t, err)
+		assert.Assert(t, strings.Contains(string(b), `"word":`))
 
 		endpoint = fmt.Sprintf("http://%s:%d", fqdn, containerInspect.Ports[0].HostPort)
-		HTTPGetWithRetry(t, endpoint+"/words/noun", http.StatusOK, 2*time.Second, 20*time.Second)
+		r, err = HTTPGetWithRetry(endpoint+"/words/noun", 3)
+		assert.NilError(t, err)
+		assert.Equal(t, r.StatusCode, http.StatusOK)
 	})
 
 	t.Run("compose ps", func(t *testing.T) {
@@ -566,7 +577,14 @@ func TestComposeUpUpdate(t *testing.T) {
 				assert.Equal(t, containerInspect.Ports[0].HostPort, uint32(8080))
 				assert.Equal(t, containerInspect.Ports[0].ContainerPort, uint32(8080))
 			}
-			HTTPGetWithRetry(t, endpoint+route, http.StatusOK, 1*time.Second, 60*time.Second)
+			checkUp := func(t poll.LogT) poll.Result {
+				r, _ := http.Get(endpoint + route)
+				if r != nil && r.StatusCode == http.StatusOK {
+					return poll.Success()
+				}
+				return poll.Continue("Waiting for container to serve request")
+			}
+			poll.WaitOn(t, checkUp, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second))
 
 			res = c.RunDockerCmd("ps")
 			p := containerInspect.Ports[0]
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
index f7256666..7675c07f 100644
--- a/tests/e2e/e2e_test.go
+++ b/tests/e2e/e2e_test.go
@@ -56,12 +56,6 @@ func TestComposeNotImplemented(t *testing.T) {
 		ExitCode: 1,
 		Err:      `Command "compose up" not available in current context (default)`,
 	})
-
-	res = c.RunDockerOrExitError("compose", "-f", "titi.yaml", "up")
-	res.Assert(t, icmd.Expected{
-		ExitCode: 1,
-		Err:      `Command "compose up" not available in current context (default)`,
-	})
 }
 
 func TestContextDefault(t *testing.T) {
@@ -205,30 +199,9 @@ func TestLoginCommandDelegation(t *testing.T) {
 		})
 	})
 
-	t.Run("localhost registry interactive", func(t *testing.T) {
-		res := c.RunDockerOrExitError("login", "localhost:443")
-		res.Assert(t, icmd.Expected{
-			ExitCode: 1,
-			Err:      "Cannot perform an interactive login from a non TTY device",
-		})
-	})
-
-	t.Run("localhost registry", func(t *testing.T) {
-		res := c.RunDockerOrExitError("login", "localhost", "-u", "user", "-p", "password")
-		res.Assert(t, icmd.Expected{
-			ExitCode: 1,
-			Err:      "http://localhost/v2/",
-		})
-	})
-
 	t.Run("logout", func(t *testing.T) {
 		res := c.RunDockerCmd("logout", "someregistry.docker.io")
-		res.Assert(t, icmd.Expected{Out: "Removing login credentials for someregistry.docker.io"})
-	})
-
-	t.Run("logout", func(t *testing.T) {
-		res := c.RunDockerCmd("logout", "localhost:443")
-		res.Assert(t, icmd.Expected{Out: "Removing login credentials for localhost:443"})
+		res.Assert(t, icmd.Expected{Out: "someregistry.docker.io"})
 	})
 
 	t.Run("existing context", func(t *testing.T) {
@@ -242,6 +215,18 @@ func TestLoginCommandDelegation(t *testing.T) {
 	})
 }
 
+func TestCloudLogin(t *testing.T) {
+	c := NewParallelE2eCLI(t, binDir)
+
+	t.Run("unknown backend", func(t *testing.T) {
+		res := c.RunDockerOrExitError("login", "mycloudbackend")
+		res.Assert(t, icmd.Expected{
+			ExitCode: 1,
+			Err:      "unknown backend type for cloud login: mycloudbackend",
+		})
+	})
+}
+
 func TestMissingExistingCLI(t *testing.T) {
 	t.Parallel()
 	home, err := ioutil.TempDir("", "")
diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go
index d15313cf..1e79c18c 100644
--- a/tests/framework/e2e.go
+++ b/tests/framework/e2e.go
@@ -34,7 +34,6 @@ import (
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	"gotest.tools/v3/icmd"
-	"gotest.tools/v3/poll"
 
 	"github.com/docker/compose-cli/api/containers"
 )
@@ -202,28 +201,19 @@ func ParseContainerInspect(stdout string) (*containers.Container, error) {
 }
 
 // HTTPGetWithRetry performs an HTTP GET on an `endpoint`.
-// In the case of an error or the response status is not the expeted one, it retries the same request,
-// returning the response body as a string (empty if we could not reach it)
-func HTTPGetWithRetry(t *testing.T, endpoint string, expectedStatus int, retryDelay time.Duration, timeout time.Duration) string {
+// In the case of an error it retries the same request after a 5 second sleep,
+// returning the error if count of `tries` is reached
+func HTTPGetWithRetry(endpoint string, tries int) (*http.Response, error) {
 	var (
 		r   *http.Response
 		err error
 	)
-	checkUp := func(t poll.LogT) poll.Result {
+	for t := 0; t < tries; t++ {
 		r, err = http.Get(endpoint)
-		if err != nil {
-			return poll.Continue("reaching %q: Error %s", endpoint, err.Error())
-		}
-		if r.StatusCode == expectedStatus {
-			return poll.Success()
+		if err == nil || t == tries-1 {
+			break
 		}
-		return poll.Continue("reaching %q: %d != %d", endpoint, r.StatusCode, expectedStatus)
-	}
-	poll.WaitOn(t, checkUp, poll.WithDelay(retryDelay), poll.WithTimeout(timeout))
-	if r != nil {
-		b, err := ioutil.ReadAll(r.Body)
-		assert.NilError(t, err)
-		return string(b)
+		time.Sleep(5 * time.Second)
 	}
-	return ""
+	return r, err
 }