--- tags: 案件 --- # AWS CI/CD sample # Sample project ## ディレクトリ構造 ```= (aws-cicd-sample) takumi:~/environment/aws-cicd-sample (master) $ tree . ├── README.md ├── main │   ├── __init__.py │   ├── deleteImageById │   │   ├── __init__.py │   │   ├── delete_image_by_id.py │   │   └── requirements.txt │   ├── getImageById │   │   ├── __init__.py │   │   ├── get_image_by_id.py │   │   └── requirements.txt │   ├── getImages │   │   ├── __init__.py │   │   ├── get_images.py │   │   └── requirements.txt │   ├── postImages │   │   ├── __init__.py │   │   ├── post_images.py │   │   └── requirements.txt │   └── updateImage │   ├── __init__.py │   ├── requirements.txt │   └── update_image.py └── tests │ ├── __init__.py │ ├── postImages │    ├── __init__.py │    └── test_postImages.py ├── api-tests ├── buildspec.yml ├── samconfig.toml ├── swagger.yaml ├── template.yaml ├── sonar-scanner-4.2.0.1873-linux ├── sonar-project.properties ├── coverage.xml ├── .aws-sam    └── build    ├── template.yaml    ├── deleteImageById    │   ├── delete_image_by_id.py    │   ├── __init__.py    │   └── requirements.txt    ├── getImageById    │   ├── get_image_by_id.py    │   ├── __init__.py    │   └── requirements.txt    ├── getImages    │   ├── get_images.py    │   ├── __init__.py    │   └── requirements.txt    ├── postImages    │   ├── __init__.py    │   ├── post_images.py    │   └── requirements.txt └── updateImage    ├── __init__.py    ├── requirements.txt    └── update_image.py ``` # Buildステップ(試行錯誤中) ## 手動 0. 準備 ``` $ pip install --upgrade aws-sam-cli $ pip install pytest $ pip install pytest-cov $ wget -O tmp https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.2.0.1873-linux.zip $ $unzip tmp ``` 2. 単体テスト ```Bash $ TABLE_NAME=photos pytest --cov=main --cov-report=xml tests/ ``` - ローカルで実行する場合は、pipでpytestとpytest-covを事前にインストールしておく。 - テスト対象のモジュールがDynamoDB名を環境変数(TABLE_NAME)として利用するので、pytestコマンドの前に設定。ローカルテストとCIサーバ上テスト切分け設定を外出しにしたい(TBD)。 3. (option)単体テスト結果をSonarQubeサーバへ転送 ```Bash $ sonar-scanner-4.2.0.1873-linux/bin/sonar-scanner -Dsonar.host.url=http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:22222 ``` - sonar-scannerはlinux用をzipでDLしたものを利用。 - docker版もあるので、それを使うのがベターだが、CIサーバ(CodeBuild)のジョブは、dockerコンテナなので、その中でdockerコマンドが使えるか不明(dind)。ローカルなら、docker版成功。[→こちら参考](https://github.com/SonarSource/sonar-scanner-cli-docker) 4. パッケージ(前準備) ```Bash $ sam buil ``` - projectディレクトリ直下にあるtemplate.yaml(line:35)をベースに、sam-cli用のプロジェクトを生成。.aws-samディレクトリ配下が作成される(lines:39-61)。 5. パッケージ ```Bash $ sam package --template-file template.yaml --s3-bucket aws-cicd-sample-managed-s3-bucket-artifacts --output-template-file transformed.yaml ``` - projectディレクトリ直下にあるtemplate.yaml(line:35)をベースに、sam-cli用のプロジェクトを生成。.aws-samディレクトリ配下が作成される(lines:39-61)。 - デプロイ用のtransformed.yaml(template.yamlに実際のリソースID(ARNとか)が定義されたもの)はプロジェクト直下に作成されるようだ。 6. デプロイ ```Bash $ sam deploy --template-file /home/ec2-user/environment/aws-cicd-sample/transformed.yaml --stack-name cicd-sampleBetaStack ``` 7. クリーンナップ(スタック削除) ```Bash $ aws cloudformation delete-stack --stack-name cicd-sampleBetaStack ``` ### コメント - Step4、5でsamコマンドを使ってパッケージ化&デプロイを実施しているが、[こちら](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-deploying.html#serverless-sam-cli-using-package-and-deploy)によると、Cloudformationコマンドでも同じらしい。 - APIの定義はswaggerを利用。template.yaml(line:35)の中からswagger.yaml(line:34)を呼んでいる: ```Bash Api: Type: 'AWS::Serverless::Api' Properties: StageName: Prod DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: swagger.yaml ``` ## 自動 デモ稼働中。定義は↓ ### CI/CD pipeline ```Bash (aws-cicd-sample) takumi:~/environment/aws-cicd-sample (master) $ aws codepipeline get-pipeline --name aws-cicd-sample { "pipeline": { "roleArn": "arn:aws:iam::XXXXXXXXXXXX:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1-aws-cicd-sample", "stages": [ { "name": "Source", "actions": [ { "inputArtifacts": [], "name": "Source", "region": "ap-northeast-1", "actionTypeId": { "category": "Source", "owner": "AWS", "version": "1", "provider": "CodeCommit" }, "outputArtifacts": [ { "name": "SourceRepo" } ], "configuration": { "PollForSourceChanges": "false", "BranchName": "master", "RepositoryName": "aws-cicd-sample" }, "runOrder": 1 } ] }, { "name": "Build", "actions": [ { "inputArtifacts": [ { "name": "SourceRepo" } ], "name": "CodeBuild", "region": "ap-northeast-1", "actionTypeId": { "category": "Build", "owner": "AWS", "version": "1", "provider": "CodeBuild" }, "outputArtifacts": [ { "name": "CompiledCFNTemplate" } ], "configuration": { "ProjectName": "aws-cicd-sample" }, "runOrder": 1 } ] }, { "name": "Beta", "actions": [ { "inputArtifacts": [ { "name": "CompiledCFNTemplate" } ], "name": "CreateBetaChangeSet", "region": "ap-northeast-1", "actionTypeId": { "category": "Deploy", "owner": "AWS", "version": "1", "provider": "CloudFormation" }, "outputArtifacts": [], "configuration": { "ActionMode": "CHANGE_SET_REPLACE", "ChangeSetName": "cicd-sampleChangeSet", "RoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/cloudformation-lambda-execution-role", "Capabilities": "CAPABILITY_IAM", "StackName": "cicd-sampleBetaStack", "TemplatePath": "CompiledCFNTemplate::transformed.yaml" }, "runOrder": 1 }, { "inputArtifacts": [], "name": "ExecuteChangeSet", "region": "ap-northeast-1", "actionTypeId": { "category": "Deploy", "owner": "AWS", "version": "1", "provider": "CloudFormation" }, "outputArtifacts": [ { "name": "AppDeploymentValues" } ], "configuration": { "StackName": "cicd-sampleBetaStack", "ActionMode": "CHANGE_SET_EXECUTE", "ChangeSetName": "cicd-sampleChangeSet", "OutputFileName": "StackOutputs.json" }, "runOrder": 2 } ] } ], "artifactStore": { "type": "S3", "location": "codepipeline-ap-northeast-1-XXXXXXXXXXXX" }, "name": "aws-cicd-sample", "version": 4 }, "metadata": { "pipelineArn": "arn:aws:codepipeline:ap-northeast-1:XXXXXXXXXXXX:aws-cicd-sample", "updated": 1581311899.015, "created": 1581062874.369 } } ``` # 各種サーバ設定 ## Redmine 暫定的にEC2上のコンテナで稼働。公式イメージは[こちら](https://hub.docker.com/_/redmine)から。 - [Go to Redmine Server](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:11111/) - docker-compose設定ファイル ``` [ec2-user@ip-172-31-34-117 redmine]$ cat docker-compose.yml version: '3.1' services: redmine: image: redmine restart: always ports: - 11111:3000 environment: REDMINE_DB_MYSQL: db REDMINE_DB_PASSWORD: example db: image: mysql:5.7 restart: always command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci environment: MYSQL_ROOT_PASSWORD: example MYSQL_DATABASE: redmine ``` ## SonarQube 暫定的にEC2上のコンテナで稼働。公式イメージは[こちら](https://hub.docker.com/_/sonarqube)から。公式サイトにはdocker-composeのサンプルがなかったので、下記の通りカスタマイズ。 - [Go to SonarQube Server](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:22222/) - docker-compose設定ファイル ``` [ec2-user@ip-172-31-34-117 sonarqube]$ cat docker-compose.yml version: '2' services: sonarqube: image: sonarqube restart: always ports: - "22222:9000" volumes: - sonarqube_conf:/opt/sonarqube/conf - sonarqube_extensions:/opt/sonarqube/extensions - sonarqube_logs:/opt/sonarqube/logs - sonarqube_data:/opt/sonarqube/data volumes: sonarqube_conf: driver: local sonarqube_extensions: driver: local sonarqube_logs: driver: local sonarqube_data: driver: local ``` ## Swagger 暫定的にEC2上のコンテナで稼働。GutHubの[こちら](https://github.com/elevennines-inc/swagger-all-in-one-docker-compose)参考。 - [Go to swagger-editor](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:18081/) - [Go to swagger-ui](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:18082/) - [Go to swagger-api](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:18083/) - [Go to swagger-nginx](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:18084/) - docker-compose設定ファイル ```Bash [ec2-user@ip-172-31-34-117 swagger]$ cat docker-compose.yml version: "3.3" services: swagger-editor: image: swaggerapi/swagger-editor container_name: "swagger-editor" ports: - "8081:8080" swagger-ui: image: swaggerapi/swagger-ui container_name: "swagger-ui" ports: - "8082:8080" volumes: - ./swagger/openapi.json:/openapi.json environment: SWAGGER_JSON: /openapi.json # API_URL: "" swagger-api: image: danielgtaylor/apisprout container_name: "swagger-api" ports: - "8083:8000" volumes: - ./swagger/openapi.json:/openapi.json command: /openapi.json networks: swagger_link: aliases: - local.swagger.apisprout swagger-nginx: image: nginx:mainline-alpine container_name: "swagger-nginx" ports: - "8084:8084" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf networks: swagger_link: aliases: - local.swagger.api networks: swagger_link: external: true ``` ## ReDoc 暫定的にEC2上のコンテナで稼働。GutHubの[こちら](https://github.com/elevennines-inc/swagger-all-in-one-docker-compose)参考。 - [Go to ReDoc](http://ec2-18-180-2-56.ap-northeast-1.compute.amazonaws.com:44444/) - docker-compose設定ファイル ```Bash [ec2-user@ip-172-31-34-117 redoc]$ cat docker-compose.yml version: '2' services: redoc: image: redocly/redoc restart: always ports: - "44444:80" volumes: - ./swagger.yaml:/usr/share/nginx/html/swagger.yaml environment: - SPEC_URL=swagger.yaml ``` # 残作業(ToDo) - SonarQubeでできる事確認 - PRをトリガーにCI/CDが発火するパイプラインを作成 - テスト結果をCodeCommitのPRにフィードバックできるか調査 - デモはmasterへのマージをトリガーにCI/CDを発火 - ローカルデバックのやり方調査 - [AWS SAM Local と LocalStack を使って ローカルでAWS Lambdaのコードを動かす](https://dev.classmethod.jp/etc/sam-local-with-localstack/) - [AWS Lambda(Python) の開発環境・テスト・デプロイ・CI 考察](https://dev.classmethod.jp/server-side/serverless/aws-lambda-dev-test-deploy-ci/) - CodeBuild実行に必要な秘匿性パラメータはパラメータストアに格納 - CodeBuildから管理サーバへの通信は、内部経由で通信させたい(デモはインターネット経由で通信) - Sonar-scannerのdockerでの実行方法調査(特にCodeBuildのジョブ内でdocker使えるか?) - TABLE_NAMEなど、ローカルとCI/CD環境での切替方式。 # コマンド ```Bash aws --endpoint-url=http://localhost:4572 s3api create-bucket --bucket aws-cicd-sample-managed-s3-bucket-artifacts ``` テストコード ```Bash curl -X POST http://127.0.0.1:3000/images -d '{"type":"image/jpeg","size":1}' ``` Redmine https://qiita.com/nkenbou/items/e512b4aea9de40da606a 確かに Admin Area > Settings > Network > Outbound requests > Allow requests to the local network from hooks and services のチェックが入っていませんでしたので、このチェックを入れてテストすると…