From 5d6299f7bd576585c5c4dfcbd500e4773d276b16 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Tue, 7 Mar 2023 22:41:05 +0000 Subject: [PATCH 1/9] chore: reorg code from lib to inventory package Signed-off-by: Bradley Jones --- ecg/inventory/ecs.go | 79 ++++++++++++++++++++++ ecg/inventory/report.go | 70 ++++++++++++++++++++ ecg/lib.go | 136 +------------------------------------- internal/logger/logger.go | 1 - 4 files changed, 150 insertions(+), 136 deletions(-) create mode 100644 ecg/inventory/ecs.go diff --git a/ecg/inventory/ecs.go b/ecg/inventory/ecs.go new file mode 100644 index 0000000..edb17ca --- /dev/null +++ b/ecg/inventory/ecs.go @@ -0,0 +1,79 @@ +package inventory + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ecs" +) + +// Check if AWS are present, should be stored in ~/.aws/credentials +func checkAWSCredentials(sess *session.Session) error { + _, err := sess.Config.Credentials.Get() + if err != nil { + // TODO: Add some logs here detailing where to put the credentials + return fmt.Errorf("unable to get AWS credentials: %w", err) + } + return nil +} + +func fetchClusters(client *ecs.ECS) ([]*string, error) { + input := &ecs.ListClustersInput{} + + result, err := client.ListClusters(input) + if err != nil { + return nil, err + } + + return result.ClusterArns, nil +} + +func fetchTasksFromCluster(client *ecs.ECS, cluster string) ([]*string, error) { + input := &ecs.ListTasksInput{ + Cluster: aws.String(cluster), + } + + result, err := client.ListTasks(input) + if err != nil { + return nil, err + } + + return result.TaskArns, nil +} + +func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]ReportImage, error) { + input := &ecs.DescribeTasksInput{ + Cluster: aws.String(cluster), + Tasks: tasks, + } + + results, err := client.DescribeTasks(input) + if err != nil { + return []ReportImage{}, err + } + + uniqueImages := make(map[string]ReportImage) + + for _, task := range results.Tasks { + for _, container := range task.Containers { + digest := "" + if container.ImageDigest != nil { + digest = *container.ImageDigest + } + uniqueName := fmt.Sprintf("%s@%s", *container.Image, digest) + uniqueImages[uniqueName] = ReportImage{ + Tag: *container.Image, + RepoDigest: digest, + } + } + } + + // convert map of unique images to a slice + images := []ReportImage{} + for _, image := range uniqueImages { + images = append(images, image) + } + + return images, nil +} diff --git a/ecg/inventory/report.go b/ecg/inventory/report.go index 5476618..5f9f2a4 100644 --- a/ecg/inventory/report.go +++ b/ecg/inventory/report.go @@ -1,8 +1,78 @@ package inventory +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ecs" + + "github.com/anchore/anchore-ecs-inventory/internal/logger" +) + type Report struct { Timestamp string `json:"timestamp,omitempty"` // Should be generated using time.Now.UTC() and formatted according to RFC Y-M-DTH:M:SZ Results []ReportItem `json:"results"` ClusterName string `json:"cluster_name,omitempty"` // NOTE: The key here is ClusterName to match the Anchore API but it's actually the region InventoryType string `json:"inventory_type"` } + +// GetInventoryReport is an atomic method for getting in-use image results, in parallel for multiple clusters +func GetInventoryReport(region string) (Report, error) { + sessConfig := &aws.Config{} + if region != "" { + sessConfig.Region = aws.String(region) + } + sess, err := session.NewSession(sessConfig) + if err != nil { + logger.Log.Error("Failed to create AWS session", err) + } + + err = checkAWSCredentials(sess) + if err != nil { + return Report{}, err + } + + ecsClient := ecs.New(sess) + + clusters, err := fetchClusters(ecsClient) + if err != nil { + return Report{}, err + } + + results := []ReportItem{} + + for _, cluster := range clusters { + logger.Log.Debug("Found cluster", "cluster", *cluster) + + // Fetch tasks in cluster + tasks, err := fetchTasksFromCluster(ecsClient, *cluster) + if err != nil { + return Report{}, err + } + + images := []ReportImage{} + // Must be at least one task to continue + if len(tasks) == 0 { + logger.Log.Debug("No tasks found in cluster", "cluster", *cluster) + } else { + images, err = fetchImagesFromTasks(ecsClient, *cluster, tasks) + if err != nil { + return Report{}, err + } + } + + results = append(results, ReportItem{ + Namespace: *cluster, // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN + Images: images, + }) + } + // NOTE: clusterName not used for ECS as the clusternARN (used as the namespace in results payload) provides sufficient + // unique location data (account, region, clustername) + return Report{ + Timestamp: time.Now().UTC().Format(time.RFC3339), + Results: results, + ClusterName: "", + InventoryType: "ecs", + }, nil +} diff --git a/ecg/lib.go b/ecg/lib.go index b6ec2eb..a925481 100644 --- a/ecg/lib.go +++ b/ecg/lib.go @@ -6,10 +6,6 @@ import ( "os" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ecs" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" "github.com/anchore/anchore-ecs-inventory/ecg/inventory" "github.com/anchore/anchore-ecs-inventory/ecg/logger" @@ -50,7 +46,7 @@ func PeriodicallyGetInventoryReport(pollingIntervalSeconds int, anchoreDetails c ticker := time.NewTicker(time.Duration(pollingIntervalSeconds) * time.Second) for { - report, err := GetInventoryReport(region) + report, err := inventory.GetInventoryReport(region) if err != nil { log.Error("Failed to get Inventory Report", err) } else { @@ -65,136 +61,6 @@ func PeriodicallyGetInventoryReport(pollingIntervalSeconds int, anchoreDetails c } } -// GetInventoryReport is an atomic method for getting in-use image results, in parallel for multiple clusters -func GetInventoryReport(region string) (inventory.Report, error) { - sessConfig := &aws.Config{} - if region != "" { - sessConfig.Region = aws.String(region) - } - sess, err := session.NewSession(sessConfig) - if err != nil { - log.Error("Failed to create AWS session", err) - } - - err = checkAWSCredentials(sess) - if err != nil { - return inventory.Report{}, err - } - - ecsClient := ecs.New(sess) - - clusters, err := fetchClusters(ecsClient) - if err != nil { - return inventory.Report{}, err - } - - results := []inventory.ReportItem{} - - for _, cluster := range clusters { - log.Debug("Found cluster", "cluster", *cluster) - - // Fetch tasks in cluster - tasks, err := fetchTasksFromCluster(ecsClient, *cluster) - if err != nil { - return inventory.Report{}, err - } - - images := []inventory.ReportImage{} - // Must be at least one task to continue - if len(tasks) == 0 { - log.Debug("No tasks found in cluster", "cluster", *cluster) - } else { - images, err = fetchImagesFromTasks(ecsClient, *cluster, tasks) - if err != nil { - return inventory.Report{}, err - } - } - - results = append(results, inventory.ReportItem{ - Namespace: *cluster, // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN - Images: images, - }) - } - // NOTE: clusterName not used for ECS as the clusternARN (used as the namespace in results payload) provides sufficient - // unique location data (account, region, clustername) - return inventory.Report{ - Timestamp: time.Now().UTC().Format(time.RFC3339), - Results: results, - ClusterName: "", - InventoryType: "ecs", - }, nil -} - func SetLogger(logger logger.Logger) { log = logger } - -// Check if AWS are present, should be stored in ~/.aws/credentials -func checkAWSCredentials(sess *session.Session) error { - _, err := sess.Config.Credentials.Get() - if err != nil { - // TODO: Add some logs here detailing where to put the credentials - return fmt.Errorf("unable to get AWS credentials: %w", err) - } - return nil -} - -func fetchClusters(client *ecs.ECS) ([]*string, error) { - input := &ecs.ListClustersInput{} - - result, err := client.ListClusters(input) - if err != nil { - return nil, err - } - - return result.ClusterArns, nil -} - -func fetchTasksFromCluster(client *ecs.ECS, cluster string) ([]*string, error) { - input := &ecs.ListTasksInput{ - Cluster: aws.String(cluster), - } - - result, err := client.ListTasks(input) - if err != nil { - return nil, err - } - - return result.TaskArns, nil -} - -func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]inventory.ReportImage, error) { - input := &ecs.DescribeTasksInput{ - Cluster: aws.String(cluster), - Tasks: tasks, - } - - results, err := client.DescribeTasks(input) - if err != nil { - return []inventory.ReportImage{}, err - } - - uniqueImages := make(map[string]inventory.ReportImage) - - for _, task := range results.Tasks { - for _, container := range task.Containers { - digest := "" - if container.ImageDigest != nil { - digest = *container.ImageDigest - } - uniqueName := fmt.Sprintf("%s@%s", *container.Image, digest) - uniqueImages[uniqueName] = inventory.ReportImage{ - Tag: *container.Image, - RepoDigest: digest, - } - } - } - - // convert map of unique images to a slice - images := []inventory.ReportImage{} - for _, image := range uniqueImages { - images = append(images, image) - } - - return images, nil -} diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 30bdf22..3cc95ea 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -44,7 +44,6 @@ func InitLogger(logConfig LogConfig) { var cfg zap.Config level, err := zap.ParseAtomicLevel(logConfig.Level) - if err != nil { log.Printf("Invalid log level: %s, defaulting to `info`", logConfig.Level) level = zap.NewAtomicLevelAt(zap.InfoLevel) From c23a108ad3ad51db5f96fd9f088b4ac5b90109d2 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Tue, 7 Mar 2023 22:51:19 +0000 Subject: [PATCH 2/9] chore: rename ecg package to pkg Signed-off-by: Bradley Jones --- cmd/cmd.go | 4 ++-- cmd/root.go | 4 ++-- internal/config/config.go | 2 +- internal/config/config_test.go | 2 +- {ecg => pkg}/connection/connection.go | 0 {ecg => pkg}/inventory/ecs.go | 0 {ecg => pkg}/inventory/report.go | 0 {ecg => pkg}/inventory/reportitem.go | 0 {ecg => pkg}/lib.go | 10 +++++----- {ecg => pkg}/logger/logger.go | 0 {ecg => pkg}/reporter/reporter.go | 4 ++-- {ecg => pkg}/reporter/reporter_test.go | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) rename {ecg => pkg}/connection/connection.go (100%) rename {ecg => pkg}/inventory/ecs.go (100%) rename {ecg => pkg}/inventory/report.go (100%) rename {ecg => pkg}/inventory/reportitem.go (100%) rename {ecg => pkg}/lib.go (88%) rename {ecg => pkg}/logger/logger.go (100%) rename {ecg => pkg}/reporter/reporter.go (94%) rename {ecg => pkg}/reporter/reporter_test.go (88%) diff --git a/cmd/cmd.go b/cmd/cmd.go index e93eb0f..5cc261c 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -7,9 +7,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/anchore/anchore-ecs-inventory/ecg" "github.com/anchore/anchore-ecs-inventory/internal/config" "github.com/anchore/anchore-ecs-inventory/internal/logger" + "github.com/anchore/anchore-ecs-inventory/pkg" ) var ( @@ -61,7 +61,7 @@ func initLogging() { logger.InitLogger(logConfig) log = logger.Log - ecg.SetLogger(logger.Log) + pkg.SetLogger(logger.Log) } func logAppConfig() { diff --git a/cmd/root.go b/cmd/root.go index 3beca33..4e56995 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -8,8 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/anchore/anchore-ecs-inventory/ecg" "github.com/anchore/anchore-ecs-inventory/internal/config" + "github.com/anchore/anchore-ecs-inventory/pkg" ) // rootCmd represents the base command when called without any subcommands @@ -43,7 +43,7 @@ var rootCmd = &cobra.Command{ } */ - ecg.PeriodicallyGetInventoryReport(appConfig.PollingIntervalSeconds, appConfig.AnchoreDetails, appConfig.Region) + pkg.PeriodicallyGetInventoryReport(appConfig.PollingIntervalSeconds, appConfig.AnchoreDetails, appConfig.Region) }, } diff --git a/internal/config/config.go b/internal/config/config.go index d3c78a1..63101ae 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,8 +20,8 @@ import ( "github.com/spf13/viper" "gopkg.in/yaml.v2" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" "github.com/anchore/anchore-ecs-inventory/internal" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" ) const redacted = "******" diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 5188def..0440989 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/assert" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" ) func TestLoadConfigFromFileCliConfigPath(t *testing.T) { diff --git a/ecg/connection/connection.go b/pkg/connection/connection.go similarity index 100% rename from ecg/connection/connection.go rename to pkg/connection/connection.go diff --git a/ecg/inventory/ecs.go b/pkg/inventory/ecs.go similarity index 100% rename from ecg/inventory/ecs.go rename to pkg/inventory/ecs.go diff --git a/ecg/inventory/report.go b/pkg/inventory/report.go similarity index 100% rename from ecg/inventory/report.go rename to pkg/inventory/report.go diff --git a/ecg/inventory/reportitem.go b/pkg/inventory/reportitem.go similarity index 100% rename from ecg/inventory/reportitem.go rename to pkg/inventory/reportitem.go diff --git a/ecg/lib.go b/pkg/lib.go similarity index 88% rename from ecg/lib.go rename to pkg/lib.go index a925481..1dd9a7f 100644 --- a/ecg/lib.go +++ b/pkg/lib.go @@ -1,4 +1,4 @@ -package ecg +package pkg import ( "encoding/json" @@ -6,10 +6,10 @@ import ( "os" "time" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" - "github.com/anchore/anchore-ecs-inventory/ecg/inventory" - "github.com/anchore/anchore-ecs-inventory/ecg/logger" - "github.com/anchore/anchore-ecs-inventory/ecg/reporter" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" + "github.com/anchore/anchore-ecs-inventory/pkg/inventory" + "github.com/anchore/anchore-ecs-inventory/pkg/logger" + "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) var log logger.Logger diff --git a/ecg/logger/logger.go b/pkg/logger/logger.go similarity index 100% rename from ecg/logger/logger.go rename to pkg/logger/logger.go diff --git a/ecg/reporter/reporter.go b/pkg/reporter/reporter.go similarity index 94% rename from ecg/reporter/reporter.go rename to pkg/reporter/reporter.go index 1da8010..a5a2500 100644 --- a/ecg/reporter/reporter.go +++ b/pkg/reporter/reporter.go @@ -10,9 +10,9 @@ import ( "net/url" "time" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" - "github.com/anchore/anchore-ecs-inventory/ecg/inventory" "github.com/anchore/anchore-ecs-inventory/internal/logger" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" + "github.com/anchore/anchore-ecs-inventory/pkg/inventory" ) const ReportAPIPath = "v1/enterprise/inventories" diff --git a/ecg/reporter/reporter_test.go b/pkg/reporter/reporter_test.go similarity index 88% rename from ecg/reporter/reporter_test.go rename to pkg/reporter/reporter_test.go index f399b07..2b0006f 100644 --- a/ecg/reporter/reporter_test.go +++ b/pkg/reporter/reporter_test.go @@ -3,7 +3,7 @@ package reporter import ( "testing" - "github.com/anchore/anchore-ecs-inventory/ecg/connection" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" ) func TestBuildUrl(t *testing.T) { From 1746dee4db08cd0b3466cd8407e0e6a1d76c2223 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 00:02:26 +0000 Subject: [PATCH 3/9] feat: post to enterprise per cluster Some additional code reorg to separate Report types and posting vs inventory gathering. Signed-off-by: Bradley Jones --- pkg/inventory/ecs.go | 12 +-- pkg/inventory/report.go | 98 ++++++++++++++++------- pkg/lib.go | 38 +-------- pkg/reporter/report.go | 8 ++ pkg/reporter/reporter.go | 3 +- pkg/{inventory => reporter}/reportitem.go | 4 +- 6 files changed, 87 insertions(+), 76 deletions(-) create mode 100644 pkg/reporter/report.go rename pkg/{inventory => reporter}/reportitem.go (84%) diff --git a/pkg/inventory/ecs.go b/pkg/inventory/ecs.go index edb17ca..1106fe9 100644 --- a/pkg/inventory/ecs.go +++ b/pkg/inventory/ecs.go @@ -6,6 +6,8 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ecs" + + "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) // Check if AWS are present, should be stored in ~/.aws/credentials @@ -42,7 +44,7 @@ func fetchTasksFromCluster(client *ecs.ECS, cluster string) ([]*string, error) { return result.TaskArns, nil } -func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]ReportImage, error) { +func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]reporter.ReportImage, error) { input := &ecs.DescribeTasksInput{ Cluster: aws.String(cluster), Tasks: tasks, @@ -50,10 +52,10 @@ func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]R results, err := client.DescribeTasks(input) if err != nil { - return []ReportImage{}, err + return []reporter.ReportImage{}, err } - uniqueImages := make(map[string]ReportImage) + uniqueImages := make(map[string]reporter.ReportImage) for _, task := range results.Tasks { for _, container := range task.Containers { @@ -62,7 +64,7 @@ func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]R digest = *container.ImageDigest } uniqueName := fmt.Sprintf("%s@%s", *container.Image, digest) - uniqueImages[uniqueName] = ReportImage{ + uniqueImages[uniqueName] = reporter.ReportImage{ Tag: *container.Image, RepoDigest: digest, } @@ -70,7 +72,7 @@ func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]R } // convert map of unique images to a slice - images := []ReportImage{} + images := []reporter.ReportImage{} for _, image := range uniqueImages { images = append(images, image) } diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index 5f9f2a4..44fe580 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -1,6 +1,9 @@ package inventory import ( + "encoding/json" + "fmt" + "os" "time" "github.com/aws/aws-sdk-go/aws" @@ -8,17 +11,36 @@ import ( "github.com/aws/aws-sdk-go/service/ecs" "github.com/anchore/anchore-ecs-inventory/internal/logger" + "github.com/anchore/anchore-ecs-inventory/pkg/connection" + "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) -type Report struct { - Timestamp string `json:"timestamp,omitempty"` // Should be generated using time.Now.UTC() and formatted according to RFC Y-M-DTH:M:SZ - Results []ReportItem `json:"results"` - ClusterName string `json:"cluster_name,omitempty"` // NOTE: The key here is ClusterName to match the Anchore API but it's actually the region - InventoryType string `json:"inventory_type"` +// Output the JSON formatted report to stdout +func reportToStdout(report reporter.Report) error { + enc := json.NewEncoder(os.Stdout) + // prevent > and < from being escaped in the payload + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + if err := enc.Encode(report); err != nil { + return fmt.Errorf("unable to show inventory: %w", err) + } + return nil +} + +func HandleReport(report reporter.Report, anchoreDetails connection.AnchoreInfo) error { + if anchoreDetails.IsValid() { + if err := reporter.Post(report, anchoreDetails); err != nil { + return fmt.Errorf("unable to report Inventory to Anchore: %w", err) + } + } else { + logger.Log.Debug("Anchore details not specified, not reporting inventory") + } + + // Encode the report to JSON and output to stdout (maintains same behaviour as when multiple presenters were supported) + return reportToStdout(report) } -// GetInventoryReport is an atomic method for getting in-use image results, in parallel for multiple clusters -func GetInventoryReport(region string) (Report, error) { +func GetInventoryReportsForRegion(region string, anchoreDetails connection.AnchoreInfo) error { sessConfig := &aws.Config{} if region != "" { sessConfig.Region = aws.String(region) @@ -30,49 +52,63 @@ func GetInventoryReport(region string) (Report, error) { err = checkAWSCredentials(sess) if err != nil { - return Report{}, err + return err } ecsClient := ecs.New(sess) clusters, err := fetchClusters(ecsClient) if err != nil { - return Report{}, err + return err } - results := []ReportItem{} - for _, cluster := range clusters { - logger.Log.Debug("Found cluster", "cluster", *cluster) - - // Fetch tasks in cluster - tasks, err := fetchTasksFromCluster(ecsClient, *cluster) + report, err := GetInventoryReportForCluster(*cluster, ecsClient) if err != nil { - return Report{}, err + return err } - images := []ReportImage{} - // Must be at least one task to continue - if len(tasks) == 0 { - logger.Log.Debug("No tasks found in cluster", "cluster", *cluster) - } else { - images, err = fetchImagesFromTasks(ecsClient, *cluster, tasks) - if err != nil { - return Report{}, err - } + err = HandleReport(report, anchoreDetails) + if err != nil { + return err } + } - results = append(results, ReportItem{ - Namespace: *cluster, // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN - Images: images, - }) + return nil +} + +// GetInventoryReportForCluster is an atomic method for getting in-use image results, for a cluster +func GetInventoryReportForCluster(cluster string, ecsClient *ecs.ECS) (reporter.Report, error) { + logger.Log.Debug("Found cluster", "cluster", cluster) + + // Fetch tasks in cluster + tasks, err := fetchTasksFromCluster(ecsClient, cluster) + if err != nil { + return reporter.Report{}, err } + + images := []reporter.ReportImage{} + // Must be at least one task to continue + if len(tasks) == 0 { + logger.Log.Debug("No tasks found in cluster", "cluster", cluster) + } else { + images, err = fetchImagesFromTasks(ecsClient, cluster, tasks) + if err != nil { + return reporter.Report{}, err + } + } + + results := []reporter.ReportItem{} + results = append(results, reporter.ReportItem{ + Namespace: "", // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN + Images: images, + }) // NOTE: clusterName not used for ECS as the clusternARN (used as the namespace in results payload) provides sufficient // unique location data (account, region, clustername) - return Report{ + return reporter.Report{ Timestamp: time.Now().UTC().Format(time.RFC3339), Results: results, - ClusterName: "", + ClusterName: cluster, InventoryType: "ecs", }, nil } diff --git a/pkg/lib.go b/pkg/lib.go index 1dd9a7f..855c287 100644 --- a/pkg/lib.go +++ b/pkg/lib.go @@ -1,44 +1,15 @@ package pkg import ( - "encoding/json" - "fmt" - "os" "time" "github.com/anchore/anchore-ecs-inventory/pkg/connection" "github.com/anchore/anchore-ecs-inventory/pkg/inventory" "github.com/anchore/anchore-ecs-inventory/pkg/logger" - "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) var log logger.Logger -// Output the JSON formatted report to stdout -func reportToStdout(report inventory.Report) error { - enc := json.NewEncoder(os.Stdout) - // prevent > and < from being escaped in the payload - enc.SetEscapeHTML(false) - enc.SetIndent("", " ") - if err := enc.Encode(report); err != nil { - return fmt.Errorf("unable to show inventory: %w", err) - } - return nil -} - -func HandleReport(report inventory.Report, anchoreDetails connection.AnchoreInfo) error { - if anchoreDetails.IsValid() { - if err := reporter.Post(report, anchoreDetails); err != nil { - return fmt.Errorf("unable to report Inventory to Anchore: %w", err) - } - } else { - log.Debug("Anchore details not specified, not reporting inventory") - } - - // Encode the report to JSON and output to stdout (maintains same behaviour as when multiple presenters were supported) - return reportToStdout(report) -} - // PeriodicallyGetInventoryReport periodically retrieve image results and report/output them according to the configuration. // Note: Errors do not cause the function to exit, since this is periodically running func PeriodicallyGetInventoryReport(pollingIntervalSeconds int, anchoreDetails connection.AnchoreInfo, region string) { @@ -46,14 +17,9 @@ func PeriodicallyGetInventoryReport(pollingIntervalSeconds int, anchoreDetails c ticker := time.NewTicker(time.Duration(pollingIntervalSeconds) * time.Second) for { - report, err := inventory.GetInventoryReport(region) + err := inventory.GetInventoryReportsForRegion(region, anchoreDetails) if err != nil { - log.Error("Failed to get Inventory Report", err) - } else { - err := HandleReport(report, anchoreDetails) - if err != nil { - log.Error("Failed to handle Inventory Report", err) - } + log.Error("Failed to get Inventory Reports for region", err) } // Wait at least as long as the ticker diff --git a/pkg/reporter/report.go b/pkg/reporter/report.go new file mode 100644 index 0000000..cfe8359 --- /dev/null +++ b/pkg/reporter/report.go @@ -0,0 +1,8 @@ +package reporter + +type Report struct { + Timestamp string `json:"timestamp,omitempty"` // Should be generated using time.Now.UTC() and formatted according to RFC Y-M-DTH:M:SZ + Results []ReportItem `json:"results"` + ClusterName string `json:"cluster_name,omitempty"` // NOTE: The key here is ClusterName to match the Anchore API but it's actually the region + InventoryType string `json:"inventory_type"` +} diff --git a/pkg/reporter/reporter.go b/pkg/reporter/reporter.go index a5a2500..e60151a 100644 --- a/pkg/reporter/reporter.go +++ b/pkg/reporter/reporter.go @@ -12,7 +12,6 @@ import ( "github.com/anchore/anchore-ecs-inventory/internal/logger" "github.com/anchore/anchore-ecs-inventory/pkg/connection" - "github.com/anchore/anchore-ecs-inventory/pkg/inventory" ) const ReportAPIPath = "v1/enterprise/inventories" @@ -20,7 +19,7 @@ const ReportAPIPath = "v1/enterprise/inventories" // This method does the actual Reporting (via HTTP) to Anchore // //nolint:gosec -func Post(report inventory.Report, anchoreDetails connection.AnchoreInfo) error { +func Post(report Report, anchoreDetails connection.AnchoreInfo) error { logger.Log.Debug("Reporting results to Anchore") tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: anchoreDetails.HTTP.Insecure}, diff --git a/pkg/inventory/reportitem.go b/pkg/reporter/reportitem.go similarity index 84% rename from pkg/inventory/reportitem.go rename to pkg/reporter/reportitem.go index 17ad38d..2df6e5b 100644 --- a/pkg/inventory/reportitem.go +++ b/pkg/reporter/reportitem.go @@ -1,4 +1,4 @@ -package inventory +package reporter import ( "fmt" @@ -6,7 +6,7 @@ import ( // ReportItem represents a cluster and all it's unique images type ReportItem struct { - Namespace string `json:"namespace,omitempty"` // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN + Namespace string `json:"namespace,omitempty"` // NOTE The key is Namespace to match the Anchore API but it's actually passed as empty string Images []ReportImage `json:"images"` } From 2b80c98d01f6f05e3a44c753784665fb7c5d4d4b Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 00:09:56 +0000 Subject: [PATCH 4/9] feat: only post report for cluster if there are images present Signed-off-by: Bradley Jones --- pkg/inventory/report.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index 44fe580..18fc18e 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -68,9 +68,12 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho return err } - err = HandleReport(report, anchoreDetails) - if err != nil { - return err + // Only report if there are images present in the cluster + if len(report.Results) != 0 { + err = HandleReport(report, anchoreDetails) + if err != nil { + return err + } } } @@ -87,22 +90,22 @@ func GetInventoryReportForCluster(cluster string, ecsClient *ecs.ECS) (reporter. return reporter.Report{}, err } - images := []reporter.ReportImage{} + results := []reporter.ReportItem{} + // Must be at least one task to continue if len(tasks) == 0 { logger.Log.Debug("No tasks found in cluster", "cluster", cluster) } else { - images, err = fetchImagesFromTasks(ecsClient, cluster, tasks) + images, err := fetchImagesFromTasks(ecsClient, cluster, tasks) if err != nil { return reporter.Report{}, err } + results = append(results, reporter.ReportItem{ + Namespace: "", // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN + Images: images, + }) } - results := []reporter.ReportItem{} - results = append(results, reporter.ReportItem{ - Namespace: "", // NOTE The key is Namespace to match the Anchore API but it's actually the cluster ARN - Images: images, - }) // NOTE: clusterName not used for ECS as the clusternARN (used as the namespace in results payload) provides sufficient // unique location data (account, region, clustername) return reporter.Report{ From c3f11612476c009091911c32d18dfa16d6e15509 Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 00:29:18 +0000 Subject: [PATCH 5/9] feat: process cluster inventories concurrently Signed-off-by: Bradley Jones --- pkg/inventory/report.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index 18fc18e..fa4796a 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "sync" "time" "github.com/aws/aws-sdk-go/aws" @@ -62,21 +63,33 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho return err } + // Waitgroup to wait for all goroutines to finish + var wg sync.WaitGroup + wg.Add(len(clusters)) + for _, cluster := range clusters { - report, err := GetInventoryReportForCluster(*cluster, ecsClient) - if err != nil { - return err - } + go func(cluster string) { + defer wg.Done() + + // New ecs client for each goroutine + ecsClient := ecs.New(sess) - // Only report if there are images present in the cluster - if len(report.Results) != 0 { - err = HandleReport(report, anchoreDetails) + report, err := GetInventoryReportForCluster(cluster, ecsClient) if err != nil { - return err + logger.Log.Error("Failed to get inventory report for cluster", err) } - } + + // Only report if there are images present in the cluster + if len(report.Results) != 0 { + err = HandleReport(report, anchoreDetails) + if err != nil { + logger.Log.Error("Failed to report inventory for cluster", err) + } + } + }(*cluster) } + wg.Wait() return nil } From a2391e1fcc4479e3ed4bcc73363c6b871178af9c Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 00:58:20 +0000 Subject: [PATCH 6/9] test: setup for mock ECS API and add initial ecs UTs Signed-off-by: Bradley Jones --- pkg/inventory/ecs.go | 7 +-- pkg/inventory/ecs_test.go | 99 +++++++++++++++++++++++++++++++++++++++ pkg/inventory/report.go | 3 +- 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 pkg/inventory/ecs_test.go diff --git a/pkg/inventory/ecs.go b/pkg/inventory/ecs.go index 1106fe9..b3db6ca 100644 --- a/pkg/inventory/ecs.go +++ b/pkg/inventory/ecs.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ecs" + "github.com/aws/aws-sdk-go/service/ecs/ecsiface" "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) @@ -20,7 +21,7 @@ func checkAWSCredentials(sess *session.Session) error { return nil } -func fetchClusters(client *ecs.ECS) ([]*string, error) { +func fetchClusters(client ecsiface.ECSAPI) ([]*string, error) { input := &ecs.ListClustersInput{} result, err := client.ListClusters(input) @@ -31,7 +32,7 @@ func fetchClusters(client *ecs.ECS) ([]*string, error) { return result.ClusterArns, nil } -func fetchTasksFromCluster(client *ecs.ECS, cluster string) ([]*string, error) { +func fetchTasksFromCluster(client ecsiface.ECSAPI, cluster string) ([]*string, error) { input := &ecs.ListTasksInput{ Cluster: aws.String(cluster), } @@ -44,7 +45,7 @@ func fetchTasksFromCluster(client *ecs.ECS, cluster string) ([]*string, error) { return result.TaskArns, nil } -func fetchImagesFromTasks(client *ecs.ECS, cluster string, tasks []*string) ([]reporter.ReportImage, error) { +func fetchImagesFromTasks(client ecsiface.ECSAPI, cluster string, tasks []*string) ([]reporter.ReportImage, error) { input := &ecs.DescribeTasksInput{ Cluster: aws.String(cluster), Tasks: tasks, diff --git a/pkg/inventory/ecs_test.go b/pkg/inventory/ecs_test.go new file mode 100644 index 0000000..271abe5 --- /dev/null +++ b/pkg/inventory/ecs_test.go @@ -0,0 +1,99 @@ +package inventory + +import ( + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" + "github.com/aws/aws-sdk-go/service/ecs/ecsiface" + "github.com/stretchr/testify/assert" +) + +type mockECSClient struct { + ecsiface.ECSAPI +} + +func (m *mockECSClient) ListClusters(*ecs.ListClustersInput) (*ecs.ListClustersOutput, error) { + return &ecs.ListClustersOutput{ + ClusterArns: []*string{ + aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-1"), + aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-2"), + }, + }, nil +} + +func (m *mockECSClient) ListTasks(*ecs.ListTasksInput) (*ecs.ListTasksOutput, error) { + return &ecs.ListTasksOutput{ + TaskArns: []*string{ + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), + }, + }, nil +} + +func (m *mockECSClient) DescribeTasks(*ecs.DescribeTasksInput) (*ecs.DescribeTasksOutput, error) { + return &ecs.DescribeTasksOutput{ + Tasks: []*ecs.Task{ + { + TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), + Containers: []*ecs.Container{ + { + Name: aws.String("container-1"), + Image: aws.String("image-1"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678901111"), + }, + { + Name: aws.String("container-2"), + Image: aws.String("image-2"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678902222"), + }, + }, + }, + { + TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), + Containers: []*ecs.Container{ + { + Name: aws.String("container-3"), + Image: aws.String("image-3"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), + }, + { + Name: aws.String("container-4-(same-image-as-3)"), + Image: aws.String("image-3"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), + }, + }, + }, + }, + }, nil +} + +func TestFetchClusters(t *testing.T) { + mockSvc := &mockECSClient{} + + clusters, err := fetchClusters(mockSvc) + + assert.NoError(t, err) + assert.Equal(t, 2, len(clusters)) +} + +func TestFetchTasksFromCluster(t *testing.T) { + mockSvc := &mockECSClient{} + + tasks, err := fetchTasksFromCluster(mockSvc, "cluster-1") + + assert.NoError(t, err) + assert.Equal(t, 2, len(tasks)) +} + +func TestFetchImagesFromTasks(t *testing.T) { + mockSvc := &mockECSClient{} + + images, err := fetchImagesFromTasks(mockSvc, "cluster-1", []*string{ + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), + }) + + assert.NoError(t, err) + assert.Equal(t, 3, len(images)) +} diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index fa4796a..724c853 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ecs" + "github.com/aws/aws-sdk-go/service/ecs/ecsiface" "github.com/anchore/anchore-ecs-inventory/internal/logger" "github.com/anchore/anchore-ecs-inventory/pkg/connection" @@ -94,7 +95,7 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho } // GetInventoryReportForCluster is an atomic method for getting in-use image results, for a cluster -func GetInventoryReportForCluster(cluster string, ecsClient *ecs.ECS) (reporter.Report, error) { +func GetInventoryReportForCluster(cluster string, ecsClient ecsiface.ECSAPI) (reporter.Report, error) { logger.Log.Debug("Found cluster", "cluster", cluster) // Fetch tasks in cluster From 9f26c0306a857df3fa619d416bd17eebb4dfe81f Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 10:59:59 +0000 Subject: [PATCH 7/9] test: add basic test for get inventory report Signed-off-by: Bradley Jones --- pkg/inventory/ecs_test.go | 61 ------------------------------- pkg/inventory/mock_ecs_test.go | 66 ++++++++++++++++++++++++++++++++++ pkg/inventory/report_test.go | 28 +++++++++++++++ 3 files changed, 94 insertions(+), 61 deletions(-) create mode 100644 pkg/inventory/mock_ecs_test.go create mode 100644 pkg/inventory/report_test.go diff --git a/pkg/inventory/ecs_test.go b/pkg/inventory/ecs_test.go index 271abe5..8b642a9 100644 --- a/pkg/inventory/ecs_test.go +++ b/pkg/inventory/ecs_test.go @@ -4,70 +4,9 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ecs" - "github.com/aws/aws-sdk-go/service/ecs/ecsiface" "github.com/stretchr/testify/assert" ) -type mockECSClient struct { - ecsiface.ECSAPI -} - -func (m *mockECSClient) ListClusters(*ecs.ListClustersInput) (*ecs.ListClustersOutput, error) { - return &ecs.ListClustersOutput{ - ClusterArns: []*string{ - aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-1"), - aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-2"), - }, - }, nil -} - -func (m *mockECSClient) ListTasks(*ecs.ListTasksInput) (*ecs.ListTasksOutput, error) { - return &ecs.ListTasksOutput{ - TaskArns: []*string{ - aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), - aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), - }, - }, nil -} - -func (m *mockECSClient) DescribeTasks(*ecs.DescribeTasksInput) (*ecs.DescribeTasksOutput, error) { - return &ecs.DescribeTasksOutput{ - Tasks: []*ecs.Task{ - { - TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), - Containers: []*ecs.Container{ - { - Name: aws.String("container-1"), - Image: aws.String("image-1"), - ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678901111"), - }, - { - Name: aws.String("container-2"), - Image: aws.String("image-2"), - ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678902222"), - }, - }, - }, - { - TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), - Containers: []*ecs.Container{ - { - Name: aws.String("container-3"), - Image: aws.String("image-3"), - ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), - }, - { - Name: aws.String("container-4-(same-image-as-3)"), - Image: aws.String("image-3"), - ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), - }, - }, - }, - }, - }, nil -} - func TestFetchClusters(t *testing.T) { mockSvc := &mockECSClient{} diff --git a/pkg/inventory/mock_ecs_test.go b/pkg/inventory/mock_ecs_test.go new file mode 100644 index 0000000..a806cff --- /dev/null +++ b/pkg/inventory/mock_ecs_test.go @@ -0,0 +1,66 @@ +package inventory + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" + "github.com/aws/aws-sdk-go/service/ecs/ecsiface" +) + +type mockECSClient struct { + ecsiface.ECSAPI +} + +func (m *mockECSClient) ListClusters(*ecs.ListClustersInput) (*ecs.ListClustersOutput, error) { + return &ecs.ListClustersOutput{ + ClusterArns: []*string{ + aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-1"), + aws.String("arn:aws:ecs:us-east-1:123456789012:cluster/cluster-2"), + }, + }, nil +} + +func (m *mockECSClient) ListTasks(*ecs.ListTasksInput) (*ecs.ListTasksOutput, error) { + return &ecs.ListTasksOutput{ + TaskArns: []*string{ + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), + aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), + }, + }, nil +} + +func (m *mockECSClient) DescribeTasks(*ecs.DescribeTasksInput) (*ecs.DescribeTasksOutput, error) { + return &ecs.DescribeTasksOutput{ + Tasks: []*ecs.Task{ + { + TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-000000000000"), + Containers: []*ecs.Container{ + { + Name: aws.String("container-1"), + Image: aws.String("image-1"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678901111"), + }, + { + Name: aws.String("container-2"), + Image: aws.String("image-2"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678902222"), + }, + }, + }, + { + TaskArn: aws.String("arn:aws:ecs:us-east-1:123456789012:task/cluster-1/12345678-1234-1234-1234-111111111111"), + Containers: []*ecs.Container{ + { + Name: aws.String("container-3"), + Image: aws.String("image-3"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), + }, + { + Name: aws.String("container-4-(same-image-as-3)"), + Image: aws.String("image-3"), + ImageDigest: aws.String("sha256:1234567890123456789012345678901234567890123456789012345678903333"), + }, + }, + }, + }, + }, nil +} diff --git a/pkg/inventory/report_test.go b/pkg/inventory/report_test.go new file mode 100644 index 0000000..5ba47db --- /dev/null +++ b/pkg/inventory/report_test.go @@ -0,0 +1,28 @@ +package inventory + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/anchore-ecs-inventory/internal/logger" +) + +func setupLogger() { + // TODO(bradjones) Setting up logging for tests like this isn't great so will change this later + logConfig := logger.LogConfig{ + Level: "debug", + } + logger.InitLogger(logConfig) +} + +func TestGetInventoryReportForCluster(t *testing.T) { + setupLogger() + + mockSvc := &mockECSClient{} + + report, err := GetInventoryReportForCluster("cluster-1", mockSvc) + + assert.NoError(t, err) + assert.Equal(t, 3, len(report.Results[0].Images)) +} From d8ad23962d730708e1f2d3336a9d9d84a4a6fe9a Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 13:45:08 +0000 Subject: [PATCH 8/9] chore: adjust spacing in json output to stdout Signed-off-by: Bradley Jones --- pkg/inventory/report.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index 724c853..e1d730c 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -22,7 +22,7 @@ func reportToStdout(report reporter.Report) error { enc := json.NewEncoder(os.Stdout) // prevent > and < from being escaped in the payload enc.SetEscapeHTML(false) - enc.SetIndent("", " ") + enc.SetIndent("", " ") if err := enc.Encode(report); err != nil { return fmt.Errorf("unable to show inventory: %w", err) } From 862db5e832f1726fa1d5802cf8e4281df05acddc Mon Sep 17 00:00:00 2001 From: Bradley Jones Date: Wed, 8 Mar 2023 13:55:16 +0000 Subject: [PATCH 9/9] chore: comment cleanup Signed-off-by: Bradley Jones --- pkg/inventory/report.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/inventory/report.go b/pkg/inventory/report.go index e1d730c..2e24ef1 100644 --- a/pkg/inventory/report.go +++ b/pkg/inventory/report.go @@ -17,7 +17,6 @@ import ( "github.com/anchore/anchore-ecs-inventory/pkg/reporter" ) -// Output the JSON formatted report to stdout func reportToStdout(report reporter.Report) error { enc := json.NewEncoder(os.Stdout) // prevent > and < from being escaped in the payload @@ -38,7 +37,6 @@ func HandleReport(report reporter.Report, anchoreDetails connection.AnchoreInfo) logger.Log.Debug("Anchore details not specified, not reporting inventory") } - // Encode the report to JSON and output to stdout (maintains same behaviour as when multiple presenters were supported) return reportToStdout(report) } @@ -64,7 +62,6 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho return err } - // Waitgroup to wait for all goroutines to finish var wg sync.WaitGroup wg.Add(len(clusters)) @@ -72,7 +69,6 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho go func(cluster string) { defer wg.Done() - // New ecs client for each goroutine ecsClient := ecs.New(sess) report, err := GetInventoryReportForCluster(cluster, ecsClient) @@ -98,7 +94,6 @@ func GetInventoryReportsForRegion(region string, anchoreDetails connection.Ancho func GetInventoryReportForCluster(cluster string, ecsClient ecsiface.ECSAPI) (reporter.Report, error) { logger.Log.Debug("Found cluster", "cluster", cluster) - // Fetch tasks in cluster tasks, err := fetchTasksFromCluster(ecsClient, cluster) if err != nil { return reporter.Report{}, err