├── .github ├── FUNDING.yml ├── dependabot.yml ├── labels.yml ├── release-drafter.yml └── workflows │ ├── action_branch.yml │ ├── action_pull_request.yml │ ├── action_schedule.yml │ ├── docker-multistage-build-extra.yml │ ├── docker-multistage-push-manifest-helm.yml │ ├── docker-multistage-push-manifest-kops.yml │ ├── lint.yml │ ├── params.yml │ ├── release-drafter.yml │ └── repository.yml ├── .gitignore ├── .yamllint ├── Dockerfiles ├── Dockerfile-aws ├── Dockerfile-awshelm ├── Dockerfile-awsk8s ├── Dockerfile-awskops ├── Dockerfile-azure ├── Dockerfile-base ├── Dockerfile-infra ├── Dockerfile-tools └── data │ └── docker-entrypoint.sh ├── LICENSE ├── Makefile ├── README.md └── tests ├── inventory ├── playbook.yml ├── test.yml └── test.yml.j2 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | --- 2 | github: [cytopia] 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | # Maintain dependencies for GitHub Actions 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "daily" 9 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # The labels in this file are automatically synced with the repository 2 | # using the micnncim/action-label-syncer action. 3 | --- 4 | - name: C-dependency 5 | color: 1abc9c 6 | description: "Category: Dependency" 7 | - name: PR-block 8 | color: 3498db 9 | description: "Pull Request: Do not merge" 10 | - name: PR-merge 11 | color: 3498db 12 | description: "Pull Request: Merge when ready" 13 | - name: bug 14 | color: d73a4a 15 | description: "Something isn't working" 16 | - name: documentation 17 | color: 0075ca 18 | description: "Improvements or additions to documentation" 19 | - name: duplicate 20 | color: cfd3d7 21 | description: "This issue or pull request already exists" 22 | - name: enhancement 23 | color: a2eeef 24 | description: "New feature or request" 25 | - name: "good first issue" 26 | color: 7057ff 27 | description: "Good for newcomers" 28 | - name: "help wanted" 29 | color: 008672 30 | description: "Extra attention is needed" 31 | - name: invalid 32 | color: e4e669 33 | description: "This doesn't seem right" 34 | - name: question 35 | color: d876e3 36 | description: "Further information is requested" 37 | - name: wontfix 38 | color: ffffff 39 | description: "This will not be worked on" 40 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name-template: '$RESOLVED_VERSION 🌈' 3 | tag-template: '$RESOLVED_VERSION' 4 | version-template: '$MAJOR.$MINOR' 5 | categories: 6 | - title: '🚀 Features' 7 | labels: 8 | - 'feature' 9 | - 'enhancement' 10 | - title: '🐛 Bug Fixes' 11 | labels: 12 | - 'fix' 13 | - 'bugfix' 14 | - 'bug' 15 | - title: '🧰 Maintenance' 16 | label: 'chore' 17 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 18 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 19 | version-resolver: 20 | major: 21 | labels: 22 | - 'major' 23 | minor: 24 | labels: 25 | - 'minor' 26 | patch: 27 | labels: 28 | - 'patch' 29 | default: minor 30 | template: | 31 | ## Changes 32 | 33 | $CHANGES 34 | -------------------------------------------------------------------------------- /.github/workflows/action_branch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ------------------------------------------------------------------------------------------------- 4 | # Job Name 5 | # ------------------------------------------------------------------------------------------------- 6 | name: build 7 | 8 | 9 | # ------------------------------------------------------------------------------------------------- 10 | # When to run 11 | # ------------------------------------------------------------------------------------------------- 12 | on: 13 | push: 14 | paths: 15 | - 'Makefile' 16 | - 'Dockerfiles/**' 17 | - 'tests/**' 18 | - '.github/workflows/action*.yml' 19 | - '.github/workflows/docker*.yml' 20 | - '.github/workflows/params.yml' 21 | 22 | jobs: 23 | 24 | # ----------------------------------------------------------------------------------------------- 25 | # (1/4) Determine parameter settings 26 | # ----------------------------------------------------------------------------------------------- 27 | params: 28 | uses: ./.github/workflows/params.yml 29 | 30 | # ----------------------------------------------------------------------------------------------- 31 | # (2/4) Configure Build and Deploy Matrices 32 | # ----------------------------------------------------------------------------------------------- 33 | configure: 34 | needs: [params] 35 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 36 | with: 37 | enabled: true 38 | can_deploy: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-') }} 39 | versions: ${{ needs.params.outputs.versions }} 40 | refs: ${{ needs.params.outputs.refs }} 41 | secrets: 42 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 43 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 44 | 45 | configure-awskops: 46 | needs: [params] 47 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 48 | with: 49 | enabled: true 50 | can_deploy: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-') }} 51 | versions: ${{ needs.params.outputs.versions }} 52 | refs: ${{ needs.params.outputs.refs }} 53 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}, {"ARCH":"ARCH"}]' 54 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}]' 55 | secrets: 56 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 57 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 58 | 59 | configure-awshelm: 60 | needs: [params] 61 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 62 | with: 63 | enabled: true 64 | can_deploy: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-') }} 65 | versions: ${{ needs.params.outputs.versions }} 66 | refs: ${{ needs.params.outputs.refs }} 67 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}, {"ARCH":"ARCH"}]' 68 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}]' 69 | secrets: 70 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 71 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 72 | 73 | 74 | # ----------------------------------------------------------------------------------------------- 75 | # (3/4) Build & Test 76 | # ----------------------------------------------------------------------------------------------- 77 | build-base: 78 | needs: 79 | - configure 80 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 81 | with: 82 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 83 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 84 | upload_artifact: true 85 | pull_base_image: true 86 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 87 | run_tests: true 88 | matrix: ${{ needs.configure.outputs.matrix_build }} 89 | stage: base 90 | stage_prev: '' 91 | secrets: 92 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 93 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 94 | 95 | build-tools: 96 | needs: 97 | - configure 98 | - build-base 99 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 100 | with: 101 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 102 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 103 | upload_artifact: true 104 | pull_base_image: false 105 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 106 | run_tests: true 107 | matrix: ${{ needs.configure.outputs.matrix_build }} 108 | stage: tools 109 | stage_prev: base 110 | secrets: 111 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 112 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 113 | 114 | build-aws: 115 | needs: 116 | - configure 117 | - build-tools 118 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 119 | with: 120 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 121 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 122 | upload_artifact: true 123 | pull_base_image: false 124 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 125 | run_tests: true 126 | matrix: ${{ needs.configure.outputs.matrix_build }} 127 | stage: aws 128 | stage_prev: tools 129 | secrets: 130 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 131 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 132 | 133 | build-azure: 134 | needs: 135 | - configure 136 | - build-tools 137 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 138 | with: 139 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 140 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 141 | upload_artifact: true 142 | pull_base_image: false 143 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 144 | run_tests: true 145 | matrix: ${{ needs.configure.outputs.matrix_build }} 146 | stage: azure 147 | stage_prev: tools 148 | secrets: 149 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 150 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 151 | 152 | build-infra: 153 | needs: 154 | - configure 155 | - build-tools 156 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 157 | with: 158 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 159 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 160 | upload_artifact: true 161 | pull_base_image: false 162 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 163 | run_tests: true 164 | matrix: ${{ needs.configure.outputs.matrix_build }} 165 | stage: infra 166 | stage_prev: tools 167 | secrets: 168 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 169 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 170 | 171 | build-awsk8s: 172 | needs: 173 | - configure 174 | - build-aws 175 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 176 | with: 177 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 178 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 179 | upload_artifact: true 180 | pull_base_image: false 181 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 182 | run_tests: true 183 | matrix: ${{ needs.configure.outputs.matrix_build }} 184 | stage: awsk8s 185 | stage_prev: aws 186 | secrets: 187 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 188 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 189 | 190 | # Note: awskops is special 191 | build-awskops: 192 | needs: 193 | - configure-awskops 194 | - build-awsk8s 195 | uses: ./.github/workflows/docker-multistage-build-extra.yml 196 | with: 197 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 198 | artifact_prefix: ${{ needs.configure-awskops.outputs.artifact_prefix }} 199 | upload_artifact: true 200 | pull_base_image: false 201 | push_image: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 202 | run_tests: true 203 | matrix: ${{ needs.configure-awskops.outputs.matrix_build }} 204 | stage: awskops 205 | stage_prev: awsk8s 206 | extra_make_var_name: KOPS 207 | secrets: 208 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 209 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 210 | 211 | # Note: awshelm is special 212 | build-awshelm: 213 | needs: 214 | - configure-awshelm 215 | - build-awsk8s 216 | uses: ./.github/workflows/docker-multistage-build-extra.yml 217 | with: 218 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 219 | artifact_prefix: ${{ needs.configure-awshelm.outputs.artifact_prefix }} 220 | upload_artifact: true 221 | pull_base_image: false 222 | push_image: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 223 | run_tests: true 224 | matrix: ${{ needs.configure-awshelm.outputs.matrix_build }} 225 | stage: awshelm 226 | stage_prev: awsk8s 227 | extra_make_var_name: HELM 228 | secrets: 229 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 230 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 231 | 232 | 233 | # ----------------------------------------------------------------------------------------------- 234 | # (4/4) Push Manifests 235 | # ----------------------------------------------------------------------------------------------- 236 | manifest-base: 237 | needs: 238 | - configure 239 | - build-base 240 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 241 | with: 242 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 243 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 244 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 245 | versions: ${{ needs.configure.outputs.versions }} 246 | stage: base 247 | secrets: 248 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 249 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 250 | 251 | manifest-tools: 252 | needs: 253 | - configure 254 | - build-tools 255 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 256 | with: 257 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 258 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 259 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 260 | versions: ${{ needs.configure.outputs.versions }} 261 | stage: tools 262 | secrets: 263 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 264 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 265 | 266 | manifest-infra: 267 | needs: 268 | - configure 269 | - build-infra 270 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 271 | with: 272 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 273 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 274 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 275 | versions: ${{ needs.configure.outputs.versions }} 276 | stage: infra 277 | secrets: 278 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 279 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 280 | 281 | manifest-azure: 282 | needs: 283 | - configure 284 | - build-azure 285 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 286 | with: 287 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 288 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 289 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 290 | versions: ${{ needs.configure.outputs.versions }} 291 | stage: azure 292 | secrets: 293 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 294 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 295 | 296 | manifest-aws: 297 | needs: 298 | - configure 299 | - build-aws 300 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 301 | with: 302 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 303 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 304 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 305 | versions: ${{ needs.configure.outputs.versions }} 306 | stage: aws 307 | secrets: 308 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 309 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 310 | 311 | manifest-awsk8s: 312 | needs: 313 | - configure 314 | - build-awsk8s 315 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 316 | with: 317 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 318 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 319 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 320 | versions: ${{ needs.configure.outputs.versions }} 321 | stage: awsk8s 322 | secrets: 323 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 324 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 325 | 326 | # Note: awskops is special 327 | manifest-awskops: 328 | needs: 329 | - configure-awskops 330 | - build-awskops 331 | uses: ./.github/workflows/docker-multistage-push-manifest-kops.yml 332 | with: 333 | can_deploy: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 334 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 335 | matrix: ${{ needs.configure-awskops.outputs.matrix_deploy }} 336 | versions: ${{ needs.configure-awskops.outputs.versions }} 337 | stage: awskops 338 | secrets: 339 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 340 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 341 | 342 | # Note: awshelm is special 343 | manifest-awshelm: 344 | needs: 345 | - configure-awshelm 346 | - build-awshelm 347 | uses: ./.github/workflows/docker-multistage-push-manifest-helm.yml 348 | with: 349 | can_deploy: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 350 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 351 | matrix: ${{ needs.configure-awshelm.outputs.matrix_deploy }} 352 | versions: ${{ needs.configure-awshelm.outputs.versions }} 353 | stage: awshelm 354 | secrets: 355 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 356 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 357 | -------------------------------------------------------------------------------- /.github/workflows/action_pull_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ------------------------------------------------------------------------------------------------- 4 | # Job Name 5 | # ------------------------------------------------------------------------------------------------- 6 | name: build 7 | 8 | 9 | # ------------------------------------------------------------------------------------------------- 10 | # When to run 11 | # ------------------------------------------------------------------------------------------------- 12 | on: 13 | pull_request: 14 | 15 | jobs: 16 | 17 | # ----------------------------------------------------------------------------------------------- 18 | # (1/4) Determine parameter settings 19 | # ----------------------------------------------------------------------------------------------- 20 | params: 21 | uses: ./.github/workflows/params.yml 22 | # Only run for forks (contributor) 23 | if: github.event.pull_request.head.repo.fork 24 | 25 | # ----------------------------------------------------------------------------------------------- 26 | # (2/4) Configure Build and Deploy Matrices 27 | # ----------------------------------------------------------------------------------------------- 28 | configure: 29 | needs: [params] 30 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 31 | with: 32 | enabled: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && (github.event.pull_request.user.login != 'cytopia')) }} 33 | can_deploy: false 34 | versions: ${{ needs.params.outputs.versions }} 35 | refs: ${{ needs.params.outputs.refs }} 36 | secrets: 37 | dockerhub_username: "" 38 | dockerhub_password: "" 39 | 40 | configure-awskops: 41 | needs: [params] 42 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 43 | with: 44 | enabled: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && (github.event.pull_request.user.login != 'cytopia')) }} 45 | can_deploy: false 46 | versions: ${{ needs.params.outputs.versions }} 47 | refs: ${{ needs.params.outputs.refs }} 48 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}, {"ARCH":"ARCH"}]' 49 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}]' 50 | secrets: 51 | dockerhub_username: "" 52 | dockerhub_password: "" 53 | 54 | configure-awshelm: 55 | needs: [params] 56 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 57 | with: 58 | enabled: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && (github.event.pull_request.user.login != 'cytopia')) }} 59 | can_deploy: false 60 | versions: ${{ needs.params.outputs.versions }} 61 | refs: ${{ needs.params.outputs.refs }} 62 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}, {"ARCH":"ARCH"}]' 63 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}]' 64 | secrets: 65 | dockerhub_username: "" 66 | dockerhub_password: "" 67 | 68 | 69 | # ----------------------------------------------------------------------------------------------- 70 | # (3/4) Build & Test 71 | # ----------------------------------------------------------------------------------------------- 72 | build-base: 73 | needs: 74 | - configure 75 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 76 | with: 77 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 78 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 79 | upload_artifact: true 80 | pull_base_image: true 81 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 82 | run_tests: true 83 | matrix: ${{ needs.configure.outputs.matrix_build }} 84 | stage: base 85 | stage_prev: '' 86 | secrets: 87 | dockerhub_username: "" 88 | dockerhub_password: "" 89 | 90 | build-tools: 91 | needs: 92 | - configure 93 | - build-base 94 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 95 | with: 96 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 97 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 98 | upload_artifact: true 99 | pull_base_image: false 100 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 101 | run_tests: true 102 | matrix: ${{ needs.configure.outputs.matrix_build }} 103 | stage: tools 104 | stage_prev: base 105 | secrets: 106 | dockerhub_username: "" 107 | dockerhub_password: "" 108 | 109 | build-aws: 110 | needs: 111 | - configure 112 | - build-tools 113 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 114 | with: 115 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 116 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 117 | upload_artifact: true 118 | pull_base_image: false 119 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 120 | run_tests: true 121 | matrix: ${{ needs.configure.outputs.matrix_build }} 122 | stage: aws 123 | stage_prev: tools 124 | secrets: 125 | dockerhub_username: "" 126 | dockerhub_password: "" 127 | 128 | build-azure: 129 | needs: 130 | - configure 131 | - build-tools 132 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 133 | with: 134 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 135 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 136 | upload_artifact: true 137 | pull_base_image: false 138 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 139 | run_tests: true 140 | matrix: ${{ needs.configure.outputs.matrix_build }} 141 | stage: azure 142 | stage_prev: tools 143 | secrets: 144 | dockerhub_username: "" 145 | dockerhub_password: "" 146 | 147 | build-infra: 148 | needs: 149 | - configure 150 | - build-tools 151 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 152 | with: 153 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 154 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 155 | upload_artifact: true 156 | pull_base_image: false 157 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 158 | run_tests: true 159 | matrix: ${{ needs.configure.outputs.matrix_build }} 160 | stage: infra 161 | stage_prev: tools 162 | secrets: 163 | dockerhub_username: "" 164 | dockerhub_password: "" 165 | 166 | build-awsk8s: 167 | needs: 168 | - configure 169 | - build-aws 170 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 171 | with: 172 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 173 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 174 | upload_artifact: true 175 | pull_base_image: false 176 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 177 | run_tests: true 178 | matrix: ${{ needs.configure.outputs.matrix_build }} 179 | stage: awsk8s 180 | stage_prev: aws 181 | secrets: 182 | dockerhub_username: "" 183 | dockerhub_password: "" 184 | 185 | # Note: awskops is special 186 | build-awskops: 187 | needs: 188 | - configure-awskops 189 | - build-awsk8s 190 | uses: ./.github/workflows/docker-multistage-build-extra.yml 191 | with: 192 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 193 | artifact_prefix: ${{ needs.configure-awskops.outputs.artifact_prefix }} 194 | upload_artifact: true 195 | pull_base_image: false 196 | push_image: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 197 | run_tests: true 198 | matrix: ${{ needs.configure-awskops.outputs.matrix_build }} 199 | stage: awskops 200 | stage_prev: awsk8s 201 | extra_make_var_name: KOPS 202 | secrets: 203 | dockerhub_username: "" 204 | dockerhub_password: "" 205 | 206 | # Note: awshelm is special 207 | build-awshelm: 208 | needs: 209 | - configure-awshelm 210 | - build-awsk8s 211 | uses: ./.github/workflows/docker-multistage-build-extra.yml 212 | with: 213 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 214 | artifact_prefix: ${{ needs.configure-awshelm.outputs.artifact_prefix }} 215 | upload_artifact: true 216 | pull_base_image: false 217 | push_image: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 218 | run_tests: true 219 | matrix: ${{ needs.configure-awshelm.outputs.matrix_build }} 220 | stage: awshelm 221 | stage_prev: awsk8s 222 | extra_make_var_name: HELM 223 | secrets: 224 | dockerhub_username: "" 225 | dockerhub_password: "" 226 | 227 | 228 | # ----------------------------------------------------------------------------------------------- 229 | # (4/4) Push Manifests 230 | # ----------------------------------------------------------------------------------------------- 231 | manifest-base: 232 | needs: 233 | - configure 234 | - build-base 235 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 236 | with: 237 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 238 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 239 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 240 | versions: ${{ needs.configure.outputs.versions }} 241 | stage: base 242 | secrets: 243 | dockerhub_username: "" 244 | dockerhub_password: "" 245 | 246 | manifest-tools: 247 | needs: 248 | - configure 249 | - build-tools 250 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 251 | with: 252 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 253 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 254 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 255 | versions: ${{ needs.configure.outputs.versions }} 256 | stage: tools 257 | secrets: 258 | dockerhub_username: "" 259 | dockerhub_password: "" 260 | 261 | manifest-infra: 262 | needs: 263 | - configure 264 | - build-infra 265 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 266 | with: 267 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 268 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 269 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 270 | versions: ${{ needs.configure.outputs.versions }} 271 | stage: infra 272 | secrets: 273 | dockerhub_username: "" 274 | dockerhub_password: "" 275 | 276 | manifest-azure: 277 | needs: 278 | - configure 279 | - build-azure 280 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 281 | with: 282 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 283 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 284 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 285 | versions: ${{ needs.configure.outputs.versions }} 286 | stage: azure 287 | secrets: 288 | dockerhub_username: "" 289 | dockerhub_password: "" 290 | 291 | manifest-aws: 292 | needs: 293 | - configure 294 | - build-aws 295 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 296 | with: 297 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 298 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 299 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 300 | versions: ${{ needs.configure.outputs.versions }} 301 | stage: aws 302 | secrets: 303 | dockerhub_username: "" 304 | dockerhub_password: "" 305 | 306 | manifest-awsk8s: 307 | needs: 308 | - configure 309 | - build-awsk8s 310 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 311 | with: 312 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 313 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 314 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 315 | versions: ${{ needs.configure.outputs.versions }} 316 | stage: awsk8s 317 | secrets: 318 | dockerhub_username: "" 319 | dockerhub_password: "" 320 | 321 | # Note: awskops is special 322 | manifest-awskops: 323 | needs: 324 | - configure-awskops 325 | - build-awskops 326 | uses: ./.github/workflows/docker-multistage-push-manifest-kops.yml 327 | with: 328 | can_deploy: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 329 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 330 | matrix: ${{ needs.configure-awskops.outputs.matrix_deploy }} 331 | versions: ${{ needs.configure-awskops.outputs.versions }} 332 | stage: awskops 333 | secrets: 334 | dockerhub_username: "" 335 | dockerhub_password: "" 336 | 337 | # Note: awshelm is special 338 | manifest-awshelm: 339 | needs: 340 | - configure-awshelm 341 | - build-awshelm 342 | uses: ./.github/workflows/docker-multistage-push-manifest-helm.yml 343 | with: 344 | can_deploy: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 345 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 346 | matrix: ${{ needs.configure-awshelm.outputs.matrix_deploy }} 347 | versions: ${{ needs.configure-awshelm.outputs.versions }} 348 | stage: awshelm 349 | secrets: 350 | dockerhub_username: "" 351 | dockerhub_password: "" 352 | -------------------------------------------------------------------------------- /.github/workflows/action_schedule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ------------------------------------------------------------------------------------------------- 4 | # Job Name 5 | # ------------------------------------------------------------------------------------------------- 6 | name: nightly 7 | 8 | 9 | # ------------------------------------------------------------------------------------------------- 10 | # When to run 11 | # ------------------------------------------------------------------------------------------------- 12 | on: 13 | # Runs daily 14 | schedule: 15 | - cron: '0 0 * * *' 16 | # Dispatch: allows for manual trigger via GH UI 17 | workflow_dispatch: 18 | 19 | jobs: 20 | 21 | # ----------------------------------------------------------------------------------------------- 22 | # (1/4) Determine parameter settings 23 | # ----------------------------------------------------------------------------------------------- 24 | params: 25 | uses: ./.github/workflows/params.yml 26 | 27 | # ----------------------------------------------------------------------------------------------- 28 | # (2/4) Configure Build and Deploy Matrices 29 | # ----------------------------------------------------------------------------------------------- 30 | configure: 31 | needs: [params] 32 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 33 | with: 34 | enabled: true 35 | can_deploy: true 36 | versions: ${{ needs.params.outputs.versions }} 37 | refs: ${{ needs.params.outputs.refs }} 38 | secrets: 39 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 40 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 41 | 42 | configure-awskops: 43 | needs: [params] 44 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 45 | with: 46 | enabled: true 47 | can_deploy: true 48 | versions: ${{ needs.params.outputs.versions }} 49 | refs: ${{ needs.params.outputs.refs }} 50 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}, {"ARCH":"ARCH"}]' 51 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"KOPS":"EXTRA"}]' 52 | secrets: 53 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 54 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 55 | 56 | configure-awshelm: 57 | needs: [params] 58 | uses: devilbox/github-actions/.github/workflows/docker-multistage-configure.yml@master 59 | with: 60 | enabled: true 61 | can_deploy: true 62 | versions: ${{ needs.params.outputs.versions }} 63 | refs: ${{ needs.params.outputs.refs }} 64 | fields_build: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}, {"ARCH":"ARCH"}]' 65 | fields_deploy: '[{"VERSION":"VERSION"}, {"FLAVOUR":"FLAVOUR"}, {"HELM":"EXTRA"}]' 66 | secrets: 67 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 68 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 69 | 70 | 71 | # ----------------------------------------------------------------------------------------------- 72 | # (3/4) Build & Test 73 | # ----------------------------------------------------------------------------------------------- 74 | build-base: 75 | needs: 76 | - configure 77 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 78 | with: 79 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 80 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 81 | upload_artifact: true 82 | pull_base_image: true 83 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 84 | run_tests: true 85 | matrix: ${{ needs.configure.outputs.matrix_build }} 86 | stage: base 87 | stage_prev: '' 88 | secrets: 89 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 90 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 91 | 92 | build-tools: 93 | needs: 94 | - configure 95 | - build-base 96 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 97 | with: 98 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 99 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 100 | upload_artifact: true 101 | pull_base_image: false 102 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 103 | run_tests: true 104 | matrix: ${{ needs.configure.outputs.matrix_build }} 105 | stage: tools 106 | stage_prev: base 107 | secrets: 108 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 109 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 110 | 111 | build-aws: 112 | needs: 113 | - configure 114 | - build-tools 115 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 116 | with: 117 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 118 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 119 | upload_artifact: true 120 | pull_base_image: false 121 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 122 | run_tests: true 123 | matrix: ${{ needs.configure.outputs.matrix_build }} 124 | stage: aws 125 | stage_prev: tools 126 | secrets: 127 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 128 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 129 | 130 | build-azure: 131 | needs: 132 | - configure 133 | - build-tools 134 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 135 | with: 136 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 137 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 138 | upload_artifact: true 139 | pull_base_image: false 140 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 141 | run_tests: true 142 | matrix: ${{ needs.configure.outputs.matrix_build }} 143 | stage: azure 144 | stage_prev: tools 145 | secrets: 146 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 147 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 148 | 149 | build-infra: 150 | needs: 151 | - configure 152 | - build-tools 153 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 154 | with: 155 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 156 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 157 | upload_artifact: true 158 | pull_base_image: false 159 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 160 | run_tests: true 161 | matrix: ${{ needs.configure.outputs.matrix_build }} 162 | stage: infra 163 | stage_prev: tools 164 | secrets: 165 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 166 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 167 | 168 | build-awsk8s: 169 | needs: 170 | - configure 171 | - build-aws 172 | uses: devilbox/github-actions/.github/workflows/docker-multistage-build.yml@master 173 | with: 174 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 175 | artifact_prefix: ${{ needs.configure.outputs.artifact_prefix }} 176 | upload_artifact: true 177 | pull_base_image: false 178 | push_image: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 179 | run_tests: true 180 | matrix: ${{ needs.configure.outputs.matrix_build }} 181 | stage: awsk8s 182 | stage_prev: aws 183 | secrets: 184 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 185 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 186 | 187 | # Note: awskops is special 188 | build-awskops: 189 | needs: 190 | - configure-awskops 191 | - build-awsk8s 192 | uses: ./.github/workflows/docker-multistage-build-extra.yml 193 | with: 194 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 195 | artifact_prefix: ${{ needs.configure-awskops.outputs.artifact_prefix }} 196 | upload_artifact: true 197 | pull_base_image: false 198 | push_image: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 199 | run_tests: true 200 | matrix: ${{ needs.configure-awskops.outputs.matrix_build }} 201 | stage: awskops 202 | stage_prev: awsk8s 203 | extra_make_var_name: KOPS 204 | secrets: 205 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 206 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 207 | 208 | # Note: awshelm is special 209 | build-awshelm: 210 | needs: 211 | - configure-awshelm 212 | - build-awsk8s 213 | uses: ./.github/workflows/docker-multistage-build-extra.yml 214 | with: 215 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 216 | artifact_prefix: ${{ needs.configure-awshelm.outputs.artifact_prefix }} 217 | upload_artifact: true 218 | pull_base_image: false 219 | push_image: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 220 | run_tests: true 221 | matrix: ${{ needs.configure-awshelm.outputs.matrix_build }} 222 | stage: awshelm 223 | stage_prev: awsk8s 224 | extra_make_var_name: HELM 225 | secrets: 226 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 227 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 228 | 229 | 230 | # ----------------------------------------------------------------------------------------------- 231 | # (4/4) Push Manifests 232 | # ----------------------------------------------------------------------------------------------- 233 | manifest-base: 234 | needs: 235 | - configure 236 | - build-base 237 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 238 | with: 239 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 240 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 241 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 242 | versions: ${{ needs.configure.outputs.versions }} 243 | stage: base 244 | secrets: 245 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 246 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 247 | 248 | manifest-tools: 249 | needs: 250 | - configure 251 | - build-tools 252 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 253 | with: 254 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 255 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 256 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 257 | versions: ${{ needs.configure.outputs.versions }} 258 | stage: tools 259 | secrets: 260 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 261 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 262 | 263 | manifest-infra: 264 | needs: 265 | - configure 266 | - build-infra 267 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 268 | with: 269 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 270 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 271 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 272 | versions: ${{ needs.configure.outputs.versions }} 273 | stage: infra 274 | secrets: 275 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 276 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 277 | 278 | manifest-azure: 279 | needs: 280 | - configure 281 | - build-azure 282 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 283 | with: 284 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 285 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 286 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 287 | versions: ${{ needs.configure.outputs.versions }} 288 | stage: azure 289 | secrets: 290 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 291 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 292 | 293 | manifest-aws: 294 | needs: 295 | - configure 296 | - build-aws 297 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 298 | with: 299 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 300 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 301 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 302 | versions: ${{ needs.configure.outputs.versions }} 303 | stage: aws 304 | secrets: 305 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 306 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 307 | 308 | manifest-awsk8s: 309 | needs: 310 | - configure 311 | - build-awsk8s 312 | uses: devilbox/github-actions/.github/workflows/docker-multistage-push-manifest.yml@master 313 | with: 314 | can_deploy: ${{ needs.configure.outputs.can_login == 'true' && needs.configure.outputs.can_push == 'true' }} 315 | has_refs: ${{ needs.configure.outputs.has_refs == 'true' }} 316 | matrix: ${{ needs.configure.outputs.matrix_deploy }} 317 | versions: ${{ needs.configure.outputs.versions }} 318 | stage: awsk8s 319 | secrets: 320 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 321 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 322 | 323 | # Note: awskops is special 324 | manifest-awskops: 325 | needs: 326 | - configure-awskops 327 | - build-awskops 328 | uses: ./.github/workflows/docker-multistage-push-manifest-kops.yml 329 | with: 330 | can_deploy: ${{ needs.configure-awskops.outputs.can_login == 'true' && needs.configure-awskops.outputs.can_push == 'true' }} 331 | has_refs: ${{ needs.configure-awskops.outputs.has_refs == 'true' }} 332 | matrix: ${{ needs.configure-awskops.outputs.matrix_deploy }} 333 | versions: ${{ needs.configure-awskops.outputs.versions }} 334 | stage: awskops 335 | secrets: 336 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 337 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 338 | 339 | # Note: awshelm is special 340 | manifest-awshelm: 341 | needs: 342 | - configure-awshelm 343 | - build-awshelm 344 | uses: ./.github/workflows/docker-multistage-push-manifest-helm.yml 345 | with: 346 | can_deploy: ${{ needs.configure-awshelm.outputs.can_login == 'true' && needs.configure-awshelm.outputs.can_push == 'true' }} 347 | has_refs: ${{ needs.configure-awshelm.outputs.has_refs == 'true' }} 348 | matrix: ${{ needs.configure-awshelm.outputs.matrix_deploy }} 349 | versions: ${{ needs.configure-awshelm.outputs.versions }} 350 | stage: awshelm 351 | secrets: 352 | dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} 353 | dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} 354 | -------------------------------------------------------------------------------- /.github/workflows/docker-multistage-build-extra.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Build multistage docker images (multi -flavours, -versions, -architectures -kops)" 3 | 4 | on: 5 | workflow_call: 6 | ### 7 | ### Variables 8 | ### 9 | inputs: 10 | matrix: 11 | description: 'The build matrix' 12 | required: true 13 | type: string 14 | stage: 15 | description: 'The stage to build (Examples: base, mods, prod or work).' 16 | required: true 17 | type: string 18 | stage_prev: 19 | description: 'The previous stage (used for downloading previous artifact).' 20 | required: true 21 | type: string 22 | artifact_prefix: 23 | description: 'Unique artifact name prefix (to avoid overriding existing artifcats during parallel runs).' 24 | required: true 25 | type: string 26 | has_refs: 27 | description: 'The ref build matrix as JSON string (list of git refs to build/deploy).' 28 | required: true 29 | type: boolean 30 | run_tests: 31 | description: 'Dertermines whether we run integration tests or not.' 32 | required: true 33 | type: boolean 34 | upload_artifact: 35 | description: 'Dertermines whether we upload the artifact not.' 36 | required: true 37 | type: boolean 38 | push_image: 39 | description: 'Push docker image after build (and test if ran)?' 40 | required: false 41 | type: boolean 42 | default: false 43 | pull_base_image: 44 | description: 'Pull Docker base image before building?' 45 | required: false 46 | type: boolean 47 | default: false 48 | extra_make_var_name: 49 | description: 'Extra makefile variable name to assign matrix.EXTRA value to' 50 | required: true 51 | type: string 52 | ### 53 | ### Secrets 54 | ### 55 | secrets: 56 | dockerhub_username: 57 | description: 'The username for Dockerhub.' 58 | required: true 59 | dockerhub_password: 60 | description: 'The password for Dockerhub.' 61 | required: true 62 | 63 | jobs: 64 | # ----------------------------------------------------------------------------------------------- 65 | # JOB: BUILD 66 | # ----------------------------------------------------------------------------------------------- 67 | build: 68 | name: ${{ matrix.NAME }}-${{ matrix.VERSION }}-${{ inputs.stage }}${{ matrix.EXTRA }} (${{ matrix.ARCH }}) ${{ matrix.REFS }} 69 | runs-on: ubuntu-latest 70 | strategy: 71 | fail-fast: false 72 | matrix: 73 | include: ${{ fromJson(inputs.matrix) }} 74 | steps: 75 | 76 | # ------------------------------------------------------------ 77 | # Setup repository 78 | # ------------------------------------------------------------ 79 | - name: "[SETUP] Checkout repository (current)" 80 | uses: actions/checkout@v3 81 | with: 82 | fetch-depth: 0 83 | if: ${{ !inputs.has_refs }} 84 | 85 | - name: "[SETUP] Checkout repository (ref: ${{ matrix.REFS }})" 86 | uses: actions/checkout@v3 87 | with: 88 | fetch-depth: 0 89 | ref: ${{ matrix.REFS }} 90 | if: ${{ inputs.has_refs }} 91 | 92 | - name: "[SETUP] Install QEMU environment" 93 | uses: docker/setup-qemu-action@v2 94 | id: qemu 95 | with: 96 | image: tonistiigi/binfmt:latest 97 | platforms: all 98 | 99 | - name: "[SETUP] Set artifact names" 100 | id: set-artifact-name 101 | run: | 102 | VERSION="$( echo "${{ matrix.VERSION }}" )" 103 | ARCH="$( echo "${{ matrix.ARCH }}" | sed 's|/|-|g' )" 104 | 105 | NAME_PREV="${{ inputs.artifact_prefix }}-${VERSION}-${ARCH}-${{ inputs.stage_prev }}" 106 | NAME_CURR="${{ inputs.artifact_prefix }}-${VERSION}-${ARCH}-${{ inputs.stage }}${{ matrix.EXTRA }}" 107 | echo "prev=${NAME_PREV}" >> $GITHUB_OUTPUT 108 | echo "curr=${NAME_CURR}" >> $GITHUB_OUTPUT 109 | 110 | - name: "[SETUP] Determine Docker tag" 111 | id: tag 112 | uses: cytopia/docker-tag-action@v0.4.22 113 | 114 | # https://github.com/alpinelinux/docker-alpine/issues/98 115 | - name: "[SETUP] Fix Docker IP forwarding" 116 | run: | 117 | sysctl net.ipv4.ip_forward 118 | sudo sysctl -w net.ipv4.ip_forward=1 119 | sudo systemctl restart docker 120 | 121 | 122 | # ------------------------------------------------------------ 123 | # Artifact Import 124 | # ------------------------------------------------------------ 125 | - name: "[Artifact Load] Download previously built image" 126 | uses: cytopia/download-artifact-retry-action@v0.1.5 127 | with: 128 | name: ${{ steps.set-artifact-name.outputs.prev }} 129 | if: ${{ inputs.stage_prev != '' }} 130 | 131 | - name: "[Artifact Load] Import previously built image" 132 | uses: cytopia/shell-command-retry-action@v0.1.6 133 | with: 134 | command: | 135 | make load INFILE=${{ steps.set-artifact-name.outputs.prev }} 136 | if: ${{ inputs.stage_prev != '' }} 137 | 138 | 139 | # ------------------------------------------------------------ 140 | # Build 141 | # ------------------------------------------------------------ 142 | - name: Pull 143 | uses: cytopia/shell-command-retry-action@v0.1.6 144 | with: 145 | command: | 146 | make docker-pull-base-image VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCH=${{ matrix.ARCH }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 147 | if: ${{ inputs.pull_base_image }} 148 | 149 | - name: Build 150 | uses: cytopia/shell-command-retry-action@v0.1.6 151 | with: 152 | command: | 153 | make build VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCH=${{ matrix.ARCH }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 154 | 155 | 156 | # ------------------------------------------------------------ 157 | # Test 158 | # ------------------------------------------------------------ 159 | - name: Test 160 | uses: cytopia/shell-command-retry-action@v0.1.6 161 | with: 162 | command: | 163 | make test VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCH=${{ matrix.ARCH }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 164 | if: ${{ inputs.run_tests }} 165 | 166 | 167 | # ------------------------------------------------------------ 168 | # Push 169 | # ------------------------------------------------------------ 170 | - name: Docker Tag 171 | uses: cytopia/shell-command-retry-action@v0.1.6 172 | with: 173 | command: | 174 | make tag VERSION="${{ matrix.VERSION }}" STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} TAG=${{ steps.tag.outputs.docker-tag }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 175 | 176 | - name: Docker login 177 | uses: docker/login-action@v2 178 | with: 179 | username: ${{ secrets.dockerhub_username }} 180 | password: ${{ secrets.dockerhub_password }} 181 | if: ${{ inputs.push_image }} 182 | 183 | - name: Docker push 184 | uses: cytopia/shell-command-retry-action@v0.1.6 185 | with: 186 | command: | 187 | make push VERSION="${{ matrix.version }}" STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.flavour }} ARCH=${{ matrix.arch }} TAG=${{ steps.tag.outputs.docker-tag }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 188 | if: ${{ inputs.push_image }} 189 | 190 | 191 | # ------------------------------------------------------------ 192 | # Artifact Export 193 | # ------------------------------------------------------------ 194 | - name: "[Artifact Save] Upload built artifact" 195 | uses: cytopia/upload-artifact-retry-action@v0.1.7 196 | with: 197 | name: ${{ steps.set-artifact-name.outputs.curr }} 198 | path: ${{ steps.set-artifact-name.outputs.curr }} 199 | pre_command: | 200 | make save-verify VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCH=${{ matrix.ARCH }} OUTFILE=${{ steps.set-artifact-name.outputs.curr }} INFILE=${{ steps.set-artifact-name.outputs.curr }} ${{ inputs.extra_make_var_name }}=${{ matrix.EXTRA }} 201 | post_command: | 202 | make load INFILE={{download_path}} 203 | if: ${{ inputs.upload_artifact }} 204 | -------------------------------------------------------------------------------- /.github/workflows/docker-multistage-push-manifest-helm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Deploy multi-arch image manifests 3 | 4 | on: 5 | workflow_call: 6 | ### 7 | ### Variables 8 | ### 9 | inputs: 10 | matrix: 11 | description: 'The version deploy matrix as JSON string ( list of objects: [{NAME, VERSION[], ARCH[]}] ).' 12 | required: true 13 | type: string 14 | versions: 15 | description: 'The build matrix set via params.yml.' 16 | required: true 17 | type: string 18 | stage: 19 | description: 'The stage to build (Examples: base, mods, prod or work).' 20 | required: true 21 | type: string 22 | can_deploy: 23 | description: 'Determines whether this workflow will also deploy (login and push).' 24 | required: true 25 | type: boolean 26 | has_refs: 27 | description: 'The ref build matrix as JSON string (list of git refs to build/deploy).' 28 | required: true 29 | type: boolean 30 | 31 | 32 | ### 33 | ### Secrets 34 | ### 35 | secrets: 36 | dockerhub_username: 37 | description: 'The username for Dockerhub.' 38 | required: false 39 | dockerhub_password: 40 | description: 'The password for Dockerhub.' 41 | required: false 42 | 43 | jobs: 44 | # ----------------------------------------------------------------------------------------------- 45 | # JOB (3/3): DEPLOY 46 | # ----------------------------------------------------------------------------------------------- 47 | deploy: 48 | name: ${{ matrix.NAME }}-${{ matrix.VERSION }}-${{ inputs.stage }}${{ matrix.EXTRA }} ${{ matrix.REFS }} 49 | runs-on: ubuntu-latest 50 | strategy: 51 | fail-fast: false 52 | matrix: 53 | include: ${{ fromJson(inputs.matrix) }} 54 | if: ${{ inputs.can_deploy }} 55 | steps: 56 | # ------------------------------------------------------------ 57 | # Setup repository 58 | # ------------------------------------------------------------ 59 | - name: "[SETUP] Checkout repository (current)" 60 | uses: actions/checkout@v3 61 | with: 62 | fetch-depth: 0 63 | if: ${{ !inputs.has_refs }} 64 | 65 | - name: "[SETUP] Checkout repository (ref: ${{ matrix.REFS }})" 66 | uses: actions/checkout@v3 67 | with: 68 | fetch-depth: 0 69 | ref: ${{ matrix.REFS }} 70 | if: ${{ inputs.has_refs }} 71 | 72 | - name: "[SETUP] Setup QEMU environment" 73 | uses: docker/setup-qemu-action@v2 74 | with: 75 | image: tonistiigi/binfmt:latest 76 | platforms: all 77 | 78 | - name: "[SETUP] Determine Docker tag" 79 | id: tag 80 | uses: cytopia/docker-tag-action@v0.4.22 81 | 82 | - name: "[SETUP] Determine manifest arches" 83 | id: manifest 84 | run: | 85 | ARCHES="$( echo '${{ inputs.versions }}' \ 86 | | jq 'group_by(.NAME, .VERSION, .FLAVOUR, .HELM, .ARCH)' \ 87 | | jq 'map({NAME: .[].NAME, VERSION: .[].VERSION[], FLAVOUR: .[].FLAVOUR[], HELM: .[].HELM[], ARCHES: .[].ARCH|join(",")})' \ 88 | | jq '.[] | select(.NAME=="${{ matrix.NAME }}" and .VERSION=="${{ matrix.VERSION }}" and .FLAVOUR=="${{ matrix.FLAVOUR }}" and .HELM=="${{ matrix.EXTRA }}") | .ARCHES' \ 89 | | jq -c -M \ 90 | )" 91 | echo "arches=${ARCHES}" >> $GITHUB_OUTPUT 92 | echo "ARCHES: ${ARCHES}" 93 | 94 | 95 | # ------------------------------------------------------------ 96 | # Login 97 | # ------------------------------------------------------------ 98 | - name: "Login" 99 | uses: docker/login-action@v2 100 | with: 101 | username: ${{ secrets.DOCKERHUB_USERNAME }} 102 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 103 | 104 | 105 | # ------------------------------------------------------------ 106 | # Create Manifest 107 | # ------------------------------------------------------------ 108 | - name: "[Create Manifest] (${{ steps.manifest.outputs.arches }})" 109 | uses: cytopia/shell-command-retry-action@v0.1.6 110 | with: 111 | command: | 112 | make manifest-create VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCHES=${{ steps.manifest.outputs.arches }} TAG=${{ steps.tag.outputs.docker-tag }} HELM=${{ matrix.EXTRA }} 113 | 114 | 115 | # ------------------------------------------------------------ 116 | # Deploy Manifest 117 | # ------------------------------------------------------------ 118 | - name: "[Push Manifest] ${{ steps.tag.outputs.docker-tag }}" 119 | uses: cytopia/shell-command-retry-action@v0.1.6 120 | with: 121 | command: | 122 | make manifest-push VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} TAG=${{ steps.tag.outputs.docker-tag }} HELM=${{ matrix.EXTRA }} 123 | -------------------------------------------------------------------------------- /.github/workflows/docker-multistage-push-manifest-kops.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Deploy multi-arch image manifests 3 | 4 | on: 5 | workflow_call: 6 | ### 7 | ### Variables 8 | ### 9 | inputs: 10 | matrix: 11 | description: 'The version deploy matrix as JSON string ( list of objects: [{NAME, VERSION[], ARCH[]}] ).' 12 | required: true 13 | type: string 14 | versions: 15 | description: 'The build matrix set via params.yml.' 16 | required: true 17 | type: string 18 | stage: 19 | description: 'The stage to build (Examples: base, mods, prod or work).' 20 | required: true 21 | type: string 22 | can_deploy: 23 | description: 'Determines whether this workflow will also deploy (login and push).' 24 | required: true 25 | type: boolean 26 | has_refs: 27 | description: 'The ref build matrix as JSON string (list of git refs to build/deploy).' 28 | required: true 29 | type: boolean 30 | 31 | 32 | ### 33 | ### Secrets 34 | ### 35 | secrets: 36 | dockerhub_username: 37 | description: 'The username for Dockerhub.' 38 | required: false 39 | dockerhub_password: 40 | description: 'The password for Dockerhub.' 41 | required: false 42 | 43 | jobs: 44 | # ----------------------------------------------------------------------------------------------- 45 | # JOB (3/3): DEPLOY 46 | # ----------------------------------------------------------------------------------------------- 47 | deploy: 48 | name: ${{ matrix.NAME }}-${{ matrix.VERSION }}-${{ inputs.stage }}${{ matrix.EXTRA }} ${{ matrix.REFS }} 49 | runs-on: ubuntu-latest 50 | strategy: 51 | fail-fast: false 52 | matrix: 53 | include: ${{ fromJson(inputs.matrix) }} 54 | if: ${{ inputs.can_deploy }} 55 | steps: 56 | # ------------------------------------------------------------ 57 | # Setup repository 58 | # ------------------------------------------------------------ 59 | - name: "[SETUP] Checkout repository (current)" 60 | uses: actions/checkout@v3 61 | with: 62 | fetch-depth: 0 63 | if: ${{ !inputs.has_refs }} 64 | 65 | - name: "[SETUP] Checkout repository (ref: ${{ matrix.REFS }})" 66 | uses: actions/checkout@v3 67 | with: 68 | fetch-depth: 0 69 | ref: ${{ matrix.REFS }} 70 | if: ${{ inputs.has_refs }} 71 | 72 | - name: "[SETUP] Setup QEMU environment" 73 | uses: docker/setup-qemu-action@v2 74 | with: 75 | image: tonistiigi/binfmt:latest 76 | platforms: all 77 | 78 | - name: "[SETUP] Determine Docker tag" 79 | id: tag 80 | uses: cytopia/docker-tag-action@v0.4.22 81 | 82 | - name: "[SETUP] Determine manifest arches" 83 | id: manifest 84 | run: | 85 | ARCHES="$( echo '${{ inputs.versions }}' \ 86 | | jq 'group_by(.NAME, .VERSION, .FLAVOUR, .KOPS, .ARCH)' \ 87 | | jq 'map({NAME: .[].NAME, VERSION: .[].VERSION[], FLAVOUR: .[].FLAVOUR[], KOPS: .[].KOPS[], ARCHES: .[].ARCH|join(",")})' \ 88 | | jq '.[] | select(.NAME=="${{ matrix.NAME }}" and .VERSION=="${{ matrix.VERSION }}" and .FLAVOUR=="${{ matrix.FLAVOUR }}" and .KOPS=="${{ matrix.EXTRA }}") | .ARCHES' \ 89 | | jq -c -M \ 90 | )" 91 | echo "arches=${ARCHES}" >> $GITHUB_OUTPUT 92 | echo "ARCHES: ${ARCHES}" 93 | 94 | 95 | # ------------------------------------------------------------ 96 | # Login 97 | # ------------------------------------------------------------ 98 | - name: "Login" 99 | uses: docker/login-action@v2 100 | with: 101 | username: ${{ secrets.DOCKERHUB_USERNAME }} 102 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 103 | 104 | 105 | # ------------------------------------------------------------ 106 | # Create Manifest 107 | # ------------------------------------------------------------ 108 | - name: "[Create Manifest] (${{ steps.manifest.outputs.arches }})" 109 | uses: cytopia/shell-command-retry-action@v0.1.6 110 | with: 111 | command: | 112 | make manifest-create VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} ARCHES=${{ steps.manifest.outputs.arches }} TAG=${{ steps.tag.outputs.docker-tag }} KOPS=${{ matrix.EXTRA }} 113 | 114 | 115 | # ------------------------------------------------------------ 116 | # Deploy Manifest 117 | # ------------------------------------------------------------ 118 | - name: "[Push Manifest] ${{ steps.tag.outputs.docker-tag }}" 119 | uses: cytopia/shell-command-retry-action@v0.1.6 120 | with: 121 | command: | 122 | make manifest-push VERSION=${{ matrix.VERSION }} STAGE=${{ inputs.stage }} FLAVOUR=${{ matrix.FLAVOUR }} TAG=${{ steps.tag.outputs.docker-tag }} KOPS=${{ matrix.EXTRA }} 123 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ------------------------------------------------------------------------------------------------- 4 | # Job Name 5 | # ------------------------------------------------------------------------------------------------- 6 | name: lint 7 | 8 | 9 | # ------------------------------------------------------------------------------------------------- 10 | # When to run 11 | # ------------------------------------------------------------------------------------------------- 12 | on: 13 | # Runs on Pull Requests 14 | pull_request: 15 | 16 | 17 | # ------------------------------------------------------------------------------------------------- 18 | # What to run 19 | # ------------------------------------------------------------------------------------------------- 20 | jobs: 21 | lint: 22 | uses: devilbox/github-actions/.github/workflows/lint-generic.yml@master 23 | -------------------------------------------------------------------------------- /.github/workflows/params.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ------------------------------------------------------------------------------------------------- 4 | # Job Name 5 | # ------------------------------------------------------------------------------------------------- 6 | name: params 7 | 8 | 9 | # ------------------------------------------------------------------------------------------------- 10 | # Custom Variables 11 | # ------------------------------------------------------------------------------------------------- 12 | env: 13 | VERSIONS: >- 14 | [ 15 | { 16 | "NAME": "ansible", 17 | "VERSION": [ 18 | "latest", 19 | "2.13", 20 | "2.12", 21 | "2.11", 22 | "2.10", 23 | "2.9", 24 | "2.8" 25 | ], 26 | "KOPS": [ 27 | "1.25", 28 | "1.24", 29 | "1.23", 30 | "1.22", 31 | "1.21", 32 | "1.20", 33 | "1.19" 34 | ], 35 | "HELM": [ 36 | "3.11", 37 | "3.10", 38 | "3.9", 39 | "3.8", 40 | "3.7", 41 | "3.6", 42 | "3.5", 43 | "3.4", 44 | "3.3", 45 | "3.2", 46 | "3.1", 47 | "3.0", 48 | "2.16" 49 | ], 50 | "FLAVOUR": ["default"], 51 | "ARCH": ["linux/amd64", "linux/arm64"] 52 | } 53 | ] 54 | 55 | # Set Refs to build for scheduled jobs 56 | REFS: >- 57 | { 58 | "DEFAULT_BRANCH": "master", 59 | "BRANCHES": "master", 60 | "NUM_LATEST_TAGS": 0 61 | } 62 | 63 | 64 | # ------------------------------------------------------------------------------------------------- 65 | # When to run 66 | # ------------------------------------------------------------------------------------------------- 67 | on: 68 | workflow_call: 69 | outputs: 70 | versions: 71 | description: "Stringified JSON of Versions definition." 72 | value: ${{ jobs.params.outputs.versions }} 73 | refs: 74 | description: "Stringified JSON of Refs definition." 75 | value: ${{ jobs.params.outputs.refs }} 76 | 77 | jobs: 78 | params: 79 | runs-on: ubuntu-latest 80 | 81 | outputs: 82 | versions: ${{ steps.set-json.outputs.versions }} 83 | refs: ${{ steps.set-json.outputs.refs }} 84 | 85 | steps: 86 | - name: "[Set-Output] JSON" 87 | id: set-json 88 | run: | 89 | VERSIONS="$( echo '${{ env.VERSIONS }}' | jq -M -c )" 90 | REFS="$( echo '${{ env.REFS }}' | jq -M -c )" 91 | 92 | echo "versions=${VERSIONS}" >> $GITHUB_OUTPUT 93 | echo "refs=${REFS}" >> $GITHUB_OUTPUT 94 | 95 | - name: "[DEBUG] Show settings'" 96 | run: | 97 | echo 'Versions' 98 | echo '--------------------' 99 | echo '${{ steps.set-json.outputs.versions }}' 100 | echo 101 | 102 | echo 'Refs' 103 | echo '--------------------' 104 | echo '${{ steps.set-json.outputs.refs }}' 105 | echo 106 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release Drafter 3 | 4 | on: 5 | push: 6 | # branches to consider in the event; optional, defaults to all 7 | branches: 8 | - master 9 | 10 | jobs: 11 | update_release_draft: 12 | runs-on: ubuntu-latest 13 | steps: 14 | # Drafts your next Release notes as Pull Requests are merged into "master" 15 | - uses: release-drafter/release-drafter@v5 16 | with: 17 | publish: true 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.RELEASE_DRAFTER_TOKEN }} 20 | -------------------------------------------------------------------------------- /.github/workflows/repository.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Repository 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | paths: 9 | - .github/labels.yml 10 | 11 | jobs: 12 | labels: 13 | name: Labels 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v3 19 | 20 | - name: Sync labels 21 | uses: micnncim/action-label-syncer@v1 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | with: 25 | manifest: .github/labels.yml 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile.docker 2 | Makefile.lint 3 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | ignore: | 5 | .yamllint 6 | 7 | 8 | rules: 9 | truthy: 10 | allowed-values: ['true', 'false'] 11 | check-keys: False 12 | level: error 13 | line-length: disable 14 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-aws: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-tools as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # build tools 12 | coreutils \ 13 | g++ \ 14 | gcc \ 15 | make \ 16 | musl-dev \ 17 | openssl-dev \ 18 | python3-dev \ 19 | # misc tools 20 | git \ 21 | # go tools 22 | cargo \ 23 | go 24 | 25 | # Python packages (copied to final image) 26 | RUN set -eux \ 27 | && pip3 install --no-cache-dir --no-compile \ 28 | awscli \ 29 | botocore \ 30 | boto \ 31 | boto3 \ 32 | && aws --version 2>&1 | grep -E '^aws-cli/[.0-9]+' \ 33 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 34 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 35 | 36 | # aws-iam-authemticator (copied to final image) 37 | RUN set -eux \ 38 | && if [ "$(uname -m)" = "aarch64" ]; then \ 39 | ARCH="arm64"; \ 40 | elif [ "$(uname -m)" = "x86_64" ]; then \ 41 | ARCH="amd64"; \ 42 | else \ 43 | fail; \ 44 | fi \ 45 | \ 46 | && git clone https://github.com/kubernetes-sigs/aws-iam-authenticator /tmp/aws-iam-authenticator \ 47 | && cd /tmp/aws-iam-authenticator \ 48 | && IAM_AUTH_VERSION="$( git tag --sort=-creatordate \ 49 | | sort -V \ 50 | | grep -E 'v[0-9]+\.[0-9]+\.[0-9]+$' \ 51 | | tail -1 \ 52 | )" \ 53 | && git checkout "${IAM_AUTH_VERSION}" \ 54 | && make build-all-bins \ 55 | && mv _output/bin/aws-iam-authenticator_${IAM_AUTH_VERSION}_linux_${ARCH} /usr/bin/aws-iam-authenticator \ 56 | && chmod +x /usr/bin/aws-iam-authenticator \ 57 | && aws-iam-authenticator version | grep -E "\"(${IAM_AUTH_VERSION}|unversioned)\"" \ 58 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 59 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 60 | 61 | 62 | # -------------------------------------------------------------------------------------------------- 63 | # Final Image 64 | # -------------------------------------------------------------------------------------------------- 65 | FROM cytopia/ansible:${VERSION}-tools as production 66 | ARG VERSION 67 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 68 | #LABEL "org.opencontainers.image.created"="" 69 | #LABEL "org.opencontainers.image.version"="" 70 | #LABEL "org.opencontainers.image.revision"="" 71 | LABEL "maintainer"="cytopia " 72 | LABEL "org.opencontainers.image.authors"="cytopia " 73 | LABEL "org.opencontainers.image.vendor"="cytopia" 74 | LABEL "org.opencontainers.image.licenses"="MIT" 75 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 76 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 77 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 78 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} aws" 79 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} aws" 80 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} aws" 81 | 82 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 83 | COPY --from=builder /usr/bin/aws /usr/bin/aws 84 | COPY --from=builder /usr/bin/aws-iam-authenticator /usr/bin/aws-iam-authenticator 85 | 86 | WORKDIR /data 87 | ENTRYPOINT ["/docker-entrypoint.sh"] 88 | CMD ["/bin/bash"] 89 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-awshelm: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-awsk8s as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # misc tools 12 | coreutils \ 13 | curl \ 14 | git 15 | 16 | # Install Helm by major and minor version 17 | ARG HELM 18 | RUN set -eux \ 19 | && if [ "$(uname -m)" = "aarch64" ]; then \ 20 | ARCH="arm64"; \ 21 | elif [ "$(uname -m)" = "x86_64" ]; then \ 22 | ARCH="amd64"; \ 23 | else \ 24 | fail; \ 25 | fi \ 26 | \ 27 | && git clone https://github.com/helm/helm \ 28 | && cd helm \ 29 | # Sort by unique minor versions (without patch) \ 30 | && version="$(git tag | grep -E "^v${HELM}\.[0-9]{1,2}$" | sort -V | tail -1)" \ 31 | && echo "${version}" \ 32 | && curl -sS -L --fail -O https://get.helm.sh/helm-${version}-linux-${ARCH}.tar.gz \ 33 | && tar xvfz helm-${version}-linux-${ARCH}.tar.gz \ 34 | && mv linux-${ARCH}/helm /usr/bin/helm \ 35 | && chmod +x /usr/bin/helm \ 36 | && /usr/bin/helm version | grep -E "${HELM}" | grep -E "${version}" 37 | 38 | 39 | # -------------------------------------------------------------------------------------------------- 40 | # Final Image 41 | # -------------------------------------------------------------------------------------------------- 42 | FROM cytopia/ansible:${VERSION}-awsk8s as production 43 | ARG VERSION 44 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 45 | #LABEL "org.opencontainers.image.created"="" 46 | #LABEL "org.opencontainers.image.version"="" 47 | #LABEL "org.opencontainers.image.revision"="" 48 | LABEL "maintainer"="cytopia " 49 | LABEL "org.opencontainers.image.authors"="cytopia " 50 | LABEL "org.opencontainers.image.vendor"="cytopia" 51 | LABEL "org.opencontainers.image.licenses"="MIT" 52 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 53 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 54 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 55 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} awshelm" 56 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} awshelm" 57 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} awshelm" 58 | 59 | COPY --from=builder /usr/bin/helm /usr/bin/helm 60 | 61 | WORKDIR /data 62 | ENTRYPOINT ["/docker-entrypoint.sh"] 63 | CMD ["/bin/bash"] 64 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-awsk8s: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-aws as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # build tools 12 | coreutils \ 13 | g++ \ 14 | gcc \ 15 | make \ 16 | musl-dev \ 17 | openssl-dev \ 18 | python3-dev \ 19 | # misc tools 20 | curl 21 | 22 | # Python packages (copied to final image) 23 | RUN set -eux \ 24 | && pip3 install --no-cache-dir --no-compile \ 25 | openshift \ 26 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 27 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 28 | 29 | # kubectl (copied to final image) 30 | RUN set -eux \ 31 | && if [ "$(uname -m)" = "aarch64" ]; then \ 32 | ARCH="arm64"; \ 33 | elif [ "$(uname -m)" = "x86_64" ]; then \ 34 | ARCH="amd64"; \ 35 | else \ 36 | fail; \ 37 | fi \ 38 | \ 39 | && KUBECTL_VERSION="$(curl -sS --fail https://storage.googleapis.com/kubernetes-release/release/stable.txt)" \ 40 | && curl -sS -L --fail -o /usr/bin/kubectl \ 41 | https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl \ 42 | && chmod +x /usr/bin/kubectl \ 43 | && kubectl version --client --short=true 2>&1 | grep -E 'v[.0-9]+' 44 | 45 | # openshift client (copied to final image) 46 | RUN set -eux \ 47 | && if [ "$(uname -m)" != "x86_64" ]; then \ 48 | echo -e '#!/bin/sh\necho "Not available for this platform"' > /usr/bin/oc \ 49 | && chmod +x /usr/bin/oc \ 50 | && exit 0; \ 51 | fi \ 52 | \ 53 | && curl -sS -L --fail -o /tmp/openshift-client-linux.tar.gz \ 54 | https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ 55 | && mkdir /tmp/openshift-client-linux/ \ 56 | && tar -xzf /tmp/openshift-client-linux.tar.gz -C /tmp/openshift-client-linux/ \ 57 | && mv /tmp/openshift-client-linux/oc /usr/bin/oc-dynamically-linked \ 58 | && echo -e '#!/bin/sh\n/lib/ld-musl-$(uname -m).so.1 --library-path /lib /usr/bin/oc-dynamically-linked "$@"' > /usr/bin/oc \ 59 | && chmod +x /usr/bin/oc \ 60 | && oc version --client 61 | 62 | 63 | # -------------------------------------------------------------------------------------------------- 64 | # Final Image 65 | # -------------------------------------------------------------------------------------------------- 66 | FROM cytopia/ansible:${VERSION}-aws as production 67 | ARG VERSION 68 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 69 | #LABEL "org.opencontainers.image.created"="" 70 | #LABEL "org.opencontainers.image.version"="" 71 | #LABEL "org.opencontainers.image.revision"="" 72 | LABEL "maintainer"="cytopia " 73 | LABEL "org.opencontainers.image.authors"="cytopia " 74 | LABEL "org.opencontainers.image.vendor"="cytopia" 75 | LABEL "org.opencontainers.image.licenses"="MIT" 76 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 77 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 78 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 79 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} awsk8s" 80 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} awsk8s" 81 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} awsk8s" 82 | 83 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 84 | COPY --from=builder /usr/bin/kubectl /usr/bin/kubectl 85 | COPY --from=builder /usr/bin/oc* /usr/bin/ 86 | 87 | WORKDIR /data 88 | ENTRYPOINT ["/docker-entrypoint.sh"] 89 | CMD ["/bin/bash"] 90 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-awskops: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-awsk8s as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # misc tools 12 | coreutils \ 13 | curl \ 14 | git 15 | 16 | # Install Kops by major and minor version 17 | ARG KOPS 18 | 19 | # Kops (copied to final image) 20 | RUN set -eux \ 21 | && if [ "$(uname -m)" = "aarch64" ]; then \ 22 | ARCH="arm64"; \ 23 | elif [ "$(uname -m)" = "x86_64" ]; then \ 24 | ARCH="amd64"; \ 25 | else \ 26 | fail; \ 27 | fi \ 28 | \ 29 | && git clone https://github.com/kubernetes/kops \ 30 | && cd kops \ 31 | # Get latest feature version 32 | && version="$( git tag | grep -E "^v?${KOPS}\.[0-9]{1,2}$" | sort -V | tail -1 | sed 's/^v//g' )" \ 33 | && echo "${version}" \ 34 | && if [ "$(curl -sS -L --fail -I -o /dev/null -w "%{http_code}" "https://github.com/kubernetes/kops/releases/download/v${version}/kops-linux-${ARCH}")" != "404" ]; then \ 35 | KOPS_URL="https://github.com/kubernetes/kops/releases/download/v${version}/kops-linux-${ARCH}"; \ 36 | else \ 37 | KOPS_URL="https://github.com/kubernetes/kops/releases/download/${version}/kops-linux-${ARCH}"; \ 38 | fi \ 39 | && echo "${KOPS_URL}" \ 40 | && curl -sS -L --fail -o /usr/bin/kops "${KOPS_URL}" \ 41 | && chmod +x /usr/bin/kops \ 42 | \ 43 | && /usr/bin/kops version \ 44 | && /usr/bin/kops version | grep -E "${KOPS}" | grep -E "^([Cc]lient\s)?[Vv]ersion(:)?\s+v?${version}" 45 | 46 | 47 | # -------------------------------------------------------------------------------------------------- 48 | # Final Image 49 | # -------------------------------------------------------------------------------------------------- 50 | FROM cytopia/ansible:${VERSION}-awsk8s as production 51 | ARG VERSION 52 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 53 | #LABEL "org.opencontainers.image.created"="" 54 | #LABEL "org.opencontainers.image.version"="" 55 | #LABEL "org.opencontainers.image.revision"="" 56 | LABEL "maintainer"="cytopia " 57 | LABEL "org.opencontainers.image.authors"="cytopia " 58 | LABEL "org.opencontainers.image.vendor"="cytopia" 59 | LABEL "org.opencontainers.image.licenses"="MIT" 60 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 61 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 62 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 63 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} awskops" 64 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} awskops" 65 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} awskops" 66 | 67 | COPY --from=builder /usr/bin/kops /usr/bin/kops 68 | 69 | WORKDIR /data 70 | ENTRYPOINT ["/docker-entrypoint.sh"] 71 | CMD ["/bin/bash"] 72 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-azure: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-tools as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # build tools 12 | coreutils \ 13 | g++ \ 14 | gcc \ 15 | linux-headers \ 16 | make \ 17 | musl-dev \ 18 | openssl-dev \ 19 | python3-dev 20 | 21 | RUN set -eux \ 22 | && pip3 install --no-cache-dir --no-compile \ 23 | azure-applicationinsights \ 24 | azure-batch \ 25 | azure-cli \ 26 | azure-cognitiveservices-personalizer \ 27 | azure-common \ 28 | azure-cosmos \ 29 | azure-eventgrid \ 30 | azure-eventhub \ 31 | azure-graphrbac \ 32 | azure-keyvault \ 33 | azure-loganalytics \ 34 | azure-mgmt-advisor \ 35 | azure-mgmt-automation \ 36 | azure-mgmt-billing \ 37 | azure-mgmt-commerce \ 38 | azure-mgmt-consumption \ 39 | azure-mgmt-hanaonazure \ 40 | azure-mgmt-maps \ 41 | azure-mgmt-monitor \ 42 | azure-mgmt-relay \ 43 | azure-mgmt-reservations \ 44 | azure-mgmt-serialconsole \ 45 | azure-search \ 46 | azure-servicebus \ 47 | azure-servicefabric \ 48 | azure-storage-queue \ 49 | azure-synapse \ 50 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 51 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 52 | 53 | 54 | # -------------------------------------------------------------------------------------------------- 55 | # Final Image 56 | # -------------------------------------------------------------------------------------------------- 57 | FROM cytopia/ansible:${VERSION}-tools as production 58 | ARG VERSION 59 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 60 | #LABEL "org.opencontainers.image.created"="" 61 | #LABEL "org.opencontainers.image.version"="" 62 | #LABEL "org.opencontainers.image.revision"="" 63 | LABEL "maintainer"="cytopia " 64 | LABEL "org.opencontainers.image.authors"="cytopia " 65 | LABEL "org.opencontainers.image.vendor"="cytopia" 66 | LABEL "org.opencontainers.image.licenses"="MIT" 67 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 68 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 69 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 70 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} azure" 71 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} azure" 72 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} azure" 73 | 74 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 75 | COPY --from=builder /usr/bin/az /usr/bin/az 76 | 77 | WORKDIR /data 78 | ENTRYPOINT ["/docker-entrypoint.sh"] 79 | CMD ["/bin/bash"] 80 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-base: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------------------------- 2 | # Builder Image 3 | # -------------------------------------------------------------------------------------------------- 4 | FROM alpine:3.16 as builder 5 | 6 | RUN set -eux \ 7 | && apk add --update --no-cache \ 8 | # build tools 9 | coreutils \ 10 | g++ \ 11 | gcc \ 12 | make \ 13 | musl-dev \ 14 | openssl-dev \ 15 | python3-dev \ 16 | # misc tools 17 | bc \ 18 | libffi-dev \ 19 | libxml2-dev \ 20 | libxslt-dev \ 21 | py3-pip \ 22 | python3 \ 23 | # Fix: ansible --version: libyaml = True 24 | # https://www.jeffgeerling.com/blog/2021/ansible-might-be-running-slow-if-libyaml-not-available 25 | && apk add --update --no-cache \ 26 | py3-yaml \ 27 | && python3 -c 'import _yaml' 28 | 29 | # Pip required tools 30 | RUN set -eux \ 31 | && pip3 install --no-cache-dir --no-compile \ 32 | wheel 33 | RUN set -eux \ 34 | && pip3 install --no-cache-dir --no-compile \ 35 | Jinja2 \ 36 | MarkupSafe \ 37 | PyNaCl \ 38 | bcrypt \ 39 | cffi \ 40 | cryptography \ 41 | pycparser 42 | 43 | ARG VERSION 44 | RUN set -eux \ 45 | && MAJOR_VERSION="$( echo "${VERSION}" | awk -F'.' '{print $1}' )" \ 46 | && MINOR_VERSION="$( echo "${VERSION}" | awk -F'.' '{print $2}' )" \ 47 | \ 48 | && if [ "${VERSION}" = "latest" ]; then \ 49 | pip3 install --no-cache-dir --no-compile ansible; \ 50 | \ 51 | elif [ "${MINOR_VERSION}" -lt "10" ]; then \ 52 | pip3 install --no-cache-dir --no-binary pyyaml ansible~=${VERSION}.0; \ 53 | \ 54 | # Ansible added a weired versioning system with ansible-core and ansible packages: 55 | # https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#ansible-community-changelogs 56 | elif [ "${VERSION}" = "2.10" ]; then\ 57 | pip3 install --no-cache-dir --no-binary pyyaml ansible~=3.0; \ 58 | \ 59 | elif [ "${VERSION}" = "2.11" ]; then\ 60 | pip3 install --no-cache-dir --no-binary pyyaml ansible~=4.0; \ 61 | \ 62 | elif [ "${VERSION}" = "2.12" ]; then\ 63 | pip3 install --no-cache-dir --no-binary pyyaml ansible~=5.0; \ 64 | \ 65 | elif [ "${VERSION}" = "2.13" ]; then\ 66 | pip3 install --no-cache-dir --no-binary pyyaml ansible~=6.0; \ 67 | \ 68 | else \ 69 | fail; \ 70 | fi \ 71 | \ 72 | && if [ "${VERSION}" != "latest" ]; then \ 73 | ansible --version | grep ^ansible | grep -E "${VERSION}\.[0-9]+" \ 74 | && ansible-playbook --version | grep ^ansible | grep -E "${VERSION}\.[0-9]+" \ 75 | && ansible-galaxy --version | grep ^ansible | grep -E "${VERSION}\.[0-9]+"; \ 76 | fi \ 77 | \ 78 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 79 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 80 | 81 | # Python packages (copied to final image) 82 | RUN set -eux \ 83 | && pip3 install --no-cache-dir --no-compile \ 84 | junit-xml \ 85 | lxml \ 86 | paramiko \ 87 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 88 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 89 | 90 | # Clean-up some site-packages to safe space 91 | RUN set -eux \ 92 | && pip3 uninstall --yes \ 93 | setuptools \ 94 | wheel \ 95 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 96 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 97 | 98 | 99 | # -------------------------------------------------------------------------------------------------- 100 | # Final Image 101 | # -------------------------------------------------------------------------------------------------- 102 | FROM alpine:3.16 as production 103 | ARG VERSION 104 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 105 | #LABEL "org.opencontainers.image.created"="" 106 | #LABEL "org.opencontainers.image.version"="" 107 | #LABEL "org.opencontainers.image.revision"="" 108 | LABEL "maintainer"="cytopia " 109 | LABEL "org.opencontainers.image.authors"="cytopia " 110 | LABEL "org.opencontainers.image.vendor"="cytopia" 111 | LABEL "org.opencontainers.image.licenses"="MIT" 112 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 113 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 114 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 115 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} base" 116 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} base" 117 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} base" 118 | 119 | RUN set -eux \ 120 | && apk add --no-cache \ 121 | # Issue: #85 libgcc required for ansible-vault 122 | libgcc \ 123 | py3-pip \ 124 | python3 \ 125 | # Issue: #76 yaml required for 'libyaml = True' (faster startup time) 126 | yaml \ 127 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 128 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf \ 129 | \ 130 | && ln -s /usr/bin/python3 /usr/bin/python 131 | 132 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 133 | COPY --from=builder /usr/bin/ansible* /usr/bin/ 134 | 135 | # Pre-compile Python for better performance 136 | RUN set -eux \ 137 | && python3 -m compileall -j 0 /usr/lib/python3.10 138 | 139 | WORKDIR /data 140 | CMD ["/bin/sh"] 141 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-infra: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION}-tools as builder 7 | 8 | # Required tools for building Python packages 9 | RUN set -eux \ 10 | && apk add --no-cache \ 11 | # build tools 12 | coreutils \ 13 | g++ \ 14 | gcc \ 15 | make \ 16 | musl-dev \ 17 | openssl-dev \ 18 | python3-dev \ 19 | # misc tools 20 | krb5-dev \ 21 | openldap-dev \ 22 | postgresql-dev \ 23 | postgresql-libs 24 | 25 | # Python packages (copied to final image) 26 | RUN set -eux \ 27 | && pip3 install --no-cache-dir --no-compile \ 28 | PyMySQL \ 29 | docker \ 30 | docker-compose \ 31 | jsondiff \ 32 | netaddr \ 33 | pexpect \ 34 | psycopg2 \ 35 | pyldap \ 36 | pymongo \ 37 | pypsexec \ 38 | pywinrm \ 39 | pywinrm[credssp] \ 40 | pywinrm[kerberos] \ 41 | smbprotocol \ 42 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 43 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 44 | 45 | 46 | # -------------------------------------------------------------------------------------------------- 47 | # Final Image 48 | # -------------------------------------------------------------------------------------------------- 49 | FROM cytopia/ansible:${VERSION}-tools as production 50 | ARG VERSION 51 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 52 | #LABEL "org.opencontainers.image.created"="" 53 | #LABEL "org.opencontainers.image.version"="" 54 | #LABEL "org.opencontainers.image.revision"="" 55 | LABEL "maintainer"="cytopia " 56 | LABEL "org.opencontainers.image.authors"="cytopia " 57 | LABEL "org.opencontainers.image.vendor"="cytopia" 58 | LABEL "org.opencontainers.image.licenses"="MIT" 59 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 60 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 61 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 62 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} infra" 63 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} infra" 64 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} infra" 65 | 66 | # Additional binaries 67 | RUN set -eux \ 68 | && apk add --no-cache \ 69 | libpq \ 70 | rsync \ 71 | sshpass 72 | 73 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 74 | 75 | WORKDIR /data 76 | ENTRYPOINT ["/docker-entrypoint.sh"] 77 | CMD ["/bin/bash"] 78 | -------------------------------------------------------------------------------- /Dockerfiles/Dockerfile-tools: -------------------------------------------------------------------------------- 1 | ARG VERSION 2 | 3 | # -------------------------------------------------------------------------------------------------- 4 | # Builder Image 5 | # -------------------------------------------------------------------------------------------------- 6 | FROM cytopia/ansible:${VERSION} as builder 7 | ARG VERSION 8 | 9 | RUN set -eux \ 10 | && apk add --update --no-cache \ 11 | curl 12 | 13 | # Python packages (copied to final image) 14 | RUN set -eux \ 15 | && if [ "${VERSION}" = "2.5" ]; then \ 16 | pip3 install --no-cache-dir --no-compile dnspython mitogen==0.2.10; \ 17 | elif [ "${VERSION}" = "2.6" ]; then \ 18 | pip3 install --no-cache-dir --no-compile dnspython mitogen==0.2.10; \ 19 | elif [ "${VERSION}" = "2.7" ]; then \ 20 | pip3 install --no-cache-dir --no-compile dnspython mitogen==0.2.10; \ 21 | elif [ "${VERSION}" = "2.8" ]; then \ 22 | pip3 install --no-cache-dir --no-compile dnspython mitogen==0.2.10; \ 23 | elif [ "${VERSION}" = "2.9" ]; then \ 24 | pip3 install --no-cache-dir --no-compile dnspython mitogen==0.2.10; \ 25 | else \ 26 | pip3 install --no-cache-dir --no-compile dnspython mitogen; \ 27 | fi \ 28 | \ 29 | && pip3 install --no-cache-dir --no-compile \ 30 | jmespath \ 31 | \ 32 | && find /usr/lib/ -name '__pycache__' -print0 | xargs -0 -n1 rm -rf \ 33 | && find /usr/lib/ -name '*.pyc' -print0 | xargs -0 -n1 rm -rf 34 | 35 | # Binaries (copied to final image) 36 | RUN set -eux \ 37 | && if [ "$(uname -m)" = "aarch64" ]; then \ 38 | ARCH="arm64"; \ 39 | elif [ "$(uname -m)" = "x86_64" ]; then \ 40 | ARCH="amd64"; \ 41 | else \ 42 | fail; \ 43 | fi \ 44 | \ 45 | && YQ="$( curl -L -sS --fail -o /dev/null -w %{url_effective} https://github.com/mikefarah/yq/releases/latest | sed 's/^.*\///g' )" \ 46 | \ 47 | && curl -L -sS --fail "https://github.com/mikefarah/yq/releases/download/${YQ}/yq_linux_${ARCH}" > /usr/bin/yq \ 48 | && chmod +x /usr/bin/yq \ 49 | \ 50 | && yq --version 51 | 52 | 53 | # -------------------------------------------------------------------------------------------------- 54 | # Final Image 55 | # -------------------------------------------------------------------------------------------------- 56 | FROM cytopia/ansible:${VERSION} as production 57 | ARG VERSION 58 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 59 | #LABEL "org.opencontainers.image.created"="" 60 | #LABEL "org.opencontainers.image.version"="" 61 | #LABEL "org.opencontainers.image.revision"="" 62 | LABEL "maintainer"="cytopia " 63 | LABEL "org.opencontainers.image.authors"="cytopia " 64 | LABEL "org.opencontainers.image.vendor"="cytopia" 65 | LABEL "org.opencontainers.image.licenses"="MIT" 66 | LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-ansible" 67 | LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-ansible" 68 | LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-ansible" 69 | LABEL "org.opencontainers.image.ref.name"="Ansible ${VERSION} tools" 70 | LABEL "org.opencontainers.image.title"="Ansible ${VERSION} tools" 71 | LABEL "org.opencontainers.image.description"="Ansible ${VERSION} tools" 72 | 73 | # Define uid/gid and user/group names 74 | ENV \ 75 | MY_USER=ansible \ 76 | MY_GROUP=ansible \ 77 | MY_UID=1000 \ 78 | MY_GID=1000 79 | 80 | # Add user and group 81 | RUN set -eux \ 82 | && addgroup -g ${MY_GID} ${MY_GROUP} \ 83 | && adduser -h /home/ansible -s /bin/bash -G ${MY_GROUP} -D -u ${MY_UID} ${MY_USER} \ 84 | \ 85 | && mkdir /home/ansible/.gnupg \ 86 | && chown ansible:ansible /home/ansible/.gnupg \ 87 | && chmod 0700 /home/ansible/.gnupg \ 88 | \ 89 | && mkdir /home/ansible/.ssh \ 90 | && chown ansible:ansible /home/ansible/.ssh \ 91 | && chmod 0700 /home/ansible/.ssh 92 | 93 | # Additional binaries 94 | RUN set -eux \ 95 | && apk add --no-cache \ 96 | bash \ 97 | git \ 98 | gnupg \ 99 | jq \ 100 | openssh-client 101 | 102 | COPY --from=builder /usr/lib/python3.10/site-packages/ /usr/lib/python3.10/site-packages/ 103 | COPY --from=builder /usr/bin/yq /usr/bin/yq 104 | COPY ./data/docker-entrypoint.sh /docker-entrypoint.sh 105 | 106 | WORKDIR /data 107 | ENTRYPOINT ["/docker-entrypoint.sh"] 108 | CMD ["/bin/bash"] 109 | -------------------------------------------------------------------------------- /Dockerfiles/data/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | # Variables set in Dockerfile 8 | # 9 | # MY_USER=ansible 10 | # MY_GROUP=ansible 11 | # MY_UID=1000 12 | # MY_GID=1000 13 | 14 | USE_NONROOT=0 15 | INIT_GPG=0 16 | 17 | 18 | # ------------------------------------------------------------------------------ 19 | # FUNCTIONS 20 | # ------------------------------------------------------------------------------ 21 | update_uid_gid() { 22 | local user="${1}" 23 | local group="${2}" 24 | local uid="${3}" 25 | local gid="${4}" 26 | 27 | 28 | echo "[INFO] Adjusting local user '${user}' with uid:${uid} and gid:${gid}" 29 | 30 | # Remove previous user/group 31 | if ! deluser "${user}"; then 32 | >&2 echo "[ERR] Failed to delete user: ${user}" 33 | exit 1 34 | fi 35 | 36 | # Check if current group id already exists and fix it 37 | tmp_gid="${gid}" 38 | if grep -q "x:${tmp_gid}:" /etc/group; then 39 | tmp_grp="$( grep "x:${tmp_gid}:" /etc/group | awk -F':' '{print $1}' )" 40 | while grep -q "x:${tmp_gid}:" /etc/group; do 41 | tmp_gid="$(( tmp_gid + 1 ))" 42 | done 43 | # Simply change the already existing group id to something else 44 | echo "[INFO] Group '${tmp_grp}' with gid '${gid}' already exists. Moving it to ${tmp_grp}:x:${tmp_gid}" 45 | sed -i'' "s/x:${gid}:/x:${tmp_gid}:/g" /etc/group 46 | fi 47 | # Check if current user id already exists and fix it 48 | tmp_uid="${uid}" 49 | if grep -q "x:${tmp_uid}:" /etc/passwd; then 50 | tmp_usr="$( grep "x:${tmp_uid}:" /etc/passwd | awk -F':' '{print $1}' )" 51 | while grep -q "x:${tmp_uid}:" /etc/passwd; do 52 | tmp_uid="$(( tmp_uid + 1 ))" 53 | done 54 | # Simply change the already existing user id to something else 55 | echo "[INFO] User '${tmp_usr}' with uid '${uid}' already exists. Moving it to ${tmp_usr}:x:${tmp_uid}" 56 | sed -i'' "s/x:${uid}:/x:${tmp_uid}:/g" /etc/passwd 57 | fi 58 | 59 | # Add new user/group 60 | if ! addgroup -g "${gid}" "${group}"; then 61 | >&2 echo "[ERR] Failed to add group ${group} (gid:${gid})" 62 | exit 1 63 | fi 64 | if ! adduser -h /home/ansible -s /bin/bash -G "${group}" -D -u "${uid}" "${user}"; then 65 | >&2 echo "[ERR] Failed to add user ${user} (uid:${uid})" 66 | exit 1 67 | fi 68 | 69 | # Adjust filesystem permissions accordingly 70 | if [ -d /home/ansible/.gnupg ]; then 71 | echo "[INFO] Adjusting ownership on directory: ~/.gnupg/" 72 | if ! chown "${user}:${group}" /home/ansible/.gnupg/; then 73 | >&2 echo "[ERR] Failed to 'chown ${user}:${group} ~/.gnupg'" 74 | exit 1 75 | fi 76 | fi 77 | if [ -d /home/ansible/.ssh ]; then 78 | echo "[INFO] Adjusting ownership on directory: ~/.ssh/" 79 | if ! chown "${user}:${group}" /home/ansible/.ssh/; then 80 | >&2 echo "[ERR] Failed to 'chown ${user}:${group} ~/.ssh'" 81 | exit 1 82 | fi 83 | fi 84 | if [ -d /home/ansible/.aws ]; then 85 | echo "[INFO] Adjusting ownership on directory: ~/.aws/" 86 | if ! chown "${user}:${group}" /home/ansible/.aws/; then 87 | >&2 echo "[ERR] Failed to 'chown ${user}:${group} ~/.aws'" 88 | exit 1 89 | fi 90 | fi 91 | if [ -d /home/ansible/.helm ]; then 92 | echo "[INFO] Adjusting ownership on directory: ~/.helm/" 93 | if ! chown "${user}:${group}" /home/ansible/.helm/; then 94 | >&2 echo "[ERR] Failed to 'chown ${user}:${group} ~/.helm'" 95 | exit 1 96 | fi 97 | fi 98 | } 99 | 100 | init_gpg_key_cmd() { 101 | local user="${1}" 102 | local cmd="${2}" 103 | 104 | if [ "${user}" = "root" ]; then 105 | if ! eval "${cmd}"; then 106 | >&2 echo "[ERR] Failed to initialize GPG via: ${cmd}" 107 | exit 1 108 | else 109 | echo "[INFO] GPG initialized successfully via: ${cmd}" 110 | fi 111 | else 112 | if ! su "${user}" -c "${cmd}"; then 113 | >&2 echo "[ERR] Failed to initialize GPG via: ${cmd}" 114 | exit 1 115 | else 116 | echo "[INFO] GPG initialized successfully via: ${cmd}" 117 | fi 118 | fi 119 | } 120 | 121 | init_gpg_key_pass() { 122 | local user="${1}" 123 | local key="${2}" 124 | local pass="${3}" 125 | 126 | if [ "${user}" = "root" ]; then 127 | if ! gpg --list-key "${key}" >/dev/null 2>&1; then 128 | >&2 echo "[ERR] GPG key does not exist: ${key}" 129 | exit 1 130 | fi 131 | 132 | if ! echo "test" \ 133 | | gpg --armor --pinentry-mode loopback --passphrase "${pass}" --recipient "${key}" --encrypt 2>/dev/null \ 134 | | gpg --pinentry-mode loopback --passphrase "${pass}" --decrypt 2>/dev/null \ 135 | | grep -q '^test$'; then 136 | >&2 echo "[ERR] Failed to initialize GPG" 137 | exit 1 138 | else 139 | echo "[INFO] GPG initialized successfully" 140 | fi 141 | else 142 | if ! su "${user}" -c "gpg --list-key '${key}' >/dev/null 2>&1"; then 143 | >&2 echo "[ERR] GPG key does not exist: ${key}" 144 | exit 1 145 | fi 146 | if ! su "${user}" -c " 147 | echo 'test' \ 148 | | gpg --armor --pinentry-mode loopback --passphrase '${pass}' --recipient '${key}' --encrypt 2>/dev/null \ 149 | | gpg --pinentry-mode loopback --passphrase '${pass}' --decrypt 2>/dev/null \ 150 | | grep -q '^test$'"; then 151 | >&2 echo "[ERR] Failed to initialize GPG" 152 | exit 1 153 | else 154 | echo "[INFO] GPG initialized successfully" 155 | fi 156 | fi 157 | } 158 | 159 | 160 | # ------------------------------------------------------------------------------ 161 | # ENTRYPOINT (ENV VARIABLES 162 | # ------------------------------------------------------------------------------ 163 | 164 | ### 165 | ### Initialize GPG key 166 | ### 167 | INIT_GPG= 168 | 169 | # Custom specified command to initliaze GPG key 170 | if [ -n "${INIT_GPG_CMD:=}" ]; then 171 | if [ -n "${INIT_GPG_KEY:=}" ]; then 172 | >&2 echo "[ERR] When using \$INIT_GPG_CMD, you cannot specify \$INIT_GPG_KEY." 173 | exit 1 174 | fi 175 | if [ -n "${INIT_GPG_PASS:=}" ]; then 176 | >&2 echo "[ERR] When using \$INIT_GPG_CMD, you cannot specify \$INIT_GPG_PASS." 177 | exit 1 178 | fi 179 | echo "[INFO] Initializing gpg key with custom command: ${INIT_GPG_CMD}" 180 | INIT_GPG="CMD" 181 | 182 | # Use GPG key/pass from environment 183 | elif [ -n "${INIT_GPG_KEY:=}" ] && [ -n "${INIT_GPG_PASS:=}" ]; then 184 | echo "[INFO] Initializing gpg key for ${INIT_GPG_KEY}" 185 | INIT_GPG="PASS" 186 | 187 | # GPG_KEY set, but GPG_PASS missing 188 | elif [ -n "${INIT_GPG_KEY:=}" ] && [ -z "${INIT_GPG_PASS:=}" ]; then 189 | >&2 echo "[ERR] When using \$INIT_GPG_KEY, you also need to specify \$INIT_GPG_PASS" 190 | exit 1 191 | 192 | # GPG_KEY missing, but GPG_PASS set 193 | elif [ -z "${INIT_GPG_KEY:=}" ] && [ -n "${INIT_GPG_PASS:=}" ]; then 194 | >&2 echo "[ERR] When using \$INIT_GPG_PASS, you also need to specify \$INIT_GPG_KEY" 195 | exit 1 196 | fi 197 | 198 | 199 | 200 | ### 201 | ### Run with root or ansible user? 202 | ### 203 | if env | grep -q '^USER='; then 204 | if [ "${USER}" = "ansible" ]; then 205 | echo "[INFO] Running container with user 'ansible'" 206 | USE_NONROOT=1 207 | else 208 | >&2 echo "[ERR} \$USER can only be set to 'ansible'. If you want to run as root, omit the env var." 209 | exit 1 210 | fi 211 | fi 212 | 213 | 214 | ### 215 | ### Gather new UID/GID 216 | ### 217 | if env | grep -q '^UID='; then 218 | # Change UID 219 | MY_UID="$( env | grep '^UID=' | sed 's/^UID=//g' )" 220 | echo "[INFO] Changing UID to ${MY_UID}" 221 | # Change GID (maybe) 222 | if env | grep -q '^GID='; then 223 | echo "[INFO] Changing GID to ${MY_GID}" 224 | MY_GID="$( env | grep '^GID=' | sed 's/^GID=//g' )" 225 | fi 226 | elif env | grep -q '^GID='; then 227 | # Change GID 228 | MY_GID="$( env | grep '^GID=' | sed 's/^GID=//g' )" 229 | echo "[INFO] Changing GID to ${MY_GID}" 230 | fi 231 | 232 | 233 | # ------------------------------------------------------------------------------ 234 | # ENTRYPOINT (CONFIGURATION) 235 | # ------------------------------------------------------------------------------ 236 | 237 | if [ "${USE_NONROOT}" = "1" ]; then 238 | 239 | update_uid_gid "${MY_USER}" "${MY_GROUP}" "${MY_UID}" "${MY_GID}" 240 | 241 | if [ "${INIT_GPG}" = "CMD" ]; then 242 | init_gpg_key_cmd "${MY_USER}" "${INIT_GPG_CMD}" 243 | elif [ "${INIT_GPG}" = "PASS" ]; then 244 | init_gpg_key_pass "${MY_USER}" "${INIT_GPG_KEY}" "${INIT_GPG_PASS}" 245 | fi 246 | echo "[INFO] ansible> ${*}" 247 | exec su "${MY_USER}" -c "${*}" 248 | 249 | else 250 | 251 | if [ "${INIT_GPG}" = "CMD" ]; then 252 | init_gpg_key_cmd "root" "${INIT_GPG_CMD}" 253 | elif [ "${INIT_GPG}" = "PASS" ]; then 254 | init_gpg_key_pass "root" "${INIT_GPG_KEY}" "${INIT_GPG_PASS}" 255 | fi 256 | echo "[INFO] root> ${*}" 257 | exec "${@}" 258 | fi 259 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 cytopia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Additional Makefiles are pulled from: 2 | # https://github.com/devilbox/makefiles/ 3 | 4 | 5 | ifneq (,) 6 | .error This Makefile requires GNU Make. 7 | endif 8 | 9 | # Ensure additional Makefiles are present 10 | MAKEFILES = Makefile.docker Makefile.lint 11 | $(MAKEFILES): URL=https://raw.githubusercontent.com/devilbox/makefiles/master/$(@) 12 | $(MAKEFILES): 13 | @if ! (curl --fail -sS -o $(@) $(URL) || wget -O $(@) $(URL)); then \ 14 | echo "Error, curl or wget required."; \ 15 | echo "Exiting."; \ 16 | false; \ 17 | fi 18 | include $(MAKEFILES) 19 | 20 | # Set default Target 21 | .DEFAULT_GOAL := help 22 | 23 | 24 | # ------------------------------------------------------------------------------------------------- 25 | # Default configuration 26 | # ------------------------------------------------------------------------------------------------- 27 | # Own vars 28 | TAG = latest 29 | 30 | # Makefile.docker overwrites 31 | NAME = ansible 32 | VERSION = latest 33 | IMAGE = cytopia/ansible 34 | FLAVOUR = default 35 | STAGE = base 36 | DIR = Dockerfiles 37 | FILE = Dockerfile-$(STAGE) 38 | DOCKER_TAG = $(VERSION) 39 | 40 | ifeq ($(strip $(STAGE)),base) 41 | DOCKER_TAG = $(VERSION) 42 | else 43 | DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM) 44 | endif 45 | 46 | # Makefile.lint overwrites 47 | FL_IGNORES = .git/,.github/,tests/ 48 | SC_IGNORES = .git/,.github/,tests/ 49 | JL_IGNORES = .git/,.github/,./tests/ 50 | 51 | 52 | # ------------------------------------------------------------------------------------------------- 53 | # Default Target 54 | # ------------------------------------------------------------------------------------------------- 55 | .PHONY: help 56 | help: 57 | @echo "--------------------------------------------------------------------------------" 58 | @echo " Build Targets" 59 | @echo "--------------------------------------------------------------------------------" 60 | @echo 61 | @echo "All Docker images are build as follows: $(IMAGE):\$$VERSION[-\$$STAGE[\$$KOPS|\$$HELM]]" 62 | @echo 63 | @echo "build [VERSION=] [ARCH=] [KOPS=] [HELM=] Build Docker image" 64 | @echo "rebuild [VERSION=] [ARCH=] [KOPS=] [HELM=] Build Docker image without cache" 65 | @echo 66 | @echo " make build VERSION=2.3" 67 | @echo " make build VERSION=2.3 STAGE=tools" 68 | @echo " make build VERSION=2.3 STAGE=infra" 69 | @echo " make build VERSION=2.3 STAGE=azure" 70 | @echo " make build VERSION=2.3 STAGE=aws" 71 | @echo " make build VERSION=2.3 STAGE=awsk8s" 72 | @echo " make build VERSION=2.3 STAGE=awshelm HELM=2.11" 73 | @echo " make build VERSION=2.3 STAGE=awskops KOPS=1.15" 74 | @echo 75 | @echo "--------------------------------------------------------------------------------" 76 | @echo " Test Targets" 77 | @echo "--------------------------------------------------------------------------------" 78 | @echo 79 | @echo "test [VERSION=] [ARCH=] [KOPS=] [HELM=] Test built Docker image" 80 | @echo 81 | @echo " make test VERSION=2.3" 82 | @echo " make test VERSION=2.3 STAGE=tools" 83 | @echo " make test VERSION=2.3 STAGE=infra" 84 | @echo " make test VERSION=2.3 STAGE=azure" 85 | @echo " make test VERSION=2.3 STAGE=aws" 86 | @echo " make test VERSION=2.3 STAGE=awsk8s" 87 | @echo " make test VERSION=2.3 STAGE=awshelm HELM=2.11" 88 | @echo " make test VERSION=2.3 STAGE=awskops KOPS=1.15" 89 | @echo 90 | @echo "--------------------------------------------------------------------------------" 91 | @echo " Tagging Target" 92 | @echo "--------------------------------------------------------------------------------" 93 | @echo 94 | @echo "tag [VERSION=] [ARCH=] [KOPS=] [HELM=] [TAG=] Tag built Docker image" 95 | @echo 96 | @echo " make tag VERSION=2.3 TAG=2.3-mysuffix" 97 | @echo " make tag VERSION=2.3 STAGE=tools TAG=2.3-tools-mysuffix" 98 | @echo " make tag VERSION=2.3 STAGE=infra TAG=2.3-infra-mysuffix" 99 | @echo " make tag VERSION=2.3 STAGE=azure TAG=2.3-azure-mysuffix" 100 | @echo " make tag VERSION=2.3 STAGE=aws TAG=2.3-aws-mysuffix" 101 | @echo " make tag VERSION=2.3 STAGE=awsk8s TAG=2.3-awsk8s-mysuffix" 102 | @echo " make tag VERSION=2.3 STAGE=awshelm HELM=2.11 TAG=2.3-awshelm-mysuffix" 103 | @echo " make tag VERSION=2.3 STAGE=awskops KOPS=1.15 TAG=2.3-awskops-mysuffix" 104 | 105 | 106 | # ------------------------------------------------------------------------------------------------- 107 | # Docker Targets 108 | # ------------------------------------------------------------------------------------------------- 109 | .PHONY: build 110 | build: ARGS+=--build-arg VERSION=$(VERSION) 111 | build: ARGS+=--build-arg KOPS=$(KOPS) 112 | build: ARGS+=--build-arg HELM=$(HELM) 113 | build: docker-arch-build 114 | 115 | .PHONY: rebuild 116 | rebuild: ARGS+=--build-arg VERSION=$(VERSION) 117 | rebuild: ARGS+=--build-arg KOPS=$(KOPS) 118 | rebuild: ARGS+=--build-arg HELM=$(HELM) 119 | rebuild: docker-arch-rebuild 120 | 121 | .PHONY: tag 122 | tag: 123 | @if [ "$(TAG)" = "latest" ]; then \ 124 | if [ "$(STAGE)" = "base" ]; then \ 125 | echo "docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)"; \ 126 | docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION); \ 127 | else \ 128 | echo "docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(STAGE)$(KOPS)$(HELM)"; \ 129 | docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(STAGE)$(KOPS)$(HELM); \ 130 | fi \ 131 | else \ 132 | if [ "$(STAGE)" = "base" ]; then \ 133 | echo "docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(TAG)"; \ 134 | docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(TAG); \ 135 | else \ 136 | echo "docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(STAGE)$(KOPS)$(HELM)-$(TAG)"; \ 137 | docker tag $(IMAGE):$(DOCKER_TAG) $(IMAGE):$(VERSION)-$(STAGE)$(KOPS)$(HELM)-$(TAG); \ 138 | fi \ 139 | fi 140 | 141 | .PHONY: push 142 | ifeq ($(strip $(TAG)),latest) 143 | ifeq ($(strip $(STAGE)),base) 144 | push: DOCKER_TAG = $(VERSION) 145 | push: docker-arch-push 146 | else 147 | push: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM) 148 | push: docker-arch-push 149 | endif 150 | else 151 | ifeq ($(strip $(STAGE)),base) 152 | push: DOCKER_TAG = $(VERSION)-$(TAG) 153 | push: docker-arch-push 154 | else 155 | push: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM)-$(TAG) 156 | push: docker-arch-push 157 | endif 158 | endif 159 | 160 | 161 | # ------------------------------------------------------------------------------------------------- 162 | # Manifest Targets 163 | # ------------------------------------------------------------------------------------------------- 164 | .PHONY: manifest-create 165 | ifeq ($(strip $(TAG)),latest) 166 | ifeq ($(strip $(STAGE)),base) 167 | manifest-create: DOCKER_TAG = $(VERSION) 168 | manifest-create: docker-manifest-create 169 | else 170 | manifest-create: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM) 171 | manifest-create: docker-manifest-create 172 | endif 173 | else 174 | ifeq ($(strip $(STAGE)),base) 175 | manifest-create: DOCKER_TAG = $(VERSION)-$(TAG) 176 | manifest-create: docker-manifest-create 177 | else 178 | manifest-create: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM)-$(TAG) 179 | manifest-create: docker-manifest-create 180 | endif 181 | endif 182 | 183 | .PHONY: manifest-push 184 | ifeq ($(strip $(TAG)),latest) 185 | ifeq ($(strip $(STAGE)),base) 186 | manifest-push: DOCKER_TAG = $(VERSION) 187 | manifest-push: docker-manifest-push 188 | else 189 | manifest-push: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM) 190 | manifest-push: docker-manifest-push 191 | endif 192 | else 193 | ifeq ($(strip $(STAGE)),base) 194 | manifest-push: DOCKER_TAG = $(VERSION)-$(TAG) 195 | manifest-push: docker-manifest-push 196 | else 197 | manifest-push: DOCKER_TAG = $(VERSION)-$(STAGE)$(KOPS)$(HELM)-$(TAG) 198 | manifest-push: docker-manifest-push 199 | endif 200 | endif 201 | 202 | 203 | # ------------------------------------------------------------------------------------------------- 204 | # Save / Load Targets 205 | # ------------------------------------------------------------------------------------------------- 206 | .PHONY: save 207 | save: docker-save 208 | 209 | .PHONY: load 210 | load: docker-load 211 | 212 | .PHONY: save-verify 213 | save-verify: save 214 | save-verify: load 215 | 216 | 217 | # ------------------------------------------------------------------------------------------------- 218 | # Test Targets 219 | # ------------------------------------------------------------------------------------------------- 220 | .PHONY: test 221 | test: test-architecture-uname 222 | test: test-architecture-inspect 223 | test: test-ansible-version 224 | test: test-python-libs 225 | test: test-binaries 226 | test: test-helm-version 227 | test: test-kops-version 228 | test: test-run-user-root 229 | test: test-run-user-ansible 230 | 231 | .PHONY: test-architecture-uname 232 | test-architecture-uname: 233 | @echo "################################################################################" 234 | @echo "# Testing correct Architecture - uname ($(ARCH))" 235 | @echo "################################################################################" 236 | @echo "docker run --rm --platform $(ARCH) --entrypoint=sh $(IMAGE):$(DOCKER_TAG) -c 'uname -m'" 237 | @\ 238 | if [ "$(ARCH)" = "linux/amd64" ]; then \ 239 | if ! docker run --rm --platform $(ARCH) --entrypoint=sh $(IMAGE):$(DOCKER_TAG) -c 'uname -m' | grep -E '^x86_64$$'; then \ 240 | echo "[FAILED]"; \ 241 | docker run --rm --platform $(ARCH) --entrypoint=sh $(IMAGE):$(DOCKER_TAG) -c 'uname -m'; \ 242 | exit 1; \ 243 | fi; \ 244 | elif [ "$(ARCH)" = "linux/arm64" ]; then \ 245 | if ! docker run --rm --platform $(ARCH) --entrypoint=sh $(IMAGE):$(DOCKER_TAG) -c 'uname -m' | grep -E '^aarch64$$'; then \ 246 | echo "[FAILED]"; \ 247 | docker run --rm --platform $(ARCH) --entrypoint=sh $(IMAGE):$(DOCKER_TAG) -c 'uname -m'; \ 248 | exit 1; \ 249 | fi; \ 250 | else \ 251 | echo "[FAILED]"; \ 252 | echo "Wrong ARCH variable specified: $(ARCH)"; \ 253 | exit 1; \ 254 | fi; \ 255 | echo "[SUCCESS]"; \ 256 | echo 257 | 258 | .PHONY: test-architecture-inspect 259 | test-architecture-inspect: 260 | @echo "################################################################################" 261 | @echo "# Testing correct Architecture - inspect ($(ARCH))" 262 | @echo "################################################################################" 263 | @echo "docker image inspect $(IMAGE):$(DOCKER_TAG) -f '{{ .Architecture }}'" 264 | @\ 265 | if [ "$(ARCH)" = "linux/amd64" ]; then \ 266 | if ! docker image inspect $(IMAGE):$(DOCKER_TAG) -f '{{ .Architecture }}' | grep -E '^amd64$$'; then \ 267 | echo "[FAILED]"; \ 268 | docker image inspect $(IMAGE):$(DOCKER_TAG) -f '{{ .Architecture }}'; \ 269 | exit 1; \ 270 | fi; \ 271 | elif [ "$(ARCH)" = "linux/arm64" ]; then \ 272 | if ! docker image inspect $(IMAGE):$(DOCKER_TAG) -f '{{ .Architecture }}' | grep -E '^arm64$$'; then \ 273 | echo "[FAILED]"; \ 274 | docker image inspect $(IMAGE):$(DOCKER_TAG) -f '{{ .Architecture }}'; \ 275 | exit 1; \ 276 | fi; \ 277 | else \ 278 | echo "[FAILED]"; \ 279 | echo "Wrong ARCH variable specified: $(ARCH)"; \ 280 | exit 1; \ 281 | fi; \ 282 | echo "[SUCCESS]"; \ 283 | echo 284 | 285 | 286 | 287 | .PHONY: test-ansible-version 288 | test-ansible-version: 289 | @echo "################################################################################" 290 | @echo "# Testing correct Ansible version" 291 | @echo "################################################################################" 292 | @\ 293 | if echo '$(ANSIBLE)' | grep -Eq 'latest\-?'; then \ 294 | echo "Fetching latest version from GitHub"; \ 295 | TEST_VERSION="$$( \ 296 | curl -L -sS https://github.com/ansible/ansible/releases/ \ 297 | | tac | tac \ 298 | | grep -Eo "ansible/ansible/releases/tag/v[.0-9]+\"" \ 299 | | sed 's/.*v//g' \ 300 | | sed 's/\"//g' \ 301 | | sort -V \ 302 | | tail -1 \ 303 | )"; \ 304 | else \ 305 | TEST_VERSION="$$( echo '$(ANSIBLE)' )"; \ 306 | fi; \ 307 | \ 308 | \ 309 | echo "Testing against Ansible version: $${TEST_VERSION}"; \ 310 | echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) ansible --version | grep -E \"^[Aa]nsible.+$${TEST_VERSION}\""; \ 311 | \ 312 | \ 313 | if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) ansible --version | grep -E "^[Aa]nsible.+$${TEST_VERSION}"; then \ 314 | echo "[FAILED]"; \ 315 | docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) ansible --version; \ 316 | exit 1; \ 317 | fi; \ 318 | echo "[SUCCESS]"; \ 319 | echo 320 | 321 | .PHONY: test-python-libs 322 | test-python-libs: 323 | @echo "################################################################################" 324 | @echo "# Testing correct Python libraries" 325 | @echo "################################################################################" 326 | @echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) pip3 freeze" 327 | @\ 328 | \ 329 | \ 330 | LIBS="$$( docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) pip3 freeze )"; \ 331 | \ 332 | \ 333 | REQUIRED_BASE="cffi cryptography paramiko Jinja2 PyYAML"; \ 334 | REQUIRED_TOOLS="dnspython mitogen jmespath"; \ 335 | REQUIRED_INFRA="docker docker-compose jsondiff pexpect psycopg2 pypsexec pymongo PyMySQL smbprotocol pywinrm"; \ 336 | REQUIRED_AZURE="azure\-.*"; \ 337 | REQUIRED_AWS="awscli botocore boto boto3"; \ 338 | REQUIRED_AWSK8S="openshift"; \ 339 | REQUIRED_AWSKOPS=""; \ 340 | REQUIRED_AWSHELM=""; \ 341 | \ 342 | \ 343 | if [ "$(STAGE)" = "base" ]; then \ 344 | for lib in $$( echo $${REQUIRED_BASE} ); do \ 345 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 346 | echo "[OK] required lib available: $${lib}"; \ 347 | else \ 348 | echo "[FAILED] required lib not available: $${lib}"; \ 349 | exit 1; \ 350 | fi; \ 351 | done; \ 352 | for lib in $${REQUIRED_TOOLS}; do \ 353 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 354 | echo "[OK] unwanted lib not available: $${lib}"; \ 355 | else \ 356 | echo "[FAILED] unwanted lib available: $${lib}"; \ 357 | exit 1; \ 358 | fi; \ 359 | done; \ 360 | \ 361 | elif [ "$(STAGE)" = "tools" ]; then \ 362 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} ); do \ 363 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 364 | echo "[OK] required lib available: $${lib}"; \ 365 | else \ 366 | echo "[FAILED] required lib not available: $${lib}"; \ 367 | exit 1; \ 368 | fi; \ 369 | done; \ 370 | for lib in $${REQUIRED_INFRA}; do \ 371 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 372 | echo "[OK] unwanted lib not available: $${lib}"; \ 373 | else \ 374 | echo "[FAILED] unwanted lib available: $${lib}"; \ 375 | exit 1; \ 376 | fi; \ 377 | done; \ 378 | \ 379 | elif [ "$(STAGE)" = "infra" ]; then \ 380 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_INFRA} ); do \ 381 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 382 | echo "[OK] required lib available: $${lib}"; \ 383 | else \ 384 | echo "[FAILED] required lib not available: $${lib}"; \ 385 | exit 1; \ 386 | fi; \ 387 | done; \ 388 | for lib in $${REQUIRED_AZURE}; do \ 389 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 390 | echo "[OK] unwanted lib not available: $${lib}"; \ 391 | else \ 392 | echo "[FAILED] unwanted lib available: $${lib}"; \ 393 | exit 1; \ 394 | fi; \ 395 | done; \ 396 | \ 397 | elif [ "$(STAGE)" = "azure" ]; then \ 398 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AZURE} ); do \ 399 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 400 | echo "[OK] required lib available: $${lib}"; \ 401 | else \ 402 | echo "[FAILED] required lib not available: $${lib}"; \ 403 | exit 1; \ 404 | fi; \ 405 | done; \ 406 | for lib in $${REQUIRED_AWS}; do \ 407 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 408 | echo "[OK] unwanted lib not available: $${lib}"; \ 409 | else \ 410 | echo "[FAILED] unwanted lib available: $${lib}"; \ 411 | exit 1; \ 412 | fi; \ 413 | done; \ 414 | \ 415 | elif [ "$(STAGE)" = "aws" ]; then \ 416 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} ); do \ 417 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 418 | echo "[OK] required lib available: $${lib}"; \ 419 | else \ 420 | echo "[FAILED] required lib not available: $${lib}"; \ 421 | exit 1; \ 422 | fi; \ 423 | done; \ 424 | for lib in $${REQUIRED_AWSK8S}; do \ 425 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 426 | echo "[OK] unwanted lib not available: $${lib}"; \ 427 | else \ 428 | echo "[FAILED] unwanted lib available: $${lib}"; \ 429 | exit 1; \ 430 | fi; \ 431 | done; \ 432 | \ 433 | elif [ "$(STAGE)" = "awsk8s" ]; then \ 434 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} ); do \ 435 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 436 | echo "[OK] required lib available: $${lib}"; \ 437 | else \ 438 | echo "[FAILED] required lib not available: $${lib}"; \ 439 | exit 1; \ 440 | fi; \ 441 | done; \ 442 | for lib in $$( echo $${REQUIRED_AWSKOPS} $${REQUIRED_AWSHELM} ); do \ 443 | if ! echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 444 | echo "[OK] unwanted lib not available: $${lib}"; \ 445 | else \ 446 | echo "[FAILED] unwanted lib available: $${lib}"; \ 447 | exit 1; \ 448 | fi; \ 449 | done; \ 450 | \ 451 | elif [ "$(STAGE)" = "awskops" ]; then \ 452 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} $${REQUIRED_AWSKOPS} ); do \ 453 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 454 | echo "[OK] required lib available: $${lib}"; \ 455 | else \ 456 | echo "[FAILED] required lib not available: $${lib}"; \ 457 | exit 1; \ 458 | fi; \ 459 | done; \ 460 | \ 461 | elif [ "$(STAGE)" = "awshelm" ]; then \ 462 | for lib in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} $${REQUIRED_AWSHELM} ); do \ 463 | if echo "$${LIBS}" | grep -E "^$${lib}" >/dev/null; then \ 464 | echo "[OK] required lib available: $${lib}"; \ 465 | else \ 466 | echo "[FAILED] required lib not available: $${lib}"; \ 467 | exit 1; \ 468 | fi; \ 469 | done; \ 470 | \ 471 | fi; \ 472 | echo "[SUCCESS]"; \ 473 | echo 474 | 475 | .PHONY: test-binaries 476 | test-binaries: 477 | @echo "################################################################################" 478 | @echo "# Testing correct Binaries" 479 | @echo "################################################################################" 480 | @echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) find /usr/bin/ -type f | sed 's|/usr/bin/||g'" 481 | @\ 482 | \ 483 | \ 484 | BINS="$$( docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) find /usr/bin/ -type f | sed 's|/usr/bin/||g' )"; \ 485 | \ 486 | \ 487 | REQUIRED_BASE="python"; \ 488 | REQUIRED_TOOLS="git gpg jq yq ssh"; \ 489 | REQUIRED_INFRA="rsync"; \ 490 | REQUIRED_AZURE="az"; \ 491 | REQUIRED_AWS="aws aws-iam-authenticator"; \ 492 | REQUIRED_AWSK8S="kubectl oc"; \ 493 | REQUIRED_AWSKOPS="kops"; \ 494 | REQUIRED_AWSHELM="helm"; \ 495 | \ 496 | \ 497 | if [ "$(STAGE)" = "base" ]; then \ 498 | for bin in $$( echo $${REQUIRED_BASE} ); do \ 499 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 500 | echo "[OK] required bin available: $${bin}"; \ 501 | else \ 502 | echo "[FAILED] required bin not available: $${bin}"; \ 503 | exit 1; \ 504 | fi; \ 505 | done; \ 506 | for bin in $${REQUIRED_TOOLS}; do \ 507 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 508 | echo "[OK] unwanted bin not available: $${bin}"; \ 509 | else \ 510 | echo "[FAILED] unwanted bin available: $${bin}"; \ 511 | exit 1; \ 512 | fi; \ 513 | done; \ 514 | \ 515 | elif [ "$(STAGE)" = "tools" ]; then \ 516 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} ); do \ 517 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 518 | echo "[OK] required bin available: $${bin}"; \ 519 | else \ 520 | echo "[FAILED] required bin not available: $${bin}"; \ 521 | exit 1; \ 522 | fi; \ 523 | done; \ 524 | for bin in $${REQUIRED_INFRA}; do \ 525 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 526 | echo "[OK] unwanted bin not available: $${bin}"; \ 527 | else \ 528 | echo "[FAILED] unwanted bin available: $${bin}"; \ 529 | exit 1; \ 530 | fi; \ 531 | done; \ 532 | \ 533 | elif [ "$(STAGE)" = "infra" ]; then \ 534 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_INFRA} ); do \ 535 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 536 | echo "[OK] required bin available: $${bin}"; \ 537 | else \ 538 | echo "[FAILED] required bin not available: $${bin}"; \ 539 | exit 1; \ 540 | fi; \ 541 | done; \ 542 | for bin in $${REQUIRED_AZURE}; do \ 543 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 544 | echo "[OK] unwanted bin not available: $${bin}"; \ 545 | else \ 546 | echo "[FAILED] unwanted bin available: $${bin}"; \ 547 | exit 1; \ 548 | fi; \ 549 | done; \ 550 | \ 551 | elif [ "$(STAGE)" = "azure" ]; then \ 552 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AZURE} ); do \ 553 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 554 | echo "[OK] required bin available: $${bin}"; \ 555 | else \ 556 | echo "[FAILED] required bin not available: $${bin}"; \ 557 | exit 1; \ 558 | fi; \ 559 | done; \ 560 | for bin in $${REQUIRED_AWS}; do \ 561 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 562 | echo "[OK] unwanted bin not available: $${bin}"; \ 563 | else \ 564 | echo "[FAILED] unwanted bin available: $${bin}"; \ 565 | exit 1; \ 566 | fi; \ 567 | done; \ 568 | \ 569 | elif [ "$(STAGE)" = "aws" ]; then \ 570 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} ); do \ 571 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 572 | echo "[OK] required bin available: $${bin}"; \ 573 | else \ 574 | echo "[FAILED] required bin not available: $${bin}"; \ 575 | exit 1; \ 576 | fi; \ 577 | done; \ 578 | for bin in $${REQUIRED_AWSK8S}; do \ 579 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 580 | echo "[OK] unwanted bin not available: $${bin}"; \ 581 | else \ 582 | echo "[FAILED] unwanted bin available: $${bin}"; \ 583 | exit 1; \ 584 | fi; \ 585 | done; \ 586 | \ 587 | elif [ "$(STAGE)" = "awsk8s" ]; then \ 588 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} ); do \ 589 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 590 | echo "[OK] required bin available: $${bin}"; \ 591 | else \ 592 | echo "[FAILED] required bin not available: $${bin}"; \ 593 | exit 1; \ 594 | fi; \ 595 | done; \ 596 | for bin in $$( echo $${REQUIRED_AWSKOPS} $${REQUIRED_AWSHELM} ); do \ 597 | if ! echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 598 | echo "[OK] unwanted bin not available: $${bin}"; \ 599 | else \ 600 | echo "[FAILED] unwanted bin available: $${bin}"; \ 601 | exit 1; \ 602 | fi; \ 603 | done; \ 604 | \ 605 | elif [ "$(STAGE)" = "awskops" ]; then \ 606 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} $${REQUIRED_AWSKOPS} ); do \ 607 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 608 | echo "[OK] required bin available: $${bin}"; \ 609 | else \ 610 | echo "[FAILED] required bin not available: $${bin}"; \ 611 | exit 1; \ 612 | fi; \ 613 | done; \ 614 | \ 615 | elif [ "$(STAGE)" = "awshelm" ]; then \ 616 | for bin in $$( echo $${REQUIRED_BASE} $${REQUIRED_TOOLS} $${REQUIRED_AWS} $${REQUIRED_AWSK8S} $${REQUIRED_AWSHELM} ); do \ 617 | if echo "$${BINS}" | grep -E "^$${bin}" >/dev/null; then \ 618 | echo "[OK] required bin available: $${bin}"; \ 619 | else \ 620 | echo "[FAILED] required bin not available: $${bin}"; \ 621 | exit 1; \ 622 | fi; \ 623 | done; \ 624 | \ 625 | fi; \ 626 | echo "[SUCCESS]"; \ 627 | echo 628 | 629 | .PHONY: test-helm-version 630 | test-helm-version: 631 | @echo "################################################################################" 632 | @echo "# Testing correct Helm version" 633 | @echo "################################################################################" 634 | @\ 635 | if [ "$(STAGE)" = "awshelm" ]; then \ 636 | if echo '$(HELM)' | grep -Eq 'latest\-?'; then \ 637 | echo "Fetching latest version from GitHub"; \ 638 | LATEST="$$( \ 639 | curl -L -sS https://github.com/helm/helm/releases \ 640 | | tac | tac \ 641 | | grep -Eo "helm/helm/releases/tag/v[.0-9]+\"" \ 642 | | head -1 \ 643 | | sed 's/.*v//g' \ 644 | | sed 's/\"//g' \ 645 | )"; \ 646 | echo "Testing for latest: $${LATEST}"; \ 647 | echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short | grep -E \"^(Client: )?v$${LATEST}\""; \ 648 | if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short | grep -E "^(Client: )?v$${LATEST}"; then \ 649 | echo "[FAILED]"; \ 650 | docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short; \ 651 | exit 1; \ 652 | fi; \ 653 | else \ 654 | VERSION="$$( echo '$(HELM)' | grep -Eo '^[.0-9]+?' )"; \ 655 | echo "Testing for version: $${VERSION}"; \ 656 | echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short | grep -E \"^(Client: )?v$${VERSION}\.\""; \ 657 | if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short | grep -E "^(Client: )?v$${VERSION}\."; then \ 658 | echo "[FAILED]"; \ 659 | docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) helm version --client --short; \ 660 | exit 1; \ 661 | fi; \ 662 | fi; \ 663 | echo "[SUCCESS]"; \ 664 | else \ 665 | echo "[SKIPPING] Not a Helm image"; \ 666 | fi; \ 667 | echo 668 | 669 | .PHONY: test-kops-version 670 | test-kops-version: 671 | @echo "################################################################################" 672 | @echo "# Testing correct Kops version" 673 | @echo "################################################################################" 674 | @\ 675 | if [ "$(STAGE)" = "awskops" ]; then \ 676 | if echo '$(KOPS)' | grep -Eq 'latest\-?'; then \ 677 | echo "Fetching latest version from GitHub"; \ 678 | LATEST="$$( \ 679 | curl -L -sS https://github.com/kubernetes/kops/releases \ 680 | | tac | tac \ 681 | | grep -Eo "kubernetes/kops/releases/tag/v[.0-9]+\"" \ 682 | | head -1 \ 683 | | sed 's/.*v//g' \ 684 | | sed 's/\"//g' \ 685 | )"; \ 686 | echo "Testing for latest: $${LATEST}"; \ 687 | echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version | grep -E \"^([Cc]lient\s)?[Vv]ersion(:)?\s+v?$${LATEST}\""; \ 688 | if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version | grep -E "^([Cc]lient\s)?[Vv]ersion(:)?\s+v?$${LATEST}"; then \ 689 | echo "[FAILED]"; \ 690 | docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version; \ 691 | exit 1; \ 692 | fi; \ 693 | else \ 694 | VERSION="$$( echo '$(KOPS)' | grep -Eo '^[.0-9]+?' )"; \ 695 | echo "Testing for version: $${VERSION}"; \ 696 | echo "docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version | grep -E \"^([Cc]lient\s)?[Vv]ersion(:)?\s+v?$${VERSION}\.\""; \ 697 | if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version | grep -E "^([Cc]lient\s)?[Vv]ersion(:)?\s+v?$${VERSION}\."; then \ 698 | echo "[FAILED]"; \ 699 | docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) kops version; \ 700 | exit 1; \ 701 | fi; \ 702 | fi; \ 703 | echo "[SUCCESS]"; \ 704 | else \ 705 | echo "[SKIPPING] Not a Kops image"; \ 706 | fi; \ 707 | echo 708 | 709 | .PHONY: test-run-user-root 710 | test-run-user-root: 711 | @echo "################################################################################" 712 | @echo "# Testing playbook (user: root)" 713 | @echo "################################################################################" 714 | @echo "docker run --rm --platform $(ARCH) $$(tty -s && echo "-it" || echo) -v $(CURRENT_DIR)/tests:/data $(IMAGE):$(DOCKER_TAG) ansible-playbook -i inventory playbook.yml" 715 | @\ 716 | if ! docker run --rm --platform $(ARCH) $$(tty -s && echo "-it" || echo) -v $(CURRENT_DIR)/tests:/data $(IMAGE):$(DOCKER_TAG) ansible-playbook -i inventory playbook.yml; then \ 717 | echo "[FAILED]"; \ 718 | exit 1; \ 719 | fi; \ 720 | echo "[SUCCESS]"; \ 721 | echo 722 | 723 | .PHONY: test-run-user-ansible 724 | test-run-user-ansible: 725 | @echo "################################################################################" 726 | @echo "# Testing playbook (user: ansible)" 727 | @echo "################################################################################" 728 | @\ 729 | if [ "$(STAGE)" = "base" ]; then \ 730 | echo "[SKIPPING] Does not have user setup"; \ 731 | else \ 732 | echo "docker run --rm --platform $(ARCH) $$(tty -s && echo "-it" || echo) -v $(CURRENT_DIR)/tests:/data -e USER=ansible -e MY_UID=$$(id -u) -e MY_GID=$$(id -g) $(IMAGE):$(DOCKER_TAG) ansible-playbook -i inventory playbook.yml"; \ 733 | if ! docker run --rm --platform $(ARCH) $$(tty -s && echo "-it" || echo) -v $(CURRENT_DIR)/tests:/data -e USER=ansible -e MY_UID=$$(id -u) -e MY_GID=$$(id -g) $(IMAGE):$(DOCKER_TAG) ansible-playbook -i inventory playbook.yml ; then \ 734 | echo "[FAILED]"; \ 735 | exit 1; \ 736 | fi; \ 737 | fi; \ 738 | echo "[SUCCESS]"; \ 739 | echo 740 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker image for `ansible` 2 | 3 | [![Tag](https://img.shields.io/github/tag/cytopia/docker-ansible.svg)](https://github.com/cytopia/docker-ansible/releases) 4 | [![](https://img.shields.io/badge/github-cytopia%2Fdocker--ansible-red.svg)](https://github.com/cytopia/docker-ansible "github.com/cytopia/docker-ansible") 5 | [![](https://img.shields.io/docker/pulls/cytopia/ansible.svg)](https://hub.docker.com/r/cytopia/ansible) 6 | [![Docker](https://badgen.net/badge/icon/:latest?icon=docker&label=cytopia/ansible)](https://hub.docker.com/r/cytopia/ansible) 7 | [![License](https://img.shields.io/badge/license-MIT-%233DA639.svg)](https://opensource.org/licenses/MIT) 8 | 9 | [![lint](https://github.com/cytopia/docker-ansible/workflows/lint/badge.svg)](https://github.com/cytopia/docker-ansible/actions?query=workflow%3Alint) 10 | [![build](https://github.com/cytopia/docker-ansible/actions/workflows/action_branch.yml/badge.svg)](https://github.com/cytopia/docker-ansible/actions/workflows/action_branch.yml) 11 | [![nightly](https://github.com/cytopia/docker-ansible/actions/workflows/action_schedule.yml/badge.svg)](https://github.com/cytopia/docker-ansible/actions/workflows/action_schedule.yml) 12 | 13 | 14 | > #### All [#awesome-ci](https://github.com/topics/awesome-ci) Docker images 15 | > 16 | > [ansible-lint][alint-git-lnk] **•** 17 | > [ansible][ansible-git-lnk] **•** 18 | > [awesome-ci][aci-git-lnk] **•** 19 | > [bandit][bandit-git-lnk] **•** 20 | > [black][black-git-lnk] **•** 21 | > [checkmake][cm-git-lnk] **•** 22 | > [eslint][elint-git-lnk] **•** 23 | > [file-lint][flint-git-lnk] **•** 24 | > [gofmt][gfmt-git-lnk] **•** 25 | > [goimports][gimp-git-lnk] **•** 26 | > [golint][glint-git-lnk] **•** 27 | > [jsonlint][jlint-git-lnk] **•** 28 | > [kubeval][kubeval-git-lnk] **•** 29 | > [linkcheck][linkcheck-git-lnk] **•** 30 | > [mypy][mypy-git-lnk] **•** 31 | > [php-cs-fixer][pcsf-git-lnk] **•** 32 | > [phpcbf][pcbf-git-lnk] **•** 33 | > [phpcs][pcs-git-lnk] **•** 34 | > [phplint][plint-git-lnk] **•** 35 | > [pycodestyle][pycs-git-lnk] **•** 36 | > [pydocstyle][pyds-git-lnk] **•** 37 | > [pylint][pylint-git-lnk] **•** 38 | > [terraform-docs][tfdocs-git-lnk] **•** 39 | > [terragrunt-fmt][tgfmt-git-lnk] **•** 40 | > [terragrunt][tg-git-lnk] **•** 41 | > [yamlfmt][yfmt-git-lnk] **•** 42 | > [yamllint][ylint-git-lnk] 43 | 44 | View **[Dockerfiles](https://github.com/cytopia/docker-ansible/blob/master/Dockerfiles/)** on GitHub. 45 | 46 | 47 | **Available Architectures:** `amd64`, `arm64` 48 | 49 | Tiny Alpine-based multistage-build dockerized version of [Ansible](https://github.com/ansible/ansible)[1] in many different flavours. 50 | It comes with **[Mitogen](https://github.com/dw/mitogen)**[2] to speed up your runs by up to **600%**[3][4] (see [Examples](#run-ansible-playbook-with-mitogen)). 51 | The image is built nightly against multiple stable versions and pushed to Dockerhub. 52 | 53 | * [1] Official project: https://github.com/ansible/ansible 54 | * [2] Official project: https://github.com/dw/mitogen 55 | * [3] [How to Speed Up Your Ansible Playbooks Over 600%](https://www.toptechskills.com/ansible-tutorials-courses/speed-up-ansible-playbooks-pipelining-mitogen/) 56 | * [4] [Mitogen for Ansible](https://networkgenomics.com/ansible/) 57 | 58 | 59 | ## :whale: Available Docker image versions 60 | 61 | This repository provides many different Ansible flavours (each flavour also divided into different Ansible versions). 62 | 63 | The following tree shows how the different flavours derive from each other (each child has all the tools and features of its parent plus its own additions). 64 | ```css 65 | base #docker-tag: :latest 66 | | : 67 | | 68 | tools #docker-tag: :latest-tools 69 | / | \ :-tools 70 | / | \ 71 | infra azure aws #docker-tag: :latest-infra :latest-azure :latest-aws 72 | | :-infra :-azure :-aws 73 | | 74 | awsk8s #docker-tag: :latest-awsk8s 75 | / \ :-awsk8s 76 | / \ 77 | awskops awshelm #docker-tag :latest-awskops :latest-awshelm 78 | :-awskops :-awshelm 79 | ``` 80 | > `` refers to the latest\[1\], patch-level version of Ansible. E.g.: `2.9`, `2.10`, `2.11`, ...
81 | > \[1\]: latest as docker images are (re)built every night via CI against the latest available patch level version of Ansible 82 | 83 | 84 | The following table shows a quick overview of provided libraries and tools for each flavour. For more details see further down below. 85 | 86 | | Flavour | Based on | Additional Python libs | Additional binaries | 87 | |---------|---------------|------------------------|---------------------| 88 | | base | - | `cffi`, `cryptography`, `Jinja2`, `junit-xml`, `lxml`, `paramiko`, `PyYAML` | - | 89 | | tools | base | `dnspython`, `JMESPath`, `mitogen` | `bash`, `git`, `gpg`, `jq`, `ssh`, `yq` | 90 | | infra | tools | `docker`, `docker-compose`, `jsondiff`, `netaddr`, `pexpect`, `psycopg2`, `pyldap`, `pypsexec`, `pymongo`, `PyMySQL`, `pywinrm`, `smbprotocol` | `rsync`, `sshpass` | 91 | | azure | tools | `azure-*` | `az` | 92 | | aws | tools | `awscli`, `botocore`, `boto`, `boto3` | `aws`, `aws-iam-authenticator` | 93 | | awsk8s | aws | `openshift` | `kubectl`, `oc` | 94 | | awskops | awsk8s | - | `kops` | 95 | | awshelm | awsk8s | - | `helm` | 96 | 97 | 98 | ## :repeat: Rolling releases 99 | 100 | The following Docker image tags are rolling releases and are built and updated every night. 101 | 102 | [![nightly](https://github.com/cytopia/docker-ansible/actions/workflows/action_schedule.yml/badge.svg)](https://github.com/cytopia/docker-ansible/actions/workflows/action_schedule.yml) 103 | 104 | ### Ansible base 105 | 106 | The following Ansible Docker images are as small as possible and only contain Ansible itself. 107 | 108 | | Docker Tag | Git Ref | Ansible | Available Architectures | 109 | |--------------------------|--------------|--------------|----------------------------------------------| 110 | | **`latest`** | master | latest | `amd64`, `arm64` | 111 | | `2.13` | master | **`2.13.x`** | `amd64`, `arm64` | 112 | | `2.12` | master | **`2.12.x`** | `amd64`, `arm64` | 113 | | `2.11` | master | **`2.11.x`** | `amd64`, `arm64` | 114 | | `2.10` | master | **`2.10.x`** | `amd64`, `arm64` | 115 | | `2.9` | master | **`2.9.x`** | `amd64`, `arm64` | 116 | | `2.8` | master | **`2.8.x`** | `amd64`, `arm64` | 117 | 118 | 119 | ### Ansible tools 120 | 121 | The following Ansible Docker images contain everything from `Ansible base` and additionally: `bash`, `git`, `gpg`, `jq`, `ssh` and `dnspython` and Ansible **`mitogen`** strategy plugin (see [Examples](#run-ansible-playbook-with-mitogen)). 122 | 123 | | Docker Tag | Git Ref | Ansible | Available Architectures | 124 | |--------------------------|--------------|--------------|----------------------------------------------| 125 | | **`latest-tools`** | master | latest | `amd64`, `arm64` | 126 | | `2.13-tools` | master | **`2.13.x`** | `amd64`, `arm64` | 127 | | `2.12-tools` | master | **`2.12.x`** | `amd64`, `arm64` | 128 | | `2.11-tools` | master | **`2.11.x`** | `amd64`, `arm64` | 129 | | `2.10-tools` | master | **`2.10.x`** | `amd64`, `arm64` | 130 | | `2.9-tools` | master | **`2.9.x`** | `amd64`, `arm64` | 131 | | `2.8-tools` | master | **`2.8.x`** | `amd64`, `arm64` | 132 | 133 | 134 | ### Ansible azure 135 | 136 | The following Ansible Docker images contain everything from `Ansible tools` and additionally: `azure`. 137 | 138 | | Docker Tag | Git Ref | Ansible | Available Architectures | 139 | |--------------------------|--------------|--------------|----------------------------------------------| 140 | | **`latest-azure`** | master | latest | `amd64`, `arm64` | 141 | | `2.13-azure` | master | **`2.13.x`** | `amd64`, `arm64` | 142 | | `2.12-azure` | master | **`2.12.x`** | `amd64`, `arm64` | 143 | | `2.11-azure` | master | **`2.11.x`** | `amd64`, `arm64` | 144 | | `2.10-azure` | master | **`2.10.x`** | `amd64`, `arm64` | 145 | | `2.9-azure` | master | **`2.9.x`** | `amd64`, `arm64` | 146 | | `2.8-azure` | master | **`2.8.x`** | `amd64`, `arm64` | 147 | 148 | 149 | ### Ansible aws 150 | 151 | The following Ansible Docker images contain everything from `Ansible tools` and additionally: `aws-cli`, `boto`, `boto3` and `botocore`. 152 | 153 | | Docker Tag | Git Ref | Ansible | Available Architectures | 154 | |--------------------------|--------------|--------------|----------------------------------------------| 155 | | **`latest-aws`** | master | latest | `amd64`, `arm64` | 156 | | `2.13-aws` | master | **`2.13.x`** | `amd64`, `arm64` | 157 | | `2.12-aws` | master | **`2.12.x`** | `amd64`, `arm64` | 158 | | `2.11-aws` | master | **`2.11.x`** | `amd64`, `arm64` | 159 | | `2.10-aws` | master | **`2.10.x`** | `amd64`, `arm64` | 160 | | `2.9-aws` | master | **`2.9.x`** | `amd64`, `arm64` | 161 | | `2.8-aws` | master | **`2.8.x`** | `amd64`, `arm64` | 162 | 163 | 164 | ### Ansible awsk8s 165 | 166 | The following Ansible Docker images contain everything from `Ansible aws` and additionally: `openshift` and `kubectl`. 167 | 168 | | Docker Tag | Git Ref | Ansible | Available Architectures | 169 | |--------------------------|--------------|--------------|----------------------------------------------| 170 | | **`latest-awsk8s`** | master | latest | `amd64`, `arm64` | 171 | | `2.13-awsk8s` | master | **`2.13.x`** | `amd64`, `arm64` | 172 | | `2.12-awsk8s` | master | **`2.12.x`** | `amd64`, `arm64` | 173 | | `2.11-awsk8s` | master | **`2.11.x`** | `amd64`, `arm64` | 174 | | `2.10-awsk8s` | master | **`2.10.x`** | `amd64`, `arm64` | 175 | | `2.9-awsk8s` | master | **`2.9.x`** | `amd64`, `arm64` | 176 | | `2.8-awsk8s` | master | **`2.8.x`** | `amd64`, `arm64` | 177 | 178 | 179 | ### Ansible awskops 180 | 181 | The following Ansible Docker images contain everything from `Ansible awsk8s` and additionally: `kops` in its latest patch level version. 182 | 183 | > https://github.com/kubernetes/kops/releases 184 | 185 | | Docker Tag | Git Ref | Ansible | Kops | Available Architectures | 186 | |--------------------------|--------------|--------------|----------|-----------------------------------| 187 | | **`latest-awskops1.25`** | master | latest | `1.25.x` | `amd64`, `arm64` | 188 | | `2.13-awskops1.25` | master | **`2.13.x`** | `1.25.x` | `amd64`, `arm64` | 189 | | `2.12-awskops1.25` | master | **`2.12.x`** | `1.25.x` | `amd64`, `arm64` | 190 | | `2.11-awskops1.25` | master | **`2.11.x`** | `1.25.x` | `amd64`, `arm64` | 191 | | `2.10-awskops1.25` | master | **`2.10.x`** | `1.25.x` | `amd64`, `arm64` | 192 | | `2.9-awskops1.25` | master | **`2.9.x`** | `1.25.x` | `amd64`, `arm64` | 193 | | `2.8-awskops1.25` | master | **`2.8.x`** | `1.25.x` | `amd64`, `arm64` | 194 | | | | | | | 195 | | **`latest-awskops1.24`** | master | latest | `1.24.x` | `amd64`, `arm64` | 196 | | `2.13-awskops1.24` | master | **`2.13.x`** | `1.24.x` | `amd64`, `arm64` | 197 | | `2.12-awskops1.24` | master | **`2.12.x`** | `1.24.x` | `amd64`, `arm64` | 198 | | `2.11-awskops1.24` | master | **`2.11.x`** | `1.24.x` | `amd64`, `arm64` | 199 | | `2.10-awskops1.24` | master | **`2.10.x`** | `1.24.x` | `amd64`, `arm64` | 200 | | `2.9-awskops1.24` | master | **`2.9.x`** | `1.24.x` | `amd64`, `arm64` | 201 | | `2.8-awskops1.24` | master | **`2.8.x`** | `1.24.x` | `amd64`, `arm64` | 202 | | | | | | | 203 | | **`latest-awskops1.23`** | master | latest | `1.23.x` | `amd64`, `arm64` | 204 | | `2.13-awskops1.23` | master | **`2.13.x`** | `1.23.x` | `amd64`, `arm64` | 205 | | `2.12-awskops1.23` | master | **`2.12.x`** | `1.23.x` | `amd64`, `arm64` | 206 | | `2.11-awskops1.23` | master | **`2.11.x`** | `1.23.x` | `amd64`, `arm64` | 207 | | `2.10-awskops1.23` | master | **`2.10.x`** | `1.23.x` | `amd64`, `arm64` | 208 | | `2.9-awskops1.23` | master | **`2.9.x`** | `1.23.x` | `amd64`, `arm64` | 209 | | `2.8-awskops1.23` | master | **`2.8.x`** | `1.23.x` | `amd64`, `arm64` | 210 | | | | | | | 211 | | **`latest-awskops1.22`** | master | latest | `1.22.x` | `amd64`, `arm64` | 212 | | `2.13-awskops1.22` | master | **`2.13.x`** | `1.22.x` | `amd64`, `arm64` | 213 | | `2.12-awskops1.22` | master | **`2.12.x`** | `1.22.x` | `amd64`, `arm64` | 214 | | `2.11-awskops1.22` | master | **`2.11.x`** | `1.22.x` | `amd64`, `arm64` | 215 | | `2.10-awskops1.22` | master | **`2.10.x`** | `1.22.x` | `amd64`, `arm64` | 216 | | `2.9-awskops1.22` | master | **`2.9.x`** | `1.22.x` | `amd64`, `arm64` | 217 | | `2.8-awskops1.22` | master | **`2.8.x`** | `1.22.x` | `amd64`, `arm64` | 218 | | | | | | | 219 | | **`latest-awskops1.21`** | master | latest | `1.21.x` | `amd64`, `arm64` | 220 | | `2.13-awskops1.21` | master | **`2.13.x`** | `1.21.x` | `amd64`, `arm64` | 221 | | `2.12-awskops1.21` | master | **`2.12.x`** | `1.21.x` | `amd64`, `arm64` | 222 | | `2.11-awskops1.21` | master | **`2.11.x`** | `1.21.x` | `amd64`, `arm64` | 223 | | `2.10-awskops1.21` | master | **`2.10.x`** | `1.21.x` | `amd64`, `arm64` | 224 | | `2.9-awskops1.21` | master | **`2.9.x`** | `1.21.x` | `amd64`, `arm64` | 225 | | `2.8-awskops1.21` | master | **`2.8.x`** | `1.21.x` | `amd64`, `arm64` | 226 | | | | | | | 227 | | **`latest-awskops1.20`** | master | latest | `1.20.x` | `amd64`, `arm64` | 228 | | `2.13-awskops1.20` | master | **`2.13.x`** | `1.20.x` | `amd64`, `arm64` | 229 | | `2.12-awskops1.20` | master | **`2.12.x`** | `1.20.x` | `amd64`, `arm64` | 230 | | `2.11-awskops1.20` | master | **`2.11.x`** | `1.20.x` | `amd64`, `arm64` | 231 | | `2.10-awskops1.20` | master | **`2.10.x`** | `1.20.x` | `amd64`, `arm64` | 232 | | `2.9-awskops1.20` | master | **`2.9.x`** | `1.20.x` | `amd64`, `arm64` | 233 | | `2.8-awskops1.20` | master | **`2.8.x`** | `1.20.x` | `amd64`, `arm64` | 234 | | | | | | | 235 | | **`latest-awskops1.19`** | master | latest | `1.19.x` | `amd64`, `arm64` | 236 | | `2.13-awskops1.19` | master | **`2.13.x`** | `1.19.x` | `amd64`, `arm64` | 237 | | `2.12-awskops1.19` | master | **`2.12.x`** | `1.19.x` | `amd64`, `arm64` | 238 | | `2.11-awskops1.19` | master | **`2.11.x`** | `1.19.x` | `amd64`, `arm64` | 239 | | `2.10-awskops1.19` | master | **`2.10.x`** | `1.19.x` | `amd64`, `arm64` | 240 | | `2.9-awskops1.19` | master | **`2.9.x`** | `1.19.x` | `amd64`, `arm64` | 241 | | `2.8-awskops1.19` | master | **`2.8.x`** | `1.19.x` | `amd64`, `arm64` | 242 | 243 | 244 | ### Ansible awshelm 245 | 246 | The following Ansible Docker images contain everything from `Ansible awsk8s` and additionally: `helm` in its latest patch level version. 247 | 248 | > https://github.com/helm/helm/releases 249 | 250 | | Docker Tag | Git Ref | Ansible | Helm | Available Architectures | 251 | |--------------------------|--------------|--------------|----------|-----------------------------------| 252 | | **`latest-awshelm3.11`** | master | latest | `3.11.x` | `amd64`, `arm64` | 253 | | `2.13-awshelm3.11` | master | **`2.13.x`** | `3.11.x` | `amd64`, `arm64` | 254 | | `2.12-awshelm3.11` | master | **`2.12.x`** | `3.11.x` | `amd64`, `arm64` | 255 | | `2.11-awshelm3.11` | master | **`2.11.x`** | `3.11.x` | `amd64`, `arm64` | 256 | | `2.10-awshelm3.11` | master | **`2.10.x`** | `3.11.x` | `amd64`, `arm64` | 257 | | `2.9-awshelm3.11` | master | **`2.9.x`** | `3.11.x` | `amd64`, `arm64` | 258 | | `2.8-awshelm3.11` | master | **`2.8.x`** | `3.11.x` | `amd64`, `arm64` | 259 | | | | | | | 260 | | **`latest-awshelm3.10`** | master | latest | `3.10.x` | `amd64`, `arm64` | 261 | | `2.13-awshelm3.10` | master | **`2.13.x`** | `3.10.x` | `amd64`, `arm64` | 262 | | `2.12-awshelm3.10` | master | **`2.12.x`** | `3.10.x` | `amd64`, `arm64` | 263 | | `2.11-awshelm3.10` | master | **`2.11.x`** | `3.10.x` | `amd64`, `arm64` | 264 | | `2.10-awshelm3.10` | master | **`2.10.x`** | `3.10.x` | `amd64`, `arm64` | 265 | | `2.9-awshelm3.10` | master | **`2.9.x`** | `3.10.x` | `amd64`, `arm64` | 266 | | `2.8-awshelm3.10` | master | **`2.8.x`** | `3.10.x` | `amd64`, `arm64` | 267 | | | | | | | 268 | | **`latest-awshelm3.9`** | master | latest | `3.9.x` | `amd64`, `arm64` | 269 | | `2.13-awshelm3.9` | master | **`2.13.x`** | `3.9.x` | `amd64`, `arm64` | 270 | | `2.12-awshelm3.9` | master | **`2.12.x`** | `3.9.x` | `amd64`, `arm64` | 271 | | `2.11-awshelm3.9` | master | **`2.11.x`** | `3.9.x` | `amd64`, `arm64` | 272 | | `2.10-awshelm3.9` | master | **`2.10.x`** | `3.9.x` | `amd64`, `arm64` | 273 | | `2.9-awshelm3.9` | master | **`2.9.x`** | `3.9.x` | `amd64`, `arm64` | 274 | | `2.8-awshelm3.9` | master | **`2.8.x`** | `3.9.x` | `amd64`, `arm64` | 275 | | | | | | | 276 | | **`latest-awshelm3.8`** | master | latest | `3.8.x` | `amd64`, `arm64` | 277 | | `2.13-awshelm3.8` | master | **`2.13.x`** | `3.8.x` | `amd64`, `arm64` | 278 | | `2.12-awshelm3.8` | master | **`2.12.x`** | `3.8.x` | `amd64`, `arm64` | 279 | | `2.11-awshelm3.8` | master | **`2.11.x`** | `3.8.x` | `amd64`, `arm64` | 280 | | `2.10-awshelm3.8` | master | **`2.10.x`** | `3.8.x` | `amd64`, `arm64` | 281 | | `2.9-awshelm3.8` | master | **`2.9.x`** | `3.8.x` | `amd64`, `arm64` | 282 | | `2.8-awshelm3.8` | master | **`2.8.x`** | `3.8.x` | `amd64`, `arm64` | 283 | | | | | | | 284 | | **`latest-awshelm3.7`** | master | latest | `3.7.x` | `amd64`, `arm64` | 285 | | `2.13-awshelm3.7` | master | **`2.13.x`** | `3.7.x` | `amd64`, `arm64` | 286 | | `2.12-awshelm3.7` | master | **`2.12.x`** | `3.7.x` | `amd64`, `arm64` | 287 | | `2.11-awshelm3.7` | master | **`2.11.x`** | `3.7.x` | `amd64`, `arm64` | 288 | | `2.10-awshelm3.7` | master | **`2.10.x`** | `3.7.x` | `amd64`, `arm64` | 289 | | `2.9-awshelm3.7` | master | **`2.9.x`** | `3.7.x` | `amd64`, `arm64` | 290 | | `2.8-awshelm3.7` | master | **`2.8.x`** | `3.7.x` | `amd64`, `arm64` | 291 | | | | | | | 292 | | **`latest-awshelm3.6`** | master | latest | `3.6.x` | `amd64`, `arm64` | 293 | | `2.13-awshelm3.6` | master | **`2.13.x`** | `3.6.x` | `amd64`, `arm64` | 294 | | `2.12-awshelm3.6` | master | **`2.12.x`** | `3.6.x` | `amd64`, `arm64` | 295 | | `2.11-awshelm3.6` | master | **`2.11.x`** | `3.6.x` | `amd64`, `arm64` | 296 | | `2.10-awshelm3.6` | master | **`2.10.x`** | `3.6.x` | `amd64`, `arm64` | 297 | | `2.9-awshelm3.6` | master | **`2.9.x`** | `3.6.x` | `amd64`, `arm64` | 298 | | `2.8-awshelm3.6` | master | **`2.8.x`** | `3.6.x` | `amd64`, `arm64` | 299 | | | | | | | 300 | | **`latest-awshelm3.5`** | master | latest | `3.5.x` | `amd64`, `arm64` | 301 | | `2.13-awshelm3.5` | master | **`2.13.x`** | `3.5.x` | `amd64`, `arm64` | 302 | | `2.12-awshelm3.5` | master | **`2.12.x`** | `3.5.x` | `amd64`, `arm64` | 303 | | `2.11-awshelm3.5` | master | **`2.11.x`** | `3.5.x` | `amd64`, `arm64` | 304 | | `2.10-awshelm3.5` | master | **`2.10.x`** | `3.5.x` | `amd64`, `arm64` | 305 | | `2.9-awshelm3.5` | master | **`2.9.x`** | `3.5.x` | `amd64`, `arm64` | 306 | | `2.8-awshelm3.5` | master | **`2.8.x`** | `3.5.x` | `amd64`, `arm64` | 307 | | | | | | | 308 | | **`latest-awshelm3.4`** | master | latest | `3.4.x` | `amd64`, `arm64` | 309 | | `2.13-awshelm3.4` | master | **`2.13.x`** | `3.4.x` | `amd64`, `arm64` | 310 | | `2.12-awshelm3.4` | master | **`2.12.x`** | `3.4.x` | `amd64`, `arm64` | 311 | | `2.11-awshelm3.4` | master | **`2.11.x`** | `3.4.x` | `amd64`, `arm64` | 312 | | `2.10-awshelm3.4` | master | **`2.10.x`** | `3.4.x` | `amd64`, `arm64` | 313 | | `2.9-awshelm3.4` | master | **`2.9.x`** | `3.4.x` | `amd64`, `arm64` | 314 | | `2.8-awshelm3.4` | master | **`2.8.x`** | `3.4.x` | `amd64`, `arm64` | 315 | | | | | | | 316 | | **`latest-awshelm3.3`** | master | latest | `3.3.x` | `amd64`, `arm64` | 317 | | `2.13-awshelm3.3` | master | **`2.13.x`** | `3.3.x` | `amd64`, `arm64` | 318 | | `2.12-awshelm3.3` | master | **`2.12.x`** | `3.3.x` | `amd64`, `arm64` | 319 | | `2.11-awshelm3.3` | master | **`2.11.x`** | `3.3.x` | `amd64`, `arm64` | 320 | | `2.10-awshelm3.3` | master | **`2.10.x`** | `3.3.x` | `amd64`, `arm64` | 321 | | `2.9-awshelm3.3` | master | **`2.9.x`** | `3.3.x` | `amd64`, `arm64` | 322 | | `2.8-awshelm3.3` | master | **`2.8.x`** | `3.3.x` | `amd64`, `arm64` | 323 | | | | | | | 324 | | **`latest-awshelm3.2`** | master | latest | `3.2.x` | `amd64`, `arm64` | 325 | | `2.13-awshelm3.2` | master | **`2.13.x`** | `3.2.x` | `amd64`, `arm64` | 326 | | `2.12-awshelm3.2` | master | **`2.12.x`** | `3.2.x` | `amd64`, `arm64` | 327 | | `2.11-awshelm3.2` | master | **`2.11.x`** | `3.2.x` | `amd64`, `arm64` | 328 | | `2.10-awshelm3.2` | master | **`2.10.x`** | `3.2.x` | `amd64`, `arm64` | 329 | | `2.9-awshelm3.2` | master | **`2.9.x`** | `3.2.x` | `amd64`, `arm64` | 330 | | `2.8-awshelm3.2` | master | **`2.8.x`** | `3.2.x` | `amd64`, `arm64` | 331 | | | | | | | 332 | | **`latest-awshelm3.1`** | master | latest | `3.1.x` | `amd64`, `arm64` | 333 | | `2.13-awshelm3.1` | master | **`2.13.x`** | `3.1.x` | `amd64`, `arm64` | 334 | | `2.12-awshelm3.1` | master | **`2.12.x`** | `3.1.x` | `amd64`, `arm64` | 335 | | `2.11-awshelm3.1` | master | **`2.11.x`** | `3.1.x` | `amd64`, `arm64` | 336 | | `2.10-awshelm3.1` | master | **`2.10.x`** | `3.1.x` | `amd64`, `arm64` | 337 | | `2.9-awshelm3.1` | master | **`2.9.x`** | `3.1.x` | `amd64`, `arm64` | 338 | | `2.8-awshelm3.1` | master | **`2.8.x`** | `3.1.x` | `amd64`, `arm64` | 339 | | | | | | | 340 | | **`latest-awshelm3.0`** | master | latest | `3.0.x` | `amd64`, `arm64` | 341 | | `2.13-awshelm3.0` | master | **`2.13.x`** | `3.0.x` | `amd64`, `arm64` | 342 | | `2.12-awshelm3.0` | master | **`2.12.x`** | `3.0.x` | `amd64`, `arm64` | 343 | | `2.11-awshelm3.0` | master | **`2.11.x`** | `3.0.x` | `amd64`, `arm64` | 344 | | `2.10-awshelm3.0` | master | **`2.10.x`** | `3.0.x` | `amd64`, `arm64` | 345 | | `2.9-awshelm3.0` | master | **`2.9.x`** | `3.0.x` | `amd64`, `arm64` | 346 | | `2.8-awshelm3.0` | master | **`2.8.x`** | `3.0.x` | `amd64`, `arm64` | 347 | | | | | | | 348 | | **`latest-awshelm2.16`** | master | latest | `2.16.x` | `amd64`, `arm64` | 349 | | `2.13-awshelm2.16` | master | **`2.13.x`** | `2.16.x` | `amd64`, `arm64` | 350 | | `2.12-awshelm2.16` | master | **`2.12.x`** | `2.16.x` | `amd64`, `arm64` | 351 | | `2.11-awshelm2.16` | master | **`2.11.x`** | `2.16.x` | `amd64`, `arm64` | 352 | | `2.10-awshelm2.16` | master | **`2.10.x`** | `2.16.x` | `amd64`, `arm64` | 353 | | `2.9-awshelm2.16` | master | **`2.9.x`** | `2.16.x` | `amd64`, `arm64` | 354 | | `2.8-awshelm2.16` | master | **`2.8.x`** | `2.16.x` | `amd64`, `arm64` | 355 | 356 | 357 | ## :new: Point in time releases 358 | 359 | The following Docker image tags are built once and can be used for reproducible builds. Its version never changes so you will have to update tags in your pipelines from time to time in order to stay up-to-date. 360 | 361 | [![build](https://github.com/cytopia/docker-ansible/actions/workflows/action_branch.yml/badge.svg)](https://github.com/cytopia/docker-ansible/actions/workflows/action_branch.yml) 362 | 363 | | Docker Tag | Git Ref | Available Architectures | 364 | |--------------------------|--------------|------------------------------------| 365 | | **`-`** | git: `` | `amd64`, `arm64` | 366 | 367 | > * Where `` refers to any of the tags listed in Rolling releases above. 368 | > * Where `` refers to the chosen git tag from this repository. 369 | 370 | 371 | ## :capital_abcd: Docker environment variables 372 | 373 | Environment variables are available for all flavours except for `Ansible base`. 374 | 375 | | Variable | Default | Allowed values | Description | 376 | |-----------------|---------|----------------|-------------| 377 | | `USER` | `` | `ansible` | Set this to `ansible` to have everything run inside the container by the user `ansible` instead of `root` | 378 | | `UID` | `1000` | integer | If your local uid is not `1000` set it to your uid to syncronize file/dir permissions during mounting | 379 | | `GID` | `1000` | integer | If your local gid is not `1000` set it to your gid to syncronize file/dir permissions during mounting | 380 | | `INIT_GPG_KEY` | `` | string | If your gpg key requires a password you can initialize it during startup and cache the password (requires `INIT_GPG_PASS` as well) | 381 | | `INIT_GPG_PASS` | `` | string | If your gpg key requires a password you can initialize it during startup and cache the password (requires `INIT_GPG_KEY` as well) | 382 | | `INIT_GPG_CMD` | `` | string | A custom command which will initialize the GPG key password. This allows for interactive mode to enter your password manually during startup. (Mutually exclusive to `INIT_GPG_KEY` and `INIT_GPG_PASS`) | 383 | 384 | 385 | ## :open_file_folder: Docker mounts 386 | 387 | The working directory inside the Docker container is **`/data/`** and should be mounted locally to 388 | the root of your project where your Ansible playbooks are. 389 | 390 | 391 | ## :information_source: Examples 392 | 393 | ### Run Ansible playbook 394 | ```bash 395 | docker run --rm -v $(pwd):/data cytopia/ansible ansible-playbook playbook.yml 396 | ``` 397 | 398 | ### Run Ansible playbook with Mitogen 399 | 400 | > [Mitogen](https://github.com/dw/mitogen) updates Ansible’s slow and wasteful shell-centric implementation with pure-Python equivalents, invoked via highly efficient remote procedure calls to persistent interpreters tunnelled over SSH. 401 | 402 | > No changes are required to target hosts. The extension is considered stable and real-world use is encouraged. 403 | 404 | **Configuration (option 1)** 405 | 406 | `ansible.cfg` 407 | ```ini 408 | [defaults] 409 | strategy_plugins = /usr/lib/python3.10/site-packages/ansible_mitogen/plugins/strategy 410 | strategy = mitogen_linear 411 | ``` 412 | 413 | **Configuratoin (option 2)** 414 | ```bash 415 | # Instead of hardcoding it via ansible.cfg, you could also add the 416 | # option on-the-fly via environment variables. 417 | export ANSIBLE_STRATEGY_PLUGINS=/usr/lib/python3.10/site-packages/ansible_mitogen/plugins/strategy 418 | export ANSIBLE_STRATEGY=mitogen_linear 419 | ``` 420 | 421 | **Invocation** 422 | 423 | ```bash 424 | docker run --rm -v $(pwd):/data cytopia/ansible:latest-tools ansible-playbook playbook.yml 425 | ``` 426 | 427 | **Further readings:** 428 | 429 | * [Mitogen on GitHub](https://github.com/dw/mitogen) 430 | * [Mitogen Documentation](https://networkgenomics.com/ansible/) 431 | * [How to Speed Up Your Ansible Playbooks Over 600%](https://www.toptechskills.com/ansible-tutorials-courses/speed-up-ansible-playbooks-pipelining-mitogen/) 432 | * [Speed up Ansible with Mitogen](https://dev.to/sshnaidm/speed-up-ansible-with-mitogen-2c3j) 433 | 434 | 435 | ### Run Ansible playbook with non-root user 436 | ```bash 437 | # Use 'ansible' user inside Docker container 438 | docker run --rm \ 439 | -e USER=ansible \ 440 | -v $(pwd):/data \ 441 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 442 | ``` 443 | ```bash 444 | # Use 'ansible' user inside Docker container 445 | # Use custom uid/gid for 'ansible' user inside Docker container 446 | docker run --rm \ 447 | -e USER=ansible \ 448 | -e MY_UID=1000 \ 449 | -e MY_GID=1000 \ 450 | -v $(pwd):/data \ 451 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 452 | ``` 453 | 454 | ### Run Ansible playbook with local ssh keys mounted 455 | ```bash 456 | # Ensure to set same uid/gid as on your local system for Docker user 457 | # to prevent permission issues during docker mounts 458 | docker run --rm \ 459 | -e USER=ansible \ 460 | -e MY_UID=1000 \ 461 | -e MY_GID=1000 \ 462 | -v ${HOME}/.ssh/:/home/ansible/.ssh/ \ 463 | -v ${SSH_AUTH_SOCK}:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent \ 464 | -v $(pwd):/data \ 465 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 466 | ``` 467 | 468 | ### Run Ansible playbook with local password-less gpg keys mounted 469 | ```bash 470 | # Ensure to set same uid/gid as on your local system for Docker user 471 | # to prevent permission issues during docker mounts 472 | docker run --rm \ 473 | -e USER=ansible \ 474 | -e MY_UID=1000 \ 475 | -e MY_GID=1000 \ 476 | -v ${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 477 | -v $(pwd):/data \ 478 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 479 | ``` 480 | 481 | ### Run Ansible playbook with local gpg keys mounted and automatically initialized 482 | This is required in case your GPG key itself is encrypted with a password. 483 | Note that the password needs to be in *single quotes*. 484 | ```bash 485 | # Ensure to set same uid/gid as on your local system for Docker user 486 | # to prevent permission issues during docker mounts 487 | docker run --rm \ 488 | -e USER=ansible \ 489 | -e MY_UID=1000 \ 490 | -e MY_GID=1000 \ 491 | -e INIT_GPG_KEY=user@domain.tld \ 492 | -e INIT_GPG_PASS='my gpg password' \ 493 | -v ${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 494 | -v $(pwd):/data \ 495 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 496 | ``` 497 | Alternatively you can also export your GPG key and password to the shell's environment: 498 | ```bash 499 | # Ensure to write the password in single quotes 500 | export MY_GPG_KEY='user@domain.tld' 501 | export MY_GPG_PASS='my gpg password' 502 | ``` 503 | ```bash 504 | # Ensure to set same uid/gid as on your local system for Docker user 505 | # to prevent permission issues during docker mounts 506 | docker run --rm \ 507 | -e USER=ansible \ 508 | -e MY_UID=1000 \ 509 | -e MY_GID=1000 \ 510 | -e INIT_GPG_KEY=${MY_GPG_KEY} \ 511 | -e INIT_GPG_PASS=${MY_GPG_PASS} \ 512 | -v ${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 513 | -v $(pwd):/data \ 514 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 515 | ``` 516 | 517 | ### Run Ansible playbook with local gpg keys mounted and interactively interactively 518 | The following will work with password-less and password-set GPG keys. 519 | In case it requires a password, it will ask for the password and you need to enter it. 520 | ```bash 521 | # Ensure to set same uid/gid as on your local system for Docker user 522 | # to prevent permission issues during docker mounts 523 | docker run --rm \ 524 | -e USER=ansible \ 525 | -e MY_UID=1000 \ 526 | -e MY_GID=1000 \ 527 | -e INIT_GPG_CMD='echo test | gpg --encrypt -r user@domain.tld | gpg --decrypt --pinentry-mode loopback' \ 528 | -v ${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 529 | -v $(pwd):/data \ 530 | cytopia/ansible:latest-tools ansible-playbook playbook.yml 531 | ``` 532 | 533 | ### Run Ansible Galaxy 534 | ```bash 535 | # Ensure to set same uid/gid as on your local system for Docker user 536 | # to prevent permission issues during docker mounts 537 | docker run --rm \ 538 | -e USER=ansible \ 539 | -e MY_UID=1000 \ 540 | -e MY_GID=1000 \ 541 | -v $(pwd):/data \ 542 | cytopia/ansible:latest-tools ansible-galaxy install -r requirements.yml 543 | ``` 544 | 545 | ### Run Ansible playbook with AWS credentials 546 | ```bash 547 | # Basic 548 | docker run --rm \ 549 | -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ 550 | -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ 551 | -v $(pwd):/data \ 552 | cytopia/ansible:latest-aws ansible-playbook playbook.yml 553 | ``` 554 | ```bash 555 | # With AWS Session Token 556 | docker run --rm \ 557 | -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ 558 | -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ 559 | -e AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN \ 560 | -v $(pwd):/data \ 561 | cytopia/ansible:latest-aws ansible-playbook playbook.yml 562 | ``` 563 | ```bash 564 | # With ~/.aws/ config and credentials directories mounted (read/only) 565 | # If you want to make explicit use of aws profiles, use this variant 566 | # Ensure to set same uid/gid as on your local system for Docker user 567 | # to prevent permission issues during docker mounts 568 | docker run --rm \ 569 | -e USER=ansible \ 570 | -e MY_UID=1000 \ 571 | -e MY_GID=1000 \ 572 | -v ${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 573 | -v ${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 574 | -v $(pwd):/data \ 575 | cytopia/ansible:latest-aws ansible-playbook playbook.yml 576 | ``` 577 | 578 | ### Run Ansible playbook against AWS with gpg vault initialization 579 | ```bash 580 | # Ensure to set same uid/gid as on your local system for Docker user 581 | # to prevent permission issues during docker mounts 582 | docker run --rm \ 583 | -e USER=ansible \ 584 | -e MY_UID=1000 \ 585 | -e MY_GID=1000 \ 586 | -e INIT_GPG_KEY=user@domain.tld \ 587 | -e INIT_GPG_PASS='my gpg password' \ 588 | -v ${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 589 | -v ${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 590 | -v ${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 591 | -v $(pwd):/data \ 592 | cytopia/ansible:latest-aws \ 593 | ansible-playbook playbook.yml 594 | ``` 595 | As the command is getting pretty long, you could wrap it into a Makefile. 596 | ```make 597 | ifneq (,) 598 | .error This Makefile requires GNU Make. 599 | endif 600 | 601 | .PHONY: dry run 602 | 603 | CURRENT_DIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 604 | ANSIBLE = 2.8 605 | UID = 1000 606 | GID = 1000 607 | 608 | # Ansible check mode uses mitogen_linear strategy for much faster roll-outs 609 | dry: 610 | ifndef GPG_PASS 611 | docker run --rm -it \ 612 | -e ANSIBLE_STRATEGY_PLUGINS=/usr/lib/python3.10/site-packages/ansible_mitogen/plugins/strategy \ 613 | -e ANSIBLE_STRATEGY=mitogen_linear \ 614 | -e USER=ansible \ 615 | -e MY_UID=$(UID) \ 616 | -e MY_GID=$(GID) \ 617 | -v $${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 618 | -v $${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 619 | -v $${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 620 | -v $(CURRENT_DIR):/data \ 621 | cytopia/ansible:$(ANSIBLE)-aws \ 622 | ansible-playbook playbook.yml --check 623 | else 624 | docker run --rm -it \ 625 | -e ANSIBLE_STRATEGY_PLUGINS=/usr/lib/python3.10/site-packages/ansible_mitogen/plugins/strategy \ 626 | -e ANSIBLE_STRATEGY=mitogen_linear \ 627 | -e USER=ansible \ 628 | -e MY_UID=$(UID) \ 629 | -e MY_GID=$(GID) \ 630 | -e INIT_GPG_KEY=$${GPG_KEY} \ 631 | -e INIT_GPG_PASS=$${GPG_PASS} \ 632 | -v $${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 633 | -v $${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 634 | -v $${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 635 | -v $(CURRENT_DIR):/data \ 636 | cytopia/ansible:$(ANSIBLE)-aws \ 637 | ansible-playbook playbook.yml --check 638 | endif 639 | 640 | # Ansible real run uses default strategy 641 | run: 642 | ifndef GPG_PASS 643 | docker run --rm -it \ 644 | -e USER=ansible \ 645 | -e MY_UID=$(UID) \ 646 | -e MY_GID=$(GID) \ 647 | -v $${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 648 | -v $${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 649 | -v $${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 650 | -v $(CURRENT_DIR):/data \ 651 | cytopia/ansible:$(ANSIBLE)-aws ansible-playbook playbook.yml 652 | else 653 | docker run --rm -it \ 654 | -e USER=ansible \ 655 | -e MY_UID=$(UID) \ 656 | -e MY_GID=$(GID) \ 657 | -e INIT_GPG_KEY=$${GPG_KEY} \ 658 | -e INIT_GPG_PASS=$${GPG_PASS} \ 659 | -v $${HOME}/.aws/config:/home/ansible/.aws/config:ro \ 660 | -v $${HOME}/.aws/credentials:/home/ansible/.aws/credentials:ro \ 661 | -v $${HOME}/.gnupg/:/home/ansible/.gnupg/ \ 662 | -v $(CURRENT_DIR):/data \ 663 | cytopia/ansible:$(ANSIBLE)-aws \ 664 | ansible-playbook playbook.yml 665 | endif 666 | ``` 667 | **Important:** 668 | 669 | THE `GPG_KEY` and `GPG_PASS` will not be echo'ed out by the Make command and you are advised to 670 | export those values via your shell's `export` command to the env in order to hide it. 671 | 672 | If you still want to specify them on the command line via `make dry GPG_KEY='pass'` 673 | and your pass or key contains one or more `$` characters 674 | then they must all be escaped with an additional `$` in front. This is not necessary if you export 675 | them. 676 | 677 | **Example:** If your password is `test$5`, then you must use `make dry GPG_PASS='test$$5'`. 678 | 679 | 680 | Then you can call it easily: 681 | ```bash 682 | # With GPG password from the env 683 | export GPG_KEY='user@domain.tld' 684 | export GPG_PASS='THE_GPG_PASSWORD_HERE' 685 | make dry 686 | make run 687 | 688 | # With GPG password on the cli 689 | make dry GPG_KEY='user@domain.tld' GPG_PASS='THE_GPG_PASSWORD_HERE' 690 | make run GPG_KEY='user@domain.tld' GPG_PASS='THE_GPG_PASSWORD_HERE' 691 | 692 | # Without GPG password 693 | make dry 694 | make run 695 | 696 | # With different Ansible version 697 | make dry ANSIBLE=2.6 698 | make run ANSIBLE=2.6 699 | 700 | # With different uid/gid 701 | make dry UID=1001 GID=1001 702 | make run UID=1001 GID=1001 703 | ``` 704 | 705 | 706 | ## :computer: Build locally 707 | 708 | To build locally you require GNU Make to be installed. Instructions as shown below. 709 | 710 | ### amd64 vs arm64 711 | If you want to build the Ansible image for a different platform, use the `ARCH` make variable as shown below. This also applies to all other examples below. 712 | ```bash 713 | # Build amd64 images (default) 714 | make build 715 | make build ARCH=linux/amd64 716 | 717 | # Build arm64 images 718 | make build ARCH=linux/arm64 719 | ``` 720 | 721 | ### Ansible base 722 | ```bash 723 | # Build latest Ansible base 724 | # image: cytopia/ansible:latest 725 | make build 726 | 727 | # Build Ansible 2.6 base 728 | # image: cytopia/ansible:2.6 729 | make build VERSION=2.6 730 | ``` 731 | ### Ansible tools 732 | ```bash 733 | # Build latest Ansible tools 734 | # image: cytopia/ansible:latest-tools 735 | make build VERSION=latest STAGE=tools 736 | 737 | # Build Ansible 2.6 tools 738 | # image: cytopia/ansible:2.6-tools 739 | make build VERSION=2.6 STAGE=tools 740 | ``` 741 | 742 | ### Ansible infra 743 | ```bash 744 | # Build latest Ansible infra 745 | # image: cytopia/ansible:latest-infra 746 | make build VERSION=latest STAGE=infra 747 | 748 | # Build Ansible 2.6 infra 749 | # image: cytopia/ansible:2.6-infra 750 | make build VERSION=2.6 STAGE=infra 751 | ``` 752 | 753 | ### Ansible azure 754 | ```bash 755 | # Build latest Ansible azure 756 | # image: cytopia/ansible:latest-azure 757 | make build VERSION=latest STAGE=azure 758 | 759 | # Build Ansible 2.6 azure 760 | # image: cytopia/ansible:2.6-azure 761 | make build VERSION=2.6 STAGE=azure 762 | ``` 763 | 764 | ### Ansible aws 765 | ```bash 766 | # Build latest Ansible aws 767 | # image: cytopia/ansible:latest-aws 768 | make build VERSION=latest STAGE=aws 769 | 770 | # Build Ansible 2.6 aws 771 | # image: cytopia/ansible:2.6-aws 772 | make build VERSION=2.6 STAGE=aws 773 | ``` 774 | 775 | ### Ansible awsk8s 776 | ```bash 777 | # Build latest Ansible awsk8s 778 | # image: cytopia/ansible:latest-awsk8s 779 | make build VERSION=latest STAGE=awsk8s 780 | 781 | # Build Ansible 2.6 awsk8s 782 | # image: cytopia/ansible:2.6-awsk8s 783 | make build VERSION=2.6 STAGE=awsk8s 784 | ``` 785 | 786 | ### Ansible awskops 787 | ```bash 788 | # Build latest Ansible with Kops 1.8 789 | # image: cytopia/ansible:latest-awskops1.8 790 | make build VERSION=latest STAGE=awskops KOPS=1.8 791 | 792 | # Build Ansible 2.6 with Kops 1.8 793 | # image: cytopia/ansible:2.6-awskops1.8 794 | make build VERSION=2.6 STAGE=awskops KOPS=1.8 795 | ``` 796 | 797 | ### Ansible awshelm 798 | ```bash 799 | # Build latest Ansible with Helm 2.14 800 | # image: cytopia/ansible:latest-awshelm2.14 801 | make build VERSION=latest STAGE=awshelm HELM=2.14 802 | ``` 803 | 804 | 805 | ## :arrows_counterclockwise: Related [#awesome-ci](https://github.com/topics/awesome-ci) projects 806 | 807 | ### Docker images 808 | 809 | Save yourself from installing lot's of dependencies and pick a dockerized version of your favourite 810 | linter below for reproducible local or remote CI tests: 811 | 812 | | GitHub | DockerHub | Type | Description | 813 | |--------|-----------|------|-------------| 814 | | [awesome-ci][aci-git-lnk] | [![aci-hub-img]][aci-hub-lnk] | Basic | Tools for git, file and static source code analysis | 815 | | [file-lint][flint-git-lnk] | [![flint-hub-img]][flint-hub-lnk] | Basic | Baisc source code analysis | 816 | | [linkcheck][linkcheck-git-lnk] | [![linkcheck-hub-img]][flint-hub-lnk] | Basic | Search for URLs in files and validate their HTTP status code | 817 | | [ansible][ansible-git-lnk] | [![ansible-hub-img]][ansible-hub-lnk] | Ansible | Multiple versions and flavours of Ansible | 818 | | [ansible-lint][alint-git-lnk] | [![alint-hub-img]][alint-hub-lnk] | Ansible | Lint Ansible | 819 | | [gofmt][gfmt-git-lnk] | [![gfmt-hub-img]][gfmt-hub-lnk] | Go | Format Go source code **[1]** | 820 | | [goimports][gimp-git-lnk] | [![gimp-hub-img]][gimp-hub-lnk] | Go | Format Go source code **[1]** | 821 | | [golint][glint-git-lnk] | [![glint-hub-img]][glint-hub-lnk] | Go | Lint Go code | 822 | | [eslint][elint-git-lnk] | [![elint-hub-img]][elint-hub-lnk] | Javascript | Lint Javascript code | 823 | | [jsonlint][jlint-git-lnk] | [![jlint-hub-img]][jlint-hub-lnk] | JSON | Lint JSON files **[1]** | 824 | | [kubeval][kubeval-git-lnk] | [![kubeval-hub-img]][kubeval-hub-lnk] | K8s | Lint Kubernetes files | 825 | | [checkmake][cm-git-lnk] | [![cm-hub-img]][cm-hub-lnk] | Make | Lint Makefiles | 826 | | [phpcbf][pcbf-git-lnk] | [![pcbf-hub-img]][pcbf-hub-lnk] | PHP | PHP Code Beautifier and Fixer | 827 | | [phpcs][pcs-git-lnk] | [![pcs-hub-img]][pcs-hub-lnk] | PHP | PHP Code Sniffer | 828 | | [phplint][plint-git-lnk] | [![plint-hub-img]][plint-hub-lnk] | PHP | PHP Code Linter **[1]** | 829 | | [php-cs-fixer][pcsf-git-lnk] | [![pcsf-hub-img]][pcsf-hub-lnk] | PHP | PHP Coding Standards Fixer | 830 | | [bandit][bandit-git-lnk] | [![bandit-hub-img]][bandit-hub-lnk] | Python | A security linter from PyCQA 831 | | [black][black-git-lnk] | [![black-hub-img]][black-hub-lnk] | Python | The uncompromising Python code formatter | 832 | | [mypy][mypy-git-lnk] | [![mypy-hub-img]][mypy-hub-lnk] | Python | Static source code analysis | 833 | | [pycodestyle][pycs-git-lnk] | [![pycs-hub-img]][pycs-hub-lnk] | Python | Python style guide checker | 834 | | [pydocstyle][pyds-git-lnk] | [![pyds-hub-img]][pyds-hub-lnk] | Python | Python docstyle checker | 835 | | [pylint][pylint-git-lnk] | [![pylint-hub-img]][pylint-hub-lnk] | Python | Python source code, bug and quality checker | 836 | | [terraform-docs][tfdocs-git-lnk] | [![tfdocs-hub-img]][tfdocs-hub-lnk] | Terraform | Terraform doc generator (TF 0.12 ready) **[1]** | 837 | | [terragrunt][tg-git-lnk] | [![tg-hub-img]][tg-hub-lnk] | Terraform | Terragrunt and Terraform | 838 | | [terragrunt-fmt][tgfmt-git-lnk] | [![tgfmt-hub-img]][tgfmt-hub-lnk] | Terraform | `terraform fmt` for Terragrunt files **[1]** | 839 | | [yamlfmt][yfmt-git-lnk] | [![yfmt-hub-img]][yfmt-hub-lnk] | Yaml | Format Yaml files **[1]** | 840 | | [yamllint][ylint-git-lnk] | [![ylint-hub-img]][ylint-hub-lnk] | Yaml | Lint Yaml files | 841 | 842 | > **[1]** Uses a shell wrapper to add **enhanced functionality** not available by original project. 843 | 844 | [aci-git-lnk]: https://github.com/cytopia/awesome-ci 845 | [aci-hub-img]: https://img.shields.io/docker/pulls/cytopia/awesome-ci.svg 846 | [aci-hub-lnk]: https://hub.docker.com/r/cytopia/awesome-ci 847 | 848 | [flint-git-lnk]: https://github.com/cytopia/docker-file-lint 849 | [flint-hub-img]: https://img.shields.io/docker/pulls/cytopia/file-lint.svg 850 | [flint-hub-lnk]: https://hub.docker.com/r/cytopia/file-lint 851 | 852 | [linkcheck-git-lnk]: https://github.com/cytopia/docker-linkcheck 853 | [linkcheck-hub-img]: https://img.shields.io/docker/pulls/cytopia/linkcheck.svg 854 | [linkcheck-hub-lnk]: https://hub.docker.com/r/cytopia/linkcheck 855 | 856 | [jlint-git-lnk]: https://github.com/cytopia/docker-jsonlint 857 | [jlint-hub-img]: https://img.shields.io/docker/pulls/cytopia/jsonlint.svg 858 | [jlint-hub-lnk]: https://hub.docker.com/r/cytopia/jsonlint 859 | 860 | [ansible-git-lnk]: https://github.com/cytopia/docker-ansible 861 | [ansible-hub-img]: https://img.shields.io/docker/pulls/cytopia/ansible.svg 862 | [ansible-hub-lnk]: https://hub.docker.com/r/cytopia/ansible 863 | 864 | [alint-git-lnk]: https://github.com/cytopia/docker-ansible-lint 865 | [alint-hub-img]: https://img.shields.io/docker/pulls/cytopia/ansible-lint.svg 866 | [alint-hub-lnk]: https://hub.docker.com/r/cytopia/ansible-lint 867 | 868 | [kubeval-git-lnk]: https://github.com/cytopia/docker-kubeval 869 | [kubeval-hub-img]: https://img.shields.io/docker/pulls/cytopia/kubeval.svg 870 | [kubeval-hub-lnk]: https://hub.docker.com/r/cytopia/kubeval 871 | 872 | [gfmt-git-lnk]: https://github.com/cytopia/docker-gofmt 873 | [gfmt-hub-img]: https://img.shields.io/docker/pulls/cytopia/gofmt.svg 874 | [gfmt-hub-lnk]: https://hub.docker.com/r/cytopia/gofmt 875 | 876 | [gimp-git-lnk]: https://github.com/cytopia/docker-goimports 877 | [gimp-hub-img]: https://img.shields.io/docker/pulls/cytopia/goimports.svg 878 | [gimp-hub-lnk]: https://hub.docker.com/r/cytopia/goimports 879 | 880 | [glint-git-lnk]: https://github.com/cytopia/docker-golint 881 | [glint-hub-img]: https://img.shields.io/docker/pulls/cytopia/golint.svg 882 | [glint-hub-lnk]: https://hub.docker.com/r/cytopia/golint 883 | 884 | [elint-git-lnk]: https://github.com/cytopia/docker-eslint 885 | [elint-hub-img]: https://img.shields.io/docker/pulls/cytopia/eslint.svg 886 | [elint-hub-lnk]: https://hub.docker.com/r/cytopia/eslint 887 | 888 | [cm-git-lnk]: https://github.com/cytopia/docker-checkmake 889 | [cm-hub-img]: https://img.shields.io/docker/pulls/cytopia/checkmake.svg 890 | [cm-hub-lnk]: https://hub.docker.com/r/cytopia/checkmake 891 | 892 | [pcbf-git-lnk]: https://github.com/cytopia/docker-phpcbf 893 | [pcbf-hub-img]: https://img.shields.io/docker/pulls/cytopia/phpcbf.svg 894 | [pcbf-hub-lnk]: https://hub.docker.com/r/cytopia/phpcbf 895 | 896 | [pcs-git-lnk]: https://github.com/cytopia/docker-phpcs 897 | [pcs-hub-img]: https://img.shields.io/docker/pulls/cytopia/phpcs.svg 898 | [pcs-hub-lnk]: https://hub.docker.com/r/cytopia/phpcs 899 | 900 | [plint-git-lnk]: https://github.com/cytopia/docker-phplint 901 | [plint-hub-img]: https://img.shields.io/docker/pulls/cytopia/phplint.svg 902 | [plint-hub-lnk]: https://hub.docker.com/r/cytopia/phplint 903 | 904 | [pcsf-git-lnk]: https://github.com/cytopia/docker-php-cs-fixer 905 | [pcsf-hub-img]: https://img.shields.io/docker/pulls/cytopia/php-cs-fixer.svg 906 | [pcsf-hub-lnk]: https://hub.docker.com/r/cytopia/php-cs-fixer 907 | 908 | [bandit-git-lnk]: https://github.com/cytopia/docker-bandit 909 | [bandit-hub-img]: https://img.shields.io/docker/pulls/cytopia/bandit.svg 910 | [bandit-hub-lnk]: https://hub.docker.com/r/cytopia/bandit 911 | 912 | [black-git-lnk]: https://github.com/cytopia/docker-black 913 | [black-hub-img]: https://img.shields.io/docker/pulls/cytopia/black.svg 914 | [black-hub-lnk]: https://hub.docker.com/r/cytopia/black 915 | 916 | [mypy-git-lnk]: https://github.com/cytopia/docker-mypy 917 | [mypy-hub-img]: https://img.shields.io/docker/pulls/cytopia/mypy.svg 918 | [mypy-hub-lnk]: https://hub.docker.com/r/cytopia/mypy 919 | 920 | [pycs-git-lnk]: https://github.com/cytopia/docker-pycodestyle 921 | [pycs-hub-img]: https://img.shields.io/docker/pulls/cytopia/pycodestyle.svg 922 | [pycs-hub-lnk]: https://hub.docker.com/r/cytopia/pycodestyle 923 | 924 | [pyds-git-lnk]: https://github.com/cytopia/docker-pydocstyle 925 | [pyds-hub-img]: https://img.shields.io/docker/pulls/cytopia/pydocstyle.svg 926 | [pyds-hub-lnk]: https://hub.docker.com/r/cytopia/pydocstyle 927 | 928 | [pylint-git-lnk]: https://github.com/cytopia/docker-pylint 929 | [pylint-hub-img]: https://img.shields.io/docker/pulls/cytopia/pylint.svg 930 | [pylint-hub-lnk]: https://hub.docker.com/r/cytopia/pylint 931 | 932 | [tfdocs-git-lnk]: https://github.com/cytopia/docker-terraform-docs 933 | [tfdocs-hub-img]: https://img.shields.io/docker/pulls/cytopia/terraform-docs.svg 934 | [tfdocs-hub-lnk]: https://hub.docker.com/r/cytopia/terraform-docs 935 | 936 | [tg-git-lnk]: https://github.com/cytopia/docker-terragrunt 937 | [tg-hub-img]: https://img.shields.io/docker/pulls/cytopia/terragrunt.svg 938 | [tg-hub-lnk]: https://hub.docker.com/r/cytopia/terragrunt 939 | 940 | [tgfmt-git-lnk]: https://github.com/cytopia/docker-terragrunt-fmt 941 | [tgfmt-hub-img]: https://img.shields.io/docker/pulls/cytopia/terragrunt-fmt.svg 942 | [tgfmt-hub-lnk]: https://hub.docker.com/r/cytopia/terragrunt-fmt 943 | 944 | [yfmt-git-lnk]: https://github.com/cytopia/docker-yamlfmt 945 | [yfmt-hub-img]: https://img.shields.io/docker/pulls/cytopia/yamlfmt.svg 946 | [yfmt-hub-lnk]: https://hub.docker.com/r/cytopia/yamlfmt 947 | 948 | [ylint-git-lnk]: https://github.com/cytopia/docker-yamllint 949 | [ylint-hub-img]: https://img.shields.io/docker/pulls/cytopia/yamllint.svg 950 | [ylint-hub-lnk]: https://hub.docker.com/r/cytopia/yamllint 951 | 952 | 953 | ### Makefiles 954 | 955 | Visit **[cytopia/makefiles](https://github.com/cytopia/makefiles)** for dependency-less, seamless project integration and minimum required best-practice code linting for CI. 956 | The provided Makefiles will only require GNU Make and Docker itself removing the need to install anything else. 957 | 958 | 959 | ## :page_facing_up: License 960 | 961 | 962 | **[MIT License](LICENSE)** 963 | 964 | Copyright (c) 2019 [cytopia](https://github.com/cytopia) 965 | -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | [all] 2 | localhost 3 | -------------------------------------------------------------------------------- /tests/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | var1: value1 6 | var2: value2 7 | tasks: 8 | - name: Ensure message is printed 9 | debug: 10 | msg: Test 11 | - name: Ensure template is created 12 | template: 13 | src: "{{ playbook_dir }}/test.yml.j2" 14 | dest: "{{ playbook_dir }}/test.yml" 15 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | yaml: 3 | key1: value1 4 | key2: value2 5 | -------------------------------------------------------------------------------- /tests/test.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | yaml: 3 | key1: {{ var1 }} 4 | key2: {{ var2 }} 5 | --------------------------------------------------------------------------------