この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
渡辺です。
APIを開発するとき、 OpenAPI/Swagger 2.0 API で定義をゴリゴリ書いていけば、API Gatewayへのデプロイも簡単ですし、ドキュメントも生成できて超便利です。 ドキュメントの生成ツールは色々あるようですが、やっぱり自動的に生成したいですよねぇ。 毎回、コマンド打つのも面倒です。 CodePipelineでHTML吐いて、S3にアップロードしたいですね。
こんな感じに。
cfn-swagger-docs
というわけで、 cfn-swagger-docs を作ったので公開しておきます。 ドキュメントは spectacleを利用しました。 Dockerファイル公開しているので、CodeBuildがラクチン。 サンプルは こんな感じ。
コードはGithubのプライベートリポジトリにあることを想定しています。 Oatuhトークンなどが必要なので、 CodePipelineのS3へのデプロイを使って、CloudFormation一撃で静的Webサイトの構築をやってみるを参考にしてください。
ソース内にSwaggerファイルに対し、コマンドを実行するのが buildspec.yml
です。
version: 0.2
phases:
build:
commands:
- echo Build started on `date`
- spectacle --version
- mkdir build
- spectacle -t build api.swagger.yml
artifacts:
base-directory: build
files:
- "**/*"
ここでは、ソースのルートディレクトリに api.swagger.yml
がある前提なので、適宜書き換えてください。
buildspec.yml
のパスはCloudFormationのパラメータで指定します。
複数のAPIを持つ場合はこんな感じに。
version: 0.2
phases:
build:
commands:
- echo Build started on `date`
- spectacle --version
- mkdir build
- mkdir build/api
- spectacle -t build/api api/api.swagger.yaml
- mkdir build/admin
- spectacle -t build/admin api/admin.swagger.yaml
artifacts:
base-directory: build
files:
- api/**/*
- admin/**/*
注意
CloudFrontで全世界に公開されますので、公開が困る人はテンプレートを修正してくださいw
Template
---
AWSTemplateFormatVersion: 2010-09-09
Description: API documents
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Build Settings"
Parameters:
- BuildSpec
- Label:
default: "Github Repository Settings"
Parameters:
- GitHubOwner
- GitHubRepo
- GitHubBranch
- Label:
default: "Github OAuth"
Parameters:
- GitHubOAuthToken
- Label:
default: "Github Webhook"
Parameters:
- SecretToken
ParameterLabels:
GitHubOwner:
default: "Owner"
GitHubRepo:
default: "Repository"
GitHubBranch:
default: "Branch"
GitHubOAuthToken:
default: "OAuthToken"
SecretToken:
default: "SecretToken"
BuildSpec:
default: "BuildSpec"
Parameters:
GitHubOwner:
Type: String
GitHubRepo:
Type: String
GitHubBranch:
Type: String
Default: develop
GitHubOAuthToken:
Type: String
NoEcho: true
SecretToken:
Type: String
BuildSpec:
Type: String
Default: buildspec.yml
Resources:
S3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub api-docs-${AWS::Region}-${AWS::AccountId}
CloudFrontOriginAccessIdentity:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: api-docs
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Statement:
- Sid: "1"
Action: s3:GetObject
Effect: Allow
Resource: !Sub arn:aws:s3:::${S3Bucket}/*
Principal:
AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Origins:
- Id: !Sub S3-${S3Bucket.DomainName}
DomainName: !GetAtt S3Bucket.DomainName
S3OriginConfig:
OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}
DefaultRootObject: index.html
DefaultCacheBehavior:
TargetOriginId: !Sub S3-${S3Bucket.DomainName}
ViewerProtocolPolicy: allow-all
ForwardedValues:
QueryString: false
PriceClass: PriceClass_200
ArtifactBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub artifact-${AWS::Region}-${AWS::AccountId}
ServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /service-role/
RoleName: api_docs_role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
- Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: build
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: '*'
Effect: Allow
Action:
- codebuild:StartBuild
- codebuild:BatchGetBuilds
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource:
- !Sub arn:aws:s3:::${ArtifactBucket}/*
- !Sub arn:aws:s3:::${S3Bucket}/*
Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:GetObjectVersion
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: api-docs
ServiceRole: !GetAtt ServiceRole.Arn
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
BuildSpec: !Ref BuildSpec
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: sourcey/spectacle
Type: LINUX_CONTAINER
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: api-docs
RoleArn: !GetAtt ServiceRole.Arn
ArtifactStore:
Type: S3
Location: !Ref ArtifactBucket
Stages:
- Name: Source
Actions:
- Name: PullFromGithub
ActionTypeId:
Category: Source
Owner: ThirdParty
Provider: GitHub
Version: 1
RunOrder: 1
Configuration:
Owner: !Ref GitHubOwner
Repo: !Ref GitHubRepo
Branch: !Ref GitHubBranch
OAuthToken: !Ref GitHubOAuthToken
PollForSourceChanges: false
OutputArtifacts:
- Name: SourceArtifact
- Name: Build
Actions:
- Name: BuildAPIDocuments
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Configuration:
ProjectName: !Ref CodeBuildProject
RunOrder: 1
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
- Name: Deploy
Actions:
- Name: Upload
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: S3
Version: 1
Configuration:
BucketName: !Ref S3Bucket
Extract: true
RunOrder: 1
InputArtifacts:
- Name: BuildArtifact
PipelineWebhook:
Type: AWS::CodePipeline::Webhook
Properties:
Authentication: GITHUB_HMAC
AuthenticationConfiguration:
SecretToken: !Ref SecretToken
Filters:
-
JsonPath: "$.ref"
MatchEquals: refs/heads/{Branch}
TargetPipeline: !Ref CodePipeline
TargetAction: PullFromGithub
TargetPipelineVersion: !GetAtt CodePipeline.Version
RegisterWithThirdParty: true
Outputs:
ApiDocsUrl:
Value: !Join [ "", [ "https://", !GetAtt [ Distribution, DomainName ]]]