Repository: docker/compose-cli
Pull request #1067 (2020-12-15 14:46:11)

Avoiding more ACI flakyness
some fixed in a804136b1c395f3a7d958d2516c8eec45b126ce7 (fixing `docker prune --dry-run --force` , exact same issue here with `docker prune --force`)

Signed-off-by: Guillaume Tardif <guillaume.tardif@gmail.com>

**What I did**
* detect strange ACI error message and retry docker prune --force one sec later

**Related issue**
https://github.com/docker/compose-cli/runs/1557354494#step:6:196

<!-- optional tests
You can add a / mention to run tests executed by default only on main branch : 
* `test-aci` to run ACI E2E tests
* `test-ecs` to run ECS E2E tests
* `test-windows` to run tests & E2E tests on windows
-->
/test-aci

**(not mandatory) A picture of a cute animal, if possible in relation with what you did**



Patch:
diff --git a/ecs/aws.go b/ecs/aws.go
index e20fe66a..5cf50fbf 100644
--- a/ecs/aws.go
+++ b/ecs/aws.go
@@ -40,7 +40,6 @@ type API interface {
 	CheckVPC(ctx context.Context, vpcID string) error
 	GetDefaultVPC(ctx context.Context) (string, error)
 	GetSubNets(ctx context.Context, vpcID string) ([]awsResource, error)
-	IsPublicSubnet(ctx context.Context, vpcID string, subNetID string) (bool, error)
 	GetRoleArn(ctx context.Context, name string) (string, error)
 	StackExists(ctx context.Context, name string) (bool, error)
 	CreateStack(ctx context.Context, name string, region string, template []byte) error
diff --git a/ecs/awsResources.go b/ecs/awsResources.go
index d1ff7cf4..012b3182 100644
--- a/ecs/awsResources.go
+++ b/ecs/awsResources.go
@@ -185,22 +185,10 @@ func (b *ecsAPIService) parseVPCExtension(ctx context.Context, project *types.Pr
 	if err != nil {
 		return "", nil, err
 	}
-
-	var publicSubNets []awsResource
-	for _, subNet := range subNets {
-		isPublic, err := b.aws.IsPublicSubnet(ctx, vpc, subNet.ID())
-		if err != nil {
-			return "", nil, err
-		}
-		if isPublic {
-			publicSubNets = append(publicSubNets, subNet)
-		}
-	}
-
-	if len(publicSubNets) < 2 {
-		return "", nil, fmt.Errorf("VPC %s should have at least 2 associated public subnets in different availability zones", vpc)
+	if len(subNets) < 2 {
+		return "", nil, fmt.Errorf("VPC %s should have at least 2 associated subnets in different availability zones", vpc)
 	}
-	return vpc, publicSubNets, nil
+	return vpc, subNets, nil
 }
 
 func (b *ecsAPIService) parseLoadBalancerExtension(ctx context.Context, project *types.Project) (awsResource, string, error) {
diff --git a/ecs/aws_mock.go b/ecs/aws_mock.go
index 486648f4..9d438bf2 100644
--- a/ecs/aws_mock.go
+++ b/ecs/aws_mock.go
@@ -6,13 +6,12 @@ package ecs
 
 import (
 	context "context"
-	reflect "reflect"
-
 	cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
 	ecs "github.com/aws/aws-sdk-go/service/ecs"
 	compose "github.com/docker/compose-cli/api/compose"
 	secrets "github.com/docker/compose-cli/api/secrets"
 	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
 )
 
 // MockAPI is a mock of API interface
@@ -454,21 +453,6 @@ func (mr *MockAPIMockRecorder) InspectSecret(arg0, arg1 interface{}) *gomock.Cal
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectSecret", reflect.TypeOf((*MockAPI)(nil).InspectSecret), arg0, arg1)
 }
 
-// IsPublicSubnet mocks base method
-func (m *MockAPI) IsPublicSubnet(ctx context.Context, arg0 string, arg1 string) (bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsPublicSubnet", arg0, arg1)
-	ret0, _ := ret[0].(bool)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// IsPublicSubnet indicates an expected call of IsPublicSubnet
-func (mr *MockAPIMockRecorder) IsPublicSubnet(arg0, arg1 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPublicSubnet", reflect.TypeOf((*MockAPI)(nil).IsPublicSubnet), arg0, arg1)
-}
-
 // ListFileSystems mocks base method
 func (m *MockAPI) ListFileSystems(arg0 context.Context, arg1 map[string]string) ([]awsResource, error) {
 	m.ctrl.T.Helper()
diff --git a/ecs/sdk.go b/ecs/sdk.go
index a8e89946..b44ecbfa 100644
--- a/ecs/sdk.go
+++ b/ecs/sdk.go
@@ -211,37 +211,6 @@ func (s sdk) GetSubNets(ctx context.Context, vpcID string) ([]awsResource, error
 	return ids, nil
 }
 
-func (s sdk) IsPublicSubnet(ctx context.Context, vpcID string, subNetID string) (bool, error) {
-	tables, err := s.EC2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{
-		Filters: []*ec2.Filter{
-			{
-				Name:   aws.String("association.subnet-id"),
-				Values: []*string{aws.String(subNetID)},
-			},
-		},
-	})
-	if err != nil {
-		return false, err
-	}
-	if len(tables.RouteTables) == 0 {
-		// If a subnet is not explicitly associated with any route table, it is implicitly associated with the main route table.
-		// https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-route-tables.html
-		return true, nil
-	}
-	for _, routeTable := range tables.RouteTables {
-		for _, route := range routeTable.Routes {
-			if aws.StringValue(route.State) != "active" {
-				continue
-			}
-			if strings.HasPrefix(aws.StringValue(route.GatewayId), "igw-") {
-				// Connected to an internet Gateway
-				return true, nil
-			}
-		}
-	}
-	return false, nil
-}
-
 func (s sdk) GetRoleArn(ctx context.Context, name string) (string, error) {
 	role, err := s.IAM.GetRoleWithContext(ctx, &iam.GetRoleInput{
 		RoleName: aws.String(name),


Test patch:
diff --git a/ecs/cloudformation_test.go b/ecs/cloudformation_test.go
index 0021114a..275721c3 100644
--- a/ecs/cloudformation_test.go
+++ b/ecs/cloudformation_test.go
@@ -591,8 +591,6 @@ func useDefaultVPC(m *MockAPIMockRecorder) {
 		existingAWSResource{id: "subnet1"},
 		existingAWSResource{id: "subnet2"},
 	}, nil)
-	m.IsPublicSubnet(gomock.Any(), "subnet1").Return(true, nil)
-	m.IsPublicSubnet(gomock.Any(), "subnet2").Return(true, nil)
 }
 
 func useGPU(m *MockAPIMockRecorder) {
diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go
index fdad7d76..44f46128 100644
--- a/tests/aci-e2e/e2e-aci_test.go
+++ b/tests/aci-e2e/e2e-aci_test.go
@@ -500,7 +500,12 @@ func TestContainerRunAttached(t *testing.T) {
 		l := Lines(res.Stdout())
 		assert.Equal(t, 2, len(l))
 
-		res = c.RunDockerCmd("prune", "--force")
+		res = c.RunDockerOrExitError("prune", "--force")
+		if strings.Contains(res.Stderr(), "unsupported protocol scheme") { //Flaky strange error on azure SDK call happening only during prune --force
+			time.Sleep(1 * time.Second)
+			res = c.RunDockerCmd("prune", "--force")
+		}
+
 		assert.Equal(t, "Deleted resources:\n"+container+"\nTotal CPUs reclaimed: 0.10, total memory reclaimed: 0.10 GB\n", res.Stdout())
 
 		res = c.RunDockerCmd("ps", "--all")