diff --git a/.circleci/config.yml b/.circleci/config.yml index e21b8c7..680b30d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,10 +1,13 @@ +references: + circleci: &circleci trussworks/circleci:29ab89fdada1f85c5d8fb685a2c71660f0c5f60c + jobs: release: docker: - auth: password: $DOCKER_PASSWORD username: $DOCKER_USERNAME - image: trussworks/circleci:29ab89fdada1f85c5d8fb685a2c71660f0c5f60c + image: *circleci steps: - checkout - setup_remote_docker @@ -24,21 +27,27 @@ jobs: - auth: password: $DOCKER_PASSWORD username: $DOCKER_USERNAME - image: trussworks/circleci:29ab89fdada1f85c5d8fb685a2c71660f0c5f60c + image: *circleci steps: - checkout - restore_cache: keys: - pre-commit-dot-cache-{{ checksum ".pre-commit-config.yaml" }} + - go-mod-sources-v1-{{ checksum "go.sum" }} - run: command: pre-commit run --all-files name: Run pre-commit tests + - run: + command: make test + name: Run Go tests - save_cache: key: pre-commit-dot-cache-{{ checksum ".pre-commit-config.yaml" }} paths: - ~/.cache/pre-commit -references: - circleci: trussworks/circleci:29ab89fdada1f85c5d8fb685a2c71660f0c5f60c + - save_cache: + key: go-mod-sources-v1-{{ checksum "go.sum" }} + paths: + - ~/go/pkg/mod version: 2.1 workflows: release: diff --git a/.golangci.yml b/.golangci.yml index d872159..c144397 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -30,6 +30,3 @@ issues: # A better practice is for each repo to choose which ones to disable exclude-use-default: false fix: true - -run: - modules-download-mode: readonly diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c033cae..cd2634f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,23 +1,23 @@ repos: - repo: git://github.com/golangci/golangci-lint - rev: v1.28.2 + rev: v1.34.1 hooks: - id: golangci-lint - repo: git://github.com/pre-commit/pre-commit-hooks - rev: v3.1.0 + rev: v3.4.0 hooks: - id: check-merge-conflict - id: check-yaml - id: trailing-whitespace - repo: git://github.com/igorshubovych/markdownlint-cli - rev: v0.23.2 + rev: v0.26.0 hooks: - id: markdownlint - repo: git://github.com/trussworks/pre-commit-hooks - rev: v0.0.4 + rev: v1.0.0 hooks: - id: circleci-validate - id: goreleaser-check diff --git a/Makefile b/Makefile index ef2be72..2578a6f 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,10 @@ help: ## Print the help documentation bin/ecs-service-logs: go build -ldflags "$(LDFLAGS) -X main.version=${VERSION}" -o bin/ecs-service-logs . +.PHONY: test +test: + go test -v ./... + .PHONY: clean clean: ## Clean all generated files rm -rf ./bin diff --git a/go.mod b/go.mod index 75a3d0b..edea06b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/trussworks/ecs-service-logs -go 1.14 +go 1.15 require ( github.com/aws/aws-sdk-go v1.36.19 @@ -8,4 +8,5 @@ require ( github.com/spf13/cobra v0.0.7 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 + github.com/stretchr/testify v1.3.0 ) diff --git a/main.go b/main.go index c5af357..a8bc95c 100644 --- a/main.go +++ b/main.go @@ -69,7 +69,6 @@ const ( logGitCommit string = "git_commit" ) -var environments = []string{"prod", "staging", "experimental"} var ecsTaskStatuses = []string{"RUNNING", "STOPPED", "ALL"} var logLevels = []string{"debug", "info", "warn", "error", "panic", "fatal"} @@ -114,14 +113,6 @@ func (e *errInvalidRegion) Error() string { return fmt.Sprintf("invalid region %q", e.Region) } -type errInvalidEnvironment struct { - Environment string -} - -func (e *errInvalidEnvironment) Error() string { - return fmt.Sprintf("invalid environment %q, expecting one of %q", e.Environment, environments) -} - type errInvalidTaskStatus struct { Status string } @@ -182,20 +173,27 @@ func initFlags(flag *pflag.FlagSet) { flag.BoolP(flagVerbose, "v", false, "Print section lines") } -func checkConfig(v *viper.Viper) error { - - regions, ok := endpoints.RegionsForService(endpoints.DefaultPartitions(), endpoints.AwsPartitionID, endpoints.EcsServiceID) - if !ok { - return fmt.Errorf("could not find regions for service %q", endpoints.EcsServiceID) - } - +func checkRegion(v *viper.Viper) error { region := v.GetString(flagAWSRegion) if len(region) == 0 { return errors.Wrap(&errInvalidRegion{Region: region}, fmt.Sprintf("%q is invalid", flagAWSRegion)) } + // PartitionForRegion checks for the first region in a partition + // and for regions matching a regex pattern. + // So this checks if a region exists in any of the SDK regions, which are + // AWS Standard, AWS China, AWS GovCloud, AWS ISO, and AWS ISOB. + if _, ok := endpoints.PartitionForRegion(endpoints.DefaultPartitions(), region); !ok { + return fmt.Errorf("%s is invalid: %w", flagAWSRegion, &errInvalidRegion{Region: region}) + } - if _, ok := regions[region]; !ok { - return errors.Wrap(&errInvalidRegion{Region: region}, fmt.Sprintf("%q is invalid", flagAWSRegion)) + return nil +} + +func checkConfig(v *viper.Viper) error { + + err := checkRegion(v) + if err != nil { + return err } logLevel := strings.ToLower(v.GetString(flagLogLevel)) @@ -242,16 +240,6 @@ func checkConfig(v *viper.Viper) error { if len(environment) == 0 { return errors.New("when status is set to STOPPED then environment must be set") } - valid := false - for _, str := range environments { - if environment == str { - valid = true - break - } - } - if !valid { - return errors.Wrap(&errInvalidEnvironment{Environment: environment}, fmt.Sprintf("%q is invalid", flagEnvironment)) - } if serviceName := v.GetString(flagService); len(serviceName) == 0 { return &errInvalidService{Service: serviceName} diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..f2d37c5 --- /dev/null +++ b/main_test.go @@ -0,0 +1,70 @@ +package main + +import ( + "io/ioutil" + "log" + "os" + "testing" + + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/spf13/viper" + "github.com/stretchr/testify/suite" +) + +type cliTestSuite struct { + suite.Suite + viper *viper.Viper + logger *log.Logger +} + +func (suite *cliTestSuite) Setup() { + // Disable any logging that isn't attached to the logger unless using the verbose flag + log.SetOutput(ioutil.Discard) + log.SetFlags(0) + + // Setup logger + var logger = log.New(os.Stdout, "", log.LstdFlags) + + // Remove the flags for the logger + logger.SetFlags(0) + suite.SetLogger(logger) + + // Setup viper + v := viper.New() + suite.SetViper(v) +} + +func (suite *cliTestSuite) TestCheckRegion() { + suite.Setup() + + testValues := []string{ + endpoints.UsEast1RegionID, + endpoints.UsEast2RegionID, + endpoints.UsWest1RegionID, + endpoints.UsWest2RegionID, + endpoints.UsGovWest1RegionID, + } + for _, testValue := range testValues { + suite.viper.Set(flagAWSRegion, testValue) + suite.NoError(checkRegion(suite.viper)) + } + testValuesWithErrors := []string{ + "AnyOtherRegionName", + } + for _, testValue := range testValuesWithErrors { + suite.viper.Set(flagAWSRegion, testValue) + suite.Error(checkRegion(suite.viper)) + } +} + +func (suite *cliTestSuite) SetViper(v *viper.Viper) { + suite.viper = v +} + +func (suite *cliTestSuite) SetLogger(logger *log.Logger) { + suite.logger = logger +} + +func TestCLISuite(t *testing.T) { + suite.Run(t, &cliTestSuite{}) +}