mirror of https://github.com/docker/compose.git
`ps` shows LoadBalancer URL
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
324443deb6
commit
f892ee1004
|
@ -14,7 +14,31 @@ func (b *Backend) Ps(ctx context.Context, project *types.Project) ([]compose.Ser
|
||||||
cluster = project.Name
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -26,7 +50,7 @@ func (b *Backend) Ps(ctx context.Context, project *types.Project) ([]compose.Ser
|
||||||
}
|
}
|
||||||
ports := []string{}
|
ports := []string{}
|
||||||
for _, p := range s.Ports {
|
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
|
state.Ports = ports
|
||||||
status[i] = state
|
status[i] = state
|
||||||
|
|
|
@ -105,7 +105,6 @@ func (b Backend) GetLoadBalancer(ctx context.Context, project *types.Project) (s
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("Load Balancer does not exist: %s", lb)
|
return "", fmt.Errorf("Load Balancer does not exist: %s", lb)
|
||||||
}
|
}
|
||||||
return b.api.GetLoadBalancerARN(ctx, lbName)
|
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,15 @@ type API interface {
|
||||||
StackExists(ctx context.Context, name string) (bool, error)
|
StackExists(ctx context.Context, name string) (bool, error)
|
||||||
CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error
|
CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error
|
||||||
DeleteStack(ctx context.Context, name 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)
|
GetStackID(ctx context.Context, name string) (string, error)
|
||||||
WaitStackComplete(ctx context.Context, name string, operation int) error
|
WaitStackComplete(ctx context.Context, name string, operation int) error
|
||||||
DescribeStackEvents(ctx context.Context, stackID string) ([]*cf.StackEvent, error)
|
DescribeStackEvents(ctx context.Context, stackID string) ([]*cf.StackEvent, error)
|
||||||
|
|
||||||
LoadBalancerExists(ctx context.Context, name string) (bool, error)
|
DescribeServices(ctx context.Context, cluster string, arns []string) ([]compose.ServiceStatus, error)
|
||||||
GetLoadBalancerARN(ctx context.Context, name string) (string, 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)
|
ClusterExists(ctx context.Context, name string) (bool, error)
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
func (s sdk) DeleteStack(ctx context.Context, name string) error {
|
||||||
logrus.Debug("Delete CloudFormation stack")
|
logrus.Debug("Delete CloudFormation stack")
|
||||||
_, err := s.CF.DeleteStackWithContext(ctx, &cloudformation.DeleteStackInput{
|
_, 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) {
|
func (s sdk) ListSecrets(ctx context.Context) ([]compose.Secret, error) {
|
||||||
|
|
||||||
logrus.Debug("List secrets ...")
|
logrus.Debug("List secrets ...")
|
||||||
response, err := s.SM.ListSecrets(&secretsmanager.ListSecretsInput{})
|
response, err := s.SM.ListSecrets(&secretsmanager.ListSecretsInput{})
|
||||||
if err != nil {
|
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) {
|
func (s sdk) DescribeServices(ctx context.Context, cluster string, arns []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
|
|
||||||
}
|
|
||||||
|
|
||||||
services, err := s.ECS.DescribeServicesWithContext(ctx, &ecs.DescribeServicesInput{
|
services, err := s.ECS.DescribeServicesWithContext(ctx, &ecs.DescribeServicesInput{
|
||||||
Cluster: aws.String(cluster),
|
Cluster: aws.String(cluster),
|
||||||
Services: list.ServiceArns,
|
Services: aws.StringSlice(arns),
|
||||||
Include: aws.StringSlice([]string{"TAGS"}),
|
Include: aws.StringSlice([]string{"TAGS"}),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -356,17 +368,13 @@ func (s sdk) DescribeServices(ctx context.Context, cluster string, project strin
|
||||||
status := []compose.ServiceStatus{}
|
status := []compose.ServiceStatus{}
|
||||||
for _, service := range services.Services {
|
for _, service := range services.Services {
|
||||||
var name string
|
var name string
|
||||||
var stack string
|
|
||||||
for _, t := range service.Tags {
|
for _, t := range service.Tags {
|
||||||
switch *t.Key {
|
if *t.Key == compose.ServiceTag {
|
||||||
case compose.ProjectTag:
|
|
||||||
stack = *t.Value
|
|
||||||
case compose.ServiceTag:
|
|
||||||
name = *t.Value
|
name = *t.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stack != project {
|
if name == "" {
|
||||||
continue
|
return nil, fmt.Errorf("service %s doesn't have a %s tag", *service.ServiceArn, compose.ServiceTag)
|
||||||
}
|
}
|
||||||
status = append(status, compose.ServiceStatus{
|
status = append(status, compose.ServiceStatus{
|
||||||
ID: *service.ServiceName,
|
ID: *service.ServiceName,
|
||||||
|
@ -410,10 +418,10 @@ func (s sdk) GetPublicIPs(ctx context.Context, interfaces ...string) (map[string
|
||||||
return publicIPs, nil
|
return publicIPs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sdk) LoadBalancerExists(ctx context.Context, name string) (bool, error) {
|
func (s sdk) LoadBalancerExists(ctx context.Context, arn string) (bool, error) {
|
||||||
logrus.Debug("Check if cluster was already created: ", name)
|
logrus.Debug("Check if LoadBalancer exists: ", arn)
|
||||||
lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
|
lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
|
||||||
Names: []*string{aws.String(name)},
|
LoadBalancerArns: []*string{aws.String(arn)},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -421,13 +429,13 @@ func (s sdk) LoadBalancerExists(ctx context.Context, name string) (bool, error)
|
||||||
return len(lbs.LoadBalancers) > 0, nil
|
return len(lbs.LoadBalancers) > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sdk) GetLoadBalancerARN(ctx context.Context, name string) (string, error) {
|
func (s sdk) GetLoadBalancerURL(ctx context.Context, arn string) (string, error) {
|
||||||
logrus.Debug("Check if cluster was already created: ", name)
|
logrus.Debug("Retrieve load balancer URL: ", arn)
|
||||||
lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
|
lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
|
||||||
Names: []*string{aws.String(name)},
|
LoadBalancerArns: []*string{aws.String(arn)},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return *lbs.LoadBalancers[0].LoadBalancerArn, nil
|
return *lbs.LoadBalancers[0].DNSName, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,13 @@ package compose
|
||||||
|
|
||||||
import "encoding/json"
|
import "encoding/json"
|
||||||
|
|
||||||
|
type StackResource struct {
|
||||||
|
LogicalID string
|
||||||
|
Type string
|
||||||
|
ARN string
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
|
||||||
type ServiceStatus struct {
|
type ServiceStatus struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
|
|
Loading…
Reference in New Issue