Skip to content

Commit

Permalink
feat: support more than 100 clusters (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
keidarcy authored May 17, 2024
1 parent 50a48dc commit cd72ea6
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ _testmain.go

*.log
dist
e1s_*
66 changes: 51 additions & 15 deletions internal/api/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,40 @@ package api
import (
"context"
"log/slog"
"math"
"sort"

"github.com/aws/aws-sdk-go-v2/service/ecs"
"github.com/aws/aws-sdk-go-v2/service/ecs/types"
"golang.org/x/sync/errgroup"
)

// Equivalent to
// aws ecs list-clusters
// aws ecs describe-clusters --clusters ${clusters}
func (store *Store) ListClusters() ([]types.Cluster, error) {
limit := int32(100)
clustersOutput, err := store.ecs.ListClusters(context.Background(), &ecs.ListClustersInput{
batchSize := 100
limit := int32(batchSize)
clusterARNs := []string{}
params := &ecs.ListClustersInput{
MaxResults: &limit,
})
}

if err != nil {
slog.Warn("failed to run aws api to list clusters", "error", err)
return []types.Cluster{}, err
for {
clustersOutput, err := store.ecs.ListClusters(context.Background(), params)
if err != nil {
slog.Warn("failed to run aws api to list clusters", "error", err)
if len(clusterARNs) == 0 {
return []types.Cluster{}, err
}
continue
}
clusterARNs = append(clusterARNs, clustersOutput.ClusterArns...)
if clustersOutput.NextToken != nil {
params.NextToken = clustersOutput.NextToken
} else {
break
}
}

include := []types.ClusterField{
Expand All @@ -30,20 +46,40 @@ func (store *Store) ListClusters() ([]types.Cluster, error) {
types.ClusterFieldStatistics,
types.ClusterFieldTags,
}
describeInput := &ecs.DescribeClustersInput{
Clusters: clustersOutput.ClusterArns,
Include: include,
}

results := []types.Cluster{}
g := new(errgroup.Group)

describeClusterOutput, err := store.ecs.DescribeClusters(context.Background(), describeInput)
if err != nil {
slog.Warn("failed to run aws api to describe clusters", "error", err)
return []types.Cluster{}, err
clusterCount := len(clusterARNs)
loopCount := clusterCount / batchSize

if clusterCount%batchSize == 0 {
loopCount = loopCount - 1
}

results = append(results, describeClusterOutput.Clusters...)
for i := 0; i <= loopCount; i++ {
i := i
g.Go(func() error {
clusters := clusterARNs[i*batchSize : int(math.Min(float64((i+1)*batchSize), float64(clusterCount)))]

// If describe more than 100, InvalidParameterException: Clusters cannot have more than 100 elements
describeClusterOutput, err := store.ecs.DescribeClusters(context.Background(), &ecs.DescribeClustersInput{
Clusters: clusters,
Include: include,
})
if err != nil {
slog.Warn("failed to run aws api to describe clusters", "error", err)
return err
}

results = append(results, describeClusterOutput.Clusters...)
return nil
})
}

if err := g.Wait(); err != nil {
return []types.Cluster{}, err
}

// sort by running task count, name ascending
sort.Slice(results, func(i, j int) bool {
Expand Down
13 changes: 6 additions & 7 deletions internal/api/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import (
// aws ecs list-services --cluster ${cluster}
// aws ecs describe-services --cluster ${cluster} --services ${service}
func (store *Store) ListServices(clusterName *string) ([]types.Service, error) {
limit := int32(100)
// You may specify up to 100 services to describe.
// If there are > 100 services in the cluster, loop and slice by 100
// to describe them in batches of <= 100.
batchSize := 100
limit := int32(batchSize)
params := &ecs.ListServicesInput{
Cluster: clusterName,
MaxResults: &limit,
Expand Down Expand Up @@ -47,10 +51,6 @@ func (store *Store) ListServices(clusterName *string) ([]types.Service, error) {
}
}

// You may specify up to 10 services to describe.
// If there are > 10 services in the cluster, loop and slice by 10
// to describe them in batches of <= 10.
batchSize := 10
serviceCount := len(serviceARNs)
loopCount := serviceCount / batchSize

Expand Down Expand Up @@ -89,8 +89,7 @@ func (store *Store) ListServices(clusterName *string) ([]types.Service, error) {
})
}

err := g.Wait()
if err != nil {
if err := g.Wait(); err != nil {
return []types.Service{}, err
}

Expand Down

0 comments on commit cd72ea6

Please sign in to comment.