Skip to content

Commit

Permalink
chore(deploy): update deploy/cfn package to support task run command (
Browse files Browse the repository at this point in the history
#1134)

This PR includes changes to deploy a task to CloudFormation.

Related #702 

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
  • Loading branch information
Lou1415926 authored Jul 13, 2020
1 parent 4d9c1b0 commit 417be99
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
47 changes: 47 additions & 0 deletions internal/pkg/deploy/cloudformation/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package cloudformation

import (
"errors"
"fmt"

"github.com/aws/copilot-cli/internal/pkg/aws/cloudformation"
"github.com/aws/copilot-cli/internal/pkg/deploy"
"github.com/aws/copilot-cli/internal/pkg/deploy/cloudformation/stack"
)

// DeployTask deploys a task stack and waits until the deployment is done.
// If the task stack doesn't exist, then it creates the stack.
// If the task stack already exists, it updates the stack.
// If the task stack doesn't have any changes, it returns nil
func (cf CloudFormation) DeployTask(input *deploy.CreateTaskResourcesInput) error {
conf := stack.NewTaskStackConfig(input)
stack, err := toStack(conf)
if err != nil {
return err
}

err = cf.cfnClient.CreateAndWait(stack)
if err == nil {
return nil
}

var errAlreadyExists *cloudformation.ErrStackAlreadyExists
if !errors.As(err, &errAlreadyExists) {
return fmt.Errorf("create stack: %w", err)
}

err = cf.cfnClient.UpdateAndWait(stack)
if err == nil {
return nil
}

var errChangeSetEmpty *cloudformation.ErrChangeSetEmpty
if !errors.As(err, &errChangeSetEmpty) {
return fmt.Errorf("update stack: %w", err)
}

return nil
}
83 changes: 83 additions & 0 deletions internal/pkg/deploy/cloudformation/task_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package cloudformation

import (
"errors"
"testing"

"github.com/aws/copilot-cli/internal/pkg/deploy"

"github.com/stretchr/testify/require"

"github.com/aws/copilot-cli/internal/pkg/aws/cloudformation"

"github.com/aws/copilot-cli/internal/pkg/deploy/cloudformation/mocks"
"github.com/golang/mock/gomock"
)

func TestCloudFormation_DeployTask(t *testing.T) {
mockTask := &deploy.CreateTaskResourcesInput{
Name: "my-task",
}

testCases := map[string]struct {
mockCfnClient func(m *mocks.MockcfnClient)
wantedError error
}{
"create a new stack": {
mockCfnClient: func(m *mocks.MockcfnClient) {
m.EXPECT().CreateAndWait(gomock.Any()).Return(nil)
m.EXPECT().UpdateAndWait(gomock.Any()).Times(0)
},
},
"failed to create stack": {
mockCfnClient: func(m *mocks.MockcfnClient) {
m.EXPECT().CreateAndWait(gomock.Any()).Return(errors.New("error"))
m.EXPECT().UpdateAndWait(gomock.Any()).Times(0)
},
wantedError: errors.New("create stack: error"),
},
"update the stack": {
mockCfnClient: func(m *mocks.MockcfnClient) {
m.EXPECT().CreateAndWait(gomock.Any()).Return(&cloudformation.ErrStackAlreadyExists{
Name: "my-task",
})
m.EXPECT().UpdateAndWait(gomock.Any()).Times(1).Return(nil)
},
},
"failed to update stack": {
mockCfnClient: func(m *mocks.MockcfnClient) {
m.EXPECT().CreateAndWait(gomock.Any()).Return(&cloudformation.ErrStackAlreadyExists{
Name: "my-task",
})
m.EXPECT().UpdateAndWait(gomock.Any()).Return(errors.New("error"))
},
wantedError: errors.New("update stack: error"),
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockCfnClient := mocks.NewMockcfnClient(ctrl)
if tc.mockCfnClient != nil {
tc.mockCfnClient(mockCfnClient)
}

cf := CloudFormation{
cfnClient: mockCfnClient,
}

err := cf.DeployTask(mockTask)
if tc.wantedError != nil {
require.EqualError(t, tc.wantedError, err.Error())
} else {
require.NoError(t, err)
}
})
}
}

0 comments on commit 417be99

Please sign in to comment.