From fc4733d0c8f483fcedbfd1a9eda86397706c1bc2 Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Thu, 15 Apr 2021 11:22:21 -0500 Subject: [PATCH 01/19] add stepmachine client --- Makefile | 1 + .../stepfunctions/mocks/mock_stepfunctions.go | 50 +++++++++++++ .../pkg/aws/stepfunctions/stepfunctions.go | 41 +++++++++++ .../aws/stepfunctions/stepfunctions_test.go | 70 +++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 internal/pkg/aws/stepfunctions/mocks/mock_stepfunctions.go create mode 100644 internal/pkg/aws/stepfunctions/stepfunctions.go create mode 100644 internal/pkg/aws/stepfunctions/stepfunctions_test.go diff --git a/Makefile b/Makefile index f21a9438ebd..c636d91db76 100644 --- a/Makefile +++ b/Makefile @@ -172,6 +172,7 @@ gen-mocks: tools ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/aws/cloudformation/mocks/mock_cloudformation.go -source=./internal/pkg/aws/cloudformation/interfaces.go ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/aws/cloudformation/stackset/mocks/mock_stackset.go -source=./internal/pkg/aws/cloudformation/stackset/stackset.go ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/aws/ssm/mocks/mock_ssm.go -source=./internal/pkg/aws/ssm/ssm.go + ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/aws/stepfunctions/mocks/mock_stepfunctions.go -source=./internal/pkg/aws/stepfunctions/stepfunctions.go ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/addon/mocks/mock_addons.go -source=./internal/pkg/addon/addons.go ${GOBIN}/mockgen -package=exec -source=./internal/pkg/exec/exec.go -destination=./internal/pkg/exec/mock_exec.go ${GOBIN}/mockgen -package=mocks -destination=./internal/pkg/deploy/mocks/mock_deploy.go -source=./internal/pkg/deploy/deploy.go diff --git a/internal/pkg/aws/stepfunctions/mocks/mock_stepfunctions.go b/internal/pkg/aws/stepfunctions/mocks/mock_stepfunctions.go new file mode 100644 index 00000000000..f1ec5cad55e --- /dev/null +++ b/internal/pkg/aws/stepfunctions/mocks/mock_stepfunctions.go @@ -0,0 +1,50 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/pkg/aws/stepfunctions/stepfunctions.go + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + sfn "github.com/aws/aws-sdk-go/service/sfn" + gomock "github.com/golang/mock/gomock" +) + +// Mockapi is a mock of api interface. +type Mockapi struct { + ctrl *gomock.Controller + recorder *MockapiMockRecorder +} + +// MockapiMockRecorder is the mock recorder for Mockapi. +type MockapiMockRecorder struct { + mock *Mockapi +} + +// NewMockapi creates a new mock instance. +func NewMockapi(ctrl *gomock.Controller) *Mockapi { + mock := &Mockapi{ctrl: ctrl} + mock.recorder = &MockapiMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *Mockapi) EXPECT() *MockapiMockRecorder { + return m.recorder +} + +// DescribeStateMachine mocks base method. +func (m *Mockapi) DescribeStateMachine(input *sfn.DescribeStateMachineInput) (*sfn.DescribeStateMachineOutput, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DescribeStateMachine", input) + ret0, _ := ret[0].(*sfn.DescribeStateMachineOutput) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DescribeStateMachine indicates an expected call of DescribeStateMachine. +func (mr *MockapiMockRecorder) DescribeStateMachine(input interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DescribeStateMachine", reflect.TypeOf((*Mockapi)(nil).DescribeStateMachine), input) +} diff --git a/internal/pkg/aws/stepfunctions/stepfunctions.go b/internal/pkg/aws/stepfunctions/stepfunctions.go new file mode 100644 index 00000000000..dfabddbbe21 --- /dev/null +++ b/internal/pkg/aws/stepfunctions/stepfunctions.go @@ -0,0 +1,41 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package stepfunctions provides a client to make API requests to Amazon Step Functions. +package stepfunctions + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/sfn" +) + +type api interface { + DescribeStateMachine(input *sfn.DescribeStateMachineInput) (*sfn.DescribeStateMachineOutput, error) +} + +// StepFunctions wraps an AWS StepFunctions client. +type StepFunctions struct { + client api +} + +// New returns StepFunctions configured against the input session. +func New(s *session.Session) *StepFunctions { + return &StepFunctions{ + client: sfn.New(s), + } +} + +// StateMachineDefinition returns the JSON-based state machine definition. +func (s *StepFunctions) StateMachineDefinition(stateMachineARN string) (string, error) { + out, err := s.client.DescribeStateMachine(&sfn.DescribeStateMachineInput{ + StateMachineArn: aws.String(stateMachineARN), + }) + if err != nil { + return "", fmt.Errorf("describe state machine: %w", err) + } + + return aws.StringValue(out.Definition), nil +} diff --git a/internal/pkg/aws/stepfunctions/stepfunctions_test.go b/internal/pkg/aws/stepfunctions/stepfunctions_test.go new file mode 100644 index 00000000000..aecafa1ec54 --- /dev/null +++ b/internal/pkg/aws/stepfunctions/stepfunctions_test.go @@ -0,0 +1,70 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package stepfunctions provides a client to make API requests to Amazon Step Functions. +package stepfunctions + +import ( + "errors" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/sfn" + + "github.com/stretchr/testify/require" + + "github.com/aws/copilot-cli/internal/pkg/aws/stepfunctions/mocks" + "github.com/golang/mock/gomock" +) + +func TestStepFunctions_StateMachineDefinition(t *testing.T) { + testCases := map[string]struct { + inStateMachineARN string + + mockStepFunctionsClient func(m *mocks.Mockapi) + + wantedError error + wantedDefinition string + }{ + "fail to describe state machine": { + inStateMachineARN: "ninth inning", + mockStepFunctionsClient: func(m *mocks.Mockapi) { + m.EXPECT().DescribeStateMachine(&sfn.DescribeStateMachineInput{ + StateMachineArn: aws.String("ninth inning"), + }).Return(nil, errors.New("some error")) + }, + wantedError: errors.New("describe state machine: some error"), + }, + "success": { + inStateMachineARN: "ninth inning", + mockStepFunctionsClient: func(m *mocks.Mockapi) { + m.EXPECT().DescribeStateMachine(&sfn.DescribeStateMachineInput{ + StateMachineArn: aws.String("ninth inning"), + }).Return(&sfn.DescribeStateMachineOutput{ + Definition: aws.String("{\n \"Version\": \"42\",\n \"Comment\": \"very important comment\"\n}"), + }, nil) + }, + wantedDefinition: "{\n \"Version\": \"42\",\n \"Comment\": \"very important comment\"\n}", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockStepFunctionsClient := mocks.NewMockapi(ctrl) + tc.mockStepFunctionsClient(mockStepFunctionsClient) + sfn := StepFunctions{ + client: mockStepFunctionsClient, + } + + out, err := sfn.StateMachineDefinition(tc.inStateMachineARN) + if tc.wantedError != nil { + require.EqualError(t, tc.wantedError, err.Error()) + } else { + require.Equal(t, tc.wantedDefinition, out) + } + }) + } +} From 38ca113b82c49c4fa1b34d9369845c39be8739d0 Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 30 Apr 2021 14:36:21 -0500 Subject: [PATCH 02/19] describe job neetwork config --- .../pkg/aws/resourcegroups/resourcegroups.go | 4 + internal/pkg/ecs/ecs.go | 91 ++++++++++- internal/pkg/ecs/ecs_test.go | 146 ++++++++++++++++++ internal/pkg/ecs/mocks/mock_ecs.go | 38 +++++ 4 files changed, 275 insertions(+), 4 deletions(-) diff --git a/internal/pkg/aws/resourcegroups/resourcegroups.go b/internal/pkg/aws/resourcegroups/resourcegroups.go index c824559fb72..9cbfa7a0175 100644 --- a/internal/pkg/aws/resourcegroups/resourcegroups.go +++ b/internal/pkg/aws/resourcegroups/resourcegroups.go @@ -13,6 +13,10 @@ import ( "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" ) +const ( + ResourceTypeStateMachine = "states:stateMachine" +) + type api interface { GetResources(input *resourcegroupstaggingapi.GetResourcesInput) (*resourcegroupstaggingapi.GetResourcesOutput, error) } diff --git a/internal/pkg/ecs/ecs.go b/internal/pkg/ecs/ecs.go index 7f573de5a18..c0a6c60e0b3 100644 --- a/internal/pkg/ecs/ecs.go +++ b/internal/pkg/ecs/ecs.go @@ -5,9 +5,13 @@ package ecs import ( + "encoding/json" "fmt" "strings" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/copilot-cli/internal/pkg/aws/stepfunctions" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/copilot-cli/internal/pkg/aws/ecs" @@ -38,6 +42,10 @@ type ecsClient interface { NetworkConfiguration(cluster, serviceName string) (*ecs.NetworkConfiguration, error) } +type stepFunctionsClient interface { + StateMachineDefinition(stateMachineARN string) (string, error) +} + // ServiceDesc contains the description of an ECS service. type ServiceDesc struct { Name string @@ -47,15 +55,17 @@ type ServiceDesc struct { // Client retrieves Copilot information from ECS endpoint. type Client struct { - rgGetter resourceGetter - ecsClient ecsClient + rgGetter resourceGetter + ecsClient ecsClient + StepFuncClient stepFunctionsClient } // New inits a new Client. func New(sess *session.Session) *Client { return &Client{ - rgGetter: resourcegroups.New(sess), - ecsClient: ecs.New(sess), + rgGetter: resourcegroups.New(sess), + ecsClient: ecs.New(sess), + StepFuncClient: stepfunctions.New(sess), } } @@ -220,6 +230,46 @@ func (c Client) NetworkConfiguration(app, env, svc string) (*ecs.NetworkConfigur return c.ecsClient.NetworkConfiguration(clusterARN, svcName) } +func (c Client) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkConfiguration, error) { + jobARN, err := c.stateMachineARN(app, env, job) + if err != nil { + return nil, err + } + + raw, err := c.StepFuncClient.StateMachineDefinition(jobARN) + if err != nil { + return nil, fmt.Errorf("get state machine definition for job %s: %w", job, err) + } + + var definition definition + err = json.Unmarshal([]byte(raw), &definition) + if err != nil { + return nil, fmt.Errorf("unmarshal state machine definition: %w", err) + } + + state := definition.States[targetState] + config := state.parameter.NetworkConfiguration + return &ecs.NetworkConfiguration{ + Subnets: config.AWSVPCConfiguration.Subnets, + SecurityGroups: config.AWSVPCConfiguration.SecurityGroups, + AssignPublicIp: config.AWSVPCConfiguration.AssignPublicIp, + }, nil +} + +type parameter struct { + NetworkConfiguration struct { + AWSVPCConfiguration ecs.NetworkConfiguration `json:"AwsvpcConfiguration"` + } `json:"NetworkConfiguration"` +} + +type state struct { + parameter `json:"Parameters"` +} + +type definition struct { + States map[string]state `json:"States"` +} + func (c Client) listActiveCopilotTasks(opts listActiveCopilotTasksOpts) ([]*ecs.Task, error) { var tasks []*ecs.Task if opts.TaskGroup != "" { @@ -309,3 +359,36 @@ func (c Client) serviceARN(app, env, svc string) (*ecs.ServiceArn, error) { serviceArn := ecs.ServiceArn(services[0].ARN) return &serviceArn, nil } + +func (c Client) stateMachineARN(app, env, job string) (string, error) { + resources, err := c.rgGetter.GetResourcesByTags(resourcegroups.ResourceTypeStateMachine, map[string]string{ + deploy.AppTagKey: app, + deploy.EnvTagKey: env, + deploy.ServiceTagKey: job, + }) + if err != nil { + return "", fmt.Errorf("get state machine resource by tags for job %s: %w", job, err) + } + + var stateMachineARN string + targetName := fmt.Sprintf(fmtStateMachineName, app, env, job) + for _, r := range resources { + parsedARN, err := arn.Parse(r.ARN) + if err != nil { + continue + } + parts := strings.Split(parsedARN.Resource, ":") + if len(parts) != 2 { + continue + } + if parts[1] == targetName { + stateMachineARN = r.ARN + break + } + } + + if stateMachineARN == "" { + return "", fmt.Errorf("state machine for job %s not found", job) + } + return stateMachineARN, nil +} diff --git a/internal/pkg/ecs/ecs_test.go b/internal/pkg/ecs/ecs_test.go index a9d9fa80fad..446fa2ca5b5 100644 --- a/internal/pkg/ecs/ecs_test.go +++ b/internal/pkg/ecs/ecs_test.go @@ -21,6 +21,7 @@ import ( type clientMocks struct { resourceGetter *mocks.MockresourceGetter ecsClient *mocks.MockecsClient + StepFuncClient *mocks.MockstepFunctionsClient } func TestClient_ClusterARN(t *testing.T) { @@ -1016,3 +1017,148 @@ func Test_NetworkConfiguration(t *testing.T) { }) } } + +func Test_NetworkConfigurationForJob(t *testing.T) { + const ( + testApp = "testApp" + testEnv = "testEnv" + testJob = "testJob" + testARN = "arn:aws:states:us-east-1:1234456789012:stateMachine:testApp-testEnv-testJob" + + testStateMachineDefinition = `{ + "Version": "1.0", + "Comment": "Run AWS Fargate task", + "StartAt": "Run Fargate Task", + "States": { + "Run Fargate Task": { + "Type": "Task", + "Resource": "arn:aws:states:::ecs:runTask.sync", + "Parameters": { + "LaunchType": "FARGATE", + "PlatformVersion": "1.4.0", + "Cluster": "cluster", + "TaskDefinition": "def", + "PropagateTags": "TASK_DEFINITION", + "Group.$": "$$.Execution.Name", + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "Subnets": ["sbn-1", "sbn-2"], + "AssignPublicIp": "ENABLED", + "SecurityGroups": ["sg-1", "sg-2"] + } + } + }, + "End": true + } + } + }` + ) + + testCases := map[string]struct { + setupMocks func(m clientMocks) + + wantedConfig *ecs.NetworkConfiguration + wantedError error + }{ + "success": { + setupMocks: func(m clientMocks) { + m.resourceGetter.EXPECT().GetResourcesByTags(resourcegroups.ResourceTypeStateMachine, map[string]string{ + deploy.AppTagKey: testApp, + deploy.EnvTagKey: testEnv, + deploy.ServiceTagKey: testJob, + }).Return([]*resourcegroups.Resource{ + { + ARN: "random-arn-doesn't matter", + }, + { + ARN: testARN, + }, + }, nil) + + m.StepFuncClient.EXPECT().StateMachineDefinition(testARN).Return(testStateMachineDefinition, nil) + }, + wantedConfig: &ecs.NetworkConfiguration{ + Subnets: []string{"sbn-1", "sbn-2"}, + SecurityGroups: []string{"sg-1", "sg-2"}, + AssignPublicIp: "ENABLED", + }, + }, + "fail to get resources by tags": { + setupMocks: func(m clientMocks) { + m.resourceGetter.EXPECT().GetResourcesByTags(resourcegroups.ResourceTypeStateMachine, map[string]string{ + deploy.AppTagKey: testApp, + deploy.EnvTagKey: testEnv, + deploy.ServiceTagKey: testJob, + }).Return(nil, errors.New("some error")) + }, + wantedError: errors.New("get state machine resource by tags for job testJob: some error"), + }, + "state machine resource not found": { + setupMocks: func(m clientMocks) { + m.resourceGetter.EXPECT().GetResourcesByTags(resourcegroups.ResourceTypeStateMachine, map[string]string{ + deploy.AppTagKey: testApp, + deploy.EnvTagKey: testEnv, + deploy.ServiceTagKey: testJob, + }).Return([]*resourcegroups.Resource{ + { + ARN: "rabbit", + }, + { + ARN: "cabbage", + }, + }, nil) + }, + wantedError: errors.New("state machine for job testJob not found"), + }, + "fail to get state machine definition": { + setupMocks: func(m clientMocks) { + m.resourceGetter.EXPECT().GetResourcesByTags(resourcegroups.ResourceTypeStateMachine, map[string]string{ + deploy.AppTagKey: testApp, + deploy.EnvTagKey: testEnv, + deploy.ServiceTagKey: testJob, + }).Return([]*resourcegroups.Resource{ + { + ARN: "random-arn-doesn't matter", + }, + { + ARN: testARN, + }, + }, nil) + + m.StepFuncClient.EXPECT().StateMachineDefinition(testARN).Return("", errors.New("some error")) + }, + wantedError: errors.New("get state machine definition for job testJob: some error"), + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + // GIVEN + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // GIVEN + m := clientMocks{ + StepFuncClient: mocks.NewMockstepFunctionsClient(ctrl), + resourceGetter: mocks.NewMockresourceGetter(ctrl), + } + tc.setupMocks(m) + + client := Client{ + rgGetter: m.resourceGetter, + StepFuncClient: m.StepFuncClient, + } + + // WHEN + get, err := client.NetworkConfigurationForJob(testApp, testEnv, testJob) + + // THEN + if tc.wantedError != nil { + require.EqualError(t, err, tc.wantedError.Error()) + } else { + require.NoError(t, err) + require.Equal(t, get, tc.wantedConfig) + } + }) + } +} diff --git a/internal/pkg/ecs/mocks/mock_ecs.go b/internal/pkg/ecs/mocks/mock_ecs.go index f89af636ca0..8b55365726c 100644 --- a/internal/pkg/ecs/mocks/mock_ecs.go +++ b/internal/pkg/ecs/mocks/mock_ecs.go @@ -181,3 +181,41 @@ func (mr *MockecsClientMockRecorder) TaskDefinition(taskDefName interface{}) *go mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TaskDefinition", reflect.TypeOf((*MockecsClient)(nil).TaskDefinition), taskDefName) } + +// MockstepFunctionsClient is a mock of stepFunctionsClient interface. +type MockstepFunctionsClient struct { + ctrl *gomock.Controller + recorder *MockstepFunctionsClientMockRecorder +} + +// MockstepFunctionsClientMockRecorder is the mock recorder for MockstepFunctionsClient. +type MockstepFunctionsClientMockRecorder struct { + mock *MockstepFunctionsClient +} + +// NewMockstepFunctionsClient creates a new mock instance. +func NewMockstepFunctionsClient(ctrl *gomock.Controller) *MockstepFunctionsClient { + mock := &MockstepFunctionsClient{ctrl: ctrl} + mock.recorder = &MockstepFunctionsClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockstepFunctionsClient) EXPECT() *MockstepFunctionsClientMockRecorder { + return m.recorder +} + +// StateMachineDefinition mocks base method. +func (m *MockstepFunctionsClient) StateMachineDefinition(stateMachineARN string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateMachineDefinition", stateMachineARN) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateMachineDefinition indicates an expected call of StateMachineDefinition. +func (mr *MockstepFunctionsClientMockRecorder) StateMachineDefinition(stateMachineARN interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateMachineDefinition", reflect.TypeOf((*MockstepFunctionsClient)(nil).StateMachineDefinition), stateMachineARN) +} From 14442f6f8bbf659e1360601ecee70b9d461dd157 Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 30 Apr 2021 14:36:43 -0500 Subject: [PATCH 03/19] run task request from job --- .../pkg/ecs/mocks/mock_run_task_request.go | 68 +++++++++++++++++++ internal/pkg/ecs/run_task_request.go | 40 +++++++++++ internal/pkg/ecs/run_task_request_test.go | 25 +++++++ 3 files changed, 133 insertions(+) diff --git a/internal/pkg/ecs/mocks/mock_run_task_request.go b/internal/pkg/ecs/mocks/mock_run_task_request.go index 2c3efdbec1b..2ee04ff04e8 100644 --- a/internal/pkg/ecs/mocks/mock_run_task_request.go +++ b/internal/pkg/ecs/mocks/mock_run_task_request.go @@ -146,3 +146,71 @@ func (mr *MockserviceDescriberMockRecorder) TaskDefinition(app, env, svc interfa mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TaskDefinition", reflect.TypeOf((*MockserviceDescriber)(nil).TaskDefinition), app, env, svc) } + +// MockjobDescriber is a mock of jobDescriber interface. +type MockjobDescriber struct { + ctrl *gomock.Controller + recorder *MockjobDescriberMockRecorder +} + +// MockjobDescriberMockRecorder is the mock recorder for MockjobDescriber. +type MockjobDescriberMockRecorder struct { + mock *MockjobDescriber +} + +// NewMockjobDescriber creates a new mock instance. +func NewMockjobDescriber(ctrl *gomock.Controller) *MockjobDescriber { + mock := &MockjobDescriber{ctrl: ctrl} + mock.recorder = &MockjobDescriberMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockjobDescriber) EXPECT() *MockjobDescriberMockRecorder { + return m.recorder +} + +// ClusterARN mocks base method. +func (m *MockjobDescriber) ClusterARN(app, env string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClusterARN", app, env) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ClusterARN indicates an expected call of ClusterARN. +func (mr *MockjobDescriberMockRecorder) ClusterARN(app, env interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClusterARN", reflect.TypeOf((*MockjobDescriber)(nil).ClusterARN), app, env) +} + +// NetworkConfigurationForJob mocks base method. +func (m *MockjobDescriber) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkConfiguration, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetworkConfigurationForJob", app, env, job) + ret0, _ := ret[0].(*ecs.NetworkConfiguration) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NetworkConfigurationForJob indicates an expected call of NetworkConfigurationForJob. +func (mr *MockjobDescriberMockRecorder) NetworkConfigurationForJob(app, env, job interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkConfigurationForJob", reflect.TypeOf((*MockjobDescriber)(nil).NetworkConfigurationForJob), app, env, job) +} + +// TaskDefinition mocks base method. +func (m *MockjobDescriber) TaskDefinition(app, env, job string) (*ecs.TaskDefinition, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TaskDefinition", app, env, job) + ret0, _ := ret[0].(*ecs.TaskDefinition) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TaskDefinition indicates an expected call of TaskDefinition. +func (mr *MockjobDescriberMockRecorder) TaskDefinition(app, env, job interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TaskDefinition", reflect.TypeOf((*MockjobDescriber)(nil).TaskDefinition), app, env, job) +} diff --git a/internal/pkg/ecs/run_task_request.go b/internal/pkg/ecs/run_task_request.go index 530315f3d31..bd687394b35 100644 --- a/internal/pkg/ecs/run_task_request.go +++ b/internal/pkg/ecs/run_task_request.go @@ -13,6 +13,11 @@ import ( awsecs "github.com/aws/copilot-cli/internal/pkg/aws/ecs" ) +const ( + fmtStateMachineName = "%s-%s-%s" // refer to workload's state-machine partial template. + targetState = "Run Fargate Task" +) + // ECSServiceDescriber provides information on an ECS service. type ECSServiceDescriber interface { Service(clusterName, serviceName string) (*awsecs.Service, error) @@ -27,6 +32,12 @@ type ServiceDescriber interface { ClusterARN(app, env string) (string, error) } +type jobDescriber interface { + TaskDefinition(app, env, job string) (*awsecs.TaskDefinition, error) + NetworkConfigurationForJob(app, env, job string) (*awsecs.NetworkConfiguration, error) + ClusterARN(app, env string) (string, error) +} + // RunTaskRequest contains information to generate a task run command. type RunTaskRequest struct { networkConfiguration awsecs.NetworkConfiguration @@ -117,6 +128,35 @@ func RunTaskRequestFromService(client ServiceDescriber, app, env, svc string) (* }, nil } +func RunTaskRequestFromJob(client jobDescriber, app, env, job string) (*RunTaskRequest, error) { + config, err := client.NetworkConfigurationForJob(app, env, job) + + cluster, err := client.ClusterARN(app, env) + if err != nil { + return nil, fmt.Errorf("retrieve cluster ARN created for environment %s in application %s: %w", env, app, err) + } + + // container info? + taskDef, err := client.TaskDefinition(app, env, job) + if err != nil { + return nil, fmt.Errorf("retrieve task definition for job %s: %w", job, err) + } + + containerName := job // NOTE: refer to workload's CloudFormation template. The container name is set to be the workload's name. + containerInfo, err := containerInformation(taskDef, containerName) + if err != nil { + return nil, err + } + + return &RunTaskRequest{ + networkConfiguration: *config, + executionRole: aws.StringValue(taskDef.ExecutionRoleArn), + taskRole: aws.StringValue(taskDef.TaskRoleArn), + containerInfo: *containerInfo, + cluster: cluster, + }, nil +} + // String stringifies a RunTaskRequest. func (r RunTaskRequest) CLIString() string { output := []string{"copilot task run"} diff --git a/internal/pkg/ecs/run_task_request_test.go b/internal/pkg/ecs/run_task_request_test.go index 4c979016fef..747ddf7ed84 100644 --- a/internal/pkg/ecs/run_task_request_test.go +++ b/internal/pkg/ecs/run_task_request_test.go @@ -2,8 +2,13 @@ package ecs import ( "errors" + "fmt" "testing" + "github.com/aws/copilot-cli/internal/pkg/aws/resourcegroups" + "github.com/aws/copilot-cli/internal/pkg/aws/sessions" + "github.com/aws/copilot-cli/internal/pkg/aws/stepfunctions" + "github.com/aws/copilot-cli/internal/pkg/ecs/mocks" "github.com/aws/aws-sdk-go/aws" @@ -278,3 +283,23 @@ func Test_RunTaskRequestFromService(t *testing.T) { }) } } + +func Test_RunTaskRequestFromJob(t *testing.T) { + sess, err := sessions.NewProvider().Default() + if err != nil { + fmt.Println(err) + return + } + + j := &Client{ + //JobDescriber: ecs.New(sess), + StepFuncClient: stepfunctions.New(sess), + rgGetter: resourcegroups.New(sess), + } + + config, err := j.NetworkConfigurationForJob("generate", "test", "job-delete") + if err != nil { + fmt.Println(err) + } + fmt.Println(config) +} From e282a61ab479d2ede8353da7be8b17b318315c9d Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 30 Apr 2021 17:53:47 -0500 Subject: [PATCH 04/19] implement custom unmarshaling to avoid deeply nested struct --- internal/pkg/ecs/ecs.go | 48 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/internal/pkg/ecs/ecs.go b/internal/pkg/ecs/ecs.go index c0a6c60e0b3..6b2c15adb27 100644 --- a/internal/pkg/ecs/ecs.go +++ b/internal/pkg/ecs/ecs.go @@ -241,33 +241,39 @@ func (c Client) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkCo return nil, fmt.Errorf("get state machine definition for job %s: %w", job, err) } - var definition definition - err = json.Unmarshal([]byte(raw), &definition) + var config NetworkConfiguration + err = json.Unmarshal([]byte(raw), &config) + + return (*ecs.NetworkConfiguration)(&config), nil +} + +type NetworkConfiguration ecs.NetworkConfiguration + +func (n *NetworkConfiguration) UnmarshalJSON(b []byte) error { + var f interface{} + err := json.Unmarshal(b, &f) if err != nil { - return nil, fmt.Errorf("unmarshal state machine definition: %w", err) + return err } - state := definition.States[targetState] - config := state.parameter.NetworkConfiguration - return &ecs.NetworkConfiguration{ - Subnets: config.AWSVPCConfiguration.Subnets, - SecurityGroups: config.AWSVPCConfiguration.SecurityGroups, - AssignPublicIp: config.AWSVPCConfiguration.AssignPublicIp, - }, nil -} + states := f.(map[string]interface{})["States"].(map[string]interface{}) + parameters := states["Run Fargate Task"].(map[string]interface{})["Parameters"].(map[string]interface{}) + networkConfig := parameters["NetworkConfiguration"].(map[string]interface{})["AwsvpcConfiguration"].(map[string]interface{}) -type parameter struct { - NetworkConfiguration struct { - AWSVPCConfiguration ecs.NetworkConfiguration `json:"AwsvpcConfiguration"` - } `json:"NetworkConfiguration"` -} + var subnets []string + for _, subnet := range networkConfig["Subnets"].([]interface{}) { + subnets = append(subnets, subnet.(string)) + } -type state struct { - parameter `json:"Parameters"` -} + var securityGroups []string + for _, sg := range networkConfig["SecurityGroups"].([]interface{}) { + securityGroups = append(securityGroups, sg.(string)) + } -type definition struct { - States map[string]state `json:"States"` + n.Subnets = subnets + n.SecurityGroups = securityGroups + n.AssignPublicIp = networkConfig["AssignPublicIp"].(string) + return nil } func (c Client) listActiveCopilotTasks(opts listActiveCopilotTasksOpts) ([]*ecs.Task, error) { From fa00abb635b051d700d17f2a756cb863bc60a4f2 Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 30 Apr 2021 17:58:35 -0500 Subject: [PATCH 05/19] fix lint --- internal/pkg/ecs/ecs.go | 3 +++ internal/pkg/ecs/run_task_request.go | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/pkg/ecs/ecs.go b/internal/pkg/ecs/ecs.go index 6b2c15adb27..28389d17136 100644 --- a/internal/pkg/ecs/ecs.go +++ b/internal/pkg/ecs/ecs.go @@ -243,6 +243,9 @@ func (c Client) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkCo var config NetworkConfiguration err = json.Unmarshal([]byte(raw), &config) + if err != nil { + return nil, fmt.Errorf("unmarshal state machine definition: %w", err) + } return (*ecs.NetworkConfiguration)(&config), nil } diff --git a/internal/pkg/ecs/run_task_request.go b/internal/pkg/ecs/run_task_request.go index bd687394b35..8263101a923 100644 --- a/internal/pkg/ecs/run_task_request.go +++ b/internal/pkg/ecs/run_task_request.go @@ -15,7 +15,6 @@ import ( const ( fmtStateMachineName = "%s-%s-%s" // refer to workload's state-machine partial template. - targetState = "Run Fargate Task" ) // ECSServiceDescriber provides information on an ECS service. @@ -130,6 +129,9 @@ func RunTaskRequestFromService(client ServiceDescriber, app, env, svc string) (* func RunTaskRequestFromJob(client jobDescriber, app, env, job string) (*RunTaskRequest, error) { config, err := client.NetworkConfigurationForJob(app, env, job) + if err != nil { + return nil, fmt.Errorf("retrieve network configuration for job %s: %w", job, err) + } cluster, err := client.ClusterARN(app, env) if err != nil { From d92579e7abc813ebb6eb29555842c199a35fc0dd Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 7 May 2021 12:44:02 -0500 Subject: [PATCH 06/19] add test --- internal/pkg/ecs/run_task_request.go | 1 - internal/pkg/ecs/run_task_request_test.go | 134 +++++++++++++++++++--- 2 files changed, 116 insertions(+), 19 deletions(-) diff --git a/internal/pkg/ecs/run_task_request.go b/internal/pkg/ecs/run_task_request.go index 8263101a923..0b18efd0d9b 100644 --- a/internal/pkg/ecs/run_task_request.go +++ b/internal/pkg/ecs/run_task_request.go @@ -138,7 +138,6 @@ func RunTaskRequestFromJob(client jobDescriber, app, env, job string) (*RunTaskR return nil, fmt.Errorf("retrieve cluster ARN created for environment %s in application %s: %w", env, app, err) } - // container info? taskDef, err := client.TaskDefinition(app, env, job) if err != nil { return nil, fmt.Errorf("retrieve task definition for job %s: %w", job, err) diff --git a/internal/pkg/ecs/run_task_request_test.go b/internal/pkg/ecs/run_task_request_test.go index 747ddf7ed84..c09846ca1b1 100644 --- a/internal/pkg/ecs/run_task_request_test.go +++ b/internal/pkg/ecs/run_task_request_test.go @@ -2,13 +2,8 @@ package ecs import ( "errors" - "fmt" "testing" - "github.com/aws/copilot-cli/internal/pkg/aws/resourcegroups" - "github.com/aws/copilot-cli/internal/pkg/aws/sessions" - "github.com/aws/copilot-cli/internal/pkg/aws/stepfunctions" - "github.com/aws/copilot-cli/internal/pkg/ecs/mocks" "github.com/aws/aws-sdk-go/aws" @@ -285,21 +280,124 @@ func Test_RunTaskRequestFromService(t *testing.T) { } func Test_RunTaskRequestFromJob(t *testing.T) { - sess, err := sessions.NewProvider().Default() - if err != nil { - fmt.Println(err) - return - } + var ( + testApp = "test-app" + testEnv = "test-env" + testJob = "test-job" + ) + testCases := map[string]struct { + setUpMock func(m *mocks.MockjobDescriber) - j := &Client{ - //JobDescriber: ecs.New(sess), - StepFuncClient: stepfunctions.New(sess), - rgGetter: resourcegroups.New(sess), + wantedRunTaskRequest *RunTaskRequest + wantedError error + }{ + "returns RunTaskRequest with job's main container": { + setUpMock: func(m *mocks.MockjobDescriber) { + m.EXPECT().TaskDefinition(testApp, testEnv, testJob).Return(&ecs.TaskDefinition{ + ExecutionRoleArn: aws.String("execution-role"), + TaskRoleArn: aws.String("task-role"), + ContainerDefinitions: []*awsecs.ContainerDefinition{ + { + Name: aws.String(testJob), + Image: aws.String("beautiful-image"), + EntryPoint: aws.StringSlice([]string{"enter", "here"}), + Command: aws.StringSlice([]string{"do", "not", "enter", "here"}), + Environment: []*awsecs.KeyValuePair{ + { + Name: aws.String("enter"), + Value: aws.String("no"), + }, + { + Name: aws.String("kidding"), + Value: aws.String("yes"), + }, + }, + Secrets: []*awsecs.Secret{ + { + Name: aws.String("truth"), + ValueFrom: aws.String("go-ask-the-wise"), + }, + }, + }, + { + Name: aws.String("random-container-that-we-do-not-care"), + }, + }, + }, nil) + m.EXPECT().NetworkConfigurationForJob(testApp, testEnv, testJob).Return(&ecs.NetworkConfiguration{ + AssignPublicIp: "1.2.3.4", + Subnets: []string{"sbn-1", "sbn-2"}, + SecurityGroups: []string{"sg-1", "sg-2"}, + }, nil) + m.EXPECT().ClusterARN(testApp, testEnv).Return("kamura-village", nil) + }, + wantedRunTaskRequest: &RunTaskRequest{ + networkConfiguration: ecs.NetworkConfiguration{ + AssignPublicIp: "1.2.3.4", + Subnets: []string{"sbn-1", "sbn-2"}, + SecurityGroups: []string{"sg-1", "sg-2"}, + }, + + executionRole: "execution-role", + taskRole: "task-role", + + containerInfo: containerInfo{ + image: "beautiful-image", + entryPoint: []string{"enter", "here"}, + command: []string{"do", "not", "enter", "here"}, + envVars: map[string]string{ + "enter": "no", + "kidding": "yes", + }, + secrets: map[string]string{ + "truth": "go-ask-the-wise", + }, + }, + + cluster: "kamura-village", + }, + }, + "unable to retrieve task definition": { + setUpMock: func(m *mocks.MockjobDescriber) { + m.EXPECT().TaskDefinition(testApp, testEnv, testJob).Return(nil, errors.New("some error")) + m.EXPECT().NetworkConfigurationForJob(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + m.EXPECT().ClusterARN(gomock.Any(), gomock.Any()).AnyTimes() + }, + wantedError: errors.New("retrieve task definition for job test-job: some error"), + }, + "unable to retrieve network configuration": { + setUpMock: func(m *mocks.MockjobDescriber) { + m.EXPECT().TaskDefinition(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + m.EXPECT().NetworkConfigurationForJob(testApp, testEnv, testJob).Return(nil, errors.New("some error")) + m.EXPECT().ClusterARN(gomock.Any(), gomock.Any()).AnyTimes() + }, + wantedError: errors.New("retrieve network configuration for job test-job: some error"), + }, + "unable to obtain cluster ARN": { + setUpMock: func(m *mocks.MockjobDescriber) { + m.EXPECT().TaskDefinition(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + m.EXPECT().NetworkConfigurationForJob(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + m.EXPECT().ClusterARN(testApp, testEnv).Return("", errors.New("some error")) + }, + wantedError: errors.New("retrieve cluster ARN created for environment test-env in application test-app: some error"), + }, } - config, err := j.NetworkConfigurationForJob("generate", "test", "job-delete") - if err != nil { - fmt.Println(err) + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + m := mocks.NewMockjobDescriber(ctrl) + tc.setUpMock(m) + + got, err := RunTaskRequestFromJob(m, testApp, testEnv, testJob) + if tc.wantedError != nil { + require.EqualError(t, tc.wantedError, err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tc.wantedRunTaskRequest, got) + } + }) } - fmt.Println(config) } From 9adce70b37f2e2916e2c648ce4d38c4b2ab52c9e Mon Sep 17 00:00:00 2001 From: Wanxian Yang Date: Fri, 7 May 2021 12:47:54 -0500 Subject: [PATCH 07/19] add public comment --- internal/pkg/ecs/ecs.go | 3 +++ internal/pkg/ecs/run_task_request.go | 1 + 2 files changed, 4 insertions(+) diff --git a/internal/pkg/ecs/ecs.go b/internal/pkg/ecs/ecs.go index 28389d17136..76dbb490736 100644 --- a/internal/pkg/ecs/ecs.go +++ b/internal/pkg/ecs/ecs.go @@ -230,6 +230,7 @@ func (c Client) NetworkConfiguration(app, env, svc string) (*ecs.NetworkConfigur return c.ecsClient.NetworkConfiguration(clusterARN, svcName) } +// NetworkConfigurationForJob returns the network configuration of the job. func (c Client) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkConfiguration, error) { jobARN, err := c.stateMachineARN(app, env, job) if err != nil { @@ -250,8 +251,10 @@ func (c Client) NetworkConfigurationForJob(app, env, job string) (*ecs.NetworkCo return (*ecs.NetworkConfiguration)(&config), nil } +// NetworkConfiguration wraps an ecs.NetworkConfiguration struct. type NetworkConfiguration ecs.NetworkConfiguration +// UnmarshalJSON implements custom logic to unmarshal a network configuration. func (n *NetworkConfiguration) UnmarshalJSON(b []byte) error { var f interface{} err := json.Unmarshal(b, &f) diff --git a/internal/pkg/ecs/run_task_request.go b/internal/pkg/ecs/run_task_request.go index 0b18efd0d9b..98a26cb05b2 100644 --- a/internal/pkg/ecs/run_task_request.go +++ b/internal/pkg/ecs/run_task_request.go @@ -127,6 +127,7 @@ func RunTaskRequestFromService(client ServiceDescriber, app, env, svc string) (* }, nil } +// RunTaskRequestFromJob populates a RunTaskRequest with information from a Copilot job. func RunTaskRequestFromJob(client jobDescriber, app, env, job string) (*RunTaskRequest, error) { config, err := client.NetworkConfigurationForJob(app, env, job) if err != nil { From c585dfa6a25af8bb4fffe3b35fd8a1eb85f69286 Mon Sep 17 00:00:00 2001 From: Wanxian Yang <79273084+Lou1415926@users.noreply.github.com> Date: Fri, 7 May 2021 14:55:13 -0500 Subject: [PATCH 08/19] chore: implement ask for secret init (#2271) Proceeding PR: #2266 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --- internal/pkg/cli/secret_init.go | 104 ++++++++++++++- internal/pkg/cli/secret_init_test.go | 192 +++++++++++++++++++++++++++ 2 files changed, 294 insertions(+), 2 deletions(-) diff --git a/internal/pkg/cli/secret_init.go b/internal/pkg/cli/secret_init.go index 414a3e91092..dcfb0327e38 100644 --- a/internal/pkg/cli/secret_init.go +++ b/internal/pkg/cli/secret_init.go @@ -6,10 +6,26 @@ package cli import ( "fmt" + "github.com/aws/copilot-cli/internal/pkg/term/color" + "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/aws/copilot-cli/internal/pkg/config" + "github.com/aws/copilot-cli/internal/pkg/term/log" + "github.com/aws/copilot-cli/internal/pkg/term/prompt" + "github.com/aws/copilot-cli/internal/pkg/term/selector" +) + +const ( + secretInitAppPrompt = "Which application do you want to add the secret to?" + secretInitAppPromptHelp = "The secret can then be versioned by your existing environments inside the application." + + secretInitSecretNamePrompt = "What would you like to name this secret?" + secretInitSecretNamePromptHelp = "The name of the secret, such as 'db_password'." + + fmtSecretInitSecretValuePrompt = "What is the value of secret %s in environment %s?" + fmtSecretInitSecretValuePromptHelp = "If you do not wish to add the secret %s to environment %s, you can leave this blank by pressing 'Enter' without entering any value." ) type secretInitVars struct { @@ -28,6 +44,9 @@ type secretInitOpts struct { store store fs afero.Fs + + prompter prompter + selector appSelector } func newSecretInitOpts(vars secretInitVars) (*secretInitOpts, error) { @@ -36,14 +55,19 @@ func newSecretInitOpts(vars secretInitVars) (*secretInitOpts, error) { return nil, fmt.Errorf("new config store: %w", err) } + prompter := prompt.New() opts := secretInitOpts{ secretInitVars: vars, store: store, fs: &afero.Afero{Fs: afero.NewOsFs()}, + + prompter: prompter, + selector: selector.NewSelect(prompter, store), } return &opts, nil } +// Validate returns an error if the flag values passed by the user are invalid. func (o *secretInitOpts) Validate() error { if o.appName != "" { _, err := o.store.GetApplication(o.appName) @@ -74,21 +98,97 @@ func (o *secretInitOpts) Validate() error { return nil } +// Ask prompts the user for any required or important fields that are not provided. func (o *secretInitOpts) Ask() error { + if o.overwrite { + log.Infof("You have specified %s flag. Please note that overwriting an existing secret may break your deployed service.\n", color.HighlightCode("--overwrite")) + } + if err := o.askForAppName(); err != nil { + return err + } + if err := o.askForSecretName(); err != nil { + return err + } + if err := o.askForSecretValues(); err != nil { + return err + } return nil } +// Execute creates the secrets. func (o *secretInitOpts) Execute() error { return nil } -// BuildSecretInitCmd build the command for creating or updating a new secret. +func (o *secretInitOpts) askForAppName() error { + if o.appName != "" { + return nil + } + + app, err := o.selector.Application(secretInitAppPrompt, secretInitAppPromptHelp) + if err != nil { + return fmt.Errorf("ask for an application to add the secret to: %w", err) + } + o.appName = app + return nil +} + +func (o *secretInitOpts) askForSecretName() error { + if o.name != "" { + return nil + } + + name, err := o.prompter.Get(secretInitSecretNamePrompt, + secretInitSecretNamePromptHelp, + validateSecretName, + prompt.WithFinalMessage("secret name: ")) + if err != nil { + return fmt.Errorf("ask for the secret name: %w", err) + } + + o.name = name + return nil +} + +func (o *secretInitOpts) askForSecretValues() error { + if o.values != nil { + return nil + } + + envs, err := o.store.ListEnvironments(o.appName) + if err != nil { + return fmt.Errorf("list environments in app %s: %w", o.appName, err) + } + + if len(envs) == 0 { + log.Errorf("Secrets environment-level resources. Please run %s before running %s.\n", + color.HighlightCode("copilot env init"), + color.HighlightCode("copilot secret init")) + return fmt.Errorf("no environment is found in app %s", o.appName) + } + + values := make(map[string]string) + for _, env := range envs { + value, err := o.prompter.GetSecret( + fmt.Sprintf(fmtSecretInitSecretValuePrompt, color.HighlightUserInput(o.name), env.Name), + fmt.Sprintf(fmtSecretInitSecretValuePromptHelp, color.HighlightUserInput(o.name), env.Name)) + if err != nil { + return fmt.Errorf("get secret value for %s in environment %s: %w", color.HighlightUserInput(o.name), env.Name, err) + } + + values[env.Name] = value + } + o.values = values + return nil +} + +// BuildSecretInitCmd build the command for creating a new secret or updating an existing one. func BuildSecretInitCmd() *cobra.Command { vars := secretInitVars{} cmd := &cobra.Command{ Use: "init", Short: "Create or update an SSM SecureString parameter.", - Example: `secret init`, + Example: ``, // TODO RunE: runCmdE(func(cmd *cobra.Command, args []string) error { opts, err := newSecretInitOpts(vars) if err != nil { diff --git a/internal/pkg/cli/secret_init_test.go b/internal/pkg/cli/secret_init_test.go index b3d8b87210d..975a281c385 100644 --- a/internal/pkg/cli/secret_init_test.go +++ b/internal/pkg/cli/secret_init_test.go @@ -5,6 +5,7 @@ package cli import ( "errors" + "fmt" "testing" "github.com/aws/copilot-cli/internal/pkg/config" @@ -130,3 +131,194 @@ func TestSecretInitOpts_Validate(t *testing.T) { }) } } + +type secretInitAskMocks struct { + mockStore *mocks.Mockstore + mockPrompter *mocks.Mockprompter + mockSelector *mocks.MockappSelector +} + +func TestSecretInitOpts_Ask(t *testing.T) { + var ( + wantedName = "db-password" + wantedApp = "my-app" + wantedValues = map[string]string{ + "test": "test-password", + "dev": "dev-password", + "prod": "prod-password", + } + wantedVars = secretInitVars{ + appName: wantedApp, + name: wantedName, + values: wantedValues, + } + ) + testCases := map[string]struct { + inAppName string + inName string + inValues map[string]string + + setupMocks func(m secretInitAskMocks) + + wantedVars secretInitVars + wantedError error + }{ + "prompt to select an app if not specified": { + inName: wantedName, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) { + m.mockSelector.EXPECT().Application(secretInitAppPrompt, gomock.Any()).Return(wantedApp, nil) + }, + wantedVars: wantedVars, + }, + "error prompting to select an app": { + setupMocks: func(m secretInitAskMocks) { + m.mockSelector.EXPECT().Application(secretInitAppPrompt, gomock.Any()).Return("", errors.New("some error")) + }, + wantedError: errors.New("ask for an application to add the secret to: some error"), + }, + "do not prompt for app if specified": { + inAppName: wantedApp, + inName: wantedName, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) { + m.mockSelector.EXPECT().Application(gomock.Any(), gomock.Any()).Times(0) + }, + wantedVars: secretInitVars{ + appName: wantedApp, + name: wantedName, + values: wantedValues, + }, + }, + "ask for a secret name if not specified": { + inAppName: wantedApp, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) { + m.mockPrompter.EXPECT().Get(secretInitSecretNamePrompt, gomock.Any(), gomock.Any(), gomock.Any()). + Return("db-password", nil) + }, + wantedVars: wantedVars, + }, + "error prompting for a secret name": { + inAppName: wantedApp, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) { + m.mockPrompter.EXPECT().Get(secretInitSecretNamePrompt, gomock.Any(), gomock.Any(), gomock.Any()). + Return("", errors.New("some error")) + }, + wantedError: errors.New("ask for the secret name: some error"), + }, + "do not ask for a secret name if specified": { + inName: "db-password", + inAppName: wantedApp, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) { + m.mockPrompter.EXPECT().Get(secretInitSecretNamePrompt, gomock.Any(), gomock.Any(), gomock.Any()).Times(0) + }, + wantedVars: wantedVars, + }, + "ask for values for each existing environment if not specified": { + inAppName: wantedApp, + inName: wantedName, + setupMocks: func(m secretInitAskMocks) { + m.mockStore.EXPECT().ListEnvironments("my-app").Return([]*config.Environment{ + { + Name: "test", + }, + { + Name: "dev", + }, + { + Name: "prod", + }, + }, nil) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "test"), gomock.Any()). + Return("test-password", nil) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "dev"), gomock.Any()). + Return("dev-password", nil) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "prod"), gomock.Any()). + Return("prod-password", nil) + }, + wantedVars: wantedVars, + }, + "error listing environments": { + inAppName: wantedApp, + inName: wantedName, + setupMocks: func(m secretInitAskMocks) { + m.mockStore.EXPECT().ListEnvironments("my-app").Return(nil, errors.New("some error")) + }, + wantedError: errors.New("list environments in app my-app: some error"), + }, + "error prompting for values": { + inAppName: wantedApp, + inName: wantedName, + setupMocks: func(m secretInitAskMocks) { + m.mockStore.EXPECT().ListEnvironments("my-app").Return([]*config.Environment{ + { + Name: "test", + }, + { + Name: "dev", + }, + { + Name: "prod", + }, + }, nil) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "test"), gomock.Any()). + Return("", errors.New("some error")) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "dev"), gomock.Any()).MinTimes(0).MaxTimes(1) + m.mockPrompter.EXPECT().GetSecret(fmt.Sprintf(fmtSecretInitSecretValuePrompt, "db-password", "prod"), gomock.Any()).MinTimes(0).MaxTimes(1) + }, + wantedError: errors.New("get secret value for db-password in environment test: some error"), + }, + "error if no env is found": { + inAppName: wantedApp, + inName: wantedName, + setupMocks: func(m secretInitAskMocks) { + m.mockStore.EXPECT().ListEnvironments(wantedApp).Return([]*config.Environment{}, nil) + }, + wantedError: errors.New("no environment is found in app my-app"), + }, + "do not ask for values if specified": { + inAppName: wantedApp, + inName: wantedName, + inValues: wantedValues, + setupMocks: func(m secretInitAskMocks) {}, + wantedVars: wantedVars, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + m := secretInitAskMocks{ + mockPrompter: mocks.NewMockprompter(ctrl), + mockSelector: mocks.NewMockappSelector(ctrl), + mockStore: mocks.NewMockstore(ctrl), + } + + opts := secretInitOpts{ + secretInitVars: secretInitVars{ + appName: tc.inAppName, + name: tc.inName, + values: tc.inValues, + }, + prompter: m.mockPrompter, + store: m.mockStore, + selector: m.mockSelector, + } + + tc.setupMocks(m) + + err := opts.Ask() + if tc.wantedError == nil { + require.NoError(t, err) + require.Equal(t, tc.wantedVars, opts.secretInitVars) + } else { + require.EqualError(t, tc.wantedError, err.Error()) + } + }) + } +} From 4718cf58d13f7dc200fe7e0e4f5e95ce87e8a558 Mon Sep 17 00:00:00 2001 From: Tori Hara Date: Sun, 9 May 2021 02:20:10 +0900 Subject: [PATCH 09/19] docs(ja): add localized docs for Copilot v1.6.0 (#2286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is a continued work from #2225 by @efekarakus, and adds localized docs for Japanese language in our docs 🚀 Note that the localized docs are translated from the v1.6 Copilot docs - https://github.com/aws/copilot-cli/tree/v1.6.0/site, and are not from the mainline branch. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --- .github/CODEOWNERS | 4 +- mkdocs.yml | 4 + site/content/community/get-involved.ja.md | 8 + site/content/community/guides.ja.md | 39 ++ site/content/docs/commands/app-delete.ja.md | 21 + site/content/docs/commands/app-init.ja.md | 45 ++ site/content/docs/commands/app-ls.ja.md | 24 + site/content/docs/commands/app-show.ja.md | 26 + site/content/docs/commands/completion.ja.md | 34 ++ site/content/docs/commands/deploy.ja.md | 39 ++ site/content/docs/commands/docs.ja.md | 14 + site/content/docs/commands/env-delete.ja.md | 27 + site/content/docs/commands/env-init.ja.md | 57 ++ site/content/docs/commands/env-ls.ja.md | 25 + site/content/docs/commands/env-show.ja.md | 29 + site/content/docs/commands/init.ja.md | 38 ++ site/content/docs/commands/job-delete.ja.md | 35 ++ site/content/docs/commands/job-deploy.ja.md | 40 ++ site/content/docs/commands/job-init.ja.md | 45 ++ site/content/docs/commands/job-ls.ja.md | 24 + site/content/docs/commands/job-package.ja.md | 35 ++ .../docs/commands/pipeline-delete.ja.md | 20 + .../content/docs/commands/pipeline-init.ja.md | 24 + site/content/docs/commands/pipeline-ls.ja.md | 21 + .../content/docs/commands/pipeline-show.ja.md | 26 + .../docs/commands/pipeline-status.ja.md | 25 + .../docs/commands/pipeline-update.ja.md | 19 + site/content/docs/commands/storage-init.ja.md | 70 +++ site/content/docs/commands/svc-delete.ja.md | 23 + site/content/docs/commands/svc-deploy.ja.md | 27 + site/content/docs/commands/svc-exec.ja.md | 40 ++ site/content/docs/commands/svc-init.ja.md | 38 ++ site/content/docs/commands/svc-logs.ja.md | 47 ++ site/content/docs/commands/svc-ls.ja.md | 21 + site/content/docs/commands/svc-package.ja.md | 28 + site/content/docs/commands/svc-show.ja.md | 22 + site/content/docs/commands/svc-status.ja.md | 20 + site/content/docs/commands/task-delete.ja.md | 36 ++ site/content/docs/commands/task-exec.ja.md | 70 +++ site/content/docs/commands/task-run.ja.md | 82 +++ site/content/docs/commands/version.ja.md | 12 + site/content/docs/concepts/applications.ja.md | 97 +++ site/content/docs/concepts/environments.ja.md | 88 +++ site/content/docs/concepts/jobs.ja.md | 37 ++ site/content/docs/concepts/overview.ja.md | 31 + site/content/docs/concepts/pipelines.ja.md | 156 +++++ site/content/docs/concepts/services.ja.md | 177 ++++++ site/content/docs/credentials.ja.md | 62 ++ .../developing/additional-aws-resources.ja.md | 114 ++++ .../developing/environment-variables.ja.md | 57 ++ site/content/docs/developing/secrets.ja.md | 38 ++ .../docs/developing/service-discovery.ja.md | 36 ++ site/content/docs/developing/sidecars.ja.md | 147 +++++ site/content/docs/developing/storage.ja.md | 343 +++++++++++ .../getting-started/first-app-tutorial.ja.md | 73 +++ .../docs/getting-started/install.ja.md | 47 ++ .../content/docs/getting-started/verify.ja.md | 201 ++++++ .../docs/include/common-svc-fields.ja.md | 226 +++++++ site/content/docs/include/http-config.ja.md | 53 ++ site/content/docs/include/http-config.md | 1 - site/content/docs/include/image-config.ja.md | 41 ++ .../docs/include/image-healthcheck.ja.md | 18 + .../docs/manifest/backend-service.ja.md | 71 +++ .../docs/manifest/lb-web-service.ja.md | 69 +++ site/content/docs/manifest/overview.ja.md | 8 + site/content/docs/manifest/pipeline.ja.md | 85 +++ .../content/docs/manifest/scheduled-job.ja.md | 219 +++++++ site/content/docs/overview.ja.md | 15 + site/content/index.ja.md | 4 + site/overrides/layouts/home.ja.html | 572 ++++++++++++++++++ 70 files changed, 4368 insertions(+), 2 deletions(-) create mode 100644 site/content/community/get-involved.ja.md create mode 100644 site/content/community/guides.ja.md create mode 100644 site/content/docs/commands/app-delete.ja.md create mode 100644 site/content/docs/commands/app-init.ja.md create mode 100644 site/content/docs/commands/app-ls.ja.md create mode 100644 site/content/docs/commands/app-show.ja.md create mode 100644 site/content/docs/commands/completion.ja.md create mode 100644 site/content/docs/commands/deploy.ja.md create mode 100644 site/content/docs/commands/docs.ja.md create mode 100644 site/content/docs/commands/env-delete.ja.md create mode 100644 site/content/docs/commands/env-init.ja.md create mode 100644 site/content/docs/commands/env-ls.ja.md create mode 100644 site/content/docs/commands/env-show.ja.md create mode 100644 site/content/docs/commands/init.ja.md create mode 100644 site/content/docs/commands/job-delete.ja.md create mode 100644 site/content/docs/commands/job-deploy.ja.md create mode 100644 site/content/docs/commands/job-init.ja.md create mode 100644 site/content/docs/commands/job-ls.ja.md create mode 100644 site/content/docs/commands/job-package.ja.md create mode 100644 site/content/docs/commands/pipeline-delete.ja.md create mode 100644 site/content/docs/commands/pipeline-init.ja.md create mode 100644 site/content/docs/commands/pipeline-ls.ja.md create mode 100644 site/content/docs/commands/pipeline-show.ja.md create mode 100644 site/content/docs/commands/pipeline-status.ja.md create mode 100644 site/content/docs/commands/pipeline-update.ja.md create mode 100644 site/content/docs/commands/storage-init.ja.md create mode 100644 site/content/docs/commands/svc-delete.ja.md create mode 100644 site/content/docs/commands/svc-deploy.ja.md create mode 100644 site/content/docs/commands/svc-exec.ja.md create mode 100644 site/content/docs/commands/svc-init.ja.md create mode 100644 site/content/docs/commands/svc-logs.ja.md create mode 100644 site/content/docs/commands/svc-ls.ja.md create mode 100644 site/content/docs/commands/svc-package.ja.md create mode 100644 site/content/docs/commands/svc-show.ja.md create mode 100644 site/content/docs/commands/svc-status.ja.md create mode 100644 site/content/docs/commands/task-delete.ja.md create mode 100644 site/content/docs/commands/task-exec.ja.md create mode 100644 site/content/docs/commands/task-run.ja.md create mode 100644 site/content/docs/commands/version.ja.md create mode 100644 site/content/docs/concepts/applications.ja.md create mode 100644 site/content/docs/concepts/environments.ja.md create mode 100644 site/content/docs/concepts/jobs.ja.md create mode 100644 site/content/docs/concepts/overview.ja.md create mode 100644 site/content/docs/concepts/pipelines.ja.md create mode 100644 site/content/docs/concepts/services.ja.md create mode 100644 site/content/docs/credentials.ja.md create mode 100644 site/content/docs/developing/additional-aws-resources.ja.md create mode 100644 site/content/docs/developing/environment-variables.ja.md create mode 100644 site/content/docs/developing/secrets.ja.md create mode 100644 site/content/docs/developing/service-discovery.ja.md create mode 100644 site/content/docs/developing/sidecars.ja.md create mode 100644 site/content/docs/developing/storage.ja.md create mode 100644 site/content/docs/getting-started/first-app-tutorial.ja.md create mode 100644 site/content/docs/getting-started/install.ja.md create mode 100644 site/content/docs/getting-started/verify.ja.md create mode 100644 site/content/docs/include/common-svc-fields.ja.md create mode 100644 site/content/docs/include/http-config.ja.md create mode 100644 site/content/docs/include/image-config.ja.md create mode 100644 site/content/docs/include/image-healthcheck.ja.md create mode 100644 site/content/docs/manifest/backend-service.ja.md create mode 100644 site/content/docs/manifest/lb-web-service.ja.md create mode 100644 site/content/docs/manifest/overview.ja.md create mode 100644 site/content/docs/manifest/pipeline.ja.md create mode 100644 site/content/docs/manifest/scheduled-job.ja.md create mode 100644 site/content/docs/overview.ja.md create mode 100644 site/content/index.ja.md create mode 100644 site/overrides/layouts/home.ja.html diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d2ae2d30066..61d953f6b79 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,5 @@ # @See https://help.github.com/articles/about-codeowners/ -* @aws/aws-ecs-devx \ No newline at end of file +* @aws/aws-ecs-devx + +*.ja.md @toricls diff --git a/mkdocs.yml b/mkdocs.yml index a1435271e8a..8560d68a9c5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,6 +14,9 @@ extra: - name: English link: ./en/ lang: en + - name: 日本語 + link: ./ja/ + lang: ja nav: - Home: index.en.md @@ -164,6 +167,7 @@ plugins: default_language: en languages: en: english + ja: japanese material_alternate: false - macros: include_dir: site/content/docs/include diff --git a/site/content/community/get-involved.ja.md b/site/content/community/get-involved.ja.md new file mode 100644 index 00000000000..3607d1fac6f --- /dev/null +++ b/site/content/community/get-involved.ja.md @@ -0,0 +1,8 @@ +AWS Copilot コミュニティへようこそ ❤️ + +[[アプリケーション、ブログ記事、動画](https://aws.github.io/copilot-cli/community/guides/)] のような AWS Copilot CLI に関連するリソースを皆で共有しましょう👩‍✈️ + +コミュニティへの参加方法は他にもあります! + +* GitHub リポジトリに [![GitHub イシュー](https://img.shields.io/github/issues/aws/copilot-cli)](https://github.com/aws/copilot-cli/issues)を作成してみる +* [![Gitter チャット](https://badges.gitter.im/aws/copilot-cli.svg)](https://gitter.im/aws/copilot-cli?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)で Copilot な仲間達と会話してみよう diff --git a/site/content/community/guides.ja.md b/site/content/community/guides.ja.md new file mode 100644 index 00000000000..3593b860f9b --- /dev/null +++ b/site/content/community/guides.ja.md @@ -0,0 +1,39 @@ +Copilot な仲間たちとアプリケーションや動画、ブログポストを共有しよう! + +## ブログポスト + +| タイトル | 概要 | +| ----------- | ------------------------------------ | +| [**Pilot your containers like a boss with AWS Copilot!**](https://blog.flolight.dev/pilot-your-containers-like-a-boss-with-aws-copilot) by @FlolightC | Florian simplifies getting started with AWS Copilot by demoing deployment of a [sample app](https://github.com/aws-samples/amazon-ecs-cli-sample-app) from start to finish, including links to both required and optional resources. +| [**Use AWS Copilot CLI to deploy containers on an existing infrastructure - Tutorial**](https://dannys.cloud/aws-copilot-cli-deploy-containers-existing-infrastructure-tutorial) by @dannysteenman | Danny explains how to use your existing VPC and subnets with AWS Copilot to quickly set up a working container environment. Follow along as he deploys a Django app with an RDS Postgres database and Elasticache Redis cluster. | +| [**Automatically deploying your container application with AWS Copilot**](https://aws.amazon.com/blogs/containers/automatically-deploying-your-container-application-with-aws-copilot/) by @nathankpeck | Nathan shows how to set up a release pipeline with the CLI that builds, pushes, and deploys an application. Finally, he sets up integration tests for validation before releasing to production. | +| [**Deploying containers with the AWS Copilot CLI**](https://maartenbruntink.nl/blog/2020/08/16/deploying-containers-with-the-aws-copilot-cli-part-1/) by @maartenbruntink | Maarten shows how to use the AWS Copilot CLI to deploy the [sample Docker voting app](https://github.com/dockersamples/example-voting-app), which showcases how to set up your own Redis and Postgres servers. In the [second part](https://maartenbruntink.nl/blog/2020/08/16/deploying-containers-with-the-aws-copilot-cli-part-2), he automates the release process. | +| [**AWS Copilot: an application-first CLI for containers on AWS**](https://aws.amazon.com/blogs/containers/aws-copilot-an-application-first-cli-for-containers-on-aws/) by @efekarakus | Efe walks through the design tenets of the CLI: why they were chosen, how they map to Copilot features, and the vision for how the CLI will evolve in the future. | +| [**Introducing AWS Copilot**](https://aws.amazon.com/blogs/containers/introducing-aws-copilot/) by @nathankpeck | Nathan explains how with the AWS Copilot CLI you can go from idea to implementation much faster, with the confidence that the infrastructure you have deployed has production-ready configuration. | + + + +## 動画 + +| タイトル | 概要 | +| ----------- | ------------------------------------ | +| [**Containers from the Couch series**](https://www.youtube.com/c/ContainersfromtheCouch/search?query=copilot) by @realadamjkeller, @brentContained, and guests | Join Adam and Brent to learn about all the existing features of AWS Copilot with fun demos. From setting up a three-tier application with autoscaling to creating a continuous delivery pipeline with integration tests. | +| [**AWS re:Invent 2020: AWS Copilot: Simplifying container development**](https://youtu.be/EqW--TKQ_PQ) by @efekarakus | Learn about the motivation behind AWS Copilot, get an overview of the existing commands and a demo of how to deploy a three-tier application. | +| [**How to Deploy a .NET Application to Amazon Elastic Container Service (ECS) with AWS Copilot**](https://youtu.be/nWaw8Rp8JgQ) by @ignacioafuentes | Get a demo on how to build and deploy a .NET application on Amazon ECS and AWS Fargate. | +| [**AWS What's Next**](https://www.youtube.com/watch?v=vmTJgVDERZU) by @nathankpeck and @efekarakus | Nathan and Efe discuss what makes AWS Copilot unique compared to other infrastructure provisioning tools and then demo an overview of the existing commands. | + + + +## コード・サンプル + +| リポジトリ | 詳細 | 特徴 | +| ----------- | ------------------------------------ | ------------ | +[**github.com/copilot-example-voting-app**](https://github.com/copilot-example-voting-app) | A voting application distributed over three ECS services created with AWS Copilot. | Amazon Aurora PostgreSQL database, service discovery, autoscaling | +[**#1925**](https://github.com/aws/copilot-cli/discussions/1925) | Show and tell explaining how you can do continuous deployments from branches with AWS Copilot pipelines. | Branch-based deploys, AWS CodePipeline | + + +## ワークショップ + +| タイトル | 詳細 | +| ----------- | ------------------------------------ | +[**ECS Workshop**](https://ecsworkshop.com/microservices/) | In this workshop, we deploy a three tier microservices application using the copilot-cli | diff --git a/site/content/docs/commands/app-delete.ja.md b/site/content/docs/commands/app-delete.ja.md new file mode 100644 index 00000000000..1c9311f11db --- /dev/null +++ b/site/content/docs/commands/app-delete.ja.md @@ -0,0 +1,21 @@ +# app delete +```bash +$ copilot app delete [flags] +``` + +## コマンドの概要 + +`copilot app delete` Application に関連付けられた全てのリソースを削除します。 + +## フラグ + +```bash +-h, --help help for delete + --yes Skips confirmation prompt. +``` + +## 実行例 +Application を強制的に削除します。 +```bash +$ copilot app delete --yes +``` diff --git a/site/content/docs/commands/app-init.ja.md b/site/content/docs/commands/app-init.ja.md new file mode 100644 index 00000000000..94392b2a9ea --- /dev/null +++ b/site/content/docs/commands/app-init.ja.md @@ -0,0 +1,45 @@ +# app init +```bash +$ copilot app init [name] [flags] +``` + +## コマンドの概要 +`copilot app init` はコマンドを実行したディレクトリ内に新しい [Application](../concepts/applications.ja.md) を作成します。 Service は Application 内に作成していきます。 + +質問への回答の後、CLI は、Service 用に作成されたインフラストラクチャーを管理する為の AWS Identity and Access Management ロールを作成します。 +作業ディレクトリ配下に新しいサブディレクトリ `copilot/` を確認できます。 `copilot` ディレクトリには Service 用の Manifest ファイルと追加のインフラストラクチャーが格納されます。 + +`copilot app init` はカスタムドメイン名や AWS タグを利用したい場合に利用します。それ以外の典型的なケースでは、同じ動作をする `copilot init` を利用します。 + +## フラグ +Copilot CLI における全てのコマンドと同じ様に、必要なフラグを指定しなかった場合、必要な情報を全て入力する様に求められます。 +フラグを指定して情報を指定すると、プロンプトをスキップできます。 +```bash + --domain string Optional. Your existing custom domain name. + -h, --help help for init + --resource-tags stringToString Optional. Labels with a key and value separated by commas. + Allows you to categorize resources. (default []) +``` +`--domain` フラグは、 Application が利用している AWS アカウント上の Amazon Route 53 に登録されたドメイン名を指定します。 +これにより Application 内の全てのサービスが同じドメイン名を利用することが出来るようになります。次の例の様に Service に対してアクセス出来るようになります。 +[https://{svcName}.{envName}.{appName}.{domain}](https://{svcName}.{envName}.{appName}.{domain}) + +`--resource-tags` フラグは、Application 内の全てのリソースに対してカスタム[タグ](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html)を追加します。 +コマンド例: `copilot app init --resource-tags department=MyDept,team=MyTeam` + +## 実行例 +"my-app"という名前の新しい Application を作成します。 +```bash +$ copilot app init my-app +``` +Route 53 に登録済みの既存ドメイン名を利用して新しい Application を作成します。 +```bash +$ copilot app init --domain example.com +``` +リソースタグを指定して新しい Application を作成します。 +```bash +$ copilot app init --resource-tags department=MyDept,team=MyTeam +``` +## 出力例 + +![Running copilot app init](https://raw.githubusercontent.com/kohidave/copilot-demos/master/app-init.edited.svg?sanitize=true) diff --git a/site/content/docs/commands/app-ls.ja.md b/site/content/docs/commands/app-ls.ja.md new file mode 100644 index 00000000000..53fea28ca3a --- /dev/null +++ b/site/content/docs/commands/app-ls.ja.md @@ -0,0 +1,24 @@ +# app ls +```bash +$ copilot app ls [flags] +``` + +## コマンドの概要 + +`copilot app ls` は、AWS アカウントにある全ての Copilot Application を一覧表示します。 + +## フラグ + +```bash +-h, --help help for ls +``` + +## 実行例 +AWS アカウント、リージョンにある全ての Application を一覧表示します。 +```bash +$ copilot app ls +``` + +## 出力例 + +![Running copilot ls](https://raw.githubusercontent.com/kohidave/copilot-demos/master/app-ls.svg?sanitize=true) diff --git a/site/content/docs/commands/app-show.ja.md b/site/content/docs/commands/app-show.ja.md new file mode 100644 index 00000000000..d48c962d412 --- /dev/null +++ b/site/content/docs/commands/app-show.ja.md @@ -0,0 +1,26 @@ +# app show +```bash +$ copilot app show [flags] +``` + +## コマンドの概要 + +`copilot app show` は Application の設定、Environment、Service を出力します。 + +## フラグ + +```bash +-h, --help help for show + --json Optional. Outputs in JSON format. +-n, --name string Name of the application. +``` + +## 実行例 +"my-app"という Application に関する情報を出力します。 +```bash +$ copilot app show -n my-app +``` + +## 出力例 + +![Running copilot app show](https://raw.githubusercontent.com/kohidave/copilot-demos/master/app-show.svg?sanitize=true) diff --git a/site/content/docs/commands/completion.ja.md b/site/content/docs/commands/completion.ja.md new file mode 100644 index 00000000000..1b14cd6338c --- /dev/null +++ b/site/content/docs/commands/completion.ja.md @@ -0,0 +1,34 @@ +# completion +``` +$ copilot completion [shell] [flags] +``` + +## コマンドの概要 +`copilot completion` は、bash や zsh のシェル補完コードを出力します。コマンドをインタラクティブに補完するためには、このコードが評価されなければなりません。 + +それぞれのシェルで自動補完を設定する方法については、ヘルプメニューを参照してください。 + +## フラグ +```bash +-h, --help help for completion +``` + +## 例 +zsh の補完をインストールします。 +```bash +$ source <(copilot completion zsh) +$ copilot completion zsh > "${fpath[1]}/_copilot" # to autoload on startup +``` +bash の補完を homebrew を使って macOS にインストールします。 +```bash +$ brew install bash-completion # if running 3.2 +$ brew install bash-completion@2 # if running Bash 4.1+ +$ copilot completion bash > /usr/local/etc/bash_completion.d +``` +Install bash completion on linux +bash の補完を Linux にインストールします。 +```bash +$ source <(copilot completion bash) +$ copilot completion bash > copilot.sh +$ sudo mv copilot.sh /etc/bash_completion.d/copilot +``` diff --git a/site/content/docs/commands/deploy.ja.md b/site/content/docs/commands/deploy.ja.md new file mode 100644 index 00000000000..cef77436ea8 --- /dev/null +++ b/site/content/docs/commands/deploy.ja.md @@ -0,0 +1,39 @@ +# copilot deploy +``` +$ copilot deploy +``` + +## コマンドの概要 + +このコマンドは、[`copilot svc deploy`](../commands/svc-deploy.ja.md) または [`copilot job deploy`](../commands/job-deploy.ja.md) の内部で利用されています。 +`copilot deploy` の中で実行される各ステップは、`copilot svc deploy` や `copilot job deploy` で実行されるステップと同様です。 + +1. ローカルの Dockerfile からコンテナイメージを作成 +2. `--tag` で指定された値、または最新の git sha を利用してタグ付け(git 管理されている場合) +3. コンテナイメージを ECR に対してプッシュ +4. Manifest ファイルと Addon を CloudFormation テンプレートにパッケージ +5. ECS タスク定義を作成/更新し、Job や Service を作成/更新 + +## フラグ + +```bash + -a, --app string Name of the application. + -e, --env string Name of the environment. + -h, --help help for deploy + -n, --name string Name of the service or job. + --resource-tags stringToString Optional. Labels with a key and value separated by commas. + Allows you to categorize resources. (default []) + --tag string Optional. The container image tag. +``` + +## 実行例 + +"frontend"という名前の Service を "test" Environment にデプロイします。 +```bash + $ copilot deploy --name frontend --env test +``` + +"mailer"という名前の Job を、追加のリソースタグを付加して、"prod" Environment にデプロイします。 +```bash +$ copilot deploy -n mailer -e prod --resource-tags source/revision=bb133e7,deployment/initiator=manual +``` diff --git a/site/content/docs/commands/docs.ja.md b/site/content/docs/commands/docs.ja.md new file mode 100644 index 00000000000..d1bdcc7b356 --- /dev/null +++ b/site/content/docs/commands/docs.ja.md @@ -0,0 +1,14 @@ +# docs +```bash +$ copilot docs [flags] +``` + +## コマンドの概要 + +`copilot docs` は、Copilot のドキュメントをブラウザ上で開きます。 + +## フラグ + +```bash + -h, --help help for docs +``` diff --git a/site/content/docs/commands/env-delete.ja.md b/site/content/docs/commands/env-delete.ja.md new file mode 100644 index 00000000000..2a189a92288 --- /dev/null +++ b/site/content/docs/commands/env-delete.ja.md @@ -0,0 +1,27 @@ +# env delete +```bash +$ copilot env delete [flags] +``` + +## コマンドの概要 +`copilot env delete`は、Applicationから Environment を削除します。 Environment 内に実行中のアプリケーションがある場合は、はじめに [`copilot svc delete`](../commands/svc-delete.ja.md) を実行する必要があります。 + +質問に答えた後、Environment 用の AWS CloudFormation スタックが削除されたことを確認してください。 + +## フラグ +``` +-h, --help help for delete +-n, --name string Name of the environment. + --yes Skips confirmation prompt. +-a, --app string Name of the application. +``` + +## 実行例 +"test" Environment を削除します。 +```bash +$ copilot env delete --name test +``` +"test" Environment をプロンプトなしで削除します。 +```bash +$ copilot env delete --name test --yes +``` diff --git a/site/content/docs/commands/env-init.ja.md b/site/content/docs/commands/env-init.ja.md new file mode 100644 index 00000000000..13847c8ec97 --- /dev/null +++ b/site/content/docs/commands/env-init.ja.md @@ -0,0 +1,57 @@ +# env init +```bash +$ copilot env init [flags] +``` + +## コマンドの概要 +`copilot env init` は、Service 実行用に新しい [Environment](../concepts/environments.ja.md) を作成します。 + +質問に答えると、CLI は VPC, Application Load Balancer, ECS Cluster などの Service で共有される共通のインフラストラクチャーを作成します。さらに、デフォルトのリソース設定や既存リソースのインポートなど、[Copilot の Environment をカスタマイズ](../concepts/environments.ja.md#Environment-のカスタマイズ)できます。 + +[名前付きプロファイル](../credentials.ja.md#Environment-用の認証情報)を使用して、Environment を作成する AWS アカウントとリージョンを指定します。 + +## フラグ +AWS Copilot CLI の全てのコマンド同様、必須フラグを省略した場合にはそれらの情報の入力をインタラクティブに求められます。必須フラグを明示的に渡してコマンドを実行することでこれをスキップできます。 +``` +Common Flags + --aws-access-key-id string Optional. An AWS access key. + --aws-secret-access-key string Optional. An AWS secret access key. + --aws-session-token string Optional. An AWS session token for temporary credentials. + --default-config Optional. Skip prompting and use default environment configuration. + -n, --name string Name of the environment. + --prod If the environment contains production services. + --profile string Name of the profile. + --region string Optional. An AWS region where the environment will be created. + +Import Existing Resources Flags + --import-private-subnets strings Optional. Use existing private subnet IDs. + --import-public-subnets strings Optional. Use existing public subnet IDs. + --import-vpc-id string Optional. Use an existing VPC ID. + +Configure Default Resources Flags + --override-private-cidrs strings Optional. CIDR to use for private subnets (default 10.0.2.0/24,10.0.3.0/24). + --override-public-cidrs strings Optional. CIDR to use for public subnets (default 10.0.0.0/24,10.0.1.0/24). + --override-vpc-cidr ipNet Optional. Global CIDR to use for VPC (default 10.0.0.0/16). + +Global Flags + -a, --app string Name of the application. +``` + +## 実行例 +AWS プロファイルの "default" に、デフォルト設定を使用して test Environment を作成します。 + +```bash +$ copilot env init --name test --profile default --default-config +``` + +AWS プロファイルの "prod-admin" を利用して既存の VPC に prod-iad Environment を作成します。 +```bash +$ copilot env init --name prod-iad --profile prod-admin --prod \ +--import-vpc-id vpc-099c32d2b98cdcf47 \ +--import-public-subnets subnet-013e8b691862966cf,subnet-014661ebb7ab8681a \ +--import-private-subnets subnet-055fafef48fb3c547,subnet-00c9e76f288363e7f +``` + +## 出力例 +![Running copilot env init](https://raw.githubusercontent.com/kohidave/copilot-demos/master/env-init.svg?sanitize=true) + diff --git a/site/content/docs/commands/env-ls.ja.md b/site/content/docs/commands/env-ls.ja.md new file mode 100644 index 00000000000..924a3fb5be6 --- /dev/null +++ b/site/content/docs/commands/env-ls.ja.md @@ -0,0 +1,25 @@ +# env ls +```bash +$ copilot env ls [flags] +``` + +## コマンドの概要 +`copilot env ls` は、Application 内の全ての Environment を一覧表示します。 + +## フラグ +```bash +-h, --help help for ls + --json Optional. Outputs in JSON format. +-a, --app string Name of the application. +``` +結果をプログラムでパースしたい場合 `--json` フラグを利用することができます。 + +## 実行例 +frontend Application の全ての Environment を一覧表示します。 +```bash +$ copilot env ls -a frontend +``` + +## 出力例 + +![Running copilot env ls](https://raw.githubusercontent.com/kohidave/copilot-demos/master/env-ls.svg?sanitize=true) diff --git a/site/content/docs/commands/env-show.ja.md b/site/content/docs/commands/env-show.ja.md new file mode 100644 index 00000000000..4ad51856ffd --- /dev/null +++ b/site/content/docs/commands/env-show.ja.md @@ -0,0 +1,29 @@ +# env show +```bash +$ copilot env show [flags] +``` + +## コマンドの概要 +`copilot env show` は、特定の Environment に関する以下のような情報を表示します。 + +* Environment があるリージョンとアカウント +* Environment が production かどうか +* Environment に現在デプロイされている Service +* Environment に関連するタグ + +オプションで `--resources` フラグを付けると Environment に関連する AWS リソースが表示されます。 + +## フラグ +```bash +-h, --help help for show + --json Optional. Outputs in JSON format. +-n, --name string Name of the environment. + --resources Optional. Show the resources in your environment. +``` +結果をプログラムでパースしたい場合 `--json` フラグを利用することができます。 + +## 実行例 +"test" Environment に関する情報を表示します。 +```bash +$ copilot env show -n test +``` diff --git a/site/content/docs/commands/init.ja.md b/site/content/docs/commands/init.ja.md new file mode 100644 index 00000000000..a69d358560e --- /dev/null +++ b/site/content/docs/commands/init.ja.md @@ -0,0 +1,38 @@ +# init +```bash +$ copilot init +``` + +## コマンドの概要 +`copilot init` は、コンテナアプリを Amazon ECS 上にデプロイしたい場合の出発点となります。Dockerfile を含むディレクトリ内で実行すると、あとは `init` の質問に答えていくだけですぐに Application を作成し、実行できます。 + +すべての質問に答えると、`copilot init` は ECR リポジトリをセットアップし、デプロイするかどうかを尋ねます。デプロイを選択すると、ネットワークスタックとロールを備えた新しい `test` Environemnt を作成します。そして、Dockerfile をビルドして Amazon ECR に Push し、Service や Job をデプロイします。 + +既存の Application への Service と Job の追加も `copilot init` で行えます。この場合は Service や Job を追加する Application の選択を求められます。 + +## フラグ + +Copilot CLI の全てのコマンドと同様に、必要なフラグを指定しない場合は、アプリの実行に必要な情報をすべて入力するように求められます。フラグを介して情報を提供することで、プロンプトをスキップできます。 + +```sh + -a, --app string Name of the application. + --deploy Deploy your service or job to a "test" environment. + -d, --dockerfile string Path to the Dockerfile. + Mutually exclusive with -i, --image + -h, --help help for init + -i, --image string The location of an existing Docker image. + Mutually exclusive with -d, --dockerfile + -n, --name string Name of the service or job. + --port uint16 Optional. The port on which your service listens. + --retries int Optional. The number of times to try restarting the job on a failure. + --schedule string The schedule on which to run this job. + Accepts cron expressions of the format (M H DoM M DoW) and schedule definition strings. + For example: "0 * * * *", "@daily", "@weekly", "@every 1h30m". + AWS Schedule Expressions of the form "rate(10 minutes)" or "cron(0 12 L * ? 2021)" + are also accepted. + --tag string Optional. The container image tag. + --timeout string Optional. The total execution time for the task, including retries. + Accepts valid Go duration strings. For example: "2h", "1h30m", "900s". + -t, --type string Type of service to create. Must be one of: + "Load Balanced Web Service", "Backend Service", "Scheduled Job" +``` diff --git a/site/content/docs/commands/job-delete.ja.md b/site/content/docs/commands/job-delete.ja.md new file mode 100644 index 00000000000..2024e41668b --- /dev/null +++ b/site/content/docs/commands/job-delete.ja.md @@ -0,0 +1,35 @@ +# job delete +```bash +$ copilot job delete [flags] +``` + +## コマンドの概要 + +`copilot job delete` は特定の Environment 内で Job に関連づけられたすべてのリソースを削除します。 + +## フラグ + +```bash + -a, --app string Name of the application. + -e, --env string Name of the environment. + -h, --help help for delete + -n, --name string Name of the job. + --yes Skips confirmation prompt. +``` + +## 実行例 + +"report-generator" Job を "my-app" Application から削除します。このコマンドはワークスペースの外からでも実行できます。 +```bash +$ copilot job delete --name report-generator --app my-app +``` + +"report-generator" Job を "prod" Environment からのみ削除します。 +```bash +$ copilot job delete --name report-generator --env prod +``` + +確認をプロンプトに表示せず "report-generator" Job を削除します。 +```bash +$ copilot job delete --name report-generator --yes +``` diff --git a/site/content/docs/commands/job-deploy.ja.md b/site/content/docs/commands/job-deploy.ja.md new file mode 100644 index 00000000000..1b9eb48a431 --- /dev/null +++ b/site/content/docs/commands/job-deploy.ja.md @@ -0,0 +1,40 @@ +# job deploy +```bash +$ copilot job deploy +``` + +## 概要 + +`job deploy` はローカルのコードと設定を元に Job をデプロイします。 + +`job deploy` は以下のステップを実行します。 + +1. ローカルの Dockerfile をビルドしてコンテナイメージを作成 +2. `--tag` あるいは git ディレクトリにいる場合は最新の git ハッシュ値を使ってコンテナイメージにタグ付け +3. ECR にコンテナイメージをプッシュ +4. Manifest ファイルと Addon をまとめて CloudFormation テンプレートを生成する。 +5. ECS のタスク定義と Job を作成/更新 + +## フラグ + +```bash + -a, --app string Name of the application. + -e, --env string Name of the environment. + -h, --help help for deploy + -n, --name string Name of the job. + --resource-tags stringToString Optional. Labels with a key and value separated by commas. + Allows you to categorize resources. (default []) + --tag string Optional. The container image tag. +``` + +## 実行例 + +"report-gen" という Job を "test" Environment にデプロイします。 +```bash +$ copilot job deploy --name report-gen --env test +``` + +追加のリソースタグを付与して Job をデプロイします。 +```bash +$ copilot job deploy --resource-tags source/revision=bb133e7,deployment/initiator=manual` +``` diff --git a/site/content/docs/commands/job-init.ja.md b/site/content/docs/commands/job-init.ja.md new file mode 100644 index 00000000000..ddc85d91f1b --- /dev/null +++ b/site/content/docs/commands/job-init.ja.md @@ -0,0 +1,45 @@ +# job init +```bash +$ copilot job init +``` + +## コマンドの概要 + +`copilot job init` は新しく [Job](../concepts/jobs.ja.md) を作成します。 + +このコマンドを実行すると、 Copilot CLI は [Manifest ファイル](../manifest/overview.ja.md) を格納するための Application 名がついたディレクトリを `copilot` ディレクトリ配下に作成します。 Job のデフォルト設定を変更したい場合は Manifest ファイルを更新してください。 CLI はさらに全ての [Environment](../concepts/environments.ja.md) からプルできるポリシーをアタッチした ECR リポジトリをセットアップします。最後に Job は AWS Systems Manager パラメータストアに登録され CLI が Job をトラックできるようになります。 + +その後すでにセットアップされた Environment があるなら、 `copilot job deploy` コマンドを実行してその Environment に Job をデプロイできます。 + +## フラグ + +```bash + -a, --app string Name of the application. + -d, --dockerfile string Path to the Dockerfile. + Mutually exclusive with -i, --image + -h, --help help for init + -i, --image string The location of an existing Docker image. + Mutually exclusive with -d, --dockerfile + -t, --job-type string Type of job to create. Must be one of: + "Scheduled Job" + -n, --name string Name of the job. + --retries int Optional. The number of times to try restarting the job on a failure. + -s, --schedule string The schedule on which to run this job. + Accepts cron expressions of the format (M H DoM M DoW) and schedule definition strings. + For example: "0 * * * *", "@daily", "@weekly", "@every 1h30m". + AWS Schedule Expressions of the form "rate(10 minutes)" or "cron(0 12 L * ? 2021)" + are also accepted. + --timeout string Optional. The total execution time for the task, including retries. + Accepts valid Go duration strings. For example: "2h", "1h30m", "900s". +``` + +## 実行例 + +1 日 1 回実行される "reaper" という名前のスケジュールされたタスクを作成します。 +```bash +$ copilot job init --name reaper --dockerfile ./frontend/Dockerfile --schedule "every 2 hours" +``` +リトライ回数を指定した "report-generator" という名前のスケジュールされたタスクを作成します。 +```bash +$ copilot job init --name report-generator --schedule "@monthly" --retries 3 --timeout 900s +``` diff --git a/site/content/docs/commands/job-ls.ja.md b/site/content/docs/commands/job-ls.ja.md new file mode 100644 index 00000000000..f5ca2f6c955 --- /dev/null +++ b/site/content/docs/commands/job-ls.ja.md @@ -0,0 +1,24 @@ +# job ls +```bash +$ copilot job ls +``` + +## コマンドの概要 + +`copilot job ls` は、特定の Application に含まれる全ての Copilot の Job を一覧表示します。 + +## フラグ + +```bash + -a, --app string Name of the application. + -h, --help help for ls + --json Optional. Outputs in JSON format. + --local Only show jobs in the workspace. +``` + +## 実行例 + +"myapp" Application に含まれる全ての Job を一覧表示します。 +```bash +$ copilot job ls --app myapp +``` diff --git a/site/content/docs/commands/job-package.ja.md b/site/content/docs/commands/job-package.ja.md new file mode 100644 index 00000000000..78e80156dd7 --- /dev/null +++ b/site/content/docs/commands/job-package.ja.md @@ -0,0 +1,35 @@ +# job package +```bash +$ copilot job package +``` + +## コマンドの概要 + +`copilot job package` は Job を Environment にデプロイするための CloudFormation テンプレートを生成します。 + +## フラグ + +```bash + -a, --app string Name of the application. + -e, --env string Name of the environment. + -h, --help help for package + -n, --name string Name of the job. + --output-dir string Optional. Writes the stack template and template configuration to a directory. + --tag string Optional. The container image tag. +``` + +## 実行例 + +"report-generator" Job を作成する CloudFormation テンプレートを、"test" Environment にデプロイする形で出力します。 + +```bash +$ copilot job package -n report-generator -e test +``` + +CloudFormation テンプレートと設定を "infrastructure/" ディレクトリ以下に書き出します。 + +```bash +$ copilot job package -n report-generator -e test --output-dir ./infrastructure +$ ls ./infrastructure + report-generator-test.stack.yml report-generator-test.params.yml +``` diff --git a/site/content/docs/commands/pipeline-delete.ja.md b/site/content/docs/commands/pipeline-delete.ja.md new file mode 100644 index 00000000000..ee16f7394c3 --- /dev/null +++ b/site/content/docs/commands/pipeline-delete.ja.md @@ -0,0 +1,20 @@ +# pipeline delete +```bash +$ copilot pipeline delete [flags] +``` + +## コマンドの概要 +`copilot pipeline delete` は、ワークスペースに紐付いている Pipeline を削除します。 + +## フラグ +```bash + --delete-secret Deletes AWS Secrets Manager secret associated with a pipeline source repository. +-h, --help help for delete + --yes Skips confirmation prompt. +``` + +## 実行例 +ワークスペースに紐付いている Pipeline を削除します。 +```bash +$ copilot pipeline delete +``` diff --git a/site/content/docs/commands/pipeline-init.ja.md b/site/content/docs/commands/pipeline-init.ja.md new file mode 100644 index 00000000000..102029eb9fc --- /dev/null +++ b/site/content/docs/commands/pipeline-init.ja.md @@ -0,0 +1,24 @@ +# pipeline init +```bash +$ copilot pipeline init [flags] +``` + +## コマンドの概要 +`copilot pipeline init` は、ワークスペース内の全ての Service をデプロイする Pipeline 用の Manifest を作成します。この Manifest では Application に関連づけられた Environment がデプロイターゲットとなります。 + +## フラグ +```bash +-a, --app string Name of the application. +-e, --environments strings Environments to add to the pipeline. +-b, --git-branch string Branch used to trigger your pipeline. +-u, --url string The repository URL to trigger your pipeline. +-h, --help help for init +``` + +## 実行例 +ワークスペース内の全ての Service をデプロイする Pipeline 用の Manifest を作成します。 +```bash +$ copilot pipeline init \ +--url https://github.com/gitHubUserName/myFrontendApp.git \ +--environments "test,prod" +``` diff --git a/site/content/docs/commands/pipeline-ls.ja.md b/site/content/docs/commands/pipeline-ls.ja.md new file mode 100644 index 00000000000..a4710d84fe0 --- /dev/null +++ b/site/content/docs/commands/pipeline-ls.ja.md @@ -0,0 +1,21 @@ +# pipeline ls +```bash +$ copilot pipeline ls [flags] +``` + +## コマンドの概要 +`copilot pipeline ls` は、Application にデプロイされた全ての Pipeline を一覧表示します。 + +## フラグ +```bash +-a, --app string Name of the application. +-h, --help help for ls + --json Optional. Outputs in JSON format. +``` + +## 実行例 +Application "phonetool" のすべての Pipeline を一覧表示します。 + +```bash +$ copilot pipeline ls -a phonetool +``` diff --git a/site/content/docs/commands/pipeline-show.ja.md b/site/content/docs/commands/pipeline-show.ja.md new file mode 100644 index 00000000000..179da2f09f4 --- /dev/null +++ b/site/content/docs/commands/pipeline-show.ja.md @@ -0,0 +1,26 @@ +# pipeline show +```bash +$ copilot pipeline show [flags] +``` + +## コマンドの概要 +`copilot pipeline show` は、Application にデプロイされた Pipeline の構成情報 (アカウント、リージョン、ステージなど) を表示します。 + +## フラグ +```bash +-a, --app string Name of the application. +-h, --help help for show + --json Optional. Outputs in JSON format. +-n, --name string Name of the pipeline. + --resources Optional. Show the resources in your pipeline. +``` + +## 実行例 +Application "myapp" の Pipeline に関する情報を表示します。 +```bash +$ copilot pipeline show --app myapp --resources +``` + +## 出力例 + +![Running copilot pipeline show](https://raw.githubusercontent.com/kohidave/copilot-demos/master/pipeline-show.svg?sanitize=true) diff --git a/site/content/docs/commands/pipeline-status.ja.md b/site/content/docs/commands/pipeline-status.ja.md new file mode 100644 index 00000000000..1008c3fb66a --- /dev/null +++ b/site/content/docs/commands/pipeline-status.ja.md @@ -0,0 +1,25 @@ +# pipeline status +```bash +$ copilot pipeline status [flags] +``` + +## コマンドの概要 +`copilot pipeline status` では、デプロイされた Pipeline のステージの状態を表示します。 + +## フラグ +```bash +-a, --app string Name of the application. +-h, --help help for status + --json Optional. Outputs in JSON format. +-n, --name string Name of the pipeline. +``` + +## 実行例 +Pipeline "pipeline-myapp-myrepo" の状態を表示します。 +```bash +$ copilot pipeline status -n pipeline-myapp-myrepo +``` + +## 出力例 + +![Running copilot pipeline status](https://raw.githubusercontent.com/kohidave/copilot-demos/master/pipeline-status.svg?sanitize=true) diff --git a/site/content/docs/commands/pipeline-update.ja.md b/site/content/docs/commands/pipeline-update.ja.md new file mode 100644 index 00000000000..566fcd40475 --- /dev/null +++ b/site/content/docs/commands/pipeline-update.ja.md @@ -0,0 +1,19 @@ +# pipeline update +```bash +$ copilot pipeline update [flags] +``` + +## コマンドの概要 +`copilot pipeline update` は、ワークスペース内に全ての Service がデプロイ対象となるように Pipeline を作成/更新します。あわせてこの Pipeline のデプロイターゲットが Pipeline 用 Manifest にて Application と紐付けられた Environment 群となるように作成/更新されます。 + +## フラグ +```bash +-h, --help help for update + --yes Skips confirmation prompt. +``` + +## 実行例 +ワークスペース内の Service 群をデプロイ対象とする形で Pipeline を作成/更新します。 +```bash +$ copilot pipeline update +``` diff --git a/site/content/docs/commands/storage-init.ja.md b/site/content/docs/commands/storage-init.ja.md new file mode 100644 index 00000000000..be968ae006f --- /dev/null +++ b/site/content/docs/commands/storage-init.ja.md @@ -0,0 +1,70 @@ +# storage init +```bash +$ copilot storage init +``` +## コマンドの概要 +`copilot storage init` は、ワークロードの 1 つに接続された新しいストレージリソースを作成します。サービスコンテナ内からフレンドリーな環境変数を介してアクセスできます。リソースタイプには、*S3*、*DynamoDB*、*Aurora* のいずれかを指定できます。 + +このコマンドを実行すると、CLI は `copilot/service` ディレクトリ内に、`addons` サブディレクトリが存在しなければ作成します。`copilot svc deploy` を実行すると、新規に初期化されたストレージリソースが、デプロイ先の環境に作成されます。デフォルトでは、`storage init` で指定したサービスのみが、そのストレージリソースにアクセスできます。 + +## フラグ +```bash +Required Flags + -n, --name string Name of the storage resource to create. + -t, --storage-type string Type of storage to add. Must be one of: + "DynamoDB", "S3", "Aurora" + -w, --workload string Name of the service or job to associate with storage. + +DynamoDB Flags + --lsi stringArray Optional. Attribute to use as an alternate sort key. May be specified up to 5 times. + Must be of the format ':'. + --no-lsi Optional. Don't ask about configuring alternate sort keys. + --no-sort Optional. Skip configuring sort keys. + --partition-key string Partition key for the DDB table. + Must be of the format ':'. + --sort-key string Optional. Sort key for the DDB table. + Must be of the format ':'. +Aurora Serverless Flags + --engine string The database engine used in the cluster. + Must be either "MySQL" or "PostgreSQL". + --parameter-group string Optional. The name of the parameter group to associate with the cluster. + --initial-db string The initial database to create in the cluster. +``` + +## 使用例 +"frontend" Service に "my-bucket" という名前の S3 バケットを作成します。 +``` +$ copilot storage init -n my-bucket -t S3 -w frontend +``` + +"frontend" Service にアタッチされた "my-table" という名前の基本的な DynamoDB テーブルを、ソートキーを指定して作成します。 +``` +$ copilot storage init -n my-table -t DynamoDB -w frontend --partition-key Email:S --sort-key UserId:N --no-lsi +``` + +複数の代替ソートキーを持つ DynamoDB テーブルを作成します。 +``` +$ copilot storage init \ + -n my-table -t DynamoDB -w frontend \ + --partition-key Email:S \ + --sort-key UserId:N \ + --lsi Points:N \ + --lsi Goodness:N +``` + +データベースエンジンに PostgreSQL を使用して、RDS Aurora Serverless クラスタを作成します。 +``` +$ copilot storage init \ + -n my-cluster -t Aurora -w frontend --engine PostgreSQL +``` + +## コマンド内部での動作 +Copilotは、S3 バケットや DDB テーブルを指定した CloudFormation テンプレートを `addons` ディレクトリに格納します。`copilot svc deploy` を実行すると、CLI はこのテンプレートを addons ディレクトリ内の他のすべてのテンプレートとマージして、Service に関連付けられたネストされた (入れ子になった) スタックを作成します。このネストされたスタックには、その Service に関連付けられたすべての追加リソースが記述されており、その Service がデプロイできる場所ではどこにでもデプロイ可能です。 + +これは、実行後に、 +``` +$ copilot storage init -n bucket -t S3 -w fe +$ copilot svc deploy -n fe -e test +$ copilot svc deploy -n fe -e prod +``` +2 つのバケットがデプロイされます。1 つは "test" Environment、もう 1 つは "prod" Environmentで、それぞれの "fe" Service からのみアクセスできます。 diff --git a/site/content/docs/commands/svc-delete.ja.md b/site/content/docs/commands/svc-delete.ja.md new file mode 100644 index 00000000000..b320e2edb1e --- /dev/null +++ b/site/content/docs/commands/svc-delete.ja.md @@ -0,0 +1,23 @@ +# svc delete +```bash +$ copilot svc delete [flags] +``` + +## コマンドの概要 + +`copilot svc delete` は、特定の Environment 内の Service に関連付けられたすべてのリソースを削除します。 + +## フラグ + +```bash + -e, --env string Name of the environment. + -h, --help help for delete + -n, --name string Name of the service. + --yes Skips confirmation prompt. +``` + +## 実行例 +"test" アプリケーションを全ての Environment から強制的に削除します。 +```bash +$ copilot svc delete --name test --yes +``` diff --git a/site/content/docs/commands/svc-deploy.ja.md b/site/content/docs/commands/svc-deploy.ja.md new file mode 100644 index 00000000000..c45dbbe9da5 --- /dev/null +++ b/site/content/docs/commands/svc-deploy.ja.md @@ -0,0 +1,27 @@ +# svc deploy +```bash +$ copilot svc deploy +``` + +## コマンドの概要 + +`copilot svc deploy` は、ローカルのコードや設定を元にデプロイします。 + +Service デプロイの手順は以下の通りです。 + +1. ローカルの Dockerfile をビルドしてコンテナイメージを作成 +2. `--tag` の値、または最新の git sha (git ディレクトリで作業している場合) を利用してタグ付け +3. コンテナイメージを ECR にプッシュ +4. Manifest ファイルとアドオンを CloudFormation にパッケージ +5. ECS タスク定義とサービスを作成 / 更新 + +## フラグ + +```bash + -e, --env string Name of the environment. + -h, --help help for deploy + -n, --name string Name of the service. + --resource-tags stringToString Optional. Labels with a key and value separated by commas. + Allows you to categorize resources. (default []) + --tag string Optional. The service's image tag. +``` diff --git a/site/content/docs/commands/svc-exec.ja.md b/site/content/docs/commands/svc-exec.ja.md new file mode 100644 index 00000000000..48d8c2f84cf --- /dev/null +++ b/site/content/docs/commands/svc-exec.ja.md @@ -0,0 +1,40 @@ +# svc exec +``` +$ copilot svc exec +``` + +## コマンドの概要 +`copilot svc exec` は、Service で実行中のコンテナに対してコマンドを実行します。 + +## フラグ +``` + -a, --app string Name of the application. + -c, --command string Optional. The command that is passed to a running container. (default "/bin/bash") + --container string Optional. The specific container you want to exec in. By default the first essential container will be used. + -e, --env string Name of the environment. + -h, --help help for exec + -n, --name string Name of the service, job, or task group. + --task-id string Optional. ID of the task you want to exec in. +``` + +## 実行例 + +"frontend" Service のタスクにインタラクティブなセッションを開始します。 + +```bash +$ copilot svc exec -a my-app -e test -n frontend +``` + +"backend" Service 内の ID "8c38184" から始まるタスクで 'ls' コマンドを実行します。 + +```bash +$ copilot svc exec -a my-app -e test --name backend --task-id 8c38184 --command "ls" +``` + +## 出力例 + + + +!!! info + 1. Service デプロイ前に Manifest で `exec: true` が設定されていることを確認してください。 + 2. これにより Service の Fargate Platform Version が 1.4.0 にアップデートされますのでご注意ください。プラットフォームバージョンをアップデートすると、[ECS サービスのリプレイス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html#cfn-ecs-service-platformversion)となり、サービスのダウンタイムが発生します。 diff --git a/site/content/docs/commands/svc-init.ja.md b/site/content/docs/commands/svc-init.ja.md new file mode 100644 index 00000000000..4b8bf6901ce --- /dev/null +++ b/site/content/docs/commands/svc-init.ja.md @@ -0,0 +1,38 @@ +# svc init +```bash +$ copilot svc init +``` + +## コマンドの概要 + +`copilot svc init` は、コードを実行するために新しい [Service](../concepts/services.ja.md) を作成します。 + +コマンドを実行すると、 CLI はローカルの `copilot` ディレクトリに Application 名のサブディレクトリを作成し、そこに [Manifest ファイル](../manifest/overview.ja.md)を作成します。自由に Manifest ファイルを更新し、Service のデフォルト設定を変更できます。また CLI は全ての [Environment](../concepts/environments.ja.md) からプル可能にするポリシーをもつ ECR リポジトリをセットアップします。 + +そして Service は CLI からトラックするため AWS System Manager Parameter Store に登録されます。 + +その後、既にセットアップされた Environment がある場合は copilot deploy を実行して Service をデプロイできます。 + +## フラグ + +```bash +Required Flags + -d, --dockerfile string Path to the Dockerfile. + -n, --name string Name of the service. + -t, --svc-type string Type of service to create. Must be one of: + "Load Balanced Web Service", "Backend Service" + +Load Balanced Web Service Flags + --port uint16 Optional. The port on which your service listens. + +Backend Service Flags + --port uint16 Optional. The port on which your service listens. +``` + +各 Service type には共通の必須フラグの他に、独自のオプションフラグと必須フラグがあります。"frontend" として Load Balanced Web Service を作成するには、次のように実行します。 + +`$ copilot svc init --name frontend --app-type "Load Balanced Web Service" --dockerfile ./frontend/Dockerfile` + +## 出力例 + +![Running copilot svc init](https://raw.githubusercontent.com/kohidave/copilot-demos/master/svc-init.svg?sanitize=true) diff --git a/site/content/docs/commands/svc-logs.ja.md b/site/content/docs/commands/svc-logs.ja.md new file mode 100644 index 00000000000..d55262e5e4d --- /dev/null +++ b/site/content/docs/commands/svc-logs.ja.md @@ -0,0 +1,47 @@ +# svc logs +```bash +$ copilot svc logs +``` + +## コマンドの概要 + +`copilot svc logs` はデプロイ済みの Service のログを表示します。 + +## フラグ + +```bash + -a, --app string Name of the application. + --end-time string Optional. Only return logs before a specific date (RFC3339). + Defaults to all logs. Only one of end-time / follow may be used. + -e, --env string Name of the environment. + --follow Optional. Specifies if the logs should be streamed. + -h, --help help for logs + --json Optional. Outputs in JSON format. + --limit int Optional. The maximum number of log events returned. (default 10) + -n, --name string Name of the service. + --since duration Optional. Only return logs newer than a relative duration like 5s, 2m, or 3h. + Defaults to all logs. Only one of start-time / since may be used. + --start-time string Optional. Only return logs after a specific date (RFC3339). + Defaults to all logs. Only one of start-time / since may be used. + --tasks strings Optional. Only return logs from specific task IDs. +``` + +## 実行例 + +"test" Environment の "my-svc" Service のログを表示します。 + +```bash +$ copilot svc logs -n my-svc -e test +``` + +過去 1 時間のログを表示します。 + +```bash +$ copilot svc logs --since 1h +``` + +2006-01-02T15:04:05 から 2006-01-02T15:05:05 までのログを表示します。 + +```bash +$ copilot svc logs --start-time 2006-01-02T15:04:05+00:00 --end-time 2006-01-02T15:05:05+00:00 +``` diff --git a/site/content/docs/commands/svc-ls.ja.md b/site/content/docs/commands/svc-ls.ja.md new file mode 100644 index 00000000000..b111e35f68c --- /dev/null +++ b/site/content/docs/commands/svc-ls.ja.md @@ -0,0 +1,21 @@ +# svc ls +```bash +$ copilot svc ls +``` + +## コマンドの概要 + +`copilot svc ls` は特定の Application のすべての Service を一覧表示します。 + +## フラグ + +```bash + -a, --app string Name of the application. + -h, --help help for ls + --json Optional. Outputs in JSON format. + --local Only show services in the workspace. +``` + +## 出力例 + +![Running copilot svc ls](https://raw.githubusercontent.com/kohidave/copilot-demos/master/svc-ls.svg?sanitize=true) diff --git a/site/content/docs/commands/svc-package.ja.md b/site/content/docs/commands/svc-package.ja.md new file mode 100644 index 00000000000..12cff41d6db --- /dev/null +++ b/site/content/docs/commands/svc-package.ja.md @@ -0,0 +1,28 @@ +# svc package +```bash +$ copilot svc package +``` + +## コマンドの概要 + +`copilot svc package` は任意の Environment に Service をデプロイする CloudFormation テンプレートを提供します。 + +## フラグ + +```bash + -e, --env string Name of the environment. + -h, --help help for package + -n, --name string Name of the service. + --output-dir string Optional. Writes the stack template and template configuration to a directory. + --tag string Optional. The service's image tag. +``` + +## 実行例 + +CloudFormaiton スタックと設定を表示する代わりに、"infrastructure/" サブディレクトリへ書き込みます。 + +```bash +$ copilot svc package -n frontend -e test --output-dir ./infrastructure +$ ls ./infrastructure +frontend.stack.yml frontend-test.config.yml +``` diff --git a/site/content/docs/commands/svc-show.ja.md b/site/content/docs/commands/svc-show.ja.md new file mode 100644 index 00000000000..c26b29a639c --- /dev/null +++ b/site/content/docs/commands/svc-show.ja.md @@ -0,0 +1,22 @@ +# svc show +```bash +$ copilot svc show +``` + +## コマンドの概要 + +`copilot svc show` はデプロイ済みの Service のエンドポイント、キャパシティ、Environment ごとの関連リソースなどの情報を表示します。 + +## フラグ + +```bash + -a, --app string Name of the application. + -h, --help help for show + --json Optional. Outputs in JSON format. + -n, --name string Name of the service. + --resources Optional. Show the resources in your service. +``` + +## 出力例 + +![Running copilot svc show](https://raw.githubusercontent.com/kohidave/copilot-demos/master/svc-show.svg?sanitize=true) diff --git a/site/content/docs/commands/svc-status.ja.md b/site/content/docs/commands/svc-status.ja.md new file mode 100644 index 00000000000..5a2f3ef6376 --- /dev/null +++ b/site/content/docs/commands/svc-status.ja.md @@ -0,0 +1,20 @@ +# svc status +``` +$ copilot svc status +``` + +## コマンドの概要 +`copilot svc status` はデプロイ済み Service のステータス、タスクのステータス、関連する CloudWatch アラームなどのヘルスステータスを表示します。 + +## What are the flags? +``` + -a, --app string Name of the application. + -e, --env string Name of the environment. + -h, --help help for status + --json Optional. Outputs in JSON format. + -n, --name string Name of the service. +``` + +## 出力例 + +![Running copilot svc status](https://raw.githubusercontent.com/kohidave/copilot-demos/master/svc-status.svg?sanitize=true) diff --git a/site/content/docs/commands/task-delete.ja.md b/site/content/docs/commands/task-delete.ja.md new file mode 100644 index 00000000000..127df398778 --- /dev/null +++ b/site/content/docs/commands/task-delete.ja.md @@ -0,0 +1,36 @@ +# task delete +``` +$ copilot task delete +``` + +## コマンドの概要 +`copilot task delete` はタスクを停止し、関連するリソースを削除します。 + +!!!info + v1.2.0 より前のバージョンの Copilot で作成されたタスクは `copilot task delete` で停止できません。v1.2.0 以前のバージョンで起動したタスクを使用しているお客様は、コマンド実行後に ECS コンソールを使用して手動でタスクを停止する必要があります。 + +## フラグ +``` + -a, --app string Name of the application. + --default Optional. Delete a task which was launched in the default cluster and subnets. + Cannot be specified with 'app' or 'env' + -e, --env string Name of the environment. + -h, --help help for delete + -n, --name string Name of the service. + --yes Optional. Skips confirmation prompt. +``` +## 実行例 +デフォルトのクラスターから、"test" タスクを削除します。 +``` +$ copilot task delete --name test --default +``` + +prod Environment から、"db-migrate" タスクを削除します。 +``` +$ copilot task delete --name db-migrate --env prod +``` + +確認のプロンプトを表示せずに、"test" タスクを削除します。 +``` +$ copilot task delete --name test --yes +``` diff --git a/site/content/docs/commands/task-exec.ja.md b/site/content/docs/commands/task-exec.ja.md new file mode 100644 index 00000000000..f99fc950299 --- /dev/null +++ b/site/content/docs/commands/task-exec.ja.md @@ -0,0 +1,70 @@ +# task exec +``` +$ copilot task exec +``` + +## コマンドの概要 +`copilot task exec` は実行中のタスク内のコンテナでコマンドを実行します。 + +## フラグ +``` + -a, --app string Name of the application. + -c, --command string Optional. The command that is passed to a running container. (default "/bin/bash") + --default Optional. Execute commands in running tasks in default cluster and default subnets. + Cannot be specified with 'app' or 'env'. + -e, --env string Name of the environment. + -h, --help help for exec + -n, --name string Name of the service, job, or task group. + --task-id string Optional. ID of the task you want to exec in. +``` + +## 実行例 + +現在のワークスペース配下の "test" Environment で、タスクグループ "db-migrate" 内のタスクへ対話型の bash セッションを開始します。 + +```bash +$ copilot task exec -e test -n db-migrate +``` + +タスクグループ "db-migrate" 内の、ID "1848c38" のプレフィックスを持つタスクで 'cat progress.csv' コマンドを実行します。 + +```bash +$ copilot task exec --name db-migrate --task-id 1848c38 --command "cat progress.csv" +``` + +デフォルトクラスター内で動作する、ID "38c3818" のプレフィックスを持つタスクへ対話型の bash セッションを開始します。 + +```bash +$ copilot task exec --default --task-id 38c3818 +``` + +!!! info + `copilot task exec` は特定のタスクロールの権限がないと実行できません。既存のタスクロールを使用してタスクを実行する場合、 `copilot task exec` を動作させるために必要な以下の権限が付与されていることを確認してください。 + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*", + "Effect": "Allow" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:PutLogEvents" + ], + "Resource": "*", + "Effect": "Allow" + } + ] +} +``` diff --git a/site/content/docs/commands/task-run.ja.md b/site/content/docs/commands/task-run.ja.md new file mode 100644 index 00000000000..2f643357dfb --- /dev/null +++ b/site/content/docs/commands/task-run.ja.md @@ -0,0 +1,82 @@ +# task run +``` +$ copilot task run +``` + +## コマンドの概要 +`copilot task run` はスタンドアロンタスクをデプロイ、実行します。 + +task run に関連する一般的な手順は次の通りです。 + +1. タスク用の ECR リポジトリとロググループの作成 +2. コンテナイメージのビルドと ECR へのプッシュ +3. タスク定義の作成、または更新 +4. タスクを実行し、開始されるのを待つ + +!!!info + 1. 同じグループ名のタスクは同じリソースセットを共有します。リソースセットには例えば CloudFormation スタック、ECR リポジトリ、CloudWatch ロググループ、タスク定義などが含まれます。 + 2. `--env` オプションを利用してタスクを特定の Environment にデプロイする場合、そのタスクはデプロイ先 Environment のパブリックサブネットのみを利用します + 3. `--default` フラグの利用時に「デフォルトのクラスターが存在しない」旨のエラーが発生した場合、AWS CLI で `aws ecs create-cluster` コマンドを実行してから再度 `copilot run task` コマンドを実行してください。 + +## フラグ +``` + --app string Optional. Name of the application. + Cannot be specified with 'default', 'subnets' or 'security-groups' + --cluster string Optional. The short name or full ARN of the cluster to run the task in. + --command string Optional. The command that is passed to "docker run" to override the default command. + --count int Optional. The number of tasks to set up. (default 1) + --cpu int Optional. The number of CPU units to reserve for each task. (default 256) + --default Optional. Run tasks in default cluster and default subnets. + Cannot be specified with 'app', 'env' or 'subnets'. + --dockerfile string Path to the Dockerfile. (default "Dockerfile") + --entrypoint string Optional. The entrypoint that is passed to "docker run" to override the default entrypoint. + --env string Optional. Name of the environment. + Cannot be specified with 'default', 'subnets' or 'security-groups' + --env-vars stringToString Optional. Environment variables specified by key=value separated by commas. (default []) + --execution-role string Optional. The role that grants the container agent permission to make AWS API calls. + --follow Optional. Specifies if the logs should be streamed. +-h, --help help for run + --image string Optional. The image to run instead of building a Dockerfile. + --memory int Optional. The amount of memory to reserve in MiB for each task. (default 512) + --resource-tags stringToString Optional. Labels with a key and value separated by commas. + Allows you to categorize resources. (default []) + --secrets stringToString Optional. Secrets to inject into the container. Specified by key=value separated by commas. (default []) + --security-groups strings Optional. The security group IDs for the task to use. Can be specified multiple times. + Cannot be specified with 'app' or 'env'. + --subnets strings Optional. The subnet IDs for the task to use. Can be specified multiple times. + Cannot be specified with 'app', 'env' or 'default'. + --tag string Optional. The container image tag in addition to "latest". +-n, --task-group-name string Optional. The group name of the task. Tasks with the same group name share the same set of resources. + --task-role string Optional. The role for the task to use. +``` +## 実行例 +ローカルの Dockerfile を使用してタスクを実行し、タスクの実行後はログストリームを表示します。 +コマンド実行後には質問が表示されますので、タスクを実行する Environment を指定します。 +``` +$ copilot task run --follow +``` + +現在のワークスペース配下の "test" Environment で、"db-migrate" という名前のタスクを実行します。 +``` +$ copilot task run -n db-migrate --env test --follow +``` + +2GB のメモリ、既存のイメージ、およびカスタムタスクロールを使用して 4 つのタスクを実行します。 +``` +$ copilot task run --num 4 --memory 2048 --image=rds-migrate --task-role migrate-role --follow +``` + +環境変数を使用してタスクを実行します。 +``` +$ copilot task run --env-vars name=myName,user=myUser +``` + +指定したサブネットとセキュリティグループを使用して、現在のワークスペース配下でタスクを実行します。 +``` +$ copilot task run --subnets subnet-123,subnet-456 --security-groups sg-123,sg-456 +``` + +コマンドを指定してタスクを実行します。 +``` +$ copilot task run --command "python migrate-script.py" +``` diff --git a/site/content/docs/commands/version.ja.md b/site/content/docs/commands/version.ja.md new file mode 100644 index 00000000000..e7a506c6263 --- /dev/null +++ b/site/content/docs/commands/version.ja.md @@ -0,0 +1,12 @@ +# version +``` +$ copilot version [flags] +``` + +## コマンドの概要 +`copilot version` Copilot CLI のバージョンと、ビルドのターゲットオペレーティングシステムを表示します。 + +## フラグ +```bash +-h, --help help for version +``` diff --git a/site/content/docs/concepts/applications.ja.md b/site/content/docs/concepts/applications.ja.md new file mode 100644 index 00000000000..d3dc7a0bb3c --- /dev/null +++ b/site/content/docs/concepts/applications.ja.md @@ -0,0 +1,97 @@ +# Application + +Application は、Service、Environment、Pipeline といった概念を取りまとめる概念です。あなたのアプリケーションがサービス1つですべてのことをやる +ものであるか、マイクロサービスの集まりであるかに関係なく、sCopilot はそれらとそのデプロイ先の Environment を1つの Application として取りまとめます。 + +例を見ていきましょう。ここでは投票を受け付け、結果を集計する投票アプリを構築しようとしているとします。 + +投票の受け付けと結果の集計という2つのサービスを持つ投票アプリは、`copilot init` コマンド2回で構築できます。まず最初に `copilot init` を実行すると、この Service が所属することになる Application の名前を質問されます。ここでは投票システムを構築しようとしていますので、Application を "vote" 、そして投票を受け付ける Service を "collector" と名付けることにしましょう。2回目の `init` では、既存の "vote" Application に新しい Service を追加するために、今度は Service 名のみを質問されます。こちらは集計するサービスですので "aggregator" と名付けることにしましょう。 + +あなたの Application 設定(ここに複数の Service や Environment が所属します)は、AWS アカウントの中に保存されますので、あなた以外の開発者も "vote" アプリの開発に参加できます。これにより、例えばあなたが1つの Service 開発に取り組む一方で、チームメイトは別の Service 開発を進めることができます。 + +![](https://user-images.githubusercontent.com/879348/85869625-cd858d00-b780-11ea-817c-638814049d2d.png) + +## Application の作成 + +Application のセットアップは、`copilot init` コマンドで行えます。コマンドを実行すると、新しい Application をセットアップするか、あるいは既存の Application を利用するかを質問されます。 + +```bash +copilot init +``` + +Application を作成すると、Copilot はその情報をあなたの AWS アカウント内の SSM パラメータストアに保存します。Application のセットアップに利用した AWS アカウントを「Application アカウント」と呼び、このアカウントにアクセスできる人であれば誰でもその Application の開発に参加できます。 + +Application の配下に作られる AWS リソースには `copilot-app` という [AWS リソースタグ](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_tagging.html) が付与されます。これにより、各リソースがどの Application に所属しているのかを知りやすくなります。 + +Application の名前はその AWS アカウント内の全てのリージョンにおいて一意である必要があります。 + +### 追加の Application 設定 +`copilot app init` コマンドを利用することでより細かい設定を実施できます。例えば次のようなオプションを設定できます。 + +* Application、Service、Environment にて作成される AWS リソースに対する [AWS リソースタグ](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_tagging.html) を利用した追加のタグ付け +* "Load Balanced Web Service" アーキテクチャ利用時のカスタムドメイン名設定 + +```bash +$ copilot app init \ + --domain my-awesome-app.aws \ + --resource-tags department=MyDept,team=MyTeam +``` + +## インフラストラクチャ + +Copilot が作成するインフラストラクチャリソースのほとんどは特定の Environment や Service に属しますが、Application 全体にまたがって利用するリソースもいくつかあります。 + +![](https://user-images.githubusercontent.com/879348/85869637-d0807d80-b780-11ea-8359-6d75933c562a.png) + +### ECR リポジトリ + +Service で利用するコンテナイメージを格納する ECR リポジトリはリージョン別に作成されます。Application 内の各 Service はそれぞれ専用の ECR リポジトリをリージョンごとに持ちます。 + +上図では、ある Application が3つのリージョンにそれぞれ Environment を持っていることを示しています。各リージョンには Application 内の Service と同数の ECR リポジトリが作られることになります。この図においては ECR リポジトリが1リージョン内に3つありますので、Service も3つあることが分かります。 + +新たな Service を追加すると、Copilot は利用対象の各リージョンに ECR リポジトリを作成します。これはあるリージョンでの障害発生が別リージョンで動作するアプリケーションに影響を与えないようにすることと、あるいはリージョンを跨いだイメージダウンロードによるデータ転送料金の発生を避けることを目的としています。 + +これらの ECR リポジトリは Environment が作成された AWS アカウントではなく、「Application アカウント」に作成されます。あわせて、各 Environment 用 AWS アカウントからのイメージ pull を許可する IAM ポリシーも設定されます。 + +### インフラストラクチャのリリース + +Copilot は Application 内で利用している全てのリージョンに KMS キーと S3 バケットを作成します。これらのリソースは CodePipeline がリージョン跨ぎ、あるいは AWS アカウント跨ぎのデプロイを行うために利用されます。Application 内の全ての Pipeline はこれらのリソースを共有します。 + +ECR リポジトリ同様、これらの S3 バケットと KMS キーは同一 AWS アカウント内、あるいは別 AWS アカウント内の各 Environment から暗号化されたデプロイアーティファクトを読むことを許可する IAM ポリシーが設定されています。これにより、CodePipeline がリージョン、アカウントを跨いでデプロイできるようになっています。 + +## Application の中身を掘り下げてみよう + +Application のセットアップが完了したので、Copilot を使って確認してみましょう。確認の手段として以下のような方法がよく利用されます。 + +### アカウント内に作成された Application の一覧を確認したい + +現在のアカウント・リージョン内にある全ての Application を確認するには `copilot app ls` コマンドを利用します。 + +```bash +$ copilot app ls +vote +ecs-kudos +``` + +### Application に含まれるものを確認したい + +`copilot app show` コマンドを実行すると、Application 内の Service や Environment を含んだサマリ情報を表示します。 + +```bash +$ copilot app show +About + + Name vote + URI vote-app.aws + +Environments + + Name AccountID Region + test 000000000000 us-east-1 + +Services + + Name Type + collector Load Balanced Web Service + aggregator Backend Service +``` diff --git a/site/content/docs/concepts/environments.ja.md b/site/content/docs/concepts/environments.ja.md new file mode 100644 index 00000000000..65b0d91205b --- /dev/null +++ b/site/content/docs/concepts/environments.ja.md @@ -0,0 +1,88 @@ +# Environment + +はじめて `copilot init` コマンドを実行すると、あわせて _test_ Environment を作成するかを尋ねられます。この _test_ Environment にはセキュアなネットワーク(e.g. VPC、サブネット、セキュリティグループ)を作成するために必要な AWS リソースや、複数の Service での共有を目的とした Application Load Balancer や ECS クラスタのようなリソースも含まれます。Service をこの _test_ Environment にデプロイすると、この Service は _test_ Environment のネットワークやリソースを利用します。Application は複数の Environment を持つことができ、それぞれが互いに独立したネットワークやその他のインフラストラクチャリソースを持ちます。 + +あなたの Copilot の利用開始にあわせて Copilot は _test_ Environment (テスト環境)を作成しますが、これとは異なる Environment、例えば _production_ Environment (本番環境)を新たに作るというのはごく一般的なことでしょう。この _production_ Environment は _test_ Environment とは完全に独立したもので、_production_ Environment 用のネットワークスタックやそこにデプロイされる Service を持ちます。独立したテスト環境と本番環境を持つことで、まずはテスト環境にデプロイし、問題ないことを確認した上で本番環境にデプロイするというオペレーションが可能になります。 + +下に載せた図は、_API_ と _Backend_ という2つの Service を持つ _MyApp_ という Application を表しています。これら2つの Service は _test_ と _production_ という2つの Environment にデプロイされています。_test_ Environment では両方の Service が1つのコンテナを実行している一方で、_production_ Environment ではそれぞれが3つのコンテナを実行しているのが分かるでしょうか。このように、Service はデプロイ先の Environment ごとに異なる設定を持つことができます。詳しくは[環境変数の利用ガイド](../developing/environment-variables.ja.md)もご覧ください。 + +![](https://user-images.githubusercontent.com/879348/85873795-7da9c480-b786-11ea-9990-9604a3cc5f01.png) + +## Environment の作成 + +Application 内に新しい Environment を作るには、作業ディレクトリにて `copilot env init` コマンドを実行します。コマンドを実行すると、作成する Environment の名前、そしてこの Environment の作成に利用する AWS プロファイルを Copilot が尋ねます。このプロファイルは AWS [名前付きプロファイル](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html)と呼ばれるもので、特定の AWS アカウントやリージョンと紐づいた設定です。プロファイルを選ぶと、その新しい Environment は選択されたプロファイルと紐づいた AWS アカウントとリージョンに作成されます。 + + +```bash +$ copilot env init +``` + +`copilot env init` コマンドの実行後は、Copilot が数分間に渡って Environment 内のリソースをセットアップしていく様子を確認できます。すべてのリソースが作成されると、この Environment は Application アカウントにリンクされます。これにより、今後 Copilot コマンドを実行するユーザーがこの Environment アカウントそのものにアクセスができなくとも Application にリンクされた Environment として管理できるようになります。このリンク処理の中では、必要に応じて ECR リポジトリの作成と設定も行われます。 + +### Service のデプロイ + +新しい Environment を作った時点ではまだデプロイされた Service はありません。デプロイしたい Service のディレクトリから `copilot deploy` コマンドを実行すると、どの Environment にデプロイしたいのかを尋ねられます。 + +## Environment インフラストラクチャ + +![](https://user-images.githubusercontent.com/879348/85873802-800c1e80-b786-11ea-8b2c-779b01abbaf4.png) + + +### VPC やネットワークリソース + +各 Environment はそれぞれがマルチ AZ 構成の VPC を持ちます。VPC は Environment のネットワーク上の境界であり、VPC 内に入ってくるあるいは出ていくトラフィックを許可する、またはブロックするものとして機能します。Copilot は VPC を2つのアベイラビリティゾーンにまたがって作成するため、可用性とコストのバランス確保に役立ちます。各 AZ にはパブリックとプライベートのサブネットが1つずつ作成されます。 + +Service はパブリックサブネットで実行されますが、ロードバランサーを経由したトラフィックのみを受け取ることができます。 + +### ロードバランサーと DNS + +"Load Balanced Web Service" タイプの Service を作ると、Copilot は Application Load Balancer を作成します。同一 Environment 内にデプロイされたすべての "Load Balanced Web Service" タイプの Service は、Service 固有のリスナーを作成してこのロードバランサーを共有します。ロードバランサーは VPC 内の各 Service と通信できるようにセットアップされます。 + +所有するドメイン名を Route 53 に登録するよう、Application 作成時にオプションとして設定できます。ドメイン名の利用が設定されている場合、Copilot は各 Environment の作成時に `environment-name.app-name.your-domain.com` のような形でサブドメインを登録し、ACM を通して発行した証明書を Application Load Balancer に設定します。これにより Service が HTTPS を利用できるようになります。 + +## Environment のカスタマイズ + +既存リソースをインポートするためにコマンドのフラグを利用して Environment をインタラクティブにカスタマイズしたり、あるいはデフォルトの Environment リソースを変更したりできます。現時点では VPC リソースのみがカスタマイズ可能です。他のリソースをカスタマイズしたいというリクエストがある場合、お気軽にユースケースを添えた GitHub イシューを作成してくださいね! + +## Environment の中身を掘り下げてみよう + +Environment のセットアップが完了したので、Copilot を使って確認してみましょう。確認の手段として以下のような方法がよく利用されます。 + +### Application 内にある Environment の一覧を確認したい + +Application 内にある全ての Environment を確認するには `copilot env ls` コマンドを利用します。 + +```bash +$ copilot env ls +test +production +``` + +### Environment に含まれるものを確認したい + +`copilot env show` コマンドを実行すると、Environment のサマリ情報を表示します。以下は _test_ Environment についての情報を確認する出力の例ですが、この Environment が作成されたアカウントやリージョン情報、あるいはデプロイされた Service や Environment 内のリソースに付与されるリソースタグ情報などが含まれます。さらに、`--resources` フラグを利用することでこの Environment に紐づけられたすべての AWS リソースを確認できます。 + +```bash +$ copilot env show --name test +About + + Name test + Production false + Region us-west-2 + Account ID 693652174720 + +Services + + Name Type + ---- ---- + api Load Balanced Web Service + backend Backend Service + + +Tags + + Key Value + --- ----- + copilot-application my-app + copilot-environment test +``` diff --git a/site/content/docs/concepts/jobs.ja.md b/site/content/docs/concepts/jobs.ja.md new file mode 100644 index 00000000000..512a1f83782 --- /dev/null +++ b/site/content/docs/concepts/jobs.ja.md @@ -0,0 +1,37 @@ +# Job + +Job はイベントによって起動される Amazon ECS タスクを表す概念です。Copilot は現時点では "Scheduled Jobs" (スケジュール実行される Job)のみをサポートしています。固定スケジュールで、あるいは間隔を指定して一定時間ごとに実行できます。 + +## Job の作成 + +Job を作成するもっとも簡単な方法は Dockerfile が置かれたディレクトリで `init` コマンドを実行することです。 + +```bash +$ copilot init +``` + +Job のどの Application に所属させるかを選択すると、Copilot は作成したい Job の __タイプ__ を尋ねます。現時点で指定可能なタイプは "Scheduled Job" のみです。 + +## Manifest と設定 + +`copilot init` コマンドの実行が完了すると、`manifest.yml` というファイルが作成されます。[Scheduled Job の Manifest](../manifest/scheduled-job.ja.md) はシンプルな宣言的ファイルで、スケジュール実行されるタスクの一般的な共通設定が含まれています。例えば、いつ Job を実行したいのか、割り当てるリソースサイズ、処理のタイムアウト時間や失敗時に何回までリトライを試みるかといったことを設定できます。 + +## Job のデプロイ + +要件を満たすように Manifest ファイルを編集したら、deploy コマンドを使ってそれらの変更をデプロイできます。 + +```bash +$ copilot deploy +``` + +このコマンドを実行すると、続けて以下のような作業が実施されます。 + +1. ローカル環境でのコンテナイメージのビルド +2. Job 用の ECR リポジトリへのプッシュ +3. Manifest ファイルの CloudFormation テンプレートへの変換 +4. 追加インフラストラクチャがある場合、それらの CloudFormation テンプレートへのパッケージング +5. デプロイ + +### Job に含まれるものを確認したい + +Copilot では内部的に CloudFormation を利用しているため、作成されるすべてのリソースは Copilot によってタグ付けされています。"Scheduled Jobs" には、Amazon ECS タスク定義、タスクロール、タスク実行ロール、タスクの処理が失敗した際にリトライを可能にする Step Functions ステートマシン、そしてステートマシンを実行する EventBridge ルールといったものが含まれます。 diff --git a/site/content/docs/concepts/overview.ja.md b/site/content/docs/concepts/overview.ja.md new file mode 100644 index 00000000000..dfc2617b30a --- /dev/null +++ b/site/content/docs/concepts/overview.ja.md @@ -0,0 +1,31 @@ +# コンセプト + +Copilot を利用すると、簡単にコンテナを AWS 上にセットアップ、デプロイできます。しかし、"Getting Started" セクションで見てきたことは、その旅路の最初のステップでしかありません。同じアプリケーションを1つはテスト環境で、もう1つは本番環境で実行したい場合はどうすればよいでしょうか?新しいサービスを追加したい場合は?追加したサービスも含めたすべてのサービスのデプロイをどのように管理しますか?ここからは Copilot のコアコンセプトの世界に飛び込み、Copilot がどのようにしてこれらのことを手助けしてくれるのか理解していきましょう。 + +## [Application](./applications.ja.md) + +Application は Service と Environment(後述)を包括する概念です。Copilot をこれから使い始めようというとき、あなたが最初に行うことが Application の命名です。Application の名前はあなたが作ろうとしているプロダクトのハイレベルな概要と言えるでしょう。_"frontend"_ と _"api"_ という2つの Service を持つ _"chat"_ という名前の Application、のような例が挙げられますね。例として挙げた _"frontend"_ と _"api"_ の2つの Service は、例えば _"test"_ と _"production"_ という Environment にデプロイされるかもしれません。 + + +## [Environment](./environments.ja.md) + +噂によると、バグのない完璧なコードを最初から書くことができる人というのが世の中にはいるそうです。そのような方々には脱帽しますが、私たちは新しいコードを本番環境へのデプロイよりも前に顧客向けではない場所でテストできることが重要だと考えています。Copilot の世界では、私たちは _Environment_ +を使ってこれを実現します。各 Environment ではそれぞれ異なるバージョンのサービスを実行できるため、テスト環境や本番環境といったものを作れます。テスト環境にサービスをデプロイし、全てが問題ないことを確認したら本番環境にデプロイする、といった流れです。各 Environment は互いに独立しているため、たとえバグをテスト環境に混入させたとしても本番環境を利用しているお客様にとってはなんの影響もありません。 + +ここまでは単一のサービスについて話をしてきましたが、もしあなたがさらにもう1つサービスを追加したくなったとしたらどうでしょう?ここではすでにあるフロントエンドサービスから利用するバックエンドサービスを足すシチュエーションを想像してみましょう。各 Environment には、デプロイされた全てのサービスで共有するリソース群、例えばネットワーク(VPC、サブネット、セキュリティグループなど)、ECS クラスタ、ロードバランサのようなものが含まれます。仮にあなたがフロントエンドとバックエンドサービスの両方を同一の Environment にデプロイすると、それらのサービスは同一のネットワークや ECS クラスタを利用することになります。 + +## [Service](./services.ja.md) + +Copilot における Service は、AWS 上で実行したいあなたのコードとそれに必要なインフラストラクチャリソースを指す概念です。Copilot であなたが Service をセットアップしようとすると、Copilot はどのような「タイプ」の Service を作りたいのかをあなたに尋ねます。この Service の「タイプ」は、あなたのコードを実行するために作成されるインフラストラクチャを決定する要素となります。仮にあなたがインターネット越しのリクエストを受け付けるコードを実行したいと考えているのであれば、Copilot は Application Load Balancer と AWS Fargate を利用する Amazon ECS サービスを作成します。 + +どのようなタイプのサービスを作っているのかを Copilot に教えると、Copilot はあなたのコードに含まれる Dockerfile からコンテナイメージを作成し、それを Amazon ECR リポジトリへセキュアに格納します。Copilot はそれと同時にあなたの Service の設定情報を格納した _Manifest_ と呼ばれるシンプルなファイルを作成します。Service に割り当てたいメモリや CPU の量、あるいは Service をいくつ並列で実行したいのかといったような設定もここに含まれます。 + +## [Job](./jobs.ja.md) + +Job は、イベントによって起動されるエフェメラルな Amazon ECS タスクを指す概念です。Job の作業が完了するとそのタスクは削除されます。Service 同様、Copilot はスケジュールされたタスクをクイックな作成に必要な情報をあなたに質問します。Manifest ファイルを用意することで任意の、あるいはより高度な設定も可能です。 + +## [Pipeline](./pipelines.ja.md) + +ここまでの概念で、いくつかの Environment にデプロイされた複数の Service を持つ Application を手に入れましたが、このような複数の概念を維持しつつデプロイを行っていくのは大変な作業になりがちです。そこで Copilot では、あなたが Git リポジトリ(現時点では GitHub、BitBucket、CodeCommit をサポート)にコードの変更をプッシュしたら Service をデプロイしてくれるリリースパイプラインをセットアップできます。これが Pipeline という概念です。コードのプッシュが検知されると、Pipeline は Service をビルド、コンテナイメージを ECR にプッシュし、Environment にデプロイします。 + +パイプラインのセットアップとしてよくみられるパターンの1つは、テスト環境にデプロイしたサービスに対して自動テストを実行してから本番環境にデプロイする、というものです。 diff --git a/site/content/docs/concepts/pipelines.ja.md b/site/content/docs/concepts/pipelines.ja.md new file mode 100644 index 00000000000..50c668c48b6 --- /dev/null +++ b/site/content/docs/concepts/pipelines.ja.md @@ -0,0 +1,156 @@ +# Pipeline + +自動化されたリリースプロセスを持つことはソフトウェアデリバリの重要な観点の1つです。Copilot はこれらのセットアップを可能な限り簡単にすることを追求しています 🚀 + + +このセクションでは GitHub、Bitbucket、CodeCommit リポジトリにコードの変更がプッシュされた際に自動的なビルドを実行し、Environment へのデプロイと自動テストを実行する CodePipeline を Copilot を使ってセットアップする例を見ていきます。 + + +## Why? + + +ソフトウェアリリースについての哲学的すぎる話はしませんが、果たしてリリースパイプラインを持つ意味とはなんでしょうか?`copilot deploy` コマンドを使えば手元のコンピューターから ECS へ直接デプロイできるのに、なぜわざわざ仲介する仕組みを挟むのでしょうか?良い質問です。あるアプリケーションにとっては、手動での `deploy` で十分なこともあるでしょう。一方で、例えば複数の Environment やあるいは自動テストが追加されていきリリースパイプラインが複雑化してくると、その退屈な作業を何らかの仕組みにオフロードしたくなるでしょう。2つの Service が2つの(例えばテスト環境と本番環境のような) Environment 内にそれぞれあるとして、それらに対してテスト環境へのデプロイ後のインテグレーションテストを手で実施することは驚くほどに面倒な作業になります。 + + +CodePipeline のような自動化されたリリースツールは、あなたのリリース作業を管理可能なものにする手助けをしてくれます。たとえリリース作業自体がそれほど複雑なものではなかったとしても、`git push` さえすれば変更を自動的にデプロイできる体験は、ちょっとした魔法のように感じますよね 🌈 + + +## Pipeline の構成 + +Copilot はいくつかのコマンドで CodePipeline をセットアップします。作業を始める前に、まずは最終的に作成される Pipeline の構成を見ていきましょう。Pipeline は次に挙げる基本的な構造を持っています。 + +1. __Source Stage__ - 設定した GitHub、Bitbucket、あるいは CodeCommit リポジトリにプッシュすると、Pipeline の実行が開始されます。 +2. __Build Stage__ - リポジトリからコードがダウンロードされると、Service 用のコンテナイメージがビルドされ、すべての Environment の Amazon ECR リポジトリにプッシュされます。 +3. __Deploy Stages__ - ビルドが終わると、一部あるいはすべての Environment にデプロイできます。オプションとしてデプロイ完了後のテスト実行やデプロイ実行に手動承認を挟むことが可能です。 + +Copiot を使って CodePipeline のセットアップを済ませたら、あとは GitHub、Bitbucket、あるいは CodeCommit リポジトリにプッシュするだけです。あとは CodePipeline がデプロイまでのプロセスを実行してくれます。 + +CodePipeline についてより深く学びたい場合は、[CodePipeline のドキュメント](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/welcome-introducing.html)も参考にしてください。 + +## 3ステップで作る Pipeline +Pipeline の作成に必要な手順は3つです。 + +1. 最初に Pipeline の作成準備と設定を実施します。 +2. 次に、`copilot/` ディレクトリ以下に作成されたファイルをコミットして、リモート Git リポジトリにプッシュします。 +3. 最後にクラウド上へ Pipeline を作成して完了です! + +ワークスペースのルートで以下の3コマンドを実行してみましょう。 + +```bash +$ copilot pipeline init +$ git add copilot/pipeline.yml copilot/buildspec.yml copilot/.workspace && git commit -m "Adding pipeline artifacts" && git push +$ copilot pipeline update +``` + +✨ Application アカウントに新しい Pipeline が作成されたはずです!何が起きているのか、もう少し深く知りたいですよね?読み進めましょう! + +## ステップ・バイ・ステップで見る Pipeline のセットアップ + +### ステップ1: Pipeline の設定 + +Pipeline の設定はワークスペースのレベルで作成されます。もしワークスペース内にある Service が1つの場合、Pipeline はその Service についてのみ実行されます。もしワークスペース内に複数の Service がある場合、Pipeline はそれら全てをビルドします。Pipeline のセットアップを始めるには、Service (あるいは Service 群)があるワークスペースのディレクトリに `cd` コマンドなどで入り、次のコマンドを実行します。 + + `copilot pipeline init` + +このコマンドの実行ではまだクラウド上の Pipeline は作成しませんが、Pipeline 作成に必要ないくつかのファイルをローカル環境に作成します。 + +* __Release order__: デプロイ先の Environment (複数可)を尋ねられます - どの Environment からデプロイを実施したいか、その順番にあわせて Environment を選択しましょう。(複数の Environment に対して同時にデプロイを実行することはありません)。最初に _test_ Environment へデプロイし、その後 _prod_ Environment へデプロイする、といった設定がよくある順番でしょう。 + +* __Tracking repository__: デプロイ先の Environment を選択すると、次にどの Git リポジトリを CodePipeline からトラックしたいかを尋ねられます。ここで選ぶリポジトリへのプッシュが、CodePipeline の Pipeline をトリガーするリポジトリとなります。(設定したい対象のリポジトリがここでリストに表示されない場合、 `--url` フラグで明示的に Git リポジトリの URL を渡すこともできます。) + +### ステップ2: Pipeline 用 Manifest ファイルの更新 (オプション) + +Service がシンプルな Manifest ファイルを持つのと同様に、Pipeline にも Manifest があります。`pipeline init` コマンドの実行が完了すると、`copilot/` ディレクトリ内に `pipeline.yml` と `buildspec.yml` という2つのファイルが作成されます。`pipeline.yml` の中は次のような感じになっているはずです (ここでは "api-frontend" という Service が "test" と "prod" の2つの Environment にデプロイされるものと仮定しましょう) + +```yaml +# この YAML ファイルでは Environment の関係とデプロイ順序を定義します + +# Pipeline 名 +name: pipeline-ecs-kudos-kohidave-demo-api-frontend + +# このテンプレートで利用されているスキーマバージョン +version: 1 + +# このセクションでは Pipeline の実行をトリガーするソースを定義します +source: + # ソースコードのプロバイダ名を記述します + provider: GitHub + # ソースが格納されている具体的な場所を指定する追加のプロパティです + # 例えば GitHub プロバイダには repository と branch というプロパティがあります + properties: + branch: main + repository: https://github.com/kohidave/demo-api-frontend + # オプション: 既存の CodeStar Connections で作成された接続名を利用することも可能です + # connection_name: a-connection + +# このセクションでは各 Environment のデプロイ順序を定義します +stages: + - # デプロイ先の Environment 名 + name: test + test_commands: + - make test + - echo "woo! Tests passed" + - # デプロイ先の Environment 名 + name: prod + # requires_approval: true +``` + +このファイルには大きく3つのパーツがあります。最初の `name` フィールドは CodePipeline に作成されるパイプライの名称です。そして `source` セクションは Pipeline がトラックするソースリポジトリとそのブランチといった詳細を定義し、最後の `stages` セクションでは、どの Environment に対してこの Pipeline でデプロイを行いたいか定義します。この設定ファイルはいつでも変更可能ですが、変更後は Git リポジトリへのコミットとプッシュ、その後 `copilot pipeline update` コマンドを実行する必要があります。 + +よくあるケースとしては、新たなデプロイ先の Environment を増やしたいときや、Pipeline がトラックするブランチを変更したい際にこのファイルを更新することになるでしょう。あるいはもしすでに CodeStar Connections に接続済みのリポジトリがあり、Copilot で新たに作成するのではなく既存のものを利用したい場合には、その接続名を記述することになります。また、Pipeline Manifest はデプロイの手動承認を設定したり、デプロイ後に自動テストを実行したりしたい場合の設定を記述する場所でもあります。(本ページ下部の "テストの追加" もご覧ください) + +### ステップ3: Buildspec ファイルの更新 (オプション) + +`pipeline init` コマンドでは、`pipeline.yml` と一緒に `buildspec.yml` も `copilot/` ディレクトリ内に作成されます。この `buldspec.yml` にはビルドとコンテナイメージのプッシュに関する指示が記述されています。もし `docker build` と一緒にユニットテストやスタイルチェックのような追加のコマンドを実行したい場合は、buildspec の `build` フェーズにそれらのコマンドを追加してください。 + +実際にこの buildspec が実行される際には、後方互換性の観点から `pipeline init` コマンドの実行に利用したバージョンの Copilot バイナリがダウンロードされ、利用されます。 + +### ステップ4: リポジトリに生成されたファイルをプッシュする + +`pipeline.yml`、`buildspec.yml`、そして `.workspace` ファイルが作成されたので、これらをリポジトリに追加しましょう。`copilot/` ディレクトリ以下に含まれたこれらのファイルが、Pipeline が `build` ステージを正しく実行するために必要となります。 + +### ステップ5: Pipeline の作成 + +ここからが楽しいパートです!次のコマンドを実行しましょう! + +`copilot pipeline update` + +このコマンドはあなたの `pipeline.yml` を解析し、Application と同じアカウントとリージョンの CodePipeline に Pipeline を作成し、Pipeline を実行します。AWS マネジメントコンソールにログイン、あるいは `copilot pipeline status` コマンドで Pipeline の実行状況を確認できます。 + +![処理が完了した CodePipeline の様子](https://user-images.githubusercontent.com/828419/71861318-c7083980-30aa-11ea-80bb-4bea25bf5d04.png) + + +!!! info + + もしあなたが GitHub あるいは Bitbucket リポジトリを利用する場合、Copilot は [CodeStar Connections](https://docs.aws.amazon.com/ja_jp/dtconsole/latest/userguide/welcome-connections.html) を利用してリポジトリとの接続を作成する手助けをします。この過程で GitHub や Bitbucket のアカウントに AWS がアクセスするための認証アプリケーションをインストールする必要があります (e.g. GitHub の場合、"AWS Connector for GitHub")。Copilot と AWS マネジメントコンソールのガイダンスにしたがってこのステップを進めてください。 + +## テストの追加 + +パイプラインの重要な要素の1つはもちろんですが自動化されたテストの実行です。デプロイステージの後に実行されるインテグレーションテストや E2E テストのようなものを追加するには、それらのテストを実行するコマンドを `test_commands` セクションに記述します。すべてのテストが成功すると、次のステージへと進みます。 + +`test_commands` を追加すると、[aws/codebuild/amazonlinux2-x86_64-standard:3.0](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-available.html) イメージを利用する CodeBuild プロジェクトが生成されます。例えば `make` のようなコマンドをはじめとして、Amazon Linux 2 で利用可能な多くのコマンドを利用できます。 + +テストの実行を Docker コンテナの中で実行するように設定していますか?Copilot では CodeBuild プロジェクトの Docker サポートを利用できますので、`docker build` コマンドも同様に利用可能です。 + +以下の例では、Pipeline は `make test` コマンドをソースコードディレクトリにて実行し、コマンドが正常に終了した場合のみ prod ステージに進みます。 + +```yaml +name: pipeline-ecs-kudos-kohidave-demo-api-frontend +version: 1 +source: + provider: GitHub + properties: + branch: main + repository: https://github.com/kohidave/demo-api-frontend + +stages: + - + name: test + # make test コマンドと echo コマンドが正常に終了した場合のみ + # prod ステージに進みます + test_commands: + - make test + - echo "woo! Tests passed" + - + name: prod +``` diff --git a/site/content/docs/concepts/services.ja.md b/site/content/docs/concepts/services.ja.md new file mode 100644 index 00000000000..63e70e1f8a0 --- /dev/null +++ b/site/content/docs/concepts/services.ja.md @@ -0,0 +1,177 @@ +コンテナの素晴らしい特徴の1つは、コードを書き終わったらそれを簡単に `docker run` コマンドでローカル環境にて実行できることです。Copilot は、`copilot init` コマンドでこのコンテナの AWS 上での容易な実行を可能にします。コンテナイメージをビルド、Amazon ECR へのプッシュ、サービスのスケーラブルかつセキュアな実行に必要なインフラストラクチャのセットアップという一連の流れが Copilot によって簡単に実現できます。 + +## Service の作成 + +Service を作成して AWS 上でコンテナを実行するための方法は複数あります。もっとも簡単な方法は、Dockerfile が置かれたディレクトリで `init` コマンドを実行することです。 + +```bash +$ copilot init +``` + +このコマンドを実行すると、これから作る Service をどの Application に所属させたいかを尋ねられます。Application が存在しない場合は新規での作成を促されます。その後、Copilot はあなたが作ろうとしている Service の __タイプ__ を尋ねます。 + +Service のタイプを選択すると、Copilot は Dockerfile 内で記述されたヘルスチェックや開放するポート番号を検知し、そのままデプロイするかどうかをあなたに確認します。 + +## Service タイプの選択 + +ここに辿り着くまでの間に、「Copilot は Service の実行に必要なインフラストラクチャリソースを自動的にセットアップする」といった説明をしてきました。では、Copilot はどのようにして必要なインフラストラクチャが何かを知るのでしょうか? + +その秘密は、Service の作成時に Copilot が Service の __タイプ__ を尋ねていることにあります。 + +### Load Balanced Web Service + +Service でインターネット側からのリクエストを捌きたいですか?__Load Balanced Web Service__ を選べば、Copilot は Application Load Balancer やセキュリティグループ、そしてあなたの Service を Fargate で実行するための ECS サービスを作成します。 + +![lb-web-service-infra](https://user-images.githubusercontent.com/879348/86045951-39762880-ba01-11ea-9a47-fc9278600154.png) + +### Backend Service + +VPC 外部からアクセスさせる必要はないが、Application 内の他の Service からはアクセスできる必要があるという場合は、 __Backend Service__ を +作りましょう。Copilot は AWS Fargate で実行される ECS サービスを作成しますが、インターネットに向けて解放されたエンドポイントを作成することはありません。 + +![backend-service-infra](https://user-images.githubusercontent.com/879348/86046929-e8673400-ba02-11ea-8676-addd6042e517.png) + +## Manifest と設定 + +`copilot init` コマンドを実行すると、Copilot が `manifest.yml` という名前のファイルを copilot ディレクトリ内に作成していることに気づいたかもしれません。この Manifest ファイルは Service 用の共通設定やオプションを持ちます。どのようなオプションがあるかはあなたが選択した Service のタイプによって異なりますが、共通の設定には例えば Service に割り当てるメモリや CPU のリソース量、ヘルスチェック、環境変数といったものが含まれます。 + + +_front-end_ という名前の Load Balanced Web Service 用に作られた Manifest ファイルを覗いてみましょう。 + +```yaml +name: front-end +type: Load Balanced Web Service + +image: + # Service 用の Dockerfile までのパス + build: ./Dockerfile + # コンテナがトラフィックを受け取るために開放するポート番号 + port: 8080 + +http: + # このパスに届いたリクエストが Service にルーティングされます + # すべてのリクエストをルーティングするには "/" をパスとして指定します + path: '/' + # 任意のヘルスチェックパスを指定できます. デフォルトは "/" です. + # healthcheck: '/' + +# タスクに割り当てる CPU ユニット数 +cpu: 256 +# タスクに割り当てるメモリ量 (MiB) +memory: 512 +# Service として実行される必要があるタスク数 +count: 1 + +# 以下はより高度なユースケース用のオプション設定項目です +# +variables: # キー・値のペアで環境変数を設定します + LOG_LEVEL: info + +#secrets: # AWS Systems Manager (SSM) パラメータストア から秘密情報を取得して設定します +# GITHUB_TOKEN: GH_SECRET_TOKEN # キーに環境変数名、値には SSM パラメータ名を記述します + +# Environment ごとに上記で設定された値を上書きできます +environments: + prod: + count: 2 # "prod" Environment ではタスクを2つ実行します +``` +Manifest ファイルの仕様について学ぶには、[Manifest](../manifest/overview.ja.md) ページもご覧ください。 + +## Service のデプロイ + +Service をセットアップしたら、あるいは Manifest ファイルに変更を加えたら、deploy コマンドを実行して Service をデプロイできます。 + +```bash +$ copilot deploy +``` + +このコマンドを実行すると、続けて以下のような作業が実施されます。 + +1. ローカル環境でのコンテナイメージのビルド +2. Service 用の ECR リポジトリへのプッシュ +3. Manifest ファイルの CloudFormation テンプレートへの変換 +4. 追加インフラストラクチャがある場合、それらの CloudFormation テンプレートへのパッケージング +5. Service と各種リソースの CloudFormation によるデプロイ + +もしすでに Environment が複数ある場合には、どの Environment に対してデプロイするのかを確認されます。 + +## Service の中身を掘り下げてみよう + +Service のセットアップと実行が完了したので、Copilot を使って確認してみましょう。確認の手段として以下のような方法がよく利用されます。 + +### Service に含まれるものを確認したい + +`copilot svc show` コマンドを実行すると、Service のサマリ情報を表示します。以下は Load Balanced Web Application での出力の例です。各 Environment ごとの Service 設定や Service のエンドポイント、あるいは環境変数などが確認できます。さらに、`--resources` フラグを利用することでこの Service に紐づけられたすべての AWS リソースを確認できます。 + +```bash +$ copilot svc show +About + + Application my-app + Name front-end + Type Load Balanced Web Service + +Configurations + + Environment Tasks CPU (vCPU) Memory (MiB) Port + test 1 0.25 512 80 + +Routes + + Environment URL + test http://my-ap-Publi-1RV8QEBNTEQCW-1762184596.ca-central-1.elb.amazonaws.com + +Service Discovery + + Environment Namespace + test front-end.my-app.local:8080 + +Variables + + Name Environment Value + COPILOT_APPLICATION_NAME test my-app + COPILOT_ENVIRONMENT_NAME test test + COPILOT_LB_DNS test my-ap-Publi-1RV8QEBNTEQCW-1762184596.ca-central-1.elb.amazonaws.com + COPILOT_SERVICE_DISCOVERY_ENDPOINT test my-app.local + COPILOT_SERVICE_NAME test front-end +``` + +### Service のステータスを確認したい + +Service のすべてのタスクは Healthy だろうか?なにかアラームが発火していないか?など、Service のステータスを確認できると便利です。Copilot では、`copilot svc status` でそのような情報のサマリを確認できます。 + + +```bash +$ copilot svc status +Service Status + + ACTIVE 1 / 1 running tasks (0 pending) + +Last Deployment + + Updated At 12 minutes ago + Task Definition arn:aws:ecs:ca-central-1:693652174720:task-definition/my-app-test-front-end:1 + +Task Status + + ID Image Digest Last Status Health Status Started At Stopped At + 37236ed3 da3cfcdd RUNNING HEALTHY 12 minutes ago - + +Alarms + + Name Health Last Updated Reason + CPU-Utilization OK 5 minutes ago - +``` + +### Service のログを確認したい + +Service のログの確認も簡単です。`copilot svc logs` コマンドを実行すると、直近の Service ログを確認できます。`--follow` フラグをあわせて利用すると、Service 側のログの出力をライブに追いかけることもできます。 + +```bash +$ copilot svc logs +37236ed 10.0.0.30 🚑 Health-check ok! +37236ed 10.0.0.30 🚑 Health-check ok! +37236ed 10.0.0.30 🚑 Health-check ok! +37236ed 10.0.0.30 🚑 Health-check ok! +37236ed 10.0.0.30 🚑 Health-check ok! +``` diff --git a/site/content/docs/credentials.ja.md b/site/content/docs/credentials.ja.md new file mode 100644 index 00000000000..a34fe52ec72 --- /dev/null +++ b/site/content/docs/credentials.ja.md @@ -0,0 +1,62 @@ +# 認証情報 + +この章では、みなさんの AWS Copilot CLI 体験を最高のものにするために『認証情報についての推奨事項』を説明していきます。 + +## Application 用の認証情報 + +Copilot は[デフォルトの認証情報プロバイダーチェーン](https://docs.aws.amazon.com/ja_jp/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials)に沿って認証情報を検索し、認証情報を使用して Service と Environment が関連づけられた [Application のメタデータ](concepts/applications.ja.md)を保存または検索します。 +!!! tips + **[名前付きプロファイル](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html)を使用して** Application 用の認証情報を保存することを推奨します。 + +もっとも簡単な方法は `[default]` プロファイルを利用することです: + +```ini +# ~/.aws/credentials +[default] +aws_access_key_id=AKIAIOSFODNN7EXAMPLE +aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + +# ~/.aws/config +[default] +region=us-west-2 +``` + +あるいは `AWS_PROFILE` 環境変数を設定して別の名前付きプロファイルを指定できます。例えば Application 用に `[my-app]` という名前のプロファイルを `[default]` プロファイルの代わりに用いることができます。 + +!!! note + Application に AWS アカウントのルートユーザーの認証情報を用いることは**できません**。代わりに[こちら](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_root-user.html)で説明されているようにまず IAM ユーザーを作成してください。 + +```ini +# ~/.aws/config +[my-app] +credential_process = /opt/bin/awscreds-custom --username helen +region=us-west-2 + +# 指定した名前付きプロファイルを用いた Copilot コマンドの実行 +$ export AWS_PROFILE=my-app +$ copilot deploy +``` + +!!! caution + 環境変数 `AWS_ACCESS_KEY_ID` , `AWS_SECRET_ACCESS_KEY` , `AWS_SESSION_TOKEN` を直接用いることは推奨**しません**。なぜならそれらの認証情報が上書きされたり失効したりすると Copilot が Service や Environment を検索できなくなるからです。 + +サポートされている `config` ファイルの設定についてもっと詳しく知りたい方は[設定ファイルと認証情報ファイルに関するドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html#cli-configure-files-settings)をご参照ください。 + +## Environment 用の認証情報 + +Copilot における [Environment](concepts/environments.ja.md) は Application が存在するのとは別の AWS アカウントやリージョンに作成できます。Environment を最初に作成する際 Copilot はどの一時クレデンシャルまたは[名前付きプロファイル](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html)を使用するか尋ねます。 + +```bash +$ copilot env init + +Name: prod-iad + + Which credentials would you like to use to create prod-iad? + > Enter temporary credentials + > [profile default] + > [profile test] + > [profile prod-iad] + > [profile prod-pdx] +``` + +[Application 用の認証情報](#application-用の認証情報)とは異なり、Environment 用の AWS 認証情報は Environment の作成と削除の時のみ必要です。したがって一時的な環境変数からそれらの値を安全に使うことができます。Copilot が尋ねたり使用したりする認証情報はフラグとして扱われます。なぜならデフォルトの認証プロバイダーチェーンは Application 用の認証情報のために使われるからです。 diff --git a/site/content/docs/developing/additional-aws-resources.ja.md b/site/content/docs/developing/additional-aws-resources.ja.md new file mode 100644 index 00000000000..ee21041c949 --- /dev/null +++ b/site/content/docs/developing/additional-aws-resources.ja.md @@ -0,0 +1,114 @@ +# AWS リソースを追加する + +[Service の Manifest](../manifest/overview.ja.md)とデフォルトでは統合されていない任意の AWS サービスを Copilot CLI では Addon という形で追加できます。Addon の例として Service から読み込んだり書き込んだりする必要がある DyanmoDB テーブルや S3 バケットが考えられます。 + +## S3 バケットや DynamoDB テーブルを追加する方法 + +Copilot は以下のコマンドを使っていくつかの種類の Addon を作成するお手伝いをします: + +* [`storage init`](../commands/storage-init.ja.md) は、 DynamoDB テーブルや S3 バケットを作成します。 + +ワークスペースから `copilot storage init` を実行するといくつかの質問に沿ってこれらのリソースをセットアップできます。 + +## 他のリソースを追加する方法 + +他の種類の Addon に関しては、以下の説明に則ってご自身のカスタム CloudFormation テンプレートを追加できます。 + +ワークスペースに `webhook` という名前の Service があるとしましょう。 +```bash +. +└── copilot + └── webhook + └── manifest.yml +``` +そして `webhook` に独自の DynamoDB テーブルを追加したいとしましょう。その場合は `webhook/` ディレクトリ以下に新しく `addons/` ディレクトリを作成し追加で CloudFormation テンプレートを作成します。 +```bash +. +└── copilot + └── webhook + ├── addons + │ └── mytable-ddb.yaml + └── manifest.yaml +``` +通常 `addons/` ディレクトリ以下の各ファイルは独立した Addon を表し [AWS CloudFormation (CFN) テンプレート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-anatomy.html) と解釈されます。例えばさらに Service に S3 バケット Addon を追加したい場合は、 `storage init` を実行するか、もしくは独自の `mybucket-s3.yaml` ファイルを作成するかします。 + +Service がデプロイされると Copilot はこれらのファイルを全てマージして単一の AWS CloudFormation テンプレートにして Service スタックにネストされたスタックを作成します。 + +## Addon テンプレートの構造 +Addon テンプレートは任意の有効な CloudFormation テンプレートを用いることができます。しかしデフォルトでは Copilot は `App`, `Env` そして `Name` [パラメーター](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)を渡すので、お望みならば [Conditions セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) または [Mappings セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) でリソースのプロパティをカスタマイズできます。 + +ECS タスクから [Resources セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html) にアクセスする必要がある場合以下の点に注意してください。 + +1. テンプレートの中で [IAM 管理ポリシー](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html) リソースを使ってタスクにパーミッションを与え、 [Outputs セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) を使ってパーミッションを ECS タスクロールに注入してください。 +2. [Outputs セクション](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html) を作成して ECS タスクに環境変数として注入したい値を定義してください。 + +以下は DynamoDB テーブル Addon を作成するテンプレートの例です。 + +```yaml +# これらのパラメータを使ってテンプレートの中で Conditions セクションや Mappings セクションを作成できます。 +Parameters: + App: + Type: String + Description: Your application's name. + Env: + Type: String + Description: The environment name your service, job, or workflow is being deployed to. + Name: + Type: String + Description: The name of the service, job, or workflow being deployed. + +Resources: + # AWS::DynamoDB::Table:MyTable のようにここでリソースを定義します。 + # MyTable: + # Type: AWS::DynamoDB::Table + # Properties: + # ... + + # 1. リソースを作成するだけでなく、 ECS タスクからリソースにアクセスする必要がある場合は、 + # リソースにアクセスできるパーミッションを定義する AWS::IAM::ManagedPolicy を作成する必要があります。 + # + # 例えば以下は MyTable に対するポリシーのサンプルです。 + MyTableAccessPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: DDBActions + Effect: Allow + Action: + - dynamodb:BatchGet* + - dynamodb:DescribeStream + - dynamodb:DescribeTable + - dynamodb:Get* + - dynamodb:Query + - dynamodb:Scan + - dynamodb:BatchWrite* + - dynamodb:Create* + - dynamodb:Delete* + - dynamodb:Update* + - dynamodb:PutItem + Resource: !Sub ${ MyTable.Arn} + +Outputs: + # 2. ECS タスクにリソースのプロパティを環境変数として注入したい場合は、 + # Output セクションを定義する必要があります。 + # + # 例えば MyTableName という出力値はタスクに大文字のスネークケースとして注入されます。 + MyTableName: + Description: "The name of this DynamoDB." + Value: !Ref MyTable + + # 1. さらに IAM ManagedPolicy を出力して Copilot が ECS タスクロールに注入できるようにする必要もあります。 + MyTableAccessPolicyArn: + Description: "The ARN of the ManagedPolicy to attach to the task role." + Value: !Ref MyTableAccessPolicy +``` + +次回リリースするとき Copilot はこのテンプレートを Service にネストされたスタックとして用います! + +!!! info + リソースを追加するために AWS 管理ポリシーを定義する場合は、以下のような [IAM でのベストプラクティス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html) に従うことを推奨します。 + + * addons/ ディレクトリで定義するポリシーでは[最小限のアクセス権を付与する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) + * `addons/` ディレクトリで定義したリソースに対してのみアクセスできるようにポリシーを制限するために [追加セキュリティに対するポリシー条件を使用する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#use-policy-conditions) diff --git a/site/content/docs/developing/environment-variables.ja.md b/site/content/docs/developing/environment-variables.ja.md new file mode 100644 index 00000000000..ed51641c712 --- /dev/null +++ b/site/content/docs/developing/environment-variables.ja.md @@ -0,0 +1,57 @@ +# 環境変数 + +環境変数は Service が実行されている Environment に応じてサービスから利用可能な変数です。Service は自身で定義することなくそれらの変数を参照できます。環境変数は特定の Environment に固有のデータを Service へ渡したい場合に便利です。例として、テスト用と本番用で接続するデータベースの名前を切り替える場合などです。 + +環境変数へのアクセス方法は通常、利用しているプログラミング言語によって決まります。ここではいくつかのプログラミング言語で `DATABASE_NAME` という環境変数を取得する例を示します。 + +__Go__ +```go +dbName := os.Getenv("DATABASE_NAME") +``` + +__Javascript__ +```javascript +var dbName = process.env.DATABASE_NAME; +``` + +__Python__ +```python +database_name = os.getenv('DATABASE_NAME') +``` + +## デフォルト環境変数とは +デフォルトで、AWS Copilot CLI はサービスが利用できるいくつかの環境変数を提供します。 + +* `COPILOT_APPLICATION_NAME` - この Service を実行している Application 名 +* `COPILOT_ENVIRONMENT_NAME` - Service が実行されている Environment 名(例: test、prod) +* `COPILOT_SERVICE_NAME` - 現在の Service 名 +* `COPILOT_LB_DNS` - (存在する場合)ロードバランサー名。例: _kudos-Publi-MC2WNHAIOAVS-588300247.us-west-2.elb.amazonaws.com_ 注: カスタムドメイン名を利用している場合でも、この値は ロードバランサーの DNS 名を保持します +* `COPILOT_SERVICE_DISCOVERY_ENDPOINT` - サービス検出を介して、Environment の中で他の Service と通信するために Service 名の後に追加されるエンドポイント。値は `{app name}.local` となります。サービスディスカバリについてのより詳しい情報は[サービス検出のガイド](../developing/service-discovery.ja.md) を参照してください + +## 環境変数を追加する方法 +環境変数を追加するのは簡単です。[Manifest](../manifest/overview.ja.md) の `variables` セクションに直接追加できます。 下記のスニペットでは、`LOG_LEVEL` という変数を `debug` という値で Service に渡しています。 + +```yaml +# copilot/{service name}/manifest.yml の一部 +variables: + LOG_LEVEL: debug +``` +Environment に応じて、特定の環境変数の値を渡すこともできます。上記と同じ例で、ログレベルを設定し、production の Environment の時だけ値を `info` に書き換えてみます。Manifest の変更は、それをデプロイした時に反映されるので、ローカルでの変更は安全です。 + +```yaml +# copilot/{service name}/manifest.yml の一部 +variables: + LOG_LEVEL: debug + +environments: + production: + variables: + LOG_LEVEL: info +``` +ここでは、Manifest を編集して、環境変数を Application に追加する方法の簡単なガイドを紹介しています。👇 + +![Editing the manifest to add env vars](https://raw.githubusercontent.com/kohidave/ecs-cliv2-demos/master/env-vars-edit.svg?sanitize=true) + +## DynamoDB テーブルやS3 バケット、RDS データベースなどの名前を確認する方法 + +Copilot CLI を使って、DynamoDB テーブルや S3 バケット、データベースなどの追加の AWS リソースをプロビジョニングする場合、出力の値は環境変数として、Application に渡されます。より詳しい情報は、[AWS リソースを追加する](../developing/additional-aws-resources.ja.md)を確認してください。 diff --git a/site/content/docs/developing/secrets.ja.md b/site/content/docs/developing/secrets.ja.md new file mode 100644 index 00000000000..1cc8ed5f351 --- /dev/null +++ b/site/content/docs/developing/secrets.ja.md @@ -0,0 +1,38 @@ +# シークレット + +シークレットは、OAuth トークン、シークレットキー、API キーなどの機密情報です。これらの情報はアプリケーションコードでは必要ですが、ソースコードにコミットするべきではありません。AWS Copilot CLI では、シークレットは環境変数として渡されますが、その機密性のため扱いが異なります (詳細は[環境変数を使った開発](../developing/environment-variables.ja.md)を参照して下さい) 。 + +## シークレットの追加方法 + +現在、シークレットを追加するには、シークレットを SecureString として [AWS Systems Manager パラメータストラ](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html) (SSM) に保存する必要があります。そして、SSM パラメータへの参照を [Manifest](../manifest/overview.ja.md) に追加します。 + +ここでは、`GH_WEBHOOK_SECRET` という名前のシークレットを、`secretvalue1234` という値で保存する例を見てみましょう。 + +まず、次のようにシークレットを SSM に保存します。 + +```sh +aws ssm put-parameter --name GH_WEBHOOK_SECRET --value secretvalue1234 --type SecureString\ + --tags Key=copilot-environment,Value=${ENVIRONMENT_NAME} Key=copilot-application,Value=${APP_NAME} +``` + +これにより、SSM のパラメータ `GH_WEBHOOK_SECRET` に値 `secretvalue1234` がシークレットとして格納されます。 + +!!! attention + Copilot では、このシークレットへのアクセスを制限するために、 `copilot-application` と `copilot-environment` タグが必要です。 + `${ENVIRONMENT_NAME}` と `${APP_NAME}` を、このシークレットへのアクセスを許可したい Copilot Application と Environment に置き換えることが重要です。 + + +次に、この値を渡すために Manifest ファイルを修正します。 + +```yaml +secrets: + GITHUB_WEBHOOK_SECRET: GH_WEBHOOK_SECRET +``` + +マニフェストのこの更新をデプロイすると、環境変数 `GITHUB_WEBHOOK_SECRET` にアクセスできるようになります。この環境変数には、SSM パラメータ `GH_WEBHOOK_SECRET` の値である `secretvalue1234` が格納されています。 + +これが機能するのは、ECS エージェントがタスクの開始時に SSM パラメータを解決し、環境変数を設定してくれるためです。 + +!!! info + **この機能はもっと簡単にする予定です!** Application と同じ Environment にシークレットを保存しなければならないという、いくつかの注意点があります。 + 将来的に `secrets` コマンドを追加して、どの Environment にいるのかや SSM がどのように動作するのかを気にすることなく、シークレットを追加できるようにしたいと考えています。 diff --git a/site/content/docs/developing/service-discovery.ja.md b/site/content/docs/developing/service-discovery.ja.md new file mode 100644 index 00000000000..867bb9553bb --- /dev/null +++ b/site/content/docs/developing/service-discovery.ja.md @@ -0,0 +1,36 @@ +# サービス検出 + +サービス検出はサービス同士がお互いの位置を発見し接続できるようにする方法のことです。典型的にはサービスがパブリックエンドポイントを公開している場合のみお互いに通信でき、その場合でもリクエストはインターネット越しに通信します。 [ECS サービス検出](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-discovery.html) によって作成された Service にはプライベートアドレスと DNS 名が付与されるので、お互いの Service はローカルネットワーク (VPC) から離れることもパブリックエンドポイントを公開することもなく通信できます。 + +## サービス検出の使い方 + +サービス検出は Copilot CLI を使って作成された全ての Service で有効化されています。以下の Go 言語の例を通して使い方を解説します。 `kudos` という名前の Application と 2 個の Service (`api` と `front-end`) を作成したとします。 + +この例では `front-end` Service はパブリックエンドポイントを持ち、サービス検出のエンドポイントを使って `api` Service を呼び出す場合を考えます。 + + +```go +// サービス検出を使って front-end Service から api Service を呼び出す +func ServiceDiscoveryGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { + endpoint := fmt.Sprintf("http://api.%s/some-request", os.Getenv("COPILOT_SERVICE_DISCOVERY_ENDPOINT")) + resp, err := http.Get(endpoint /* http://api.kudos.local/some-request */) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer resp.Body.Close() + body, _ := ioutil.ReadAll(resp.Body) + w.WriteHeader(http.StatusOK) + w.Write(body) +} +``` + +重要な点は `front-end` Service が `api` Service に対して特別なエンドポイントを通してリクエストを送信している点です。 + +```go +endpoint := fmt.Sprintf("http://api.%s/some-request", os.Getenv("COPILOT_SERVICE_DISCOVERY_ENDPOINT")) +``` + +`COPILOT_SERVICE_DISCOVERY_ENDPOINT` は特別な環境変数で Copilot CLI は Service 作成時にこの環境変数を設定します。これは _{app name}.local_ というフォーマットで登録されており、今回の例だと _kudos_ Application の場合、リクエストは `http://api.kudos.local/some-request` に送信されます。 _api_ Service は 80 番ポートで動いているので、 URL のなかでポートを指定していません。しかし Service が例えば 8080 番のような別のポートで動いている場合はリクエストの中にポート番号を含める必要があります。今回の例だと `http://api.kudos.local:8080/some-request` のようになります。 + +`front-end` Service がリクエストを送信するとき `api.kudos.local` というエンドポイントはプライベート IP アドレスに変換され VPC のなかでプライベートにルーティングされます。 diff --git a/site/content/docs/developing/sidecars.ja.md b/site/content/docs/developing/sidecars.ja.md new file mode 100644 index 00000000000..cca0a0ac741 --- /dev/null +++ b/site/content/docs/developing/sidecars.ja.md @@ -0,0 +1,147 @@ +# サイドカー + +サイドカーは主となるコンテナと共に実行され補助的な役割を担うコンテナのことです。サイドカーの役割はロギングや設定ファイルの取得、リクエストのプロキシ処理などの周辺的なタスクを実行することです。 + +AWS はまた ECS サービスとシームレスに組み合わせられるいくつかのプラグインを提供しており、[FireLens](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_firelens.html) や [AWS X-Ray](https://aws.amazon.com/jp/xray/)、[AWS App Mesh](https://aws.amazon.com/jp/app-mesh/) など多岐に渡ります。 + +Manifest の中で [`storage` フィールド](../developing/storage.ja.md)を使って主となるコンテナ用の EFS ボリュームを定義した場合、定義した任意のサイドカーコンテナはそのボリュームをマウントできます。 + +## Copilot でサイドカーを追加するには? +Copilot の Manifest でサイドカーを追加したい場合、[サイドカーコンテナを直接定義する](#サイドカーコンテナを直接定義する)あるいは[サイドカーパターン](#サイドカーパターン)を利用する方法があります。 + +### サイドカーコンテナを直接定義する +サイドカーコンテナイメージの URL を指定する必要があります。オプションで公開するポートや[プライベートレジストリ](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/private-auth.html)の認証パラメータを指定できます。 + +``` yaml +sidecars: + : + # 公開するポート (オプション) + port: + # サイドカーコンテナイメージの URL (必須) + image: + # プライベートレジストリの認証情報を保存している秘密情報の ARN (オプション) + credentialsParameter: + # サイドカーコンテナの環境変数 (オプション) + variables: + # サイドカーコンテナで用いる秘密情報 (オプション) + secrets: + # サービスレベルで指定する EFS ボリュームのマウントパス (オプション) + mount_points: + - # サイドカーからマウントするときのソースボリューム (必須) + source_volume: + # サイドカーからボリュームをマウントするときのパス (必須) + path: + # サイドカーにボリュームに対する読み込みのみを許可するかどうか (デフォルトでは true) + read_only: + # コンテナに付与する Docker ラベル (オプション) + labels: + {label key} :