OpenAPI/Swagger 2.0 APIドキュメント生成用CFnテンプレート
渡辺です。
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 ]]]