Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
MOCKGEN := go run go.uber.org/mock/mockgen
# go install go.uber.org/mock/mockgen@latest
MOCKGEN := mockgen
Comment thread
keroxp marked this conversation as resolved.
Outdated
Comment thread
keroxp marked this conversation as resolved.
Outdated
.PHONY: test
test:
go test ./... -coverprofile=coverage.txt -covermode=count
Expand All @@ -13,16 +14,20 @@ mocks: go.sum \
mocks/mock_awsiface/iface.go \
mocks/mock_types/iface.go \
mocks/mock_upgrade/upgrade.go \
mocks/mock_scan/scanner.go \
mocks/mock_task/task.go \
mocks/mock_taskset/taskset.go \
mocks/mock_task/factory.go \
mocks/mock_rollout/executor.go
mocks/mock_rollout/executor.go \
mocks/mock_logger/logger.go
mocks/mock_awsiface/iface.go: awsiface/iface.go
$(MOCKGEN) -source=./awsiface/iface.go > mocks/mock_awsiface/iface.go
mocks/mock_types/iface.go: types/iface.go
$(MOCKGEN) -source=./types/iface.go > mocks/mock_types/iface.go
mocks/mock_upgrade/upgrade.go: cli/cage/upgrade/upgrade.go
$(MOCKGEN) -source=./cli/cage/upgrade/upgrade.go > mocks/mock_upgrade/upgrade.go
mocks/mock_scan/scanner.go: cli/cage/scan/scanner.go
$(MOCKGEN) -source=./cli/cage/scan/scanner.go > mocks/mock_scan/scanner.go
mocks/mock_task/task.go: task/task.go
$(MOCKGEN) -source=./task/task.go > mocks/mock_task/task.go
mocks/mock_taskset/taskset.go: taskset/taskset.go
Expand All @@ -31,4 +36,6 @@ mocks/mock_task/factory.go: task/factory.go
$(MOCKGEN) -source=./task/factory.go > mocks/mock_task/factory.go
mocks/mock_rollout/executor.go: rollout/executor.go
$(MOCKGEN) -source=./rollout/executor.go > mocks/mock_rollout/executor.go
mocks/mock_logger/logger.go: logger/logger.go
$(MOCKGEN) -source=./logger/logger.go > mocks/mock_logger/logger.go
.PHONY: mocks
5 changes: 5 additions & 0 deletions awsiface/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecs"
elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
)
Expand All @@ -23,6 +24,10 @@ type (
StopTask(ctx context.Context, params *ecs.StopTaskInput, optFns ...func(*ecs.Options)) (*ecs.StopTaskOutput, error)
DescribeTaskDefinition(ctx context.Context, params *ecs.DescribeTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTaskDefinitionOutput, error)
}
EcrClient interface {
BatchGetImage(ctx context.Context, params *ecr.BatchGetImageInput, optFns ...func(*ecr.Options)) (*ecr.BatchGetImageOutput, error)
DescribeImageScanFindings(ctx context.Context, params *ecr.DescribeImageScanFindingsInput, optFns ...func(*ecr.Options)) (*ecr.DescribeImageScanFindingsOutput, error)
}
AlbClient interface {
DescribeTargetGroups(ctx context.Context, params *elbv2.DescribeTargetGroupsInput, optFns ...func(*elbv2.Options)) (*elbv2.DescribeTargetGroupsOutput, error)
DescribeTargetHealth(ctx context.Context, params *elbv2.DescribeTargetHealthInput, optFns ...func(*elbv2.Options)) (*elbv2.DescribeTargetHealthOutput, error)
Expand Down
9 changes: 8 additions & 1 deletion cli/cage/commands/flags.go → cli/cage/cageapp/flags.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package commands
package cageapp

import (
"io"

"github.com/loilo-inc/canarycage/env"
"github.com/urfave/cli/v2"
)

type App struct {
CI bool
Stdin io.Reader
}

func RegionFlag(dest *string) *cli.StringFlag {
return &cli.StringFlag{
Name: "region",
Expand Down
65 changes: 65 additions & 0 deletions cli/cage/cageapp/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package cageapp

import (
"context"
"os"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecs"
"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
cage "github.com/loilo-inc/canarycage"
"github.com/loilo-inc/canarycage/cli/cage/scan"
"github.com/loilo-inc/canarycage/env"
"github.com/loilo-inc/canarycage/key"
"github.com/loilo-inc/canarycage/logger"
"github.com/loilo-inc/canarycage/task"
"github.com/loilo-inc/canarycage/timeout"
"github.com/loilo-inc/canarycage/types"
"github.com/loilo-inc/logos/di"
"golang.org/x/xerrors"
)

func ProvideCageCli(envars *env.Envars) (types.Cage, error) {
conf, err := loadAwsConfig(envars.Region)
if err != nil {
return nil, err
}
d := di.NewDomain(func(b *di.B) {
b.Set(key.Env, envars)
b.Set(key.EcsCli, ecs.NewFromConfig(conf))
b.Set(key.EcrCli, ecr.NewFromConfig(conf))
b.Set(key.Ec2Cli, ec2.NewFromConfig(conf))
b.Set(key.AlbCli, elasticloadbalancingv2.NewFromConfig(conf))
b.Set(key.TaskFactory, task.NewFactory(b.Future()))
b.Set(key.Time, &timeout.Time{})
})
cagecli := cage.NewCage(d)
return cagecli, nil
}

func ProvideScanDI(region string) (*di.D, error) {
conf, err := loadAwsConfig(region)
if err != nil {
return nil, err
}
d := di.NewDomain(func(b *di.B) {
ecsCli := ecs.NewFromConfig(conf)
ecrCli := ecr.NewFromConfig(conf)
b.Set(key.Scanner, scan.NewScanner(ecsCli, ecrCli))
b.Set(key.Logger, logger.DefaultLogger(os.Stdout))
})
return d, nil
}

func loadAwsConfig(region string) (aws.Config, error) {
conf, err := config.LoadDefaultConfig(
context.Background(),
config.WithRegion(region))
if err != nil {
return aws.Config{}, xerrors.Errorf("failed to load aws config: %w", err)
}
return conf, nil
}
81 changes: 81 additions & 0 deletions cli/cage/cageapp/provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cageapp_test

import (
"testing"

"github.com/loilo-inc/canarycage/cli/cage/cageapp"
"github.com/loilo-inc/canarycage/env"
"github.com/stretchr/testify/assert"
)

func TestProvideCageCli(t *testing.T) {
t.Run("successfully creates cage cli with valid region", func(t *testing.T) {
envars := &env.Envars{
Region: "us-east-1",
}

cage, err := cageapp.ProvideCageCli(envars)
assert.NoError(t, err)
assert.NotNil(t, cage)
})

t.Run("returns error with invalid region", func(t *testing.T) {
envars := &env.Envars{
Region: "",
}

cage, err := cageapp.ProvideCageCli(envars)
if err != nil {
assert.Nil(t, cage, "expected cage to be nil when error occurs")
return
}
assert.NotNil(t, cage, "expected cage to be non-nil when no error")
})

t.Run("handles nil envars", func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
return
}
}()

cage, err := cageapp.ProvideCageCli(nil)
if err == nil {
assert.NotNil(t, cage, "expected cage to be non-nil when no error")
}
})
}

func TestProvideScanDI(t *testing.T) {
t.Run("successfully creates scan DI with valid region", func(t *testing.T) {
region := "us-east-1"

d, err := cageapp.ProvideScanDI(region)
assert.NoError(t, err)
assert.NotNil(t, d)
})

t.Run("returns error with invalid region", func(t *testing.T) {
region := ""

d, err := cageapp.ProvideScanDI(region)
if err != nil {
assert.Nil(t, d, "expected DI domain to be nil when error occurs")
return
}
assert.NotNil(t, d, "expected DI domain to be non-nil when no error")
})

t.Run("creates DI domain with different regions", func(t *testing.T) {
regions := []string{"us-west-2", "eu-west-1", "ap-northeast-1"}

for _, region := range regions {
d, err := cageapp.ProvideScanDI(region)
if err != nil {
t.Logf("region %s returned error: %v", region, err)
continue
}
assert.NotNil(t, d, "expected DI domain to be non-nil for region %s", region)
}
})
}
46 changes: 46 additions & 0 deletions cli/cage/commands/a_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package commands_test

import (
"io"
"testing"

"github.com/loilo-inc/canarycage/cli/cage/cageapp"
"github.com/loilo-inc/canarycage/cli/cage/commands"
"github.com/loilo-inc/canarycage/env"
"github.com/loilo-inc/canarycage/mocks/mock_types"
"github.com/loilo-inc/canarycage/types"
"github.com/urfave/cli/v2"
"go.uber.org/mock/gomock"
)

var stdinService = "ap-notheast-1\ncluster\nservice\nyes\n"
var stdinTask = "ap-notheast-1\ncluster\nyes\n"

func setup(t *testing.T, input io.Reader) (*cli.App, *mock_types.MockCage) {
ctrl := gomock.NewController(t)
cagecli := mock_types.NewMockCage(ctrl)
cageapp := &cageapp.App{Stdin: input}
app := cli.NewApp()
cmds := commands.NewCageCommands(func(envars *env.Envars) (types.Cage, error) {
return cagecli, nil
})
app.Commands = []*cli.Command{
cmds.Up(cageapp),
cmds.RollOut(cageapp),
cmds.Run(cageapp),
}
app.Flags = []cli.Flag{
&cli.BoolFlag{
Name: "ci",
Destination: &cageapp.CI,
Value: false,
},
}
return app, cagecli
}

type errorReader struct{}

func (e *errorReader) Read(p []byte) (n int, err error) {
return 0, io.EOF
}
21 changes: 7 additions & 14 deletions cli/cage/commands/command.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
package commands

import (
"io"

"github.com/aws/aws-sdk-go-v2/service/ecs"
"github.com/loilo-inc/canarycage/cli/cage/prompt"
"github.com/loilo-inc/canarycage/env"
"github.com/loilo-inc/canarycage/types"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)

type CageCommands struct {
Prompt *prompt.Prompter
cageCliProvier cageCliProvier
cageCliProvider cageCliProvider
}

func NewCageCommands(
stdin io.Reader,
cageCliProvier cageCliProvier,
cageCliProvider cageCliProvider,
) *CageCommands {
return &CageCommands{
Prompt: prompt.NewPrompter(stdin),
cageCliProvier: cageCliProvier,
}
cmds := &CageCommands{cageCliProvider: cageCliProvider}
return cmds
}

type cageCliProvier = func(envars *env.Envars) (types.Cage, error)
type cageCliProvider = func(e *env.Envars) (types.Cage, error)

func (c *CageCommands) requireArgs(
func RequireArgs(
ctx *cli.Context,
minArgs int,
maxArgs int,
Expand Down Expand Up @@ -70,7 +63,7 @@ func (c *CageCommands) setupCage(
if err := env.EnsureEnvars(envars); err != nil {
return nil, err
}
cagecli, err := c.cageCliProvier(envars)
cagecli, err := c.cageCliProvider(envars)
if err != nil {
return nil, err
}
Expand Down
Loading
Loading