├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── auto-release.yml ├── mergify.yml ├── renovate.json └── workflows │ ├── auto-context.yml │ ├── auto-format.yml │ ├── auto-readme.yml │ ├── auto-release.yml │ ├── chatops.yml │ └── validate-codeowners.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── README.yaml ├── docs ├── targets.md └── terraform.md ├── examples ├── complete │ ├── context.tf │ ├── fixtures.us-east-2.tfvars │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── env_vars_files │ ├── main.tf │ └── versions.tf ├── map_environment │ ├── main.tf │ └── versions.tf ├── multi_port_mappings │ ├── main.tf │ └── versions.tf ├── multi_type_env_vars │ ├── main.tf │ └── versions.tf ├── multiple_definitions │ ├── main.tf │ └── versions.tf └── string_env_vars │ ├── main.tf │ └── versions.tf ├── main.tf ├── outputs.tf ├── test ├── .gitignore ├── Makefile ├── Makefile.alpine └── src │ ├── .gitignore │ ├── Makefile │ ├── examples_complete_test.go │ ├── go.mod │ └── go.sum ├── variables.tf └── versions.tf /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Use this file to define individuals or teams that are responsible for code in a repository. 2 | # Read more: 3 | # 4 | # Order is important: the last matching pattern has the highest precedence 5 | 6 | # These owners will be the default owners for everything 7 | * @cloudposse/engineering @cloudposse/contributors 8 | 9 | # Cloud Posse must review any changes to Makefiles 10 | **/Makefile @cloudposse/engineering 11 | **/Makefile.* @cloudposse/engineering 12 | 13 | # Cloud Posse must review any changes to GitHub actions 14 | .github/* @cloudposse/engineering 15 | 16 | # Cloud Posse must review any changes to standard context definition, 17 | # but some changes can be rubber-stamped. 18 | **/*.tf @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers 19 | README.yaml @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers 20 | README.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers 21 | docs/*.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers 22 | 23 | # Cloud Posse Admins must review all changes to CODEOWNERS or the mergify configuration 24 | .github/mergify.yml @cloudposse/admins 25 | .github/CODEOWNERS @cloudposse/admins 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Found a bug? Maybe our [Slack Community](https://slack.cloudposse.com) can help. 11 | 12 | [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) 13 | 14 | ## Describe the Bug 15 | A clear and concise description of what the bug is. 16 | 17 | ## Expected Behavior 18 | A clear and concise description of what you expected to happen. 19 | 20 | ## Steps to Reproduce 21 | Steps to reproduce the behavior: 22 | 1. Go to '...' 23 | 2. Run '....' 24 | 3. Enter '....' 25 | 4. See error 26 | 27 | ## Screenshots 28 | If applicable, add screenshots or logs to help explain your problem. 29 | 30 | ## Environment (please complete the following information): 31 | 32 | Anything that will help us triage the bug will help. Here are some ideas: 33 | - OS: [e.g. Linux, OSX, WSL, etc] 34 | - Version [e.g. 10.15] 35 | 36 | ## Additional Context 37 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | 5 | - name: Community Slack Team 6 | url: https://cloudposse.com/slack/ 7 | about: |- 8 | Please ask and answer questions here. 9 | 10 | - name: Office Hours 11 | url: https://cloudposse.com/office-hours/ 12 | about: |- 13 | Join us every Wednesday for FREE Office Hours (lunch & learn). 14 | 15 | - name: DevOps Accelerator Program 16 | url: https://cloudposse.com/accelerate/ 17 | about: |- 18 | Own your infrastructure in record time. We build it. You drive it. 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'feature request' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Have a question? Please checkout our [Slack Community](https://slack.cloudposse.com) or visit our [Slack Archive](https://archive.sweetops.com/). 11 | 12 | [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) 13 | 14 | ## Describe the Feature 15 | 16 | A clear and concise description of what the bug is. 17 | 18 | ## Expected Behavior 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | ## Use Case 23 | 24 | Is your feature request related to a problem/challenge you are trying to solve? Please provide some additional context of why this feature or capability will be valuable. 25 | 26 | ## Describe Ideal Solution 27 | 28 | A clear and concise description of what you want to happen. If you don't know, that's okay. 29 | 30 | ## Alternatives Considered 31 | 32 | Explain what alternative solutions or features you've considered. 33 | 34 | ## Additional Context 35 | 36 | Add any other context or screenshots about the feature request here. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ann-felix/terraform-aws-ecs-container-definition/bd476eb8406e2af3b59d4621f15b0fe7f5d0202a/.github/ISSUE_TEMPLATE/question.md -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## what 2 | * Describe high-level what changed as a result of these commits (i.e. in plain-english, what do these changes mean?) 3 | * Use bullet points to be concise and to the point. 4 | 5 | ## why 6 | * Provide the justifications for the changes (e.g. business case). 7 | * Describe why these changes were made (e.g. why do these commits fix the problem?) 8 | * Use bullet points to be concise and to the point. 9 | 10 | ## references 11 | * Link to any supporting github issues or helpful documentation to add some context (e.g. stackoverflow). 12 | * Use `closes #123`, if this PR closes a GitHub issue `#123` 13 | 14 | -------------------------------------------------------------------------------- /.github/auto-release.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION' 2 | tag-template: '$RESOLVED_VERSION' 3 | version-template: '$MAJOR.$MINOR.$PATCH' 4 | version-resolver: 5 | major: 6 | labels: 7 | - 'major' 8 | minor: 9 | labels: 10 | - 'minor' 11 | - 'enhancement' 12 | patch: 13 | labels: 14 | - 'auto-update' 15 | - 'patch' 16 | - 'fix' 17 | - 'bugfix' 18 | - 'bug' 19 | - 'hotfix' 20 | - 'no-release' 21 | default: 'minor' 22 | 23 | categories: 24 | - title: '🚀 Enhancements' 25 | labels: 26 | - 'enhancement' 27 | - 'patch' 28 | - title: '🐛 Bug Fixes' 29 | labels: 30 | - 'fix' 31 | - 'bugfix' 32 | - 'bug' 33 | - 'hotfix' 34 | - title: '🤖 Automatic Updates' 35 | labels: 36 | - 'auto-update' 37 | 38 | change-template: | 39 |
40 | $TITLE @$AUTHOR (#$NUMBER) 41 | 42 | $BODY 43 |
44 | 45 | template: | 46 | $CHANGES 47 | 48 | replacers: 49 | # Remove irrelevant information from Renovate bot 50 | - search: '/(?<=---\s)\s*^#.*(Renovate configuration|Configuration)(?:.|\n)*?This PR has been generated .*/gm' 51 | replace: '' 52 | # Remove Renovate bot banner image 53 | - search: '/\[!\[[^\]]*Renovate\][^\]]*\](\([^)]*\))?\s*\n+/gm' 54 | replace: '' 55 | -------------------------------------------------------------------------------- /.github/mergify.yml: -------------------------------------------------------------------------------- 1 | # https://docs.mergify.io/conditions.html 2 | # https://docs.mergify.io/actions.html 3 | pull_request_rules: 4 | - name: "approve automated PRs that have passed checks" 5 | conditions: 6 | - "author~=^(cloudpossebot|renovate\\[bot\\])$" 7 | - "base=master" 8 | - "-closed" 9 | - "head~=^(auto-update|renovate)/.*" 10 | - "check-success=test/bats" 11 | - "check-success=test/readme" 12 | - "check-success=test/terratest" 13 | - "check-success=validate-codeowners" 14 | actions: 15 | review: 16 | type: "APPROVE" 17 | bot_account: "cloudposse-mergebot" 18 | message: "We've automatically approved this PR because the checks from the automated Pull Request have passed." 19 | 20 | - name: "merge automated PRs when approved and tests pass" 21 | conditions: 22 | - "author~=^(cloudpossebot|renovate\\[bot\\])$" 23 | - "base=master" 24 | - "-closed" 25 | - "head~=^(auto-update|renovate)/.*" 26 | - "check-success=test/bats" 27 | - "check-success=test/readme" 28 | - "check-success=test/terratest" 29 | - "check-success=validate-codeowners" 30 | - "#approved-reviews-by>=1" 31 | - "#changes-requested-reviews-by=0" 32 | - "#commented-reviews-by=0" 33 | actions: 34 | merge: 35 | method: "squash" 36 | 37 | - name: "delete the head branch after merge" 38 | conditions: 39 | - "merged" 40 | actions: 41 | delete_head_branch: {} 42 | 43 | - name: "ask to resolve conflict" 44 | conditions: 45 | - "conflict" 46 | - "-closed" 47 | actions: 48 | comment: 49 | message: "This pull request is now in conflict. Could you fix it @{{author}}? 🙏" 50 | 51 | - name: "remove outdated reviews" 52 | conditions: 53 | - "base=master" 54 | actions: 55 | dismiss_reviews: 56 | changes_requested: true 57 | approved: true 58 | message: "This Pull Request has been updated, so we're dismissing all reviews." 59 | 60 | - name: "close Pull Requests without files changed" 61 | conditions: 62 | - "#files=0" 63 | actions: 64 | close: 65 | message: "This pull request has been automatically closed by Mergify because there are no longer any changes." 66 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":preserveSemverRanges" 5 | ], 6 | "labels": ["auto-update"], 7 | "enabledManagers": ["terraform"], 8 | "terraform": { 9 | "ignorePaths": ["**/context.tf", "examples/**"] 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /.github/workflows/auto-context.yml: -------------------------------------------------------------------------------- 1 | name: "auto-context" 2 | on: 3 | schedule: 4 | # Update context.tf nightly 5 | - cron: '0 3 * * *' 6 | 7 | jobs: 8 | update: 9 | if: github.event_name == 'schedule' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: Update context.tf 15 | shell: bash 16 | id: update 17 | env: 18 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 19 | run: | 20 | if [[ -f context.tf ]]; then 21 | echo "Discovered existing context.tf! Fetching most recent version to see if there is an update." 22 | curl -o context.tf -fsSL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf 23 | if git diff --no-patch --exit-code context.tf; then 24 | echo "No changes detected! Exiting the job..." 25 | else 26 | echo "context.tf file has changed. Update examples and rebuild README.md." 27 | make init 28 | make github/init/context.tf 29 | make readme/build 30 | echo "::set-output name=create_pull_request::true" 31 | fi 32 | else 33 | echo "This module has not yet been updated to support the context.tf pattern! Please update in order to support automatic updates." 34 | fi 35 | 36 | - name: Create Pull Request 37 | if: steps.update.outputs.create_pull_request == 'true' 38 | uses: cloudposse/actions/github/create-pull-request@0.30.0 39 | with: 40 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 41 | committer: 'cloudpossebot <11232728+cloudpossebot@users.noreply.github.com>' 42 | author: 'cloudpossebot <11232728+cloudpossebot@users.noreply.github.com>' 43 | commit-message: Update context.tf from origin source 44 | title: Update context.tf 45 | body: |- 46 | ## what 47 | This is an auto-generated PR that updates the `context.tf` file to the latest version from `cloudposse/terraform-null-label` 48 | 49 | ## why 50 | To support all the features of the `context` interface. 51 | 52 | branch: auto-update/context.tf 53 | base: master 54 | delete-branch: true 55 | labels: | 56 | auto-update 57 | context 58 | -------------------------------------------------------------------------------- /.github/workflows/auto-format.yml: -------------------------------------------------------------------------------- 1 | name: Auto Format 2 | on: 3 | pull_request_target: 4 | types: [opened, synchronize] 5 | 6 | jobs: 7 | auto-format: 8 | runs-on: ubuntu-latest 9 | container: cloudposse/build-harness:latest 10 | steps: 11 | # Checkout the pull request branch 12 | # "An action in a workflow run can’t trigger a new workflow run. For example, if an action pushes code using 13 | # the repository’s GITHUB_TOKEN, a new workflow will not run even when the repository contains 14 | # a workflow configured to run when push events occur." 15 | # However, using a personal access token will cause events to be triggered. 16 | # We need that to ensure a status gets posted after the auto-format commit. 17 | # We also want to trigger tests if the auto-format made no changes. 18 | - uses: actions/checkout@v2 19 | if: github.event.pull_request.state == 'open' 20 | name: Privileged Checkout 21 | with: 22 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 23 | repository: ${{ github.event.pull_request.head.repo.full_name }} 24 | # Check out the PR commit, not the merge commit 25 | # Use `ref` instead of `sha` to enable pushing back to `ref` 26 | ref: ${{ github.event.pull_request.head.ref }} 27 | 28 | # Do all the formatting stuff 29 | - name: Auto Format 30 | if: github.event.pull_request.state == 'open' 31 | shell: bash 32 | env: 33 | GITHUB_TOKEN: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" 34 | run: make BUILD_HARNESS_PATH=/build-harness PACKAGES_PREFER_HOST=true -f /build-harness/templates/Makefile.build-harness pr/auto-format/host 35 | 36 | # Commit changes (if any) to the PR branch 37 | - name: Commit changes to the PR branch 38 | if: github.event.pull_request.state == 'open' 39 | shell: bash 40 | id: commit 41 | env: 42 | SENDER: ${{ github.event.sender.login }} 43 | run: | 44 | set -x 45 | output=$(git diff --name-only) 46 | 47 | if [ -n "$output" ]; then 48 | echo "Changes detected. Pushing to the PR branch" 49 | git config --global user.name 'cloudpossebot' 50 | git config --global user.email '11232728+cloudpossebot@users.noreply.github.com' 51 | git add -A 52 | git commit -m "Auto Format" 53 | # Prevent looping by not pushing changes in response to changes from cloudpossebot 54 | [[ $SENDER == "cloudpossebot" ]] || git push 55 | # Set status to fail, because the push should trigger another status check, 56 | # and we use success to indicate the checks are finished. 57 | printf "::set-output name=%s::%s\n" "changed" "true" 58 | exit 1 59 | else 60 | printf "::set-output name=%s::%s\n" "changed" "false" 61 | echo "No changes detected" 62 | fi 63 | 64 | - name: Auto Test 65 | uses: cloudposse/actions/github/repository-dispatch@0.30.0 66 | # match users by ID because logins (user names) are inconsistent, 67 | # for example in the REST API Renovate Bot is `renovate[bot]` but 68 | # in GraphQL it is just `renovate`, plus there is a non-bot 69 | # user `renovate` with ID 1832810. 70 | # Mergify bot: 37929162 71 | # Renovate bot: 29139614 72 | # Cloudpossebot: 11232728 73 | # Need to use space separators to prevent "21" from matching "112144" 74 | if: > 75 | contains(' 37929162 29139614 11232728 ', format(' {0} ', github.event.pull_request.user.id)) 76 | && steps.commit.outputs.changed == 'false' && github.event.pull_request.state == 'open' 77 | with: 78 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 79 | repository: cloudposse/actions 80 | event-type: test-command 81 | client-payload: |- 82 | { "slash_command":{"args": {"unnamed": {"all": "all", "arg1": "all"}}}, 83 | "pull_request": ${{ toJSON(github.event.pull_request) }}, 84 | "github":{"payload":{"repository": ${{ toJSON(github.event.repository) }}, 85 | "comment": {"id": ""} 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /.github/workflows/auto-readme.yml: -------------------------------------------------------------------------------- 1 | name: "auto-readme" 2 | on: 3 | workflow_dispatch: 4 | 5 | schedule: 6 | # Example of job definition: 7 | # .---------------- minute (0 - 59) 8 | # | .------------- hour (0 - 23) 9 | # | | .---------- day of month (1 - 31) 10 | # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... 11 | # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 12 | # | | | | | 13 | # * * * * * user-name command to be executed 14 | 15 | # Update README.md nightly at 4am UTC 16 | - cron: '0 4 * * *' 17 | 18 | jobs: 19 | update: 20 | if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - name: Find default branch name 26 | id: defaultBranch 27 | shell: bash 28 | env: 29 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 30 | run: | 31 | default_branch=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name) 32 | printf "::set-output name=defaultBranch::%s\n" "${default_branch}" 33 | printf "defaultBranchRef.name=%s\n" "${default_branch}" 34 | 35 | - name: Update readme 36 | shell: bash 37 | id: update 38 | env: 39 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 40 | DEF: "${{ steps.defaultBranch.outputs.defaultBranch }}" 41 | run: | 42 | make init 43 | make readme/build 44 | # Ignore changes if they are only whitespace 45 | if ! git diff --quiet README.md && git diff --ignore-all-space --ignore-blank-lines --quiet README.md; then 46 | git restore README.md 47 | echo Ignoring whitespace-only changes in README 48 | fi 49 | 50 | - name: Create Pull Request 51 | # This action will not create or change a pull request if there are no changes to make. 52 | # If a PR of the auto-update/readme branch is open, this action will just update it, not create a new PR. 53 | uses: cloudposse/actions/github/create-pull-request@0.30.0 54 | with: 55 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 56 | commit-message: Update README.md and docs 57 | title: Update README.md and docs 58 | body: |- 59 | ## what 60 | This is an auto-generated PR that updates the README.md and docs 61 | 62 | ## why 63 | To have most recent changes of README.md and doc from origin templates 64 | 65 | branch: auto-update/readme 66 | base: ${{ steps.defaultBranch.outputs.defaultBranch }} 67 | delete-branch: true 68 | labels: | 69 | auto-update 70 | no-release 71 | readme 72 | -------------------------------------------------------------------------------- /.github/workflows/auto-release.yml: -------------------------------------------------------------------------------- 1 | name: auto-release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | - production 9 | 10 | jobs: 11 | publish: 12 | runs-on: ubuntu-latest 13 | steps: 14 | # Get PR from merged commit to master 15 | - uses: actions-ecosystem/action-get-merged-pull-request@v1 16 | id: get-merged-pull-request 17 | with: 18 | github_token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 19 | # Drafts your next Release notes as Pull Requests are merged into "main" 20 | - uses: release-drafter/release-drafter@v5 21 | with: 22 | publish: ${{ !contains(steps.get-merged-pull-request.outputs.labels, 'no-release') }} 23 | prerelease: false 24 | config-name: auto-release.yml 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/chatops.yml: -------------------------------------------------------------------------------- 1 | name: chatops 2 | on: 3 | issue_comment: 4 | types: [created] 5 | 6 | jobs: 7 | default: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: "Handle common commands" 12 | uses: cloudposse/actions/github/slash-command-dispatch@0.30.0 13 | with: 14 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 15 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 16 | repository: cloudposse/actions 17 | commands: rebuild-readme, terraform-fmt 18 | permission: triage 19 | issue-type: pull-request 20 | 21 | test: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: "Checkout commit" 25 | uses: actions/checkout@v2 26 | - name: "Run tests" 27 | uses: cloudposse/actions/github/slash-command-dispatch@0.30.0 28 | with: 29 | token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} 30 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 31 | repository: cloudposse/actions 32 | commands: test 33 | permission: triage 34 | issue-type: pull-request 35 | reactions: false 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/validate-codeowners.yml: -------------------------------------------------------------------------------- 1 | name: Validate Codeowners 2 | on: 3 | workflow_dispatch: 4 | 5 | pull_request: 6 | 7 | jobs: 8 | validate-codeowners: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: "Checkout source code at current commit" 12 | uses: actions/checkout@v2 13 | - uses: mszostok/codeowners-validator@v0.7.1 14 | if: github.event.pull_request.head.repo.full_name == github.repository 15 | name: "Full check of CODEOWNERS" 16 | with: 17 | # For now, remove "files" check to allow CODEOWNERS to specify non-existent 18 | # files so we can use the same CODEOWNERS file for Terraform and non-Terraform repos 19 | # checks: "files,syntax,owners,duppatterns" 20 | checks: "syntax,owners,duppatterns" 21 | owner_checker_allow_unowned_patterns: "false" 22 | # GitHub access token is required only if the `owners` check is enabled 23 | github_access_token: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" 24 | - uses: mszostok/codeowners-validator@v0.7.1 25 | if: github.event.pull_request.head.repo.full_name != github.repository 26 | name: "Syntax check of CODEOWNERS" 27 | with: 28 | checks: "syntax,duppatterns" 29 | owner_checker_allow_unowned_patterns: "false" 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.tfstate 3 | *.tfstate.backup 4 | 5 | # Module directory 6 | .terraform 7 | .idea 8 | *.iml 9 | 10 | .build-harness 11 | build-harness 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018-2019 Cloud Posse, LLC 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | # List of targets the `readme` target should call before generating the readme 4 | export README_DEPS ?= docs/targets.md docs/terraform.md 5 | 6 | -include $(shell curl -sSL -o .build-harness "https://cloudposse.tools/build-harness"; echo .build-harness) 7 | 8 | ## Lint terraform code 9 | lint: 10 | $(SELF) terraform/install terraform/get-modules terraform/get-plugins terraform/lint terraform/validate -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # terraform-aws-ecs-container-definition 4 | 5 | [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-ecs-container-definition.svg)](https://github.com/cloudposse/terraform-aws-ecs-container-definition/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) 6 | 7 | 8 | [![README Header][readme_header_img]][readme_header_link] 9 | 10 | [![Cloud Posse][logo]](https://cpco.io/homepage) 11 | 12 | 32 | 33 | Terraform module to generate well-formed JSON documents that are passed to the `aws_ecs_task_definition` Terraform resource as [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions). 34 | 35 | --- 36 | 37 | This project is part of our comprehensive ["SweetOps"](https://cpco.io/sweetops) approach towards DevOps. 38 | [][share_email] 39 | [][share_googleplus] 40 | [][share_facebook] 41 | [][share_reddit] 42 | [][share_linkedin] 43 | [][share_twitter] 44 | 45 | 46 | [![Terraform Open Source Modules](https://docs.cloudposse.com/images/terraform-open-source-modules.svg)][terraform_modules] 47 | 48 | 49 | 50 | It's 100% Open Source and licensed under the [APACHE2](LICENSE). 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | We literally have [*hundreds of terraform modules*][terraform_modules] that are Open Source and well-maintained. Check them out! 59 | 60 | 61 | 62 | 63 | 64 | 65 | ## Security & Compliance [](https://bridgecrew.io/) 66 | 67 | Security scanning is graciously provided by Bridgecrew. Bridgecrew is the leading fully hosted, cloud-native solution providing continuous Terraform security and compliance. 68 | 69 | | Benchmark | Description | 70 | |--------|---------------| 71 | | [![Infrastructure Security](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/general)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=INFRASTRUCTURE+SECURITY) | Infrastructure Security Compliance | 72 | | [![CIS KUBERNETES](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/cis_kubernetes)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=CIS+KUBERNETES+V1.5) | Center for Internet Security, KUBERNETES Compliance | 73 | | [![CIS AWS](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/cis_aws)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=CIS+AWS+V1.2) | Center for Internet Security, AWS Compliance | 74 | | [![CIS AZURE](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/cis_azure)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=CIS+AZURE+V1.1) | Center for Internet Security, AZURE Compliance | 75 | | [![PCI-DSS](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/pci)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=PCI-DSS+V3.2) | Payment Card Industry Data Security Standards Compliance | 76 | | [![NIST-800-53](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/nist)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=NIST-800-53) | National Institute of Standards and Technology Compliance | 77 | | [![ISO27001](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/iso)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=ISO27001) | Information Security Management System, ISO/IEC 27001 Compliance | 78 | | [![SOC2](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/soc2)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=SOC2)| Service Organization Control 2 Compliance | 79 | | [![CIS GCP](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/cis_gcp)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=CIS+GCP+V1.1) | Center for Internet Security, GCP Compliance | 80 | | [![HIPAA](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-ecs-container-definition/hipaa)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-ecs-container-definition&benchmark=HIPAA) | Health Insurance Portability and Accountability Compliance | 81 | 82 | 83 | 84 | ## Usage 85 | 86 | 87 | **IMPORTANT:** We do not pin modules to versions in our examples because of the 88 | difficulty of keeping the versions in the documentation in sync with the latest released versions. 89 | We highly recommend that in your code you pin the version to the exact version you are 90 | using so that your infrastructure remains stable, and update versions in a 91 | systematic way so that they do not catch you by surprise. 92 | 93 | Also, because of a bug in the Terraform registry ([hashicorp/terraform#21417](https://github.com/hashicorp/terraform/issues/21417)), 94 | the registry shows many of our inputs as required when in fact they are optional. 95 | The table below correctly indicates which inputs are required. 96 | 97 | 98 | This module is meant to be used as output only, meaning it will be used to create outputs which are consumed as a parameter by Terraform resources or other modules. 99 | 100 | Caution: This module, unlike nearly all other Cloud Posse Terraform modules, does not use [terraform-null-label](https://github.com/cloudposse/terraform-null-label/). 101 | Furthermore, it has an input named `environment` which has a completely different meaning than the one in `terraform-null-label`. 102 | Do not call this module with the conventional `context = module.this.context`. See the documentation below for the usage of `environment`. 103 | 104 | For complete examples, see 105 | 106 | - [multi-port mappings](examples/multi_port_mappings) 107 | - [multi-type env vars](examples/multi_type_env_vars) 108 | - [multiple definitions](examples/multiple_definitions) 109 | - [string env vars](examples/string_env_vars) 110 | 111 | For a complete example with automated tests, see [examples/complete](examples/complete) with `bats` and `Terratest` for the example [test](test). 112 | 113 | ```hcl 114 | module "container_definition" { 115 | source = "cloudposse/ecs-container-definition/aws" 116 | # Cloud Posse recommends pinning every module to a specific version 117 | # version = "x.x.x" 118 | 119 | container_name = "geodesic" 120 | container_image = "cloudposse/geodesic" 121 | } 122 | ``` 123 | 124 | The output of this module can then be used with one of our other modules. 125 | 126 | ```hcl 127 | module "ecs_alb_service_task" { 128 | source = "cloudposse/ecs-alb-service-task/aws" 129 | # Cloud Posse recommends pinning every module to a specific version 130 | # version = "x.x.x" 131 | 132 | # ... 133 | container_definition_json = module.container_definition.json_map_encoded_list 134 | # ... 135 | } 136 | ``` 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | ## Makefile Targets 145 | ```text 146 | Available targets: 147 | 148 | help Help screen 149 | help/all Display help for all targets 150 | help/short This help short screen 151 | lint Lint terraform code 152 | 153 | ``` 154 | 155 | 156 | ## Requirements 157 | 158 | | Name | Version | 159 | |------|---------| 160 | | [terraform](#requirement\_terraform) | >= 0.13.0 | 161 | | [local](#requirement\_local) | >= 1.2 | 162 | 163 | ## Providers 164 | 165 | No providers. 166 | 167 | ## Modules 168 | 169 | No modules. 170 | 171 | ## Resources 172 | 173 | No resources. 174 | 175 | ## Inputs 176 | 177 | | Name | Description | Type | Default | Required | 178 | |------|-------------|------|---------|:--------:| 179 | | [command](#input\_command) | The command that is passed to the container | `list(string)` | `null` | no | 180 | | [container\_cpu](#input\_container\_cpu) | The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of container\_cpu of all containers in a task will need to be lower than the task-level cpu value | `number` | `0` | no | 181 | | [container\_definition](#input\_container\_definition) | Container definition overrides which allows for extra keys or overriding existing keys. | `map(any)` | `{}` | no | 182 | | [container\_depends\_on](#input\_container\_depends\_on) | The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY |
list(object({
containerName = string
condition = string
}))
| `null` | no | 183 | | [container\_image](#input\_container\_image) | The image used to start the container. Images in the Docker Hub registry available by default | `string` | n/a | yes | 184 | | [container\_memory](#input\_container\_memory) | The amount of memory (in MiB) to allow the container to use. This is a hard limit, if the container attempts to exceed the container\_memory, the container is killed. This field is optional for Fargate launch type and the total amount of container\_memory of all containers in a task will need to be lower than the task memory value | `number` | `null` | no | 185 | | [container\_memory\_reservation](#input\_container\_memory\_reservation) | The amount of memory (in MiB) to reserve for the container. If container needs to exceed this threshold, it can do so up to the set container\_memory hard limit | `number` | `null` | no | 186 | | [container\_name](#input\_container\_name) | The name of the container. Up to 255 characters ([a-z], [A-Z], [0-9], -, \_ allowed) | `string` | n/a | yes | 187 | | [disable\_networking](#input\_disable\_networking) | When this parameter is true, networking is disabled within the container. | `bool` | `null` | no | 188 | | [dns\_search\_domains](#input\_dns\_search\_domains) | Container DNS search domains. A list of DNS search domains that are presented to the container | `list(string)` | `null` | no | 189 | | [dns\_servers](#input\_dns\_servers) | Container DNS servers. This is a list of strings specifying the IP addresses of the DNS servers | `list(string)` | `null` | no | 190 | | [docker\_labels](#input\_docker\_labels) | The configuration options to send to the `docker_labels` | `map(string)` | `null` | no | 191 | | [docker\_security\_options](#input\_docker\_security\_options) | A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems. | `list(string)` | `null` | no | 192 | | [entrypoint](#input\_entrypoint) | The entry point that is passed to the container | `list(string)` | `null` | no | 193 | | [environment](#input\_environment) | The environment variables to pass to the container. This is a list of maps. map\_environment overrides environment |
list(object({
name = string
value = string
}))
| `[]` | no | 194 | | [environment\_files](#input\_environment\_files) | One or more files containing the environment variables to pass to the container. This maps to the --env-file option to docker run. The file must be hosted in Amazon S3. This option is only available to tasks using the EC2 launch type. This is a list of maps |
list(object({
value = string
type = string
}))
| `null` | no | 195 | | [essential](#input\_essential) | Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `true` | no | 196 | | [extra\_hosts](#input\_extra\_hosts) | A list of hostnames and IP address mappings to append to the /etc/hosts file on the container. This is a list of maps |
list(object({
ipAddress = string
hostname = string
}))
| `null` | no | 197 | | [firelens\_configuration](#input\_firelens\_configuration) | The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html |
object({
type = string
options = map(string)
})
| `null` | no | 198 | | [healthcheck](#input\_healthcheck) | A map containing command (string), timeout, interval (duration in seconds), retries (1-10, number of times to retry before marking container unhealthy), and startPeriod (0-300, optional grace period to wait, in seconds, before failed healthchecks count toward retries) |
object({
command = list(string)
retries = number
timeout = number
interval = number
startPeriod = number
})
| `null` | no | 199 | | [hostname](#input\_hostname) | The hostname to use for your container. | `string` | `null` | no | 200 | | [interactive](#input\_interactive) | When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated. | `bool` | `null` | no | 201 | | [links](#input\_links) | List of container names this container can communicate with without port mappings | `list(string)` | `null` | no | 202 | | [linux\_parameters](#input\_linux\_parameters) | Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html |
object({
capabilities = object({
add = list(string)
drop = list(string)
})
devices = list(object({
containerPath = string
hostPath = string
permissions = list(string)
}))
initProcessEnabled = bool
maxSwap = number
sharedMemorySize = number
swappiness = number
tmpfs = list(object({
containerPath = string
mountOptions = list(string)
size = number
}))
})
| `null` | no | 203 | | [log\_configuration](#input\_log\_configuration) | Log configuration options to send to a custom log driver for the container. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html | `any` | `null` | no | 204 | | [map\_environment](#input\_map\_environment) | The environment variables to pass to the container. This is a map of string: {key: value}. map\_environment overrides environment | `map(string)` | `null` | no | 205 | | [map\_secrets](#input\_map\_secrets) | The secrets variables to pass to the container. This is a map of string: {key: value}. map\_secrets overrides secrets | `map(string)` | `null` | no | 206 | | [mount\_points](#input\_mount\_points) | Container mount points. This is a list of maps, where each map should contain `containerPath`, `sourceVolume` and `readOnly` |
list(object({
containerPath = string
sourceVolume = string
readOnly = bool
}))
| `[]` | no | 207 | | [port\_mappings](#input\_port\_mappings) | The port mappings to configure for the container. This is a list of maps. Each map should contain "containerPort", "hostPort", and "protocol", where "protocol" is one of "tcp" or "udp". If using containers in a task with the awsvpc or host network mode, the hostPort can either be left blank or set to the same value as the containerPort |
list(object({
containerPort = number
hostPort = number
protocol = string
}))
| `[]` | no | 208 | | [privileged](#input\_privileged) | When this variable is `true`, the container is given elevated privileges on the host container instance (similar to the root user). This parameter is not supported for Windows containers or tasks using the Fargate launch type. | `bool` | `null` | no | 209 | | [pseudo\_terminal](#input\_pseudo\_terminal) | When this parameter is true, a TTY is allocated. | `bool` | `null` | no | 210 | | [readonly\_root\_filesystem](#input\_readonly\_root\_filesystem) | Determines whether a container is given read-only access to its root filesystem. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `false` | no | 211 | | [repository\_credentials](#input\_repository\_credentials) | Container repository credentials; required when using a private repo. This map currently supports a single key; "credentialsParameter", which should be the ARN of a Secrets Manager's secret holding the credentials | `map(string)` | `null` | no | 212 | | [resource\_requirements](#input\_resource\_requirements) | The type and amount of a resource to assign to a container. The only supported resource is a GPU. |
list(object({
type = string
value = string
}))
| `null` | no | 213 | | [secrets](#input\_secrets) | The secrets to pass to the container. This is a list of maps |
list(object({
name = string
valueFrom = string
}))
| `[]` | no | 214 | | [start\_timeout](#input\_start\_timeout) | Time duration (in seconds) to wait before giving up on resolving dependencies for a container | `number` | `null` | no | 215 | | [stop\_timeout](#input\_stop\_timeout) | Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own | `number` | `null` | no | 216 | | [system\_controls](#input\_system\_controls) | A list of namespaced kernel parameters to set in the container, mapping to the --sysctl option to docker run. This is a list of maps: { namespace = "", value = ""} | `list(map(string))` | `null` | no | 217 | | [ulimits](#input\_ulimits) | Container ulimit settings. This is a list of maps, where each map should contain "name", "hardLimit" and "softLimit" |
list(object({
name = string
hardLimit = number
softLimit = number
}))
| `null` | no | 218 | | [user](#input\_user) | The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set. | `string` | `null` | no | 219 | | [volumes\_from](#input\_volumes\_from) | A list of VolumesFrom maps which contain "sourceContainer" (name of the container that has the volumes to mount) and "readOnly" (whether the container can write to the volume) |
list(object({
sourceContainer = string
readOnly = bool
}))
| `[]` | no | 220 | | [working\_directory](#input\_working\_directory) | The working directory to run commands inside the container | `string` | `null` | no | 221 | 222 | ## Outputs 223 | 224 | | Name | Description | 225 | |------|-------------| 226 | | [json\_map\_encoded](#output\_json\_map\_encoded) | JSON string encoded container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | 227 | | [json\_map\_encoded\_list](#output\_json\_map\_encoded\_list) | JSON string encoded list of container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | 228 | | [json\_map\_object](#output\_json\_map\_object) | JSON map encoded container definition | 229 | | [sensitive\_json\_map\_encoded](#output\_sensitive\_json\_map\_encoded) | JSON string encoded container definitions for use with other terraform resources such as aws\_ecs\_task\_definition (sensitive) | 230 | | [sensitive\_json\_map\_encoded\_list](#output\_sensitive\_json\_map\_encoded\_list) | JSON string encoded list of container definitions for use with other terraform resources such as aws\_ecs\_task\_definition (sensitive) | 231 | | [sensitive\_json\_map\_object](#output\_sensitive\_json\_map\_object) | JSON map encoded container definition (sensitive) | 232 | 233 | 234 | 235 | 236 | ## Share the Love 237 | 238 | Like this project? Please give it a ★ on [our GitHub](https://github.com/cloudposse/terraform-aws-ecs-container-definition)! (it helps us **a lot**) 239 | 240 | Are you using this project or any of our other projects? Consider [leaving a testimonial][testimonial]. =) 241 | 242 | 243 | 244 | ## Related Projects 245 | 246 | Check out these related projects. 247 | 248 | - [terraform-aws-ecs-codepipeline](https://github.com/cloudposse/terraform-aws-ecs-codepipeline) - Terraform module for CI/CD with AWS Code Pipeline and Code Build for ECS 249 | - [terraform-aws-ecs-events](https://github.com/cloudposse/terraform-aws-ecs-events) - Provides a standard set of ECS events that notify an SNS topic 250 | - [terraform-aws-ecs-cloudwatch-autoscaling](https://github.com/cloudposse/terraform-aws-ecs-cloudwatch-autoscaling) - Terraform module to autoscale ECS Service based on CloudWatch metrics 251 | - [terraform-aws-ecs-container-definition](https://github.com/cloudposse/terraform-aws-ecs-container-definition) - Terraform module to generate well-formed JSON documents (container definitions) that are passed to the aws_ecs_task_definition Terraform resource 252 | - [terraform-aws-ecs-launch-template](https://github.com/cloudposse/terraform-aws-ecs-launch-template) - Terraform module for generating an AWS Launch Template for ECS that handles draining on Spot Termination Requests 253 | - [terraform-aws-ecs-web-app](https://github.com/cloudposse/terraform-aws-ecs-web-app) - Terraform module that implements a web app on ECS and supporting AWS resources 254 | - [terraform-aws-ecs-spot-fleet](https://github.com/cloudposse/terraform-aws-ecs-spot-fleet) - Terraform module to create a diversified spot fleet for ECS clusters 255 | - [terraform-aws-ecs-cloudwatch-sns-alarms](https://github.com/cloudposse/terraform-aws-ecs-cloudwatch-sns-alarms) - Terraform module to create CloudWatch Alarms on ECS Service level metrics 256 | - [terraform-aws-ecs-alb-service-task](https://github.com/cloudposse/terraform-aws-ecs-alb-service-task) - Terraform module which implements an ECS service which exposes a web service via ALB 257 | 258 | ## Help 259 | 260 | **Got a question?** We got answers. 261 | 262 | File a GitHub [issue](https://github.com/cloudposse/terraform-aws-ecs-container-definition/issues), send us an [email][email] or join our [Slack Community][slack]. 263 | 264 | [![README Commercial Support][readme_commercial_support_img]][readme_commercial_support_link] 265 | 266 | ## DevOps Accelerator for Startups 267 | 268 | 269 | We are a [**DevOps Accelerator**][commercial_support]. We'll help you build your cloud infrastructure from the ground up so you can own it. Then we'll show you how to operate it and stick around for as long as you need us. 270 | 271 | [![Learn More](https://img.shields.io/badge/learn%20more-success.svg?style=for-the-badge)][commercial_support] 272 | 273 | Work directly with our team of DevOps experts via email, slack, and video conferencing. 274 | 275 | We deliver 10x the value for a fraction of the cost of a full-time engineer. Our track record is not even funny. If you want things done right and you need it done FAST, then we're your best bet. 276 | 277 | - **Reference Architecture.** You'll get everything you need from the ground up built using 100% infrastructure as code. 278 | - **Release Engineering.** You'll have end-to-end CI/CD with unlimited staging environments. 279 | - **Site Reliability Engineering.** You'll have total visibility into your apps and microservices. 280 | - **Security Baseline.** You'll have built-in governance with accountability and audit logs for all changes. 281 | - **GitOps.** You'll be able to operate your infrastructure via Pull Requests. 282 | - **Training.** You'll receive hands-on training so your team can operate what we build. 283 | - **Questions.** You'll have a direct line of communication between our teams via a Shared Slack channel. 284 | - **Troubleshooting.** You'll get help to triage when things aren't working. 285 | - **Code Reviews.** You'll receive constructive feedback on Pull Requests. 286 | - **Bug Fixes.** We'll rapidly work with you to fix any bugs in our projects. 287 | 288 | ## Slack Community 289 | 290 | Join our [Open Source Community][slack] on Slack. It's **FREE** for everyone! Our "SweetOps" community is where you get to talk with others who share a similar vision for how to rollout and manage infrastructure. This is the best place to talk shop, ask questions, solicit feedback, and work together as a community to build totally *sweet* infrastructure. 291 | 292 | ## Discourse Forums 293 | 294 | Participate in our [Discourse Forums][discourse]. Here you'll find answers to commonly asked questions. Most questions will be related to the enormous number of projects we support on our GitHub. Come here to collaborate on answers, find solutions, and get ideas about the products and services we value. It only takes a minute to get started! Just sign in with SSO using your GitHub account. 295 | 296 | ## Newsletter 297 | 298 | Sign up for [our newsletter][newsletter] that covers everything on our technology radar. Receive updates on what we're up to on GitHub as well as awesome new projects we discover. 299 | 300 | ## Office Hours 301 | 302 | [Join us every Wednesday via Zoom][office_hours] for our weekly "Lunch & Learn" sessions. It's **FREE** for everyone! 303 | 304 | [![zoom](https://img.cloudposse.com/fit-in/200x200/https://cloudposse.com/wp-content/uploads/2019/08/Powered-by-Zoom.png")][office_hours] 305 | 306 | ## Contributing 307 | 308 | ### Bug Reports & Feature Requests 309 | 310 | Please use the [issue tracker](https://github.com/cloudposse/terraform-aws-ecs-container-definition/issues) to report any bugs or file feature requests. 311 | 312 | ### Developing 313 | 314 | If you are interested in being a contributor and want to get involved in developing this project or [help out](https://cpco.io/help-out) with our other projects, we would love to hear from you! Shoot us an [email][email]. 315 | 316 | In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. 317 | 318 | 1. **Fork** the repo on GitHub 319 | 2. **Clone** the project to your own machine 320 | 3. **Commit** changes to your own branch 321 | 4. **Push** your work back up to your fork 322 | 5. Submit a **Pull Request** so that we can review your changes 323 | 324 | **NOTE:** Be sure to merge the latest changes from "upstream" before making a pull request! 325 | 326 | 327 | ## Copyright 328 | 329 | Copyright © 2017-2022 [Cloud Posse, LLC](https://cpco.io/copyright) 330 | 331 | 332 | 333 | ## License 334 | 335 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 336 | 337 | See [LICENSE](LICENSE) for full details. 338 | 339 | ```text 340 | Licensed to the Apache Software Foundation (ASF) under one 341 | or more contributor license agreements. See the NOTICE file 342 | distributed with this work for additional information 343 | regarding copyright ownership. The ASF licenses this file 344 | to you under the Apache License, Version 2.0 (the 345 | "License"); you may not use this file except in compliance 346 | with the License. You may obtain a copy of the License at 347 | 348 | https://www.apache.org/licenses/LICENSE-2.0 349 | 350 | Unless required by applicable law or agreed to in writing, 351 | software distributed under the License is distributed on an 352 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 353 | KIND, either express or implied. See the License for the 354 | specific language governing permissions and limitations 355 | under the License. 356 | ``` 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | ## Trademarks 367 | 368 | All other trademarks referenced herein are the property of their respective owners. 369 | 370 | ## About 371 | 372 | This project is maintained and funded by [Cloud Posse, LLC][website]. Like it? Please let us know by [leaving a testimonial][testimonial]! 373 | 374 | [![Cloud Posse][logo]][website] 375 | 376 | We're a [DevOps Professional Services][hire] company based in Los Angeles, CA. We ❤️ [Open Source Software][we_love_open_source]. 377 | 378 | We offer [paid support][commercial_support] on all of our projects. 379 | 380 | Check out [our other projects][github], [follow us on twitter][twitter], [apply for a job][jobs], or [hire us][hire] to help with your cloud strategy and implementation. 381 | 382 | 383 | 384 | ### Contributors 385 | 386 | 387 | | [![Erik Osterman][osterman_avatar]][osterman_homepage]
[Erik Osterman][osterman_homepage] | [![Sarkis Varozian][sarkis_avatar]][sarkis_homepage]
[Sarkis Varozian][sarkis_homepage] | [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]
[Andriy Knysh][aknysh_homepage] | [![Igor Rodionov][goruha_avatar]][goruha_homepage]
[Igor Rodionov][goruha_homepage] | [![Yonatan Koren][korenyoni_avatar]][korenyoni_homepage]
[Yonatan Koren][korenyoni_homepage] | [![RB][nitrocode_avatar]][nitrocode_homepage]
[RB][nitrocode_homepage] | 388 | |---|---|---|---|---|---| 389 | 390 | 391 | [osterman_homepage]: https://github.com/osterman 392 | [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png 393 | [sarkis_homepage]: https://github.com/sarkis 394 | [sarkis_avatar]: https://img.cloudposse.com/150x150/https://github.com/sarkis.png 395 | [aknysh_homepage]: https://github.com/aknysh 396 | [aknysh_avatar]: https://img.cloudposse.com/150x150/https://github.com/aknysh.png 397 | [goruha_homepage]: https://github.com/goruha 398 | [goruha_avatar]: https://img.cloudposse.com/150x150/https://github.com/goruha.png 399 | [korenyoni_homepage]: https://github.com/korenyoni 400 | [korenyoni_avatar]: https://img.cloudposse.com/150x150/https://github.com/korenyoni.png 401 | [nitrocode_homepage]: https://github.com/nitrocode 402 | [nitrocode_avatar]: https://img.cloudposse.com/150x150/https://github.com/nitrocode.png 403 | 404 | [![README Footer][readme_footer_img]][readme_footer_link] 405 | [![Beacon][beacon]][website] 406 | 407 | [logo]: https://cloudposse.com/logo-300x69.svg 408 | [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=docs 409 | [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=website 410 | [github]: https://cpco.io/github?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=github 411 | [jobs]: https://cpco.io/jobs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=jobs 412 | [hire]: https://cpco.io/hire?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=hire 413 | [slack]: https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=slack 414 | [linkedin]: https://cpco.io/linkedin?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=linkedin 415 | [twitter]: https://cpco.io/twitter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=twitter 416 | [testimonial]: https://cpco.io/leave-testimonial?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=testimonial 417 | [office_hours]: https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=office_hours 418 | [newsletter]: https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=newsletter 419 | [discourse]: https://ask.sweetops.com/?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=discourse 420 | [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=email 421 | [commercial_support]: https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=commercial_support 422 | [we_love_open_source]: https://cpco.io/we-love-open-source?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=we_love_open_source 423 | [terraform_modules]: https://cpco.io/terraform-modules?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=terraform_modules 424 | [readme_header_img]: https://cloudposse.com/readme/header/img 425 | [readme_header_link]: https://cloudposse.com/readme/header/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=readme_header_link 426 | [readme_footer_img]: https://cloudposse.com/readme/footer/img 427 | [readme_footer_link]: https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=readme_footer_link 428 | [readme_commercial_support_img]: https://cloudposse.com/readme/commercial-support/img 429 | [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-ecs-container-definition&utm_content=readme_commercial_support_link 430 | [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-aws-ecs-container-definition&url=https://github.com/cloudposse/terraform-aws-ecs-container-definition 431 | [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-aws-ecs-container-definition&url=https://github.com/cloudposse/terraform-aws-ecs-container-definition 432 | [share_reddit]: https://reddit.com/submit/?url=https://github.com/cloudposse/terraform-aws-ecs-container-definition 433 | [share_facebook]: https://facebook.com/sharer/sharer.php?u=https://github.com/cloudposse/terraform-aws-ecs-container-definition 434 | [share_googleplus]: https://plus.google.com/share?url=https://github.com/cloudposse/terraform-aws-ecs-container-definition 435 | [share_email]: mailto:?subject=terraform-aws-ecs-container-definition&body=https://github.com/cloudposse/terraform-aws-ecs-container-definition 436 | [beacon]: https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-aws-ecs-container-definition?pixel&cs=github&cm=readme&an=terraform-aws-ecs-container-definition 437 | -------------------------------------------------------------------------------- /README.yaml: -------------------------------------------------------------------------------- 1 | name: terraform-aws-ecs-container-definition 2 | license: APACHE2 3 | github_repo: cloudposse/terraform-aws-ecs-container-definition 4 | badges: 5 | - name: Latest Release 6 | image: https://img.shields.io/github/release/cloudposse/terraform-aws-ecs-container-definition.svg 7 | url: https://github.com/cloudposse/terraform-aws-ecs-container-definition/releases/latest 8 | - name: Slack Community 9 | image: https://slack.cloudposse.com/badge.svg 10 | url: https://slack.cloudposse.com 11 | related: 12 | - name: terraform-aws-ecs-codepipeline 13 | description: Terraform module for CI/CD with AWS Code Pipeline and Code Build for 14 | ECS 15 | url: https://github.com/cloudposse/terraform-aws-ecs-codepipeline 16 | - name: terraform-aws-ecs-events 17 | description: Provides a standard set of ECS events that notify an SNS topic 18 | url: https://github.com/cloudposse/terraform-aws-ecs-events 19 | - name: terraform-aws-ecs-cloudwatch-autoscaling 20 | description: Terraform module to autoscale ECS Service based on CloudWatch metrics 21 | url: https://github.com/cloudposse/terraform-aws-ecs-cloudwatch-autoscaling 22 | - name: terraform-aws-ecs-container-definition 23 | description: Terraform module to generate well-formed JSON documents (container 24 | definitions) that are passed to the aws_ecs_task_definition Terraform resource 25 | url: https://github.com/cloudposse/terraform-aws-ecs-container-definition 26 | - name: terraform-aws-ecs-launch-template 27 | description: Terraform module for generating an AWS Launch Template for ECS that 28 | handles draining on Spot Termination Requests 29 | url: https://github.com/cloudposse/terraform-aws-ecs-launch-template 30 | - name: terraform-aws-ecs-web-app 31 | description: Terraform module that implements a web app on ECS and supporting AWS 32 | resources 33 | url: https://github.com/cloudposse/terraform-aws-ecs-web-app 34 | - name: terraform-aws-ecs-spot-fleet 35 | description: Terraform module to create a diversified spot fleet for ECS clusters 36 | url: https://github.com/cloudposse/terraform-aws-ecs-spot-fleet 37 | - name: terraform-aws-ecs-cloudwatch-sns-alarms 38 | description: Terraform module to create CloudWatch Alarms on ECS Service level metrics 39 | url: https://github.com/cloudposse/terraform-aws-ecs-cloudwatch-sns-alarms 40 | - name: terraform-aws-ecs-alb-service-task 41 | description: Terraform module which implements an ECS service which exposes a web 42 | service via ALB 43 | url: https://github.com/cloudposse/terraform-aws-ecs-alb-service-task 44 | description: Terraform module to generate well-formed JSON documents that are passed 45 | to the `aws_ecs_task_definition` Terraform resource as [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions). 46 | usage: |- 47 | This module is meant to be used as output only, meaning it will be used to create outputs which are consumed as a parameter by Terraform resources or other modules. 48 | 49 | Caution: This module, unlike nearly all other Cloud Posse Terraform modules, does not use [terraform-null-label](https://github.com/cloudposse/terraform-null-label/). 50 | Furthermore, it has an input named `environment` which has a completely different meaning than the one in `terraform-null-label`. 51 | Do not call this module with the conventional `context = module.this.context`. See the documentation below for the usage of `environment`. 52 | 53 | For complete examples, see 54 | 55 | - [multi-port mappings](examples/multi_port_mappings) 56 | - [multi-type env vars](examples/multi_type_env_vars) 57 | - [multiple definitions](examples/multiple_definitions) 58 | - [string env vars](examples/string_env_vars) 59 | 60 | For a complete example with automated tests, see [examples/complete](examples/complete) with `bats` and `Terratest` for the example [test](test). 61 | 62 | ```hcl 63 | module "container_definition" { 64 | source = "cloudposse/ecs-container-definition/aws" 65 | # Cloud Posse recommends pinning every module to a specific version 66 | # version = "x.x.x" 67 | 68 | container_name = "geodesic" 69 | container_image = "cloudposse/geodesic" 70 | } 71 | ``` 72 | 73 | The output of this module can then be used with one of our other modules. 74 | 75 | ```hcl 76 | module "ecs_alb_service_task" { 77 | source = "cloudposse/ecs-alb-service-task/aws" 78 | # Cloud Posse recommends pinning every module to a specific version 79 | # version = "x.x.x" 80 | 81 | # ... 82 | container_definition_json = module.container_definition.json_map_encoded_list 83 | # ... 84 | } 85 | ``` 86 | 87 | include: 88 | - docs/targets.md 89 | - docs/terraform.md 90 | contributors: 91 | - name: Erik Osterman 92 | github: osterman 93 | - name: Sarkis Varozian 94 | github: sarkis 95 | - name: Andriy Knysh 96 | github: aknysh 97 | - name: Igor Rodionov 98 | github: goruha 99 | - name: Yonatan Koren 100 | github: korenyoni 101 | - name: RB 102 | github: nitrocode 103 | -------------------------------------------------------------------------------- /docs/targets.md: -------------------------------------------------------------------------------- 1 | 2 | ## Makefile Targets 3 | ```text 4 | Available targets: 5 | 6 | help Help screen 7 | help/all Display help for all targets 8 | help/short This help short screen 9 | lint Lint terraform code 10 | 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /docs/terraform.md: -------------------------------------------------------------------------------- 1 | 2 | ## Requirements 3 | 4 | | Name | Version | 5 | |------|---------| 6 | | [terraform](#requirement\_terraform) | >= 0.13.0 | 7 | | [local](#requirement\_local) | >= 1.2 | 8 | 9 | ## Providers 10 | 11 | No providers. 12 | 13 | ## Modules 14 | 15 | No modules. 16 | 17 | ## Resources 18 | 19 | No resources. 20 | 21 | ## Inputs 22 | 23 | | Name | Description | Type | Default | Required | 24 | |------|-------------|------|---------|:--------:| 25 | | [command](#input\_command) | The command that is passed to the container | `list(string)` | `null` | no | 26 | | [container\_cpu](#input\_container\_cpu) | The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of container\_cpu of all containers in a task will need to be lower than the task-level cpu value | `number` | `0` | no | 27 | | [container\_definition](#input\_container\_definition) | Container definition overrides which allows for extra keys or overriding existing keys. | `map(any)` | `{}` | no | 28 | | [container\_depends\_on](#input\_container\_depends\_on) | The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY |
list(object({
containerName = string
condition = string
}))
| `null` | no | 29 | | [container\_image](#input\_container\_image) | The image used to start the container. Images in the Docker Hub registry available by default | `string` | n/a | yes | 30 | | [container\_memory](#input\_container\_memory) | The amount of memory (in MiB) to allow the container to use. This is a hard limit, if the container attempts to exceed the container\_memory, the container is killed. This field is optional for Fargate launch type and the total amount of container\_memory of all containers in a task will need to be lower than the task memory value | `number` | `null` | no | 31 | | [container\_memory\_reservation](#input\_container\_memory\_reservation) | The amount of memory (in MiB) to reserve for the container. If container needs to exceed this threshold, it can do so up to the set container\_memory hard limit | `number` | `null` | no | 32 | | [container\_name](#input\_container\_name) | The name of the container. Up to 255 characters ([a-z], [A-Z], [0-9], -, \_ allowed) | `string` | n/a | yes | 33 | | [disable\_networking](#input\_disable\_networking) | When this parameter is true, networking is disabled within the container. | `bool` | `null` | no | 34 | | [dns\_search\_domains](#input\_dns\_search\_domains) | Container DNS search domains. A list of DNS search domains that are presented to the container | `list(string)` | `null` | no | 35 | | [dns\_servers](#input\_dns\_servers) | Container DNS servers. This is a list of strings specifying the IP addresses of the DNS servers | `list(string)` | `null` | no | 36 | | [docker\_labels](#input\_docker\_labels) | The configuration options to send to the `docker_labels` | `map(string)` | `null` | no | 37 | | [docker\_security\_options](#input\_docker\_security\_options) | A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems. | `list(string)` | `null` | no | 38 | | [entrypoint](#input\_entrypoint) | The entry point that is passed to the container | `list(string)` | `null` | no | 39 | | [environment](#input\_environment) | The environment variables to pass to the container. This is a list of maps. map\_environment overrides environment |
list(object({
name = string
value = string
}))
| `[]` | no | 40 | | [environment\_files](#input\_environment\_files) | One or more files containing the environment variables to pass to the container. This maps to the --env-file option to docker run. The file must be hosted in Amazon S3. This option is only available to tasks using the EC2 launch type. This is a list of maps |
list(object({
value = string
type = string
}))
| `null` | no | 41 | | [essential](#input\_essential) | Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `true` | no | 42 | | [extra\_hosts](#input\_extra\_hosts) | A list of hostnames and IP address mappings to append to the /etc/hosts file on the container. This is a list of maps |
list(object({
ipAddress = string
hostname = string
}))
| `null` | no | 43 | | [firelens\_configuration](#input\_firelens\_configuration) | The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html |
object({
type = string
options = map(string)
})
| `null` | no | 44 | | [healthcheck](#input\_healthcheck) | A map containing command (string), timeout, interval (duration in seconds), retries (1-10, number of times to retry before marking container unhealthy), and startPeriod (0-300, optional grace period to wait, in seconds, before failed healthchecks count toward retries) |
object({
command = list(string)
retries = number
timeout = number
interval = number
startPeriod = number
})
| `null` | no | 45 | | [hostname](#input\_hostname) | The hostname to use for your container. | `string` | `null` | no | 46 | | [interactive](#input\_interactive) | When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated. | `bool` | `null` | no | 47 | | [links](#input\_links) | List of container names this container can communicate with without port mappings | `list(string)` | `null` | no | 48 | | [linux\_parameters](#input\_linux\_parameters) | Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html |
object({
capabilities = object({
add = list(string)
drop = list(string)
})
devices = list(object({
containerPath = string
hostPath = string
permissions = list(string)
}))
initProcessEnabled = bool
maxSwap = number
sharedMemorySize = number
swappiness = number
tmpfs = list(object({
containerPath = string
mountOptions = list(string)
size = number
}))
})
| `null` | no | 49 | | [log\_configuration](#input\_log\_configuration) | Log configuration options to send to a custom log driver for the container. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html | `any` | `null` | no | 50 | | [map\_environment](#input\_map\_environment) | The environment variables to pass to the container. This is a map of string: {key: value}. map\_environment overrides environment | `map(string)` | `null` | no | 51 | | [map\_secrets](#input\_map\_secrets) | The secrets variables to pass to the container. This is a map of string: {key: value}. map\_secrets overrides secrets | `map(string)` | `null` | no | 52 | | [mount\_points](#input\_mount\_points) | Container mount points. This is a list of maps, where each map should contain `containerPath`, `sourceVolume` and `readOnly` |
list(object({
containerPath = string
sourceVolume = string
readOnly = bool
}))
| `[]` | no | 53 | | [port\_mappings](#input\_port\_mappings) | The port mappings to configure for the container. This is a list of maps. Each map should contain "containerPort", "hostPort", and "protocol", where "protocol" is one of "tcp" or "udp". If using containers in a task with the awsvpc or host network mode, the hostPort can either be left blank or set to the same value as the containerPort |
list(object({
containerPort = number
hostPort = number
protocol = string
}))
| `[]` | no | 54 | | [privileged](#input\_privileged) | When this variable is `true`, the container is given elevated privileges on the host container instance (similar to the root user). This parameter is not supported for Windows containers or tasks using the Fargate launch type. | `bool` | `null` | no | 55 | | [pseudo\_terminal](#input\_pseudo\_terminal) | When this parameter is true, a TTY is allocated. | `bool` | `null` | no | 56 | | [readonly\_root\_filesystem](#input\_readonly\_root\_filesystem) | Determines whether a container is given read-only access to its root filesystem. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `false` | no | 57 | | [repository\_credentials](#input\_repository\_credentials) | Container repository credentials; required when using a private repo. This map currently supports a single key; "credentialsParameter", which should be the ARN of a Secrets Manager's secret holding the credentials | `map(string)` | `null` | no | 58 | | [resource\_requirements](#input\_resource\_requirements) | The type and amount of a resource to assign to a container. The only supported resource is a GPU. |
list(object({
type = string
value = string
}))
| `null` | no | 59 | | [secrets](#input\_secrets) | The secrets to pass to the container. This is a list of maps |
list(object({
name = string
valueFrom = string
}))
| `[]` | no | 60 | | [start\_timeout](#input\_start\_timeout) | Time duration (in seconds) to wait before giving up on resolving dependencies for a container | `number` | `null` | no | 61 | | [stop\_timeout](#input\_stop\_timeout) | Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own | `number` | `null` | no | 62 | | [system\_controls](#input\_system\_controls) | A list of namespaced kernel parameters to set in the container, mapping to the --sysctl option to docker run. This is a list of maps: { namespace = "", value = ""} | `list(map(string))` | `null` | no | 63 | | [ulimits](#input\_ulimits) | Container ulimit settings. This is a list of maps, where each map should contain "name", "hardLimit" and "softLimit" |
list(object({
name = string
hardLimit = number
softLimit = number
}))
| `null` | no | 64 | | [user](#input\_user) | The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set. | `string` | `null` | no | 65 | | [volumes\_from](#input\_volumes\_from) | A list of VolumesFrom maps which contain "sourceContainer" (name of the container that has the volumes to mount) and "readOnly" (whether the container can write to the volume) |
list(object({
sourceContainer = string
readOnly = bool
}))
| `[]` | no | 66 | | [working\_directory](#input\_working\_directory) | The working directory to run commands inside the container | `string` | `null` | no | 67 | 68 | ## Outputs 69 | 70 | | Name | Description | 71 | |------|-------------| 72 | | [json\_map\_encoded](#output\_json\_map\_encoded) | JSON string encoded container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | 73 | | [json\_map\_encoded\_list](#output\_json\_map\_encoded\_list) | JSON string encoded list of container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | 74 | | [json\_map\_object](#output\_json\_map\_object) | JSON map encoded container definition | 75 | | [sensitive\_json\_map\_encoded](#output\_sensitive\_json\_map\_encoded) | JSON string encoded container definitions for use with other terraform resources such as aws\_ecs\_task\_definition (sensitive) | 76 | | [sensitive\_json\_map\_encoded\_list](#output\_sensitive\_json\_map\_encoded\_list) | JSON string encoded list of container definitions for use with other terraform resources such as aws\_ecs\_task\_definition (sensitive) | 77 | | [sensitive\_json\_map\_object](#output\_sensitive\_json\_map\_object) | JSON map encoded container definition (sensitive) | 78 | 79 | -------------------------------------------------------------------------------- /examples/complete/context.tf: -------------------------------------------------------------------------------- 1 | # 2 | # ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label 3 | # All other instances of this file should be a copy of that one 4 | # 5 | # 6 | # Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf 7 | # and then place it in your Terraform module to automatically get 8 | # Cloud Posse's standard configuration inputs suitable for passing 9 | # to Cloud Posse modules. 10 | # 11 | # Modules should access the whole context as `module.this.context` 12 | # to get the input variables with nulls for defaults, 13 | # for example `context = module.this.context`, 14 | # and access individual variables as `module.this.`, 15 | # with final values filled in. 16 | # 17 | # For example, when using defaults, `module.this.context.delimiter` 18 | # will be null, and `module.this.delimiter` will be `-` (hyphen). 19 | # 20 | 21 | module "this" { 22 | source = "cloudposse/label/null" 23 | version = "0.24.1" # requires Terraform >= 0.13.0 24 | 25 | enabled = var.enabled 26 | namespace = var.namespace 27 | environment = var.environment 28 | stage = var.stage 29 | name = var.name 30 | delimiter = var.delimiter 31 | attributes = var.attributes 32 | tags = var.tags 33 | additional_tag_map = var.additional_tag_map 34 | label_order = var.label_order 35 | regex_replace_chars = var.regex_replace_chars 36 | id_length_limit = var.id_length_limit 37 | label_key_case = var.label_key_case 38 | label_value_case = var.label_value_case 39 | 40 | context = var.context 41 | } 42 | 43 | # Copy contents of cloudposse/terraform-null-label/variables.tf here 44 | 45 | variable "context" { 46 | type = any 47 | default = { 48 | enabled = true 49 | namespace = null 50 | environment = null 51 | stage = null 52 | name = null 53 | delimiter = null 54 | attributes = [] 55 | tags = {} 56 | additional_tag_map = {} 57 | regex_replace_chars = null 58 | label_order = [] 59 | id_length_limit = null 60 | label_key_case = null 61 | label_value_case = null 62 | } 63 | description = <<-EOT 64 | Single object for setting entire context at once. 65 | See description of individual variables for details. 66 | Leave string and numeric variables as `null` to use default value. 67 | Individual variable settings (non-null) override settings in context object, 68 | except for attributes, tags, and additional_tag_map, which are merged. 69 | EOT 70 | 71 | validation { 72 | condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) 73 | error_message = "Allowed values: `lower`, `title`, `upper`." 74 | } 75 | 76 | validation { 77 | condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) 78 | error_message = "Allowed values: `lower`, `title`, `upper`, `none`." 79 | } 80 | } 81 | 82 | variable "enabled" { 83 | type = bool 84 | default = null 85 | description = "Set to false to prevent the module from creating any resources" 86 | } 87 | 88 | variable "namespace" { 89 | type = string 90 | default = null 91 | description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" 92 | } 93 | 94 | variable "environment" { 95 | type = string 96 | default = null 97 | description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" 98 | } 99 | 100 | variable "stage" { 101 | type = string 102 | default = null 103 | description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" 104 | } 105 | 106 | variable "name" { 107 | type = string 108 | default = null 109 | description = "Solution name, e.g. 'app' or 'jenkins'" 110 | } 111 | 112 | variable "delimiter" { 113 | type = string 114 | default = null 115 | description = <<-EOT 116 | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. 117 | Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. 118 | EOT 119 | } 120 | 121 | variable "attributes" { 122 | type = list(string) 123 | default = [] 124 | description = "Additional attributes (e.g. `1`)" 125 | } 126 | 127 | variable "tags" { 128 | type = map(string) 129 | default = {} 130 | description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" 131 | } 132 | 133 | variable "additional_tag_map" { 134 | type = map(string) 135 | default = {} 136 | description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." 137 | } 138 | 139 | variable "label_order" { 140 | type = list(string) 141 | default = null 142 | description = <<-EOT 143 | The naming order of the id output and Name tag. 144 | Defaults to ["namespace", "environment", "stage", "name", "attributes"]. 145 | You can omit any of the 5 elements, but at least one must be present. 146 | EOT 147 | } 148 | 149 | variable "regex_replace_chars" { 150 | type = string 151 | default = null 152 | description = <<-EOT 153 | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. 154 | If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. 155 | EOT 156 | } 157 | 158 | variable "id_length_limit" { 159 | type = number 160 | default = null 161 | description = <<-EOT 162 | Limit `id` to this many characters (minimum 6). 163 | Set to `0` for unlimited length. 164 | Set to `null` for default, which is `0`. 165 | Does not affect `id_full`. 166 | EOT 167 | validation { 168 | condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 169 | error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." 170 | } 171 | } 172 | 173 | variable "label_key_case" { 174 | type = string 175 | default = null 176 | description = <<-EOT 177 | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`. 178 | Possible values: `lower`, `title`, `upper`. 179 | Default value: `title`. 180 | EOT 181 | 182 | validation { 183 | condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) 184 | error_message = "Allowed values: `lower`, `title`, `upper`." 185 | } 186 | } 187 | 188 | variable "label_value_case" { 189 | type = string 190 | default = null 191 | description = <<-EOT 192 | The letter case of output label values (also used in `tags` and `id`). 193 | Possible values: `lower`, `title`, `upper` and `none` (no transformation). 194 | Default value: `lower`. 195 | EOT 196 | 197 | validation { 198 | condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) 199 | error_message = "Allowed values: `lower`, `title`, `upper`, `none`." 200 | } 201 | } 202 | #### End of copy of cloudposse/terraform-null-label/variables.tf 203 | -------------------------------------------------------------------------------- /examples/complete/fixtures.us-east-2.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-east-2" 2 | 3 | namespace = "eg" 4 | 5 | stage = "test" 6 | 7 | name = "container-definition" 8 | 9 | container_name = "app" 10 | container_image = "cloudposse/geodesic" 11 | container_memory = 256 12 | container_memory_reservation = 128 13 | container_cpu = 256 14 | essential = true 15 | readonly_root_filesystem = false 16 | 17 | container_environment = [ 18 | { 19 | name = "string_var" 20 | value = "I am a string" 21 | }, 22 | { 23 | name = "true_boolean_var" 24 | value = true 25 | }, 26 | { 27 | name = "false_boolean_var" 28 | value = false 29 | }, 30 | { 31 | name = "integer_var" 32 | value = 42 33 | } 34 | ] 35 | 36 | port_mappings = [ 37 | { 38 | containerPort = 8080 39 | hostPort = 80 40 | protocol = "tcp" 41 | }, 42 | { 43 | containerPort = 8081 44 | hostPort = 443 45 | protocol = "udp" 46 | } 47 | ] 48 | 49 | log_configuration = { 50 | logDriver = "json-file" 51 | options = { 52 | "max-size" = "10m" 53 | "max-file" = "3" 54 | } 55 | secretOptions = null 56 | } 57 | 58 | privileged = false 59 | 60 | extra_hosts = [{ 61 | ipAddress = "127.0.0.1" 62 | hostname = "app.local" 63 | }, 64 | ] 65 | 66 | hostname = "hostname" 67 | pseudo_terminal = true 68 | interactive = true -------------------------------------------------------------------------------- /examples/complete/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | 5 | module "container" { 6 | source = "../.." 7 | container_name = var.container_name 8 | container_image = var.container_image 9 | container_memory = var.container_memory 10 | container_memory_reservation = var.container_memory_reservation 11 | container_cpu = var.container_cpu 12 | essential = var.essential 13 | readonly_root_filesystem = var.readonly_root_filesystem 14 | environment = var.container_environment 15 | port_mappings = var.port_mappings 16 | log_configuration = var.log_configuration 17 | privileged = var.privileged 18 | extra_hosts = var.extra_hosts 19 | hostname = var.hostname 20 | pseudo_terminal = var.pseudo_terminal 21 | interactive = var.interactive 22 | } 23 | 24 | resource "aws_ecs_task_definition" "task" { 25 | family = module.this.id 26 | container_definitions = module.container.json_map_encoded_list 27 | 28 | tags = module.this.tags 29 | } 30 | -------------------------------------------------------------------------------- /examples/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | output "json_map_encoded_list" { 2 | description = "JSON encoded list of container definitions for use with other terraform resources such as aws_ecs_task_definition" 3 | value = module.container.json_map_encoded_list 4 | } 5 | 6 | output "json_map_encoded" { 7 | description = "JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition" 8 | value = module.container.json_map_encoded 9 | } 10 | 11 | output "json_map_object" { 12 | description = "JSON map encoded container definition" 13 | value = module.container.json_map_object 14 | } 15 | 16 | output "task_definition_container_definition" { 17 | description = "The aws_ecs_task_definition container definition" 18 | value = jsondecode(aws_ecs_task_definition.task.container_definitions)[0] 19 | } -------------------------------------------------------------------------------- /examples/complete/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | type = string 3 | } 4 | 5 | variable "container_name" { 6 | type = string 7 | description = "The name of the container. Up to 255 characters ([a-z], [A-Z], [0-9], -, _ allowed)" 8 | } 9 | 10 | variable "container_image" { 11 | type = string 12 | description = "The image used to start the container. Images in the Docker Hub registry available by default" 13 | } 14 | 15 | variable "container_memory" { 16 | type = number 17 | description = "The amount of memory (in MiB) to allow the container to use. This is a hard limit, if the container attempts to exceed the container_memory, the container is killed. This field is optional for Fargate launch type and the total amount of container_memory of all containers in a task will need to be lower than the task memory value" 18 | default = null 19 | } 20 | 21 | variable "container_memory_reservation" { 22 | type = number 23 | description = "The amount of memory (in MiB) to reserve for the container. If container needs to exceed this threshold, it can do so up to the set container_memory hard limit" 24 | default = null 25 | } 26 | 27 | variable "container_definition" { 28 | type = map 29 | description = "Container definition overrides which allows for extra keys or overriding existing keys." 30 | default = {} 31 | } 32 | 33 | variable "port_mappings" { 34 | type = list(object({ 35 | containerPort = number 36 | hostPort = number 37 | protocol = string 38 | })) 39 | 40 | description = "The port mappings to configure for the container. This is a list of maps. Each map should contain \"containerPort\", \"hostPort\", and \"protocol\", where \"protocol\" is one of \"tcp\" or \"udp\". If using containers in a task with the awsvpc or host network mode, the hostPort can either be left blank or set to the same value as the containerPort" 41 | 42 | default = [] 43 | } 44 | 45 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html 46 | variable "healthcheck" { 47 | type = object({ 48 | command = list(string) 49 | retries = number 50 | timeout = number 51 | interval = number 52 | startPeriod = number 53 | }) 54 | description = "A map containing command (string), timeout, interval (duration in seconds), retries (1-10, number of times to retry before marking container unhealthy), and startPeriod (0-300, optional grace period to wait, in seconds, before failed healthchecks count toward retries)" 55 | default = null 56 | } 57 | 58 | variable "container_cpu" { 59 | type = number 60 | description = "The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of container_cpu of all containers in a task will need to be lower than the task-level cpu value" 61 | default = 0 62 | } 63 | 64 | variable "essential" { 65 | type = bool 66 | description = "Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value" 67 | default = true 68 | } 69 | 70 | variable "entrypoint" { 71 | type = list(string) 72 | description = "The entry point that is passed to the container" 73 | default = null 74 | } 75 | 76 | variable "command" { 77 | type = list(string) 78 | description = "The command that is passed to the container" 79 | default = null 80 | } 81 | 82 | variable "working_directory" { 83 | type = string 84 | description = "The working directory to run commands inside the container" 85 | default = null 86 | } 87 | 88 | variable "container_environment" { 89 | type = list(object({ 90 | name = string 91 | value = string 92 | })) 93 | description = "The environment variables to pass to the container. This is a list of maps. map_environment overrides environment" 94 | default = [] 95 | } 96 | 97 | variable "extra_hosts" { 98 | type = list(object({ 99 | ipAddress = string 100 | hostname = string 101 | })) 102 | description = "A list of hostnames and IP address mappings to append to the /etc/hosts file on the container. This is a list of maps" 103 | default = null 104 | } 105 | 106 | variable "map_environment" { 107 | type = map(string) 108 | description = "The environment variables to pass to the container. This is a map of string: {key: value}. map_environment overrides environment" 109 | default = null 110 | } 111 | 112 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_EnvironmentFile.html 113 | variable "environment_files" { 114 | type = list(object({ 115 | value = string 116 | type = string 117 | })) 118 | description = "One or more files containing the environment variables to pass to the container. This maps to the --env-file option to docker run. The file must be hosted in Amazon S3. This option is only available to tasks using the EC2 launch type. This is a list of maps" 119 | default = null 120 | } 121 | 122 | variable "secrets" { 123 | type = list(object({ 124 | name = string 125 | valueFrom = string 126 | })) 127 | description = "The secrets to pass to the container. This is a list of maps" 128 | default = null 129 | } 130 | 131 | variable "readonly_root_filesystem" { 132 | type = bool 133 | description = "Determines whether a container is given read-only access to its root filesystem. Due to how Terraform type casts booleans in json it is required to double quote this value" 134 | default = false 135 | } 136 | 137 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html 138 | variable "linux_parameters" { 139 | type = object({ 140 | capabilities = object({ 141 | add = list(string) 142 | drop = list(string) 143 | }) 144 | devices = list(object({ 145 | containerPath = string 146 | hostPath = string 147 | permissions = list(string) 148 | })) 149 | initProcessEnabled = bool 150 | maxSwap = number 151 | sharedMemorySize = number 152 | swappiness = number 153 | tmpfs = list(object({ 154 | containerPath = string 155 | mountOptions = list(string) 156 | size = number 157 | })) 158 | }) 159 | description = "Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html" 160 | default = null 161 | } 162 | 163 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html 164 | variable "log_configuration" { 165 | type = any 166 | description = "Log configuration options to send to a custom log driver for the container. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html" 167 | default = null 168 | } 169 | 170 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html 171 | variable "firelens_configuration" { 172 | type = object({ 173 | type = string 174 | options = map(string) 175 | }) 176 | description = "The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html" 177 | default = null 178 | } 179 | 180 | variable "mount_points" { 181 | type = list 182 | 183 | description = "Container mount points. This is a list of maps, where each map should contain a `containerPath` and `sourceVolume`. The `readOnly` key is optional." 184 | default = [] 185 | } 186 | 187 | variable "dns_servers" { 188 | type = list(string) 189 | description = "Container DNS servers. This is a list of strings specifying the IP addresses of the DNS servers" 190 | default = null 191 | } 192 | 193 | variable "dns_search_domains" { 194 | type = list(string) 195 | description = "Container DNS search domains. A list of DNS search domains that are presented to the container" 196 | default = null 197 | } 198 | 199 | variable "ulimits" { 200 | type = list(object({ 201 | name = string 202 | hardLimit = number 203 | softLimit = number 204 | })) 205 | description = "Container ulimit settings. This is a list of maps, where each map should contain \"name\", \"hardLimit\" and \"softLimit\"" 206 | default = null 207 | } 208 | 209 | variable "repository_credentials" { 210 | type = map(string) 211 | description = "Container repository credentials; required when using a private repo. This map currently supports a single key; \"credentialsParameter\", which should be the ARN of a Secrets Manager's secret holding the credentials" 212 | default = null 213 | } 214 | 215 | variable "volumes_from" { 216 | type = list(object({ 217 | sourceContainer = string 218 | readOnly = bool 219 | })) 220 | description = "A list of VolumesFrom maps which contain \"sourceContainer\" (name of the container that has the volumes to mount) and \"readOnly\" (whether the container can write to the volume)" 221 | default = [] 222 | } 223 | 224 | variable "links" { 225 | type = list(string) 226 | description = "List of container names this container can communicate with without port mappings" 227 | default = null 228 | } 229 | 230 | variable "user" { 231 | type = string 232 | description = "The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set." 233 | default = null 234 | } 235 | 236 | variable "container_depends_on" { 237 | type = list(object({ 238 | containerName = string 239 | condition = string 240 | })) 241 | description = "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY" 242 | default = null 243 | } 244 | 245 | variable "docker_labels" { 246 | type = map(string) 247 | description = "The configuration options to send to the `docker_labels`" 248 | default = null 249 | } 250 | 251 | variable "start_timeout" { 252 | type = number 253 | description = "Time duration (in seconds) to wait before giving up on resolving dependencies for a container" 254 | default = null 255 | } 256 | 257 | variable "stop_timeout" { 258 | type = number 259 | description = "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own" 260 | default = null 261 | } 262 | 263 | variable "privileged" { 264 | type = bool 265 | description = "When this variable is `true`, the container is given elevated privileges on the host container instance (similar to the root user). This parameter is not supported for Windows containers or tasks using the Fargate launch type." 266 | default = null 267 | } 268 | 269 | variable "system_controls" { 270 | type = list(map(string)) 271 | description = "A list of namespaced kernel parameters to set in the container, mapping to the --sysctl option to docker run. This is a list of maps: { namespace = \"\", value = \"\"}" 272 | default = null 273 | } 274 | 275 | variable "hostname" { 276 | type = string 277 | description = "The hostname to use for your container." 278 | default = null 279 | } 280 | 281 | variable "disable_networking" { 282 | type = bool 283 | description = "When this parameter is true, networking is disabled within the container." 284 | default = null 285 | } 286 | 287 | variable "interactive" { 288 | type = bool 289 | description = "When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated." 290 | default = null 291 | } 292 | 293 | variable "pseudo_terminal" { 294 | type = bool 295 | description = "When this parameter is true, a TTY is allocated. " 296 | default = null 297 | } 298 | 299 | variable "docker_security_options" { 300 | type = list(string) 301 | description = "A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems." 302 | default = null 303 | } 304 | -------------------------------------------------------------------------------- /examples/complete/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | aws = { 10 | source = "hashicorp/aws" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/env_vars_files/main.tf: -------------------------------------------------------------------------------- 1 | module "container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | environment_files = [ 7 | { 8 | value = "arn:aws:s3:::s3_bucket_name/envfile_01.env" 9 | type = "s3" 10 | }, 11 | { 12 | value = "arn:aws:s3:::s3_bucket_name/another_envfile.env" 13 | type = "s3" 14 | } 15 | ] 16 | } 17 | 18 | output "json_map_encoded" { 19 | description = "Container definition in JSON format" 20 | value = module.container.json_map_encoded 21 | } 22 | -------------------------------------------------------------------------------- /examples/env_vars_files/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/map_environment/main.tf: -------------------------------------------------------------------------------- 1 | module "container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | map_environment = { 7 | "string_var" = "I am a string" 8 | "true_boolean_var" = true 9 | "false_boolean_var" = false 10 | "integer_var" = 42 11 | } 12 | } 13 | 14 | output "json" { 15 | description = "Container definition in JSON format" 16 | value = module.container.json_map_encoded_list 17 | } 18 | -------------------------------------------------------------------------------- /examples/map_environment/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/multi_port_mappings/main.tf: -------------------------------------------------------------------------------- 1 | module "container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | environment = [ 7 | { 8 | name = "string_var" 9 | value = "I am a string" 10 | }, 11 | { 12 | name = "true_boolean_var" 13 | value = true 14 | }, 15 | { 16 | name = "false_boolean_var" 17 | value = false 18 | }, 19 | { 20 | name = "integer_var" 21 | value = 42 22 | } 23 | ] 24 | 25 | port_mappings = [ 26 | { 27 | containerPort = 8080 28 | hostPort = 80 29 | protocol = "tcp" 30 | }, 31 | { 32 | containerPort = 8081 33 | hostPort = 443 34 | protocol = "udp" 35 | } 36 | ] 37 | } 38 | 39 | output "json" { 40 | description = "Container definition in JSON format" 41 | value = module.container.json_map_encoded_list 42 | } 43 | -------------------------------------------------------------------------------- /examples/multi_port_mappings/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/multi_type_env_vars/main.tf: -------------------------------------------------------------------------------- 1 | module "container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | environment = [ 7 | { 8 | name = "string_var" 9 | value = "I am a string" 10 | }, 11 | { 12 | name = "true_boolean_var" 13 | value = true 14 | }, 15 | { 16 | name = "false_boolean_var" 17 | value = false 18 | }, 19 | { 20 | name = "integer_var" 21 | value = 42 22 | } 23 | ] 24 | } 25 | 26 | output "json" { 27 | description = "Container definition in JSON format" 28 | value = module.container.json_map_encoded_list 29 | } 30 | -------------------------------------------------------------------------------- /examples/multi_type_env_vars/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/multiple_definitions/main.tf: -------------------------------------------------------------------------------- 1 | module "first_container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | port_mappings = [ 7 | { 8 | containerPort = 8080 9 | hostPort = 80 10 | protocol = "tcp" 11 | }, 12 | { 13 | containerPort = 8081 14 | hostPort = 443 15 | protocol = "udp" 16 | } 17 | ] 18 | } 19 | 20 | module "second_container" { 21 | source = "../../" 22 | container_name = "name2" 23 | container_image = "cloudposse/geodesic" 24 | 25 | port_mappings = [ 26 | { 27 | containerPort = 8080 28 | hostPort = 8080 29 | protocol = "tcp" 30 | }, 31 | { 32 | containerPort = 8081 33 | hostPort = 444 34 | protocol = "udp" 35 | } 36 | ] 37 | } 38 | 39 | output "first_container_json" { 40 | description = "Container definition in JSON format" 41 | value = module.first_container.json_map_encoded_list 42 | } 43 | 44 | output "second_container_json" { 45 | description = "Container definition in JSON format" 46 | value = module.second_container.json_map_encoded_list 47 | } 48 | 49 | resource "aws_ecs_task_definition" "task" { 50 | family = "foo" 51 | container_definitions = jsonencode([ 52 | module.first_container.json_map_object, 53 | module.second_container.json_map_object 54 | ]) 55 | } 56 | -------------------------------------------------------------------------------- /examples/multiple_definitions/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | aws = { 10 | source = "hashicorp/aws" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/string_env_vars/main.tf: -------------------------------------------------------------------------------- 1 | module "container" { 2 | source = "../../" 3 | container_name = "name" 4 | container_image = "cloudposse/geodesic" 5 | 6 | environment = [ 7 | { 8 | name = "string_var" 9 | value = "123" 10 | }, 11 | { 12 | name = "another_string_var" 13 | value = "true" 14 | }, 15 | { 16 | name = "yet_another_string_var" 17 | value = "false" 18 | } 19 | ] 20 | } 21 | 22 | output "json" { 23 | description = "Container definition in JSON format" 24 | value = module.container.json_map_encoded_list 25 | } 26 | -------------------------------------------------------------------------------- /examples/string_env_vars/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | # Sort environment variables so terraform will not try to recreate on each plan/apply 3 | env_vars_keys = var.map_environment != null ? keys(var.map_environment) : var.environment != null ? [for m in var.environment : lookup(m, "name")] : [] 4 | env_vars_values = var.map_environment != null ? values(var.map_environment) : var.environment != null ? [for m in var.environment : lookup(m, "value")] : [] 5 | env_vars_as_map = zipmap(local.env_vars_keys, local.env_vars_values) 6 | sorted_env_vars_keys = sort(local.env_vars_keys) 7 | 8 | sorted_environment_vars = [ 9 | for key in local.sorted_env_vars_keys : 10 | { 11 | name = key 12 | value = lookup(local.env_vars_as_map, key) 13 | } 14 | ] 15 | 16 | # Sort secrets so terraform will not try to recreate on each plan/apply 17 | secrets_keys = var.map_secrets != null ? keys(var.map_secrets) : var.secrets != null ? [for m in var.secrets : lookup(m, "name")] : [] 18 | secrets_values = var.map_secrets != null ? values(var.map_secrets) : var.secrets != null ? [for m in var.secrets : lookup(m, "valueFrom")] : [] 19 | secrets_as_map = zipmap(local.secrets_keys, local.secrets_values) 20 | sorted_secrets_keys = sort(local.secrets_keys) 21 | 22 | sorted_secrets_vars = [ 23 | for key in local.sorted_secrets_keys : 24 | { 25 | name = key 26 | valueFrom = lookup(local.secrets_as_map, key) 27 | } 28 | ] 29 | 30 | mount_points = length(var.mount_points) > 0 ? [ 31 | for mount_point in var.mount_points : { 32 | containerPath = lookup(mount_point, "containerPath") 33 | sourceVolume = lookup(mount_point, "sourceVolume") 34 | readOnly = tobool(lookup(mount_point, "readOnly", false)) 35 | } 36 | ] : var.mount_points 37 | 38 | # https://www.terraform.io/docs/configuration/expressions.html#null 39 | final_environment_vars = length(local.sorted_environment_vars) > 0 ? local.sorted_environment_vars : null 40 | final_secrets_vars = length(local.sorted_secrets_vars) > 0 ? local.sorted_secrets_vars : null 41 | 42 | log_configuration_secret_options = var.log_configuration != null ? lookup(var.log_configuration, "secretOptions", null) : null 43 | log_configuration_with_null = var.log_configuration == null ? null : { 44 | logDriver = tostring(lookup(var.log_configuration, "logDriver")) 45 | options = tomap(lookup(var.log_configuration, "options")) 46 | secretOptions = local.log_configuration_secret_options == null ? null : [ 47 | for secret_option in tolist(local.log_configuration_secret_options) : { 48 | name = tostring(lookup(secret_option, "name")) 49 | valueFrom = tostring(lookup(secret_option, "valueFrom")) 50 | } 51 | ] 52 | } 53 | log_configuration_without_null = local.log_configuration_with_null == null ? null : { 54 | for k, v in local.log_configuration_with_null : 55 | k => v 56 | if v != null 57 | } 58 | user = var.firelens_configuration != null ? "0" : var.user 59 | 60 | container_definition = { 61 | name = var.container_name 62 | image = var.container_image 63 | essential = var.essential 64 | entryPoint = var.entrypoint 65 | command = var.command 66 | workingDirectory = var.working_directory 67 | readonlyRootFilesystem = var.readonly_root_filesystem 68 | mountPoints = local.mount_points 69 | dnsServers = var.dns_servers 70 | dnsSearchDomains = var.dns_search_domains 71 | ulimits = var.ulimits 72 | repositoryCredentials = var.repository_credentials 73 | links = var.links 74 | volumesFrom = var.volumes_from 75 | user = local.user 76 | dependsOn = var.container_depends_on 77 | privileged = var.privileged 78 | portMappings = var.port_mappings 79 | healthCheck = var.healthcheck 80 | firelensConfiguration = var.firelens_configuration 81 | linuxParameters = var.linux_parameters 82 | logConfiguration = local.log_configuration_without_null 83 | memory = var.container_memory 84 | memoryReservation = var.container_memory_reservation 85 | cpu = var.container_cpu 86 | environment = local.final_environment_vars 87 | environmentFiles = var.environment_files 88 | secrets = local.final_secrets_vars 89 | dockerLabels = var.docker_labels 90 | startTimeout = var.start_timeout 91 | stopTimeout = var.stop_timeout 92 | systemControls = var.system_controls 93 | extraHosts = var.extra_hosts 94 | hostname = var.hostname 95 | disableNetworking = var.disable_networking 96 | interactive = var.interactive 97 | pseudoTerminal = var.pseudo_terminal 98 | dockerSecurityOptions = var.docker_security_options 99 | resourceRequirements = var.resource_requirements 100 | } 101 | 102 | container_definition_without_null = { 103 | for k, v in local.container_definition : 104 | k => v 105 | if v != null 106 | } 107 | json_map = jsonencode(merge(local.container_definition_without_null, var.container_definition)) 108 | } 109 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "json_map_encoded_list" { 2 | description = "JSON string encoded list of container definitions for use with other terraform resources such as aws_ecs_task_definition" 3 | value = "[${local.json_map}]" 4 | } 5 | 6 | output "json_map_encoded" { 7 | description = "JSON string encoded container definitions for use with other terraform resources such as aws_ecs_task_definition" 8 | value = local.json_map 9 | } 10 | 11 | output "json_map_object" { 12 | description = "JSON map encoded container definition" 13 | value = jsondecode(local.json_map) 14 | } 15 | 16 | output "sensitive_json_map_encoded_list" { 17 | description = "JSON string encoded list of container definitions for use with other terraform resources such as aws_ecs_task_definition (sensitive)" 18 | value = "[${local.json_map}]" 19 | sensitive = true 20 | } 21 | 22 | output "sensitive_json_map_encoded" { 23 | description = "JSON string encoded container definitions for use with other terraform resources such as aws_ecs_task_definition (sensitive)" 24 | value = local.json_map 25 | sensitive = true 26 | } 27 | 28 | output "sensitive_json_map_object" { 29 | description = "JSON map encoded container definition (sensitive)" 30 | value = jsondecode(local.json_map) 31 | sensitive = true 32 | } 33 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | .test-harness 2 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git 2 | TEST_HARNESS_BRANCH ?= master 3 | TEST_HARNESS_PATH = $(realpath .test-harness) 4 | BATS_ARGS ?= --tap 5 | BATS_LOG ?= test.log 6 | 7 | # Define a macro to run the tests 8 | define RUN_TESTS 9 | @echo "Running tests in $(1)" 10 | @cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS))) 11 | endef 12 | 13 | default: all 14 | 15 | -include Makefile.* 16 | 17 | ## Provision the test-harnesss 18 | .test-harness: 19 | [ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@ 20 | 21 | ## Initialize the tests 22 | init: .test-harness 23 | 24 | ## Install all dependencies (OS specific) 25 | deps:: 26 | @exit 0 27 | 28 | ## Clean up the test harness 29 | clean: 30 | [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH) 31 | 32 | ## Run all tests 33 | all: module examples/complete 34 | 35 | ## Run basic sanity checks against the module itself 36 | module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions 37 | module: deps 38 | $(call RUN_TESTS, ../) 39 | 40 | ## Run tests against example 41 | examples/complete: export TESTS ?= installed lint get-modules get-plugins validate 42 | examples/complete: deps 43 | $(call RUN_TESTS, ../$@) 44 | -------------------------------------------------------------------------------- /test/Makefile.alpine: -------------------------------------------------------------------------------- 1 | ifneq (,$(wildcard /sbin/apk)) 2 | ## Install all dependencies for alpine 3 | deps:: init 4 | @apk add --update terraform-docs@cloudposse json2hcl@cloudposse 5 | endif 6 | -------------------------------------------------------------------------------- /test/src/.gitignore: -------------------------------------------------------------------------------- 1 | .gopath 2 | vendor/ 3 | -------------------------------------------------------------------------------- /test/src/Makefile: -------------------------------------------------------------------------------- 1 | export TF_CLI_ARGS_init ?= -get-plugins=true 2 | export TERRAFORM_VERSION ?= $(shell curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version' | cut -d. -f1-2) 3 | 4 | .DEFAULT_GOAL : all 5 | 6 | .PHONY: all 7 | ## Default target 8 | all: test 9 | 10 | .PHONY : init 11 | ## Initialize tests 12 | init: 13 | @exit 0 14 | 15 | .PHONY : test 16 | ## Run tests 17 | test: init 18 | go mod download 19 | go test -v -timeout 60m -run TestExamplesComplete 20 | 21 | ## Run tests in docker container 22 | docker/test: 23 | docker run --name terratest --rm -it -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e GITHUB_TOKEN \ 24 | -e PATH="/usr/local/terraform/$(TERRAFORM_VERSION)/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ 25 | -v $(CURDIR)/../../:/module/ cloudposse/test-harness:latest -C /module/test/src test 26 | 27 | .PHONY : clean 28 | ## Clean up files 29 | clean: 30 | rm -rf ../../examples/complete/*.tfstate* -------------------------------------------------------------------------------- /test/src/examples_complete_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "encoding/json" 7 | "github.com/gruntwork-io/terratest/modules/terraform" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | // Test the Terraform module in examples/complete using Terratest. 12 | func TestExamplesComplete(t *testing.T) { 13 | t.Parallel() 14 | 15 | terraformOptions := &terraform.Options{ 16 | // The path to where our Terraform code is located 17 | TerraformDir: "../../examples/complete", 18 | Upgrade: true, 19 | // Variables to pass to our Terraform code using -var-file options 20 | VarFiles: []string{"fixtures.us-east-2.tfvars"}, 21 | } 22 | 23 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 24 | defer terraform.Destroy(t, terraformOptions) 25 | 26 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 27 | terraform.InitAndApply(t, terraformOptions) 28 | 29 | // Run `terraform output` to get the value of an output variable 30 | jsonMap := terraform.OutputRequired(t, terraformOptions, "json_map_encoded") 31 | 32 | // Verify we're getting back the outputs we expect 33 | var jsonObject map[string]interface{} 34 | err := json.Unmarshal([]byte(jsonMap), &jsonObject) 35 | assert.NoError(t, err) 36 | 37 | assert.Equal(t, "app", jsonObject["name"]) 38 | assert.Equal(t, "cloudposse/geodesic", jsonObject["image"]) 39 | assert.Equal(t, 256, int((jsonObject["memory"]).(float64))) 40 | assert.Equal(t, 128, int((jsonObject["memoryReservation"]).(float64))) 41 | assert.Equal(t, 256, int((jsonObject["cpu"]).(float64))) 42 | assert.Equal(t, true, jsonObject["essential"]) 43 | assert.Equal(t, false, jsonObject["readonlyRootFilesystem"]) 44 | 45 | // Run `terraform output` to compare the expected container definition with the actual aws_ecs_task_definition container definition 46 | containerDefinitionExpected := terraform.OutputRequired(t, terraformOptions, "json_map_object") 47 | containerDefinition := terraform.OutputRequired(t, terraformOptions, "task_definition_container_definition") 48 | assert.Equal(t, containerDefinitionExpected, containerDefinition) 49 | } 50 | -------------------------------------------------------------------------------- /test/src/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cloudposse/terraform-aws-ecs-container-definition 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gruntwork-io/terratest v0.30.23 7 | github.com/stretchr/testify v1.6.1 8 | ) 9 | -------------------------------------------------------------------------------- /test/src/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= 9 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 10 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 11 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 12 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 13 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 14 | github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 15 | github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 16 | github.com/Azure/azure-sdk-for-go v46.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 17 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 18 | github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= 19 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 20 | github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= 21 | github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= 22 | github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= 23 | github.com/Azure/go-autorest/autorest v0.11.5/go.mod h1:foo3aIXRQ90zFve3r0QiDsrjGDUwWhKl0ZOQy1CT14k= 24 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 25 | github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= 26 | github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= 27 | github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= 28 | github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= 29 | github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= 30 | github.com/Azure/go-autorest/autorest/azure/auth v0.5.1/go.mod h1:ea90/jvmnAwDrSooLH4sRIehEPtG/EPUXavDh31MnA4= 31 | github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= 32 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 33 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= 34 | github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= 35 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 36 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 37 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= 38 | github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= 39 | github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= 40 | github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= 41 | github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= 42 | github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= 43 | github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= 44 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 45 | github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= 46 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 47 | github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= 48 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 49 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 50 | github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= 51 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 52 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 53 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 54 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 55 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 56 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 57 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 58 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 59 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 60 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= 61 | github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 62 | github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 63 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 64 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 65 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 66 | github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= 67 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 68 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 69 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 70 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 71 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 72 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 73 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= 74 | github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 75 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 76 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 77 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 78 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 79 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 80 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 81 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 82 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 83 | github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 84 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 85 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 86 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 87 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 88 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 89 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 90 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 91 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 92 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 93 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= 94 | github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= 95 | github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 96 | github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 97 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 98 | github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 99 | github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 100 | github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= 101 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 102 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 103 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 104 | github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 105 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 106 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 107 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 108 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 109 | github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 110 | github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= 111 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= 112 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 113 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 114 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 115 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 116 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 117 | github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 118 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 119 | github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= 120 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 121 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 122 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 123 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 124 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 125 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 126 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 127 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 128 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 129 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 130 | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= 131 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 132 | github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= 133 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 134 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 135 | github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= 136 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= 137 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 138 | github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= 139 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 140 | github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 141 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 142 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 143 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 144 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 145 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 146 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 147 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 148 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 149 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 150 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 151 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 152 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 153 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 154 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 155 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 156 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 157 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 158 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 159 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 160 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 161 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 162 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 163 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 164 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 165 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 166 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 167 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 168 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 169 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 170 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 171 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 172 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 173 | github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= 174 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 175 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 176 | github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 177 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 178 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 179 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 180 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 181 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 182 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 183 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 184 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 185 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 186 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 187 | github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 188 | github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= 189 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 190 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 191 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 192 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 193 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 194 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 195 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 196 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 197 | github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= 198 | github.com/gruntwork-io/terratest v0.30.23 h1:9iGmn2kL9hnchriqtSm66BGK67pYJl6SU4iOIjfD9f8= 199 | github.com/gruntwork-io/terratest v0.30.23/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= 200 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 201 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 202 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 203 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 204 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 205 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 206 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 207 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 208 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 209 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= 210 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= 211 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 212 | github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= 213 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 214 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 215 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 216 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 217 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 218 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 219 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 220 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 221 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 222 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 223 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 224 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 225 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 226 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 227 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 228 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 229 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 230 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 231 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 232 | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 233 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 234 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 235 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 236 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 237 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 238 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 239 | github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= 240 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 241 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 242 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 243 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 244 | github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 245 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 246 | github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 247 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 248 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 249 | github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= 250 | github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 251 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 252 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 253 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 254 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 255 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 256 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 257 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 258 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 259 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 260 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 261 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 262 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 263 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 264 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 265 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 266 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 267 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 268 | github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 269 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 270 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 271 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 272 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 273 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 274 | github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= 275 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 276 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 277 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 278 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 279 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 280 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 281 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 282 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 283 | github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 284 | github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= 285 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 286 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 287 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 288 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 289 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 290 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 291 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 292 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 293 | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= 294 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 295 | github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= 296 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 297 | github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= 298 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 299 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 300 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 301 | github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= 302 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 303 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 304 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 305 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 306 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 307 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 308 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 309 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 310 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 311 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 312 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 313 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 314 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 315 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 316 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 317 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 318 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 319 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 320 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 321 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 322 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 323 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 324 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 325 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 326 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 327 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 328 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 329 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 330 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 331 | github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 332 | github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= 333 | github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= 334 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 335 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 336 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 337 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 338 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 339 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 340 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 341 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 342 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 343 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 344 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 345 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 346 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 347 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 348 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 349 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 350 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 351 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 352 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 353 | golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 354 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= 355 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 356 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 357 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 358 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 359 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 360 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 361 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 362 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 363 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 364 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 365 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 366 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 367 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 368 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 369 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 370 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 371 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 372 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 373 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 374 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 375 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 376 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 377 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 378 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 379 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 380 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 381 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 382 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 383 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 384 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 385 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 386 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 387 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 388 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 389 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 390 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 391 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 392 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 393 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 394 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 395 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 396 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 397 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 398 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 399 | golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= 400 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 401 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 402 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 403 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 404 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 405 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 406 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 407 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 408 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 409 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 410 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 411 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 412 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 413 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 414 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 415 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 416 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 417 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 418 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 419 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 420 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 421 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 422 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 423 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 424 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 425 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 426 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 427 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 428 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 429 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 430 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 431 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 432 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 433 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 434 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 435 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 436 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 437 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 438 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 439 | golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= 440 | golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 441 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 442 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 443 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 444 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 445 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 446 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 447 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 448 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 449 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 450 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 451 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 452 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 453 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 454 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 455 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 456 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 457 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 458 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 459 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 460 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 461 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 462 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 463 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 464 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 465 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 466 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 467 | golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= 468 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 469 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 470 | golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 471 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 472 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 473 | golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 474 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 475 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 476 | golang.org/x/tools v0.0.0-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 477 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 478 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 479 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 480 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= 481 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 482 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= 483 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 484 | google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= 485 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 486 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 487 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 488 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 489 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 490 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 491 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 492 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 493 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 494 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 495 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 496 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 497 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 498 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 499 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 500 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 501 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 502 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 503 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 504 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 505 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 506 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 507 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 508 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 509 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 510 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 511 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 512 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 513 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 514 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 515 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 516 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 517 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 518 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 519 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 520 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 521 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 522 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 523 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 524 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 525 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 526 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 527 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 528 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 529 | gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= 530 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 531 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 532 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 533 | gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 534 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 535 | gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 536 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 537 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 538 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 539 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 540 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 541 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 542 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 543 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 544 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 545 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 546 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 547 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 548 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 549 | k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= 550 | k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= 551 | k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= 552 | k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= 553 | k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= 554 | k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= 555 | k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= 556 | k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= 557 | k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= 558 | k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= 559 | k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls= 560 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 561 | k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 562 | k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 563 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 564 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 565 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 566 | k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= 567 | k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= 568 | k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 569 | k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= 570 | k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= 571 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 572 | k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 573 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= 574 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= 575 | modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= 576 | modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= 577 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= 578 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 579 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 580 | sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= 581 | sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= 582 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 583 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 584 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "container_name" { 2 | type = string 3 | description = "The name of the container. Up to 255 characters ([a-z], [A-Z], [0-9], -, _ allowed)" 4 | } 5 | 6 | variable "container_image" { 7 | type = string 8 | description = "The image used to start the container. Images in the Docker Hub registry available by default" 9 | } 10 | 11 | variable "container_memory" { 12 | type = number 13 | description = "The amount of memory (in MiB) to allow the container to use. This is a hard limit, if the container attempts to exceed the container_memory, the container is killed. This field is optional for Fargate launch type and the total amount of container_memory of all containers in a task will need to be lower than the task memory value" 14 | default = null 15 | } 16 | 17 | variable "container_memory_reservation" { 18 | type = number 19 | description = "The amount of memory (in MiB) to reserve for the container. If container needs to exceed this threshold, it can do so up to the set container_memory hard limit" 20 | default = null 21 | } 22 | 23 | variable "container_definition" { 24 | type = map(any) 25 | description = "Container definition overrides which allows for extra keys or overriding existing keys." 26 | default = {} 27 | } 28 | 29 | variable "port_mappings" { 30 | type = list(object({ 31 | containerPort = number 32 | hostPort = number 33 | protocol = string 34 | })) 35 | 36 | description = "The port mappings to configure for the container. This is a list of maps. Each map should contain \"containerPort\", \"hostPort\", and \"protocol\", where \"protocol\" is one of \"tcp\" or \"udp\". If using containers in a task with the awsvpc or host network mode, the hostPort can either be left blank or set to the same value as the containerPort" 37 | 38 | default = [] 39 | } 40 | 41 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html 42 | variable "healthcheck" { 43 | type = object({ 44 | command = list(string) 45 | retries = number 46 | timeout = number 47 | interval = number 48 | startPeriod = number 49 | }) 50 | description = "A map containing command (string), timeout, interval (duration in seconds), retries (1-10, number of times to retry before marking container unhealthy), and startPeriod (0-300, optional grace period to wait, in seconds, before failed healthchecks count toward retries)" 51 | default = null 52 | } 53 | 54 | variable "container_cpu" { 55 | type = number 56 | description = "The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of container_cpu of all containers in a task will need to be lower than the task-level cpu value" 57 | default = 0 58 | } 59 | 60 | variable "essential" { 61 | type = bool 62 | description = "Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value" 63 | default = true 64 | } 65 | 66 | variable "entrypoint" { 67 | type = list(string) 68 | description = "The entry point that is passed to the container" 69 | default = null 70 | } 71 | 72 | variable "command" { 73 | type = list(string) 74 | description = "The command that is passed to the container" 75 | default = null 76 | } 77 | 78 | variable "working_directory" { 79 | type = string 80 | description = "The working directory to run commands inside the container" 81 | default = null 82 | } 83 | 84 | variable "environment" { 85 | type = list(object({ 86 | name = string 87 | value = string 88 | })) 89 | description = "The environment variables to pass to the container. This is a list of maps. map_environment overrides environment" 90 | default = [] 91 | } 92 | 93 | variable "extra_hosts" { 94 | type = list(object({ 95 | ipAddress = string 96 | hostname = string 97 | })) 98 | description = "A list of hostnames and IP address mappings to append to the /etc/hosts file on the container. This is a list of maps" 99 | default = null 100 | } 101 | 102 | variable "map_environment" { 103 | type = map(string) 104 | description = "The environment variables to pass to the container. This is a map of string: {key: value}. map_environment overrides environment" 105 | default = null 106 | } 107 | 108 | variable "map_secrets" { 109 | type = map(string) 110 | description = "The secrets variables to pass to the container. This is a map of string: {key: value}. map_secrets overrides secrets" 111 | default = null 112 | } 113 | 114 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_EnvironmentFile.html 115 | variable "environment_files" { 116 | type = list(object({ 117 | value = string 118 | type = string 119 | })) 120 | description = "One or more files containing the environment variables to pass to the container. This maps to the --env-file option to docker run. The file must be hosted in Amazon S3. This option is only available to tasks using the EC2 launch type. This is a list of maps" 121 | default = null 122 | } 123 | 124 | variable "secrets" { 125 | type = list(object({ 126 | name = string 127 | valueFrom = string 128 | })) 129 | description = "The secrets to pass to the container. This is a list of maps" 130 | default = [] 131 | } 132 | 133 | variable "readonly_root_filesystem" { 134 | type = bool 135 | description = "Determines whether a container is given read-only access to its root filesystem. Due to how Terraform type casts booleans in json it is required to double quote this value" 136 | default = false 137 | } 138 | 139 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html 140 | variable "linux_parameters" { 141 | type = object({ 142 | capabilities = object({ 143 | add = list(string) 144 | drop = list(string) 145 | }) 146 | devices = list(object({ 147 | containerPath = string 148 | hostPath = string 149 | permissions = list(string) 150 | })) 151 | initProcessEnabled = bool 152 | maxSwap = number 153 | sharedMemorySize = number 154 | swappiness = number 155 | tmpfs = list(object({ 156 | containerPath = string 157 | mountOptions = list(string) 158 | size = number 159 | })) 160 | }) 161 | description = "Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LinuxParameters.html" 162 | default = null 163 | } 164 | 165 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html 166 | variable "log_configuration" { 167 | type = any 168 | description = "Log configuration options to send to a custom log driver for the container. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html" 169 | default = null 170 | } 171 | 172 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html 173 | variable "firelens_configuration" { 174 | type = object({ 175 | type = string 176 | options = map(string) 177 | }) 178 | description = "The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html" 179 | default = null 180 | } 181 | 182 | variable "mount_points" { 183 | type = list(object({ 184 | containerPath = string 185 | sourceVolume = string 186 | readOnly = bool 187 | })) 188 | 189 | description = "Container mount points. This is a list of maps, where each map should contain `containerPath`, `sourceVolume` and `readOnly`" 190 | default = [] 191 | } 192 | 193 | variable "dns_servers" { 194 | type = list(string) 195 | description = "Container DNS servers. This is a list of strings specifying the IP addresses of the DNS servers" 196 | default = null 197 | } 198 | 199 | variable "dns_search_domains" { 200 | type = list(string) 201 | description = "Container DNS search domains. A list of DNS search domains that are presented to the container" 202 | default = null 203 | } 204 | 205 | variable "ulimits" { 206 | type = list(object({ 207 | name = string 208 | hardLimit = number 209 | softLimit = number 210 | })) 211 | description = "Container ulimit settings. This is a list of maps, where each map should contain \"name\", \"hardLimit\" and \"softLimit\"" 212 | default = null 213 | } 214 | 215 | variable "repository_credentials" { 216 | type = map(string) 217 | description = "Container repository credentials; required when using a private repo. This map currently supports a single key; \"credentialsParameter\", which should be the ARN of a Secrets Manager's secret holding the credentials" 218 | default = null 219 | } 220 | 221 | variable "volumes_from" { 222 | type = list(object({ 223 | sourceContainer = string 224 | readOnly = bool 225 | })) 226 | description = "A list of VolumesFrom maps which contain \"sourceContainer\" (name of the container that has the volumes to mount) and \"readOnly\" (whether the container can write to the volume)" 227 | default = [] 228 | } 229 | 230 | variable "links" { 231 | type = list(string) 232 | description = "List of container names this container can communicate with without port mappings" 233 | default = null 234 | } 235 | 236 | variable "user" { 237 | type = string 238 | description = "The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set." 239 | default = null 240 | } 241 | 242 | variable "container_depends_on" { 243 | type = list(object({ 244 | containerName = string 245 | condition = string 246 | })) 247 | description = "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY" 248 | default = null 249 | } 250 | 251 | variable "docker_labels" { 252 | type = map(string) 253 | description = "The configuration options to send to the `docker_labels`" 254 | default = null 255 | } 256 | 257 | variable "start_timeout" { 258 | type = number 259 | description = "Time duration (in seconds) to wait before giving up on resolving dependencies for a container" 260 | default = null 261 | } 262 | 263 | variable "stop_timeout" { 264 | type = number 265 | description = "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own" 266 | default = null 267 | } 268 | 269 | variable "privileged" { 270 | type = bool 271 | description = "When this variable is `true`, the container is given elevated privileges on the host container instance (similar to the root user). This parameter is not supported for Windows containers or tasks using the Fargate launch type." 272 | default = null 273 | } 274 | 275 | variable "system_controls" { 276 | type = list(map(string)) 277 | description = "A list of namespaced kernel parameters to set in the container, mapping to the --sysctl option to docker run. This is a list of maps: { namespace = \"\", value = \"\"}" 278 | default = null 279 | } 280 | 281 | variable "hostname" { 282 | type = string 283 | description = "The hostname to use for your container." 284 | default = null 285 | } 286 | 287 | variable "disable_networking" { 288 | type = bool 289 | description = "When this parameter is true, networking is disabled within the container." 290 | default = null 291 | } 292 | 293 | variable "interactive" { 294 | type = bool 295 | description = "When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated." 296 | default = null 297 | } 298 | 299 | variable "pseudo_terminal" { 300 | type = bool 301 | description = "When this parameter is true, a TTY is allocated. " 302 | default = null 303 | } 304 | 305 | variable "docker_security_options" { 306 | type = list(string) 307 | description = "A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems." 308 | default = null 309 | } 310 | 311 | # https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ResourceRequirement.html 312 | variable "resource_requirements" { 313 | type = list(object({ 314 | type = string 315 | value = string 316 | })) 317 | description = "The type and amount of a resource to assign to a container. The only supported resource is a GPU." 318 | default = null 319 | } 320 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | 4 | required_providers { 5 | local = { 6 | source = "hashicorp/local" 7 | version = ">= 1.2" 8 | } 9 | } 10 | } 11 | --------------------------------------------------------------------------------