Jelajahi Sumber

`ps` shows LoadBalancer URL

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 5 tahun lalu
induk
melakukan
f892ee1004

+ 26 - 2
ecs/pkg/amazon/backend/list.go

@@ -14,7 +14,31 @@ func (b *Backend) Ps(ctx context.Context, project *types.Project) ([]compose.Ser
 		cluster = project.Name
 	}
 
-	status, err := b.api.DescribeServices(ctx, cluster, project.Name)
+	resources, err := b.api.ListStackResources(ctx, project.Name)
+	if err != nil {
+		return nil, err
+	}
+
+	var loadBalancer string
+	if lb, ok := project.Extensions[compose.ExtensionLB]; ok {
+		loadBalancer = lb.(string)
+	}
+	servicesARN := []string{}
+	for _, r := range resources {
+		switch r.Type {
+		case "AWS::ECS::Service":
+			servicesARN = append(servicesARN, r.ARN)
+		case "AWS::ElasticLoadBalancingV2::LoadBalancer":
+			loadBalancer = r.ARN
+		}
+	}
+
+	status, err := b.api.DescribeServices(ctx, cluster, servicesARN)
+	if err != nil {
+		return nil, err
+	}
+
+	url, err := b.api.GetLoadBalancerURL(ctx, loadBalancer)
 	if err != nil {
 		return nil, err
 	}
@@ -26,7 +50,7 @@ func (b *Backend) Ps(ctx context.Context, project *types.Project) ([]compose.Ser
 		}
 		ports := []string{}
 		for _, p := range s.Ports {
-			ports = append(ports, fmt.Sprintf("*:%d->%d/%s", p.Published, p.Target, p.Protocol))
+			ports = append(ports, fmt.Sprintf("%s:%d->%d/%s", url, p.Published, p.Target, p.Protocol))
 		}
 		state.Ports = ports
 		status[i] = state

+ 0 - 1
ecs/pkg/amazon/backend/up.go

@@ -105,7 +105,6 @@ func (b Backend) GetLoadBalancer(ctx context.Context, project *types.Project) (s
 		if !ok {
 			return "", fmt.Errorf("Load Balancer does not exist: %s", lb)
 		}
-		return b.api.GetLoadBalancerARN(ctx, lbName)
 	}
 	return "", nil
 }

+ 5 - 3
ecs/pkg/amazon/sdk/api.go

@@ -16,13 +16,15 @@ type API interface {
 	StackExists(ctx context.Context, name string) (bool, error)
 	CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error
 	DeleteStack(ctx context.Context, name string) error
-	DescribeServices(ctx context.Context, cluster string, project string) ([]compose.ServiceStatus, error)
+	ListStackResources(ctx context.Context, name string) ([]compose.StackResource, error)
 	GetStackID(ctx context.Context, name string) (string, error)
 	WaitStackComplete(ctx context.Context, name string, operation int) error
 	DescribeStackEvents(ctx context.Context, stackID string) ([]*cf.StackEvent, error)
 
-	LoadBalancerExists(ctx context.Context, name string) (bool, error)
-	GetLoadBalancerARN(ctx context.Context, name string) (string, error)
+	DescribeServices(ctx context.Context, cluster string, arns []string) ([]compose.ServiceStatus, error)
+
+	LoadBalancerExists(ctx context.Context, arn string) (bool, error)
+	GetLoadBalancerURL(ctx context.Context, arn string) (string, error)
 
 	ClusterExists(ctx context.Context, name string) (bool, error)
 

+ 33 - 25
ecs/pkg/amazon/sdk/sdk.go

@@ -222,6 +222,27 @@ func (s sdk) DescribeStackEvents(ctx context.Context, stackID string) ([]*cloudf
 	}
 }
 
+func (s sdk) ListStackResources(ctx context.Context, name string) ([]compose.StackResource, error) {
+	// FIXME handle pagination
+	res, err := s.CF.ListStackResourcesWithContext(ctx, &cloudformation.ListStackResourcesInput{
+		StackName: aws.String(name),
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	resources := []compose.StackResource{}
+	for _, r := range res.StackResourceSummaries {
+		resources = append(resources, compose.StackResource{
+			LogicalID: *r.LogicalResourceId,
+			Type:      *r.ResourceType,
+			ARN:       *r.PhysicalResourceId,
+			Status:    *r.ResourceStatus,
+		})
+	}
+	return resources, nil
+}
+
 func (s sdk) DeleteStack(ctx context.Context, name string) error {
 	logrus.Debug("Delete CloudFormation stack")
 	_, err := s.CF.DeleteStackWithContext(ctx, &cloudformation.DeleteStackInput{
@@ -270,7 +291,6 @@ func (s sdk) InspectSecret(ctx context.Context, id string) (compose.Secret, erro
 }
 
 func (s sdk) ListSecrets(ctx context.Context) ([]compose.Secret, error) {
-
 	logrus.Debug("List secrets ...")
 	response, err := s.SM.ListSecrets(&secretsmanager.ListSecretsInput{})
 	if err != nil {
@@ -336,18 +356,10 @@ func (s sdk) GetLogs(ctx context.Context, name string, consumer compose.LogConsu
 	}
 }
 
-func (s sdk) DescribeServices(ctx context.Context, cluster string, project string) ([]compose.ServiceStatus, error) {
-	// TODO handle pagination
-	list, err := s.ECS.ListServicesWithContext(ctx, &ecs.ListServicesInput{
-		Cluster: aws.String(cluster),
-	})
-	if err != nil {
-		return nil, err
-	}
-
+func (s sdk) DescribeServices(ctx context.Context, cluster string, arns []string) ([]compose.ServiceStatus, error) {
 	services, err := s.ECS.DescribeServicesWithContext(ctx, &ecs.DescribeServicesInput{
 		Cluster:  aws.String(cluster),
-		Services: list.ServiceArns,
+		Services: aws.StringSlice(arns),
 		Include:  aws.StringSlice([]string{"TAGS"}),
 	})
 	if err != nil {
@@ -356,17 +368,13 @@ func (s sdk) DescribeServices(ctx context.Context, cluster string, project strin
 	status := []compose.ServiceStatus{}
 	for _, service := range services.Services {
 		var name string
-		var stack string
 		for _, t := range service.Tags {
-			switch *t.Key {
-			case compose.ProjectTag:
-				stack = *t.Value
-			case compose.ServiceTag:
+			if *t.Key == compose.ServiceTag {
 				name = *t.Value
 			}
 		}
-		if stack != project {
-			continue
+		if name == "" {
+			return nil, fmt.Errorf("service %s doesn't have a %s tag", *service.ServiceArn, compose.ServiceTag)
 		}
 		status = append(status, compose.ServiceStatus{
 			ID:       *service.ServiceName,
@@ -410,10 +418,10 @@ func (s sdk) GetPublicIPs(ctx context.Context, interfaces ...string) (map[string
 	return publicIPs, nil
 }
 
-func (s sdk) LoadBalancerExists(ctx context.Context, name string) (bool, error) {
-	logrus.Debug("Check if cluster was already created: ", name)
+func (s sdk) LoadBalancerExists(ctx context.Context, arn string) (bool, error) {
+	logrus.Debug("Check if LoadBalancer exists: ", arn)
 	lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
-		Names: []*string{aws.String(name)},
+		LoadBalancerArns: []*string{aws.String(arn)},
 	})
 	if err != nil {
 		return false, err
@@ -421,13 +429,13 @@ func (s sdk) LoadBalancerExists(ctx context.Context, name string) (bool, error)
 	return len(lbs.LoadBalancers) > 0, nil
 }
 
-func (s sdk) GetLoadBalancerARN(ctx context.Context, name string) (string, error) {
-	logrus.Debug("Check if cluster was already created: ", name)
+func (s sdk) GetLoadBalancerURL(ctx context.Context, arn string) (string, error) {
+	logrus.Debug("Retrieve load balancer URL: ", arn)
 	lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
-		Names: []*string{aws.String(name)},
+		LoadBalancerArns: []*string{aws.String(arn)},
 	})
 	if err != nil {
 		return "", err
 	}
-	return *lbs.LoadBalancers[0].LoadBalancerArn, nil
+	return *lbs.LoadBalancers[0].DNSName, nil
 }

+ 7 - 0
ecs/pkg/compose/types.go

@@ -2,6 +2,13 @@ package compose
 
 import "encoding/json"
 
+type StackResource struct {
+	LogicalID string
+	Type      string
+	ARN       string
+	Status    string
+}
+
 type ServiceStatus struct {
 	ID       string
 	Name     string