mirror of
https://github.com/ansible/awx-operator.git
synced 2026-03-27 05:43:11 +00:00
Compare commits
209 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7697825944 | ||
|
|
8a325293b1 | ||
|
|
dd53a1d415 | ||
|
|
c5db0e7104 | ||
|
|
59036fc373 | ||
|
|
c45a7bd4d7 | ||
|
|
34b6354001 | ||
|
|
801f392447 | ||
|
|
779572e8ff | ||
|
|
e7e48f92a0 | ||
|
|
3cd9ddd8c6 | ||
|
|
4e6be0a82c | ||
|
|
05943687fe | ||
|
|
9676ebc008 | ||
|
|
8352237260 | ||
|
|
35d4954027 | ||
|
|
4d6a491766 | ||
|
|
fa9eb53f92 | ||
|
|
00c9f5fbd1 | ||
|
|
fe82e9259e | ||
|
|
635d530dc9 | ||
|
|
e966e9299f | ||
|
|
683d23dbea | ||
|
|
8b3a297086 | ||
|
|
15830e3536 | ||
|
|
ef46d7f49c | ||
|
|
a5328b1a09 | ||
|
|
0983220fba | ||
|
|
3ac0232e89 | ||
|
|
75c7231afd | ||
|
|
363aa3642b | ||
|
|
bf74d5cc34 | ||
|
|
46586bd7b6 | ||
|
|
191be7bf3c | ||
|
|
b7e5f235ad | ||
|
|
6cbc6a7234 | ||
|
|
beba6a900d | ||
|
|
7f72260445 | ||
|
|
5b7baa106d | ||
|
|
9380686395 | ||
|
|
0de966153d | ||
|
|
efaa4718ec | ||
|
|
e6a473b765 | ||
|
|
859384e9f6 | ||
|
|
b66a16508f | ||
|
|
3da427f31d | ||
|
|
9f2b51a6a9 | ||
|
|
5b73ad172e | ||
|
|
2227301707 | ||
|
|
9f63fc0da5 | ||
|
|
322aea970d | ||
|
|
c4bef95662 | ||
|
|
fa705f6466 | ||
|
|
7fd5083c16 | ||
|
|
daf15a93bf | ||
|
|
dfa0f6d45e | ||
|
|
21062f0708 | ||
|
|
5372771bac | ||
|
|
8df0969e6a | ||
|
|
5af7e7f4b9 | ||
|
|
d8f91d112e | ||
|
|
379552218d | ||
|
|
1686875321 | ||
|
|
1b41d945e6 | ||
|
|
5e81729bc9 | ||
|
|
575e594314 | ||
|
|
5f76d4917e | ||
|
|
94c5c41a24 | ||
|
|
ee84625107 | ||
|
|
add76c159b | ||
|
|
375031e1f8 | ||
|
|
ca6ab0a380 | ||
|
|
236bce6970 | ||
|
|
0a9e9722c5 | ||
|
|
58ac0cc369 | ||
|
|
c3ac2e2cde | ||
|
|
589a3751e1 | ||
|
|
12a58d71fb | ||
|
|
6b873b05ab | ||
|
|
5e97ff7c08 | ||
|
|
86c31a4317 | ||
|
|
487727b454 | ||
|
|
2f47b907fd | ||
|
|
dbaf64efa0 | ||
|
|
5375fec77d | ||
|
|
9980192d9e | ||
|
|
e2fc5f46c0 | ||
|
|
5b3be06e8d | ||
|
|
3c2405f304 | ||
|
|
192611eea8 | ||
|
|
9ca14cef93 | ||
|
|
fbc2d3475c | ||
|
|
58f30fb96c | ||
|
|
c81b78aad6 | ||
|
|
c02e05925e | ||
|
|
479c009716 | ||
|
|
7807bc516e | ||
|
|
3afcd7fd89 | ||
|
|
7002131dda | ||
|
|
877943cc27 | ||
|
|
b59a0c5b80 | ||
|
|
26b1eb6c87 | ||
|
|
39437da72b | ||
|
|
e1645a2f8d | ||
|
|
224dde769a | ||
|
|
536d7dc842 | ||
|
|
eac2328bd3 | ||
|
|
3be986c96c | ||
|
|
768bc2f857 | ||
|
|
f05faaaaa0 | ||
|
|
957566993b | ||
|
|
c95f3299b0 | ||
|
|
1a0e3cf410 | ||
|
|
9368b43614 | ||
|
|
108addc06e | ||
|
|
3a3260ffb7 | ||
|
|
960d1f8a32 | ||
|
|
4d8f84eb74 | ||
|
|
1320c9d175 | ||
|
|
fab71e054e | ||
|
|
3eede3c922 | ||
|
|
d27ce3c34d | ||
|
|
18d17f2485 | ||
|
|
47d3ef57f2 | ||
|
|
8f8336b25a | ||
|
|
4aeeb8db82 | ||
|
|
5b636bb8ea | ||
|
|
83939ec007 | ||
|
|
608478e249 | ||
|
|
cb9e44fd4f | ||
|
|
cbd7da9dcf | ||
|
|
0f07a475b5 | ||
|
|
a2222a9176 | ||
|
|
79152d2417 | ||
|
|
fdbe607189 | ||
|
|
4a43de5101 | ||
|
|
345738cba3 | ||
|
|
f4995afb39 | ||
|
|
35062157e0 | ||
|
|
3150d55af6 | ||
|
|
4c51ee28f5 | ||
|
|
fbd5803f10 | ||
|
|
8972cae1cc | ||
|
|
1d8b3d9b4c | ||
|
|
57aa585a2e | ||
|
|
752813c23e | ||
|
|
48ee59e80f | ||
|
|
78fc099c75 | ||
|
|
5b577603c8 | ||
|
|
e5cfac2ba0 | ||
|
|
5ca536313a | ||
|
|
eaaf55e7f0 | ||
|
|
5d934ff2b5 | ||
|
|
84ab70f779 | ||
|
|
d74b5baf45 | ||
|
|
246bd829ec | ||
|
|
c28e4729e6 | ||
|
|
da63fe4653 | ||
|
|
7e2d726b26 | ||
|
|
fd38c33f14 | ||
|
|
a16e05d2f6 | ||
|
|
1ad5c9e981 | ||
|
|
79ee798df7 | ||
|
|
c843194cbd | ||
|
|
d1d6785b7d | ||
|
|
138964f7ab | ||
|
|
b2479c8014 | ||
|
|
277b772c46 | ||
|
|
7d20335cff | ||
|
|
fc713e7b73 | ||
|
|
26856d528d | ||
|
|
7eb6d0e0f5 | ||
|
|
fd03731a72 | ||
|
|
b0824acc48 | ||
|
|
782f97c42c | ||
|
|
09088b5b18 | ||
|
|
29879f7064 | ||
|
|
b866d682ef | ||
|
|
8aee279634 | ||
|
|
071b67a814 | ||
|
|
894b0ffa5f | ||
|
|
670b1f7d40 | ||
|
|
7b59c36263 | ||
|
|
c8d4ae16bb | ||
|
|
2e74c63c9e | ||
|
|
706dc80f17 | ||
|
|
3d6094a5b0 | ||
|
|
37470a0943 | ||
|
|
b65ba92b08 | ||
|
|
7fd4d46f6e | ||
|
|
eaff6898a4 | ||
|
|
38c64a504d | ||
|
|
563bdd6360 | ||
|
|
9eb0e35861 | ||
|
|
21fe2646b4 | ||
|
|
ebbb87f9a6 | ||
|
|
ee2980b8bb | ||
|
|
2426956a0a | ||
|
|
391e0bb1b8 | ||
|
|
5e7fe9b05f | ||
|
|
685c5efc94 | ||
|
|
e3d5827951 | ||
|
|
ebb4e76e1c | ||
|
|
f62b66d4ae | ||
|
|
1f73e2ca32 | ||
|
|
48f990f4a1 | ||
|
|
b1dcf16fc8 | ||
|
|
f0c5d1b4e3 | ||
|
|
38ec4a3b00 |
3
.github/CODE_OF_CONDUCT.md
vendored
Normal file
3
.github/CODE_OF_CONDUCT.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Community Code of Conduct
|
||||
|
||||
Please see the official [Ansible Community Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
|
||||
39
.github/ISSUE_TEMPLATE/bug_report.md
vendored
39
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
##### ISSUE TYPE
|
||||
- Bug Report
|
||||
|
||||
##### SUMMARY
|
||||
<!-- Briefly describe the problem. -->
|
||||
|
||||
##### ENVIRONMENT
|
||||
* AWX version: X.Y.Z
|
||||
* Operator version: X.Y.Z
|
||||
* Kubernetes version:
|
||||
* AWX install method: openshift, minishift, docker on linux, docker for mac, boot2docker
|
||||
|
||||
##### STEPS TO REPRODUCE
|
||||
|
||||
<!-- Please describe exactly how to reproduce the problem. -->
|
||||
|
||||
##### EXPECTED RESULTS
|
||||
|
||||
<!-- What did you expect to happen when running the steps above? -->
|
||||
|
||||
##### ACTUAL RESULTS
|
||||
|
||||
<!-- What actually happened? -->
|
||||
|
||||
##### ADDITIONAL INFORMATION
|
||||
|
||||
<!-- Include any links to sosreport, database dumps, screenshots or other
|
||||
information. -->
|
||||
|
||||
##### AWX-OPERATOR LOGS
|
||||
125
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
125
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
---
|
||||
name: Bug Report
|
||||
description: "🐞 Create a report to help us improve"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Bug Report issues are for **concrete, actionable bugs** only.
|
||||
For debugging help or technical support, please see the [Get Involved section of our README](https://github.com/ansible/awx-operator#get-involved)
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Please confirm the following
|
||||
options:
|
||||
- label: I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
|
||||
required: true
|
||||
- label: I have checked the [current issues](https://github.com/ansible/awx-operator/issues) for duplicates.
|
||||
required: true
|
||||
- label: I understand that the AWX Operator is open source software provided for free and that I might not receive a timely response.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Bug Summary
|
||||
description: Briefly describe the problem.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: awx-operator-version
|
||||
attributes:
|
||||
label: AWX Operator version
|
||||
description: What version of the AWX Operator are you running?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: awx-version
|
||||
attributes:
|
||||
label: AWX version
|
||||
description: What version of AWX are you running?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Kubernetes platform
|
||||
description: What platform did you install the Operator in?
|
||||
multiple: false
|
||||
options:
|
||||
- kubernetes
|
||||
- minikube
|
||||
- openshift
|
||||
- minishift
|
||||
- docker development environment
|
||||
- other (please specify in additional information)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: kube-version
|
||||
attributes:
|
||||
label: Kubernetes/Platform version
|
||||
description: What version of your platform/kuberneties are you using?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: modified-architecture
|
||||
attributes:
|
||||
label: Modifications
|
||||
description: >-
|
||||
Have you modified the installation, deployment topology, or container images in any way? If yes, please
|
||||
explain in the "additional information" field at the bottom of the form.
|
||||
multiple: false
|
||||
options:
|
||||
- "no"
|
||||
- "yes"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: >-
|
||||
Starting from a new installation of the system, describe exactly how a developer or quality engineer can reproduce the bug
|
||||
on infrastructure that isn't yours. Include any and all resources created, input values, test users, roles assigned, playbooks used, etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-results
|
||||
attributes:
|
||||
label: Expected results
|
||||
description: What did you expect to happpen when running the steps above?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual-results
|
||||
attributes:
|
||||
label: Actual results
|
||||
description: What actually happened?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Include any relevant log output, links to sosreport, database dumps, screenshots, AWX spec yaml, or other information.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: operator-logs
|
||||
attributes:
|
||||
label: Operator Logs
|
||||
description: Include any relevant logs generated by the operator.
|
||||
validations:
|
||||
required: false
|
||||
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: For debugging help or technical support
|
||||
url: https://github.com/ansible/awx-operator#get-involved
|
||||
about: For general debugging or technical support please see the Get Involved section of our readme.
|
||||
- name: 📝 Ansible Code of Conduct
|
||||
url: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_template_chooser
|
||||
about: AWX uses the Ansible Code of Conduct; ❤ Be nice to other members of the community. ☮ Behave.
|
||||
- name: 💼 For Enterprise
|
||||
url: https://www.ansible.com/products/engine?utm_medium=github&utm_source=issue_template_chooser
|
||||
about: Red Hat offers support for the Ansible Automation Platform
|
||||
29
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
29
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: ✨ Feature request
|
||||
description: Suggest an idea for this project
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Feature Request issues are for **feature requests** only.
|
||||
For debugging help or technical support, please see the [Get Involved section of our README](https://github.com/ansible/awx-operator#get-involved)
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Please confirm the following
|
||||
options:
|
||||
- label: I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
|
||||
required: true
|
||||
- label: I have checked the [current issues](https://github.com/ansible/awx-operator/issues) for duplicates.
|
||||
required: true
|
||||
- label: I understand that AWX Operator is open source software provided for free and that I might not receive a timely response.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Feature Summary
|
||||
description: Briefly describe the desired enhancement.
|
||||
validations:
|
||||
required: true
|
||||
3
.github/issue_labeler.yml
vendored
Normal file
3
.github/issue_labeler.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
needs_triage:
|
||||
- '.*'
|
||||
29
.github/workflows/ci.yaml
vendored
29
.github/workflows/ci.yaml
vendored
@@ -10,9 +10,9 @@ on:
|
||||
branches: [devel]
|
||||
|
||||
jobs:
|
||||
pull_request:
|
||||
molecule:
|
||||
runs-on: ubuntu-18.04
|
||||
name: pull_request
|
||||
name: molecule
|
||||
env:
|
||||
DOCKER_API_VERSION: "1.38"
|
||||
steps:
|
||||
@@ -39,3 +39,28 @@ jobs:
|
||||
sudo rm -f $(which kustomize)
|
||||
make kustomize
|
||||
KUSTOMIZE_PATH=$(readlink -f bin/kustomize) molecule test -s kind
|
||||
helm:
|
||||
runs-on: ubuntu-18.04
|
||||
name: helm
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Create k8s Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
|
||||
- name: Build operator image and load into kind
|
||||
run: |
|
||||
IMG=awx-operator-ci make docker-build
|
||||
kind load docker-image --name chart-testing awx-operator-ci
|
||||
|
||||
- name: Patch pull policy for tests
|
||||
run: |
|
||||
kustomize edit add patch --path ../testing/pull_policy/Never.yaml
|
||||
working-directory: config/default
|
||||
|
||||
- name: Build and install helm chart
|
||||
run: |
|
||||
IMG=awx-operator-ci make helm-chart
|
||||
helm install --wait my-awx-operator --namespace awx --create-namespace ./charts/awx-operator
|
||||
|
||||
11
.github/workflows/devel.yaml
vendored
11
.github/workflows/devel.yaml
vendored
@@ -13,16 +13,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Operator-SDK
|
||||
run: |
|
||||
mkdir -p $GITHUB_WORKSPACE/bin
|
||||
wget -O $GITHUB_WORKSPACE/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v0.19.4/operator-sdk-v0.19.4-x86_64-linux-gnu
|
||||
chmod +x $GITHUB_WORKSPACE/bin/operator-sdk
|
||||
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Build Image
|
||||
run: |
|
||||
operator-sdk build awx-operator:devel
|
||||
IMG=awx-operator:devel make docker-build
|
||||
|
||||
- name: Push To Quay
|
||||
uses: redhat-actions/push-to-registry@v2.1.1
|
||||
@@ -30,5 +23,5 @@ jobs:
|
||||
image: awx-operator
|
||||
tags: devel
|
||||
registry: quay.io/ansible/
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
username: ${{ secrets.QUAY_USER }}
|
||||
password: ${{ secrets.QUAY_TOKEN }}
|
||||
|
||||
40
.github/workflows/promote.yaml
vendored
Normal file
40
.github/workflows/promote.yaml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Promote AWX Operator image
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
promote:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Log in to Quay
|
||||
run: |
|
||||
echo ${{ secrets.QUAY_TOKEN }} | docker login quay.io -u ${{ secrets.QUAY_USER }} --password-stdin
|
||||
|
||||
- name: Re-tag and promote awx-operator image
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker tag ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} quay.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker tag ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} quay.io/${{ github.repository }}:latest
|
||||
docker push quay.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker push quay.io/${{ github.repository }}:latest
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Release Helm chart
|
||||
run: |
|
||||
ansible-playbook ansible/helm-release.yml -v \
|
||||
-e operator_image=quay.io/${{ github.repository }} \
|
||||
-e chart_owner=${{ github.repository_owner }} \
|
||||
-e tag=${{ github.event.release.tag_name }} \
|
||||
-e gh_token=${{ secrets.GITHUB_TOKEN }}
|
||||
28
.github/workflows/release.yaml
vendored
28
.github/workflows/release.yaml
vendored
@@ -1,28 +0,0 @@
|
||||
---
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-18.04
|
||||
name: Push tagged image to Quay
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build Image
|
||||
run: |
|
||||
IMG=awx-operator:${{ github.event.release.tag_name }} make docker-build
|
||||
|
||||
- name: Push To Quay
|
||||
uses: redhat-actions/push-to-registry@v2.1.1
|
||||
with:
|
||||
image: awx-operator
|
||||
tags: ${{ github.event.release.tag_name }}
|
||||
registry: quay.io/ansible/
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_TOKEN }}
|
||||
85
.github/workflows/stage.yml
vendored
Normal file
85
.github/workflows/stage.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: Stage Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to stage'
|
||||
required: true
|
||||
default_awx_version:
|
||||
description: 'Will be injected as the DEFAULT_AWX_VERSION build arg.'
|
||||
required: true
|
||||
confirm:
|
||||
description: 'Are you sure? Set this to yes.'
|
||||
required: true
|
||||
default: 'no'
|
||||
|
||||
jobs:
|
||||
stage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: write
|
||||
steps:
|
||||
- name: Verify inputs
|
||||
run: |
|
||||
set -e
|
||||
|
||||
if [[ ${{ github.event.inputs.confirm }} != "yes" ]]; then
|
||||
>&2 echo "Confirm must be 'yes'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${{ github.event.inputs.version }} == "" ]]; then
|
||||
>&2 echo "Set version to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
- name: Checkout awx
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/awx
|
||||
path: awx
|
||||
|
||||
- name: Checkout awx-operator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/awx-operator
|
||||
path: awx-operator
|
||||
|
||||
- name: Install playbook dependencies
|
||||
run: |
|
||||
python3 -m pip install docker
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Build and stage awx-operator
|
||||
working-directory: awx-operator
|
||||
run: |
|
||||
BUILD_ARGS="--build-arg DEFAULT_AWX_VERSION=${{ github.event.inputs.default_awx_version }} \
|
||||
--build-arg OPERATOR_VERSION=${{ github.event.inputs.version }}" \
|
||||
IMAGE_TAG_BASE=ghcr.io/${{ github.repository_owner }}/awx-operator \
|
||||
VERSION=${{ github.event.inputs.version }} make docker-build docker-push
|
||||
|
||||
- name: Run test deployment
|
||||
working-directory: awx-operator
|
||||
run: |
|
||||
python3 -m pip install -r molecule/requirements.txt
|
||||
ansible-galaxy collection install -r molecule/requirements.yml
|
||||
sudo rm -f $(which kustomize)
|
||||
make kustomize
|
||||
KUSTOMIZE_PATH=$(readlink -f bin/kustomize) molecule test -s kind
|
||||
env:
|
||||
AWX_TEST_VERSION: ${{ github.event.inputs.default_awx_version }}
|
||||
|
||||
- name: Create draft release
|
||||
working-directory: awx
|
||||
run: |
|
||||
ansible-playbook tools/ansible/stage.yml \
|
||||
-e version=${{ github.event.inputs.version }} \
|
||||
-e repo=${{ github.repository_owner }}/awx-operator \
|
||||
-e github_token=${{ secrets.GITHUB_TOKEN }}
|
||||
22
.github/workflows/triage_new.yml
vendored
Normal file
22
.github/workflows/triage_new.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
name: Label
|
||||
|
||||
steps:
|
||||
- name: Label issues
|
||||
uses: github/issue-labeler@v2.4.1
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
not-before: 2021-12-07T07:00:00Z
|
||||
configuration-path: .github/issue_labeler.yml
|
||||
enable-versioned-regex: 0
|
||||
if: github.event_name == 'issues'
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
*~
|
||||
.cache/
|
||||
/bin
|
||||
/bundle
|
||||
/bundle_tmp*
|
||||
/bundle.Dockerfile
|
||||
/charts
|
||||
/.cr-release-packages
|
||||
|
||||
23
.helm/starter/.helmignore
Normal file
23
.helm/starter/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
7
.helm/starter/Chart.yaml
Normal file
7
.helm/starter/Chart.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.0
|
||||
description: A Helm chart for Kubernetes
|
||||
name: starter
|
||||
type: application
|
||||
version: 0.1.0
|
||||
0
.helm/starter/values.yaml
Normal file
0
.helm/starter/values.yaml
Normal file
@@ -2,7 +2,14 @@
|
||||
|
||||
This is a list of high-level changes for each release of `awx-operator`. A full list of commits can be found at `https://github.com/ansible/awx-operator/releases/tag/<version>`.
|
||||
|
||||
# 0.14.0 (TBA)
|
||||
# 0.19.0 (Mar 23, 2022)
|
||||
|
||||
- Fix corrupted spec for the service with nodeport type (kurokobo) - dbaf64e
|
||||
- Add ability to deploy with OLM & added logo (Christian Adams) - 86c31a4
|
||||
- Fix backup & restore issues with special characters in the postgres password (kurokobo) - 589a375
|
||||
- Use centos:stream8 container where applicable (Shane McDonald)- 12a58d7
|
||||
|
||||
# 0.14.0 (Oct 03, 2021)
|
||||
|
||||
- Starting with awx-operator 0.14.0, the project is now based on operator-sdk 1.x.
|
||||
- To avoid a headache, you probably want to delete your existing operator Deployment and follow the README.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
FROM quay.io/operator-framework/ansible-operator:v1.12.0
|
||||
|
||||
ARG DEFAULT_AWX_VERSION
|
||||
ARG OPERATOR_VERSION
|
||||
ENV DEFAULT_AWX_VERSION=${DEFAULT_AWX_VERSION}
|
||||
ENV OPERATOR_VERSION=${OPERATOR_VERSION}
|
||||
|
||||
COPY requirements.yml ${HOME}/requirements.yml
|
||||
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
|
||||
&& chmod -R ug+rwx ${HOME}/.ansible
|
||||
|
||||
172
Makefile
172
Makefile
@@ -3,7 +3,16 @@
|
||||
# To re-generate a bundle for another specific version without changing the standard setup, you can:
|
||||
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
|
||||
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
|
||||
VERSION ?= 0.14.0
|
||||
VERSION ?= $(shell git describe --tags)
|
||||
|
||||
CONTAINER_CMD ?= docker
|
||||
|
||||
# GNU vs BSD in-place sed
|
||||
ifeq ($(shell sed --version 2>/dev/null | grep -q GNU && echo gnu),gnu)
|
||||
SED_I := sed -i
|
||||
else
|
||||
SED_I := sed -i ''
|
||||
endif
|
||||
|
||||
# CHANNELS define the bundle channels used in the bundle.
|
||||
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
|
||||
@@ -39,6 +48,14 @@ BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
|
||||
IMG ?= $(IMAGE_TAG_BASE):$(VERSION)
|
||||
NAMESPACE ?= awx
|
||||
|
||||
# Helm variables
|
||||
CHART_NAME ?= awx-operator
|
||||
CHART_DESCRIPTION ?= A Helm chart for the AWX Operator
|
||||
CHART_OWNER ?= $(GH_REPO_OWNER)
|
||||
CHART_REPO ?= awx-operator
|
||||
CHART_BRANCH ?= gh-pages
|
||||
CHART_INDEX ?= index.yaml
|
||||
|
||||
all: docker-build
|
||||
|
||||
##@ General
|
||||
@@ -63,10 +80,10 @@ run: ansible-operator ## Run against the configured Kubernetes cluster in ~/.kub
|
||||
ANSIBLE_ROLES_PATH="$(ANSIBLE_ROLES_PATH):$(shell pwd)/roles" $(ANSIBLE_OPERATOR) run
|
||||
|
||||
docker-build: ## Build docker image with the manager.
|
||||
docker build -t ${IMG} .
|
||||
${CONTAINER_CMD} build $(BUILD_ARGS) -t ${IMG} .
|
||||
|
||||
docker-push: ## Push docker image with the manager.
|
||||
docker push ${IMG}
|
||||
${CONTAINER_CMD} push ${IMG}
|
||||
|
||||
##@ Deployment
|
||||
|
||||
@@ -76,16 +93,23 @@ install: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/con
|
||||
uninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.
|
||||
$(KUSTOMIZE) build config/crd | kubectl delete -f -
|
||||
|
||||
gen-resources: kustomize ## Generate resources for controller and print to stdout
|
||||
@cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||
@cd config/default && $(KUSTOMIZE) edit set namespace ${NAMESPACE}
|
||||
@$(KUSTOMIZE) build config/default
|
||||
|
||||
deploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
|
||||
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||
cd config/default && $(KUSTOMIZE) edit set namespace ${NAMESPACE}
|
||||
$(KUSTOMIZE) build config/default | kubectl apply -f -
|
||||
@cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||
@cd config/default && $(KUSTOMIZE) edit set namespace ${NAMESPACE}
|
||||
@$(KUSTOMIZE) build config/default | kubectl apply -f -
|
||||
|
||||
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
|
||||
@cd config/default && $(KUSTOMIZE) edit set namespace ${NAMESPACE}
|
||||
$(KUSTOMIZE) build config/default | kubectl delete -f -
|
||||
|
||||
OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH := $(shell uname -m | sed 's/x86_64/amd64/')
|
||||
ARCHA := $(shell uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
|
||||
ARCHX := $(shell uname -m | sed -e 's/amd64/x86_64/' -e 's/aarch64/arm64/')
|
||||
|
||||
.PHONY: kustomize
|
||||
KUSTOMIZE = $(shell pwd)/bin/kustomize
|
||||
@@ -95,7 +119,7 @@ ifeq (,$(shell which kustomize 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(KUSTOMIZE)) ;\
|
||||
curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.8.7/kustomize_v3.8.7_$(OS)_$(ARCH).tar.gz | \
|
||||
curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v4.5.2/kustomize_v4.5.2_$(OS)_$(ARCHA).tar.gz | \
|
||||
tar xzf - -C bin/ ;\
|
||||
}
|
||||
else
|
||||
@@ -111,7 +135,7 @@ ifeq (,$(shell which ansible-operator 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\
|
||||
curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.12.0/ansible-operator_$(OS)_$(ARCH) ;\
|
||||
curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.12.0/ansible-operator_$(OS)_$(ARCHA) ;\
|
||||
chmod +x $(ANSIBLE_OPERATOR) ;\
|
||||
}
|
||||
else
|
||||
@@ -128,7 +152,7 @@ bundle: kustomize ## Generate bundle manifests and metadata, then validate gener
|
||||
|
||||
.PHONY: bundle-build
|
||||
bundle-build: ## Build the bundle image.
|
||||
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
|
||||
${CONTAINER_CMD} build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
|
||||
|
||||
.PHONY: bundle-push
|
||||
bundle-push: ## Push the bundle image.
|
||||
@@ -142,7 +166,7 @@ ifeq (,$(shell which opm 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(OPM)) ;\
|
||||
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCH)-opm ;\
|
||||
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCHA)-opm ;\
|
||||
chmod +x $(OPM) ;\
|
||||
}
|
||||
else
|
||||
@@ -167,9 +191,133 @@ endif
|
||||
# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator
|
||||
.PHONY: catalog-build
|
||||
catalog-build: opm ## Build a catalog image.
|
||||
$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
|
||||
$(OPM) index add --container-tool ${CONTAINER_CMD} --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
|
||||
|
||||
# Push the catalog image.
|
||||
.PHONY: catalog-push
|
||||
catalog-push: ## Push a catalog image.
|
||||
$(MAKE) docker-push IMG=$(CATALOG_IMG)
|
||||
|
||||
.PHONY: kubectl-slice
|
||||
KUBECTL_SLICE = $(shell pwd)/bin/kubectl-slice
|
||||
kubectl-slice: ## Download kubectl-slice locally if necessary.
|
||||
ifeq (,$(wildcard $(KUBECTL_SLICE)))
|
||||
ifeq (,$(shell which kubectl-slice 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(KUBECTL_SLICE)) ;\
|
||||
curl -sSLo - https://github.com/patrickdappollonio/kubectl-slice/releases/download/v1.1.0/kubectl-slice_1.1.0_$(OS)_$(ARCHX).tar.gz | \
|
||||
tar xzf - -C bin/ kubectl-slice ;\
|
||||
}
|
||||
else
|
||||
KUBECTL_SLICE = $(shell which kubectl-slice)
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: helm
|
||||
HELM = $(shell pwd)/bin/helm
|
||||
helm: ## Download helm locally if necessary.
|
||||
ifeq (,$(wildcard $(HELM)))
|
||||
ifeq (,$(shell which helm 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(HELM)) ;\
|
||||
curl -sSLo - https://get.helm.sh/helm-v3.8.0-$(OS)-$(ARCHA).tar.gz | \
|
||||
tar xzf - -C bin/ $(OS)-$(ARCHA)/helm ;\
|
||||
mv bin/$(OS)-$(ARCHA)/helm bin/helm ;\
|
||||
rmdir bin/$(OS)-$(ARCHA) ;\
|
||||
}
|
||||
else
|
||||
HELM = $(shell which helm)
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: yq
|
||||
YQ = $(shell pwd)/bin/yq
|
||||
yq: ## Download yq locally if necessary.
|
||||
ifeq (,$(wildcard $(YQ)))
|
||||
ifeq (,$(shell which yq 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(HELM)) ;\
|
||||
curl -sSLo - https://github.com/mikefarah/yq/releases/download/v4.20.2/yq_$(OS)_$(ARCHA).tar.gz | \
|
||||
tar xzf - -C bin/ ;\
|
||||
mv bin/yq_$(OS)_$(ARCHA) bin/yq ;\
|
||||
}
|
||||
else
|
||||
YQ = $(shell which yq)
|
||||
endif
|
||||
endif
|
||||
|
||||
PHONY: cr
|
||||
CR = $(shell pwd)/bin/cr
|
||||
cr: ## Download cr locally if necessary.
|
||||
ifeq (,$(wildcard $(CR)))
|
||||
ifeq (,$(shell which cr 2>/dev/null))
|
||||
@{ \
|
||||
set -e ;\
|
||||
mkdir -p $(dir $(CR)) ;\
|
||||
curl -sSLo - https://github.com/helm/chart-releaser/releases/download/v1.3.0/chart-releaser_1.3.0_$(OS)_$(ARCHA).tar.gz | \
|
||||
tar xzf - -C bin/ cr ;\
|
||||
}
|
||||
else
|
||||
CR = $(shell which cr)
|
||||
endif
|
||||
endif
|
||||
|
||||
charts:
|
||||
mkdir -p $@
|
||||
|
||||
.PHONY: helm-chart
|
||||
helm-chart: kustomize helm kubectl-slice yq charts
|
||||
@echo "== KUSTOMIZE (image and namespace) =="
|
||||
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||
|
||||
@echo "== HELM =="
|
||||
cd charts && \
|
||||
$(HELM) create awx-operator --starter $(shell pwd)/.helm/starter ;\
|
||||
$(YQ) -i '.version = "$(VERSION)"' $(CHART_NAME)/Chart.yaml ;\
|
||||
$(YQ) -i '.appVersion = "$(VERSION)" | .appVersion style="double"' $(CHART_NAME)/Chart.yaml ;\
|
||||
$(YQ) -i '.description = "$(CHART_DESCRIPTION)"' $(CHART_NAME)/Chart.yaml ;\
|
||||
|
||||
@cat charts/$(CHART_NAME)/Chart.yaml
|
||||
|
||||
@echo "== KUSTOMIZE (annotation) =="
|
||||
cd config/manager && $(KUSTOMIZE) edit set annotation helm.sh/chart:$(CHART_NAME)-$(VERSION)
|
||||
cd config/default && $(KUSTOMIZE) edit set annotation helm.sh/chart:$(CHART_NAME)-$(VERSION)
|
||||
|
||||
@echo "== SLICE =="
|
||||
$(KUSTOMIZE) build --load-restrictor LoadRestrictionsNone config/default | \
|
||||
$(KUBECTL_SLICE) --input-file=- \
|
||||
--output-dir=charts/$(CHART_NAME)/templates \
|
||||
--sort-by-kind
|
||||
@echo "Helm Chart $(VERSION)" > charts/$(CHART_NAME)/templates/NOTES.txt
|
||||
$(foreach file, $(wildcard charts/$(CHART_NAME)/templates/*),$(YQ) -i 'del(.. | select(has("namespace")).namespace)' $(file);)
|
||||
$(foreach file, $(wildcard charts/$(CHART_NAME)/templates/*rolebinding*),$(YQ) -i '.subjects[0].namespace = "{{ .Release.Namespace }}"' $(file);)
|
||||
rm -f charts/$(CHART_NAME)/templates/namespace*.yaml
|
||||
|
||||
|
||||
.PHONY: helm-package
|
||||
helm-package: cr helm-chart
|
||||
@echo "== CHART RELEASER (package) =="
|
||||
$(CR) package ./charts/awx-operator
|
||||
|
||||
# The actual release happens in ansible/helm-release.yml
|
||||
# until https://github.com/helm/chart-releaser/issues/122 happens
|
||||
.PHONY: helm-index
|
||||
helm-index: cr helm-chart
|
||||
@echo "== CHART RELEASER (httpsorigin) =="
|
||||
git remote add httpsorigin "https://github.com/$(CHART_OWNER)/$(CHART_REPO).git"
|
||||
git fetch httpsorigin
|
||||
|
||||
@echo "== CHART RELEASER (index) =="
|
||||
$(CR) index \
|
||||
--owner "$(CHART_OWNER)" \
|
||||
--git-repo "$(CHART_REPO)" \
|
||||
--token "$(CR_TOKEN)" \
|
||||
--pages-branch "$(CHART_BRANCH)" \
|
||||
--index-path "./charts/$(CHART_INDEX)" \
|
||||
--charts-repo "https://$(CHART_OWNER).github.io/$(CHART_REPO)/$(CHART_INDEX)" \
|
||||
--remote httpsorigin \
|
||||
--release-name-template="{{ .Version }}" \
|
||||
--push
|
||||
|
||||
635
README.md
635
README.md
@@ -1,17 +1,24 @@
|
||||
# AWX Operator
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0) [](https://github.com/ansible/awx-operator/actions)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://github.com/ansible/awx-operator/actions)
|
||||
[](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
|
||||
[](https://groups.google.com/g/awx-project)
|
||||
[](https://libera.chat)
|
||||
|
||||
An [Ansible AWX](https://github.com/ansible/awx) operator for Kubernetes built with [Operator SDK](https://github.com/operator-framework/operator-sdk) and Ansible.
|
||||
|
||||
# Table of Contents
|
||||
|
||||
<!-- Regenerate this table of contents using https://github.com/ekalinin/github-markdown-toc -->
|
||||
<!-- gh-md-toc --insert README.md -->
|
||||
<!--ts-->
|
||||
* [AWX Operator](#awx-operator)
|
||||
* [Table of Contents](#table-of-contents)
|
||||
* [Purpose](#purpose)
|
||||
* [Usage](#usage)
|
||||
* [Creating a minikube cluster for testing](#creating-a-minikube-cluster-for-testing)
|
||||
* [Basic Install](#basic-install)
|
||||
* [Helm Install on existing cluster](#helm-install-on-existing-cluster)
|
||||
* [Admin user account configuration](#admin-user-account-configuration)
|
||||
* [Network and TLS Configuration](#network-and-tls-configuration)
|
||||
* [Service Type](#service-type)
|
||||
@@ -22,37 +29,52 @@ An [Ansible AWX](https://github.com/ansible/awx) operator for Kubernetes built w
|
||||
* [Managed PostgreSQL Service](#managed-postgresql-service)
|
||||
* [Advanced Configuration](#advanced-configuration)
|
||||
* [Deploying a specific version of AWX](#deploying-a-specific-version-of-awx)
|
||||
* [Redis container capabilities](#redis-container-capabilities)
|
||||
* [Privileged Tasks](#privileged-tasks)
|
||||
* [Containers Resource Requirements](#containers-resource-requirements)
|
||||
* [Priority Classes](#priority-classes)
|
||||
* [Assigning AWX pods to specific nodes](#assigning-awx-pods-to-specific-nodes)
|
||||
* [Trusting a Custom Certificate Authority](#trusting-a-custom-certificate-authority)
|
||||
* [Enabling LDAP Integration at AWX bootstrap](#enabling-ldap-integration-at-awx-bootstrap)
|
||||
* [Persisting Projects Directory](#persisting-projects-directory)
|
||||
* [Custom Volume and Volume Mount Options](#custom-volume-and-volume-mount-options)
|
||||
* [Default execution environments from private registries](#default-execution-environments-from-private-registries)
|
||||
* [Control plane ee from private registry](#control-plane-ee-from-private-registry)
|
||||
* [Exporting Environment Variables to Containers](#exporting-environment-variables-to-containers)
|
||||
* [CSRF Cookie Secure Setting](#csrf-cookie-secure-setting)
|
||||
* [Session Cookie Secure Setting](#session-cookie-secure-setting)
|
||||
* [Extra Settings](#extra-settings)
|
||||
* [Configure no_log](#no-log)
|
||||
* [Auto Upgrade](#auto-upgrade)
|
||||
* [Upgrade of instances without auto upgrade](#upgrade-of-instances-without-auto-upgrade)
|
||||
* [Service Account](#service-account)
|
||||
* [Uninstall](#uninstall)
|
||||
* [Upgrading](#upgrading)
|
||||
* [Upgrading](#upgrading)
|
||||
* [v0.14.0](#v0140)
|
||||
* [Cluster-scope to Namespace-scope considerations](#cluster-scope-to-namespace-scope-considerations)
|
||||
* [Project is now based on v1.x of the operator-sdk project](#project-is-now-based-on-v1x-of-the-operator-sdk-project)
|
||||
* [Steps to upgrade](#steps-to-upgrade)
|
||||
* [Contributing](#contributing)
|
||||
* [Release Process](#release-process)
|
||||
* [Verifiy Functionality](#verify-functionality)
|
||||
* [Update Version](#update-version)
|
||||
* [Commit / Create Release](#commit--create-release)
|
||||
* [Author](#author)
|
||||
* [Code of Conduct](#code-of-conduct)
|
||||
* [Get Involved](#get-involved)
|
||||
|
||||
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
## Purpose
|
||||
|
||||
This operator is meant to provide a more Kubernetes-native installation method for AWX via an AWX Custom Resource Definition (CRD).
|
||||
|
||||
> :warning: The operator is not supported by Red Hat, and is in **alpha** status. For now, use it at your own risk!
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Install
|
||||
|
||||
This Kubernetes Operator is meant to be deployed in your Kubernetes cluster(s) and can manage one or more AWX instances in any namespace.
|
||||
|
||||
For testing purposes, the `awx-operator` can be deployed on a [Minikube](https://minikube.sigs.k8s.io/docs/) cluster. Due to different OS and hardware environments, please refer to the official Minikube documentation for further information.
|
||||
### Creating a minikube cluster for testing
|
||||
|
||||
If you do not have an existing cluster, the `awx-operator` can be deployed on a [Minikube](https://minikube.sigs.k8s.io/docs/) cluster for testing purposes. Due to different OS and hardware environments, please refer to the official Minikube documentation for further information.
|
||||
|
||||
```
|
||||
$ minikube start --cpus=4 --memory=6g --addons=ingress
|
||||
@@ -101,26 +123,47 @@ Let's create an alias for easier usage:
|
||||
$ alias kubectl="minikube kubectl --"
|
||||
```
|
||||
|
||||
Now you need to deploy AWX Operator into your cluster. Clone this repo and `git checkout` the latest version from https://github.com/ansible/awx-operator/releases, and then run the following command:
|
||||
### Basic Install
|
||||
|
||||
Once you have a running Kubernetes cluster, you can deploy AWX Operator into your cluster using [Kustomize](https://kubectl.docs.kubernetes.io/guides/introduction/kustomize/). Follow the instructions here to install the latest version of Kustomize: https://kubectl.docs.kubernetes.io/installation/kustomize/
|
||||
|
||||
First, create a file called `kustomization.yaml` with the following content:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
# Find the latest tag here: https://github.com/ansible/awx-operator/releases
|
||||
- github.com/ansible/awx-operator/config/default?ref=<tag>
|
||||
|
||||
# Set the image tags to match the git version from above
|
||||
images:
|
||||
- name: quay.io/ansible/awx-operator
|
||||
newTag: <tag>
|
||||
|
||||
# Specify a custom namespace in which to install AWX
|
||||
namespace: awx
|
||||
```
|
||||
|
||||
> **TIP:** If you need to change any of the default settings for the operator (such as resources.limits), you can add [patches](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/) at the bottom of your kustomization.yaml file.
|
||||
|
||||
Install the manifests by running this:
|
||||
|
||||
```
|
||||
$ export NAMESPACE=my-namespace
|
||||
$ make deploy
|
||||
cd config/manager && /home/user/awx-operator/bin/kustomize edit set image controller=quay.io/ansible/awx-operator:0.14.0
|
||||
/home/user/awx-operator/bin/kustomize build config/default | kubectl apply -f -
|
||||
namespace/my-namespace created
|
||||
$ kustomize build . | kubectl apply -f -
|
||||
namespace/awx created
|
||||
customresourcedefinition.apiextensions.k8s.io/awxbackups.awx.ansible.com created
|
||||
customresourcedefinition.apiextensions.k8s.io/awxrestores.awx.ansible.com created
|
||||
customresourcedefinition.apiextensions.k8s.io/awxs.awx.ansible.com created
|
||||
serviceaccount/awx-operator-controller-manager created
|
||||
role.rbac.authorization.k8s.io/awx-operator-awx-manager-role created
|
||||
role.rbac.authorization.k8s.io/awx-operator-leader-election-role created
|
||||
role.rbac.authorization.k8s.io/awx-operator-manager-role created
|
||||
clusterrole.rbac.authorization.k8s.io/awx-operator-metrics-reader created
|
||||
clusterrole.rbac.authorization.k8s.io/awx-operator-proxy-role created
|
||||
rolebinding.rbac.authorization.k8s.io/awx-operator-awx-manager-rolebinding created
|
||||
rolebinding.rbac.authorization.k8s.io/awx-operator-leader-election-rolebinding created
|
||||
rolebinding.rbac.authorization.k8s.io/awx-operator-manager-rolebinding created
|
||||
clusterrolebinding.rbac.authorization.k8s.io/awx-operator-proxy-rolebinding created
|
||||
configmap/awx-operator-manager-config created
|
||||
configmap/awx-operator-awx-manager-config created
|
||||
service/awx-operator-controller-manager-metrics-service created
|
||||
deployment.apps/awx-operator-controller-manager created
|
||||
```
|
||||
@@ -128,18 +171,18 @@ deployment.apps/awx-operator-controller-manager created
|
||||
Wait a bit and you should have the `awx-operator` running:
|
||||
|
||||
```
|
||||
$ kubectl get pods -n $NAMESPACE
|
||||
$ kubectl get pods -n awx
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
awx-operator-controller-manager-66ccd8f997-rhd4z 2/2 Running 0 11s
|
||||
```
|
||||
|
||||
So we don't have to keep repeating `-n $NAMESPACE`, let's set the current namespace for `kubectl`:
|
||||
So we don't have to keep repeating `-n awx`, let's set the current namespace for `kubectl`:
|
||||
|
||||
```
|
||||
$ kubectl config set-context --current --namespace=$NAMESPACE
|
||||
$ kubectl config set-context --current --namespace=awx
|
||||
```
|
||||
|
||||
Next, create a file named `awx-demo.yml` with the suggested content below. The `metadata.name` you provide, will be the name of the resulting AWX deployment.
|
||||
Next, create a file named `awx-demo.yaml` in the same folder with the suggested content below. The `metadata.name` you provide will be the name of the resulting AWX deployment.
|
||||
|
||||
**Note:** If you deploy more than one AWX instance to the same namespace, be sure to use unique names.
|
||||
|
||||
@@ -151,19 +194,33 @@ metadata:
|
||||
name: awx-demo
|
||||
spec:
|
||||
service_type: nodeport
|
||||
# default nodeport_port is 30080
|
||||
nodeport_port: <nodeport_port>
|
||||
```
|
||||
|
||||
Finally, use `kubectl` to create the awx instance in your cluster:
|
||||
> It may make sense to create and specify your own secret key for your deployment so that if the k8s secret gets deleted, it can be re-created if needed. If it is not provided, one will be auto-generated, but cannot be recovered if lost. Read more [here](#secret-key-configuration).
|
||||
|
||||
Make sure to add this new file to the list of "resources" in your `kustomization.yaml` file:
|
||||
|
||||
```yaml
|
||||
...
|
||||
resources:
|
||||
- github.com/ansible/awx-operator/config/default?ref=<tag>
|
||||
# Add this extra line:
|
||||
- awx-demo.yaml
|
||||
...
|
||||
```
|
||||
|
||||
Finally, run `kustomize` again to create the AWX instance in your cluster:
|
||||
|
||||
```
|
||||
$ kubectl apply -f awx-demo.yml
|
||||
awx.awx.ansible.com/awx-demo created
|
||||
kustomize build . | kubectl apply -f -
|
||||
```
|
||||
|
||||
After a few minutes, the new AWX instance will be deployed. You can look at the operator pod logs in order to know where the installation process is at:
|
||||
|
||||
```
|
||||
$ kubectl logs -f deployments/awx-operator-controller-manager -c manager
|
||||
$ kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager
|
||||
```
|
||||
|
||||
After a few seconds, you should see the operator begin to create new resources:
|
||||
@@ -197,17 +254,44 @@ You just completed the most basic install of an AWX instance via this operator.
|
||||
|
||||
For an example using the Nginx Controller in Minukube, don't miss our [demo video](https://asciinema.org/a/416946).
|
||||
|
||||
[](https://asciinema.org/a/416946)
|
||||
|
||||
### Helm Install on existing cluster
|
||||
|
||||
For those that wish to use [Helm](https://helm.sh/) to install the awx-operator to an existing K8s cluster:
|
||||
|
||||
```bash
|
||||
$ helm repo add awx-operator https://ansible.github.io/awx-operator/
|
||||
"awx-operator" has been added to your repositories
|
||||
|
||||
$ helm repo update
|
||||
Hang tight while we grab the latest from your chart repositories...
|
||||
...Successfully got an update from the "awx-operator" chart repository
|
||||
Update Complete. ⎈Happy Helming!⎈
|
||||
|
||||
$ helm search repo awx-operator
|
||||
NAME CHART VERSION APP VERSION DESCRIPTION
|
||||
awx-operator/awx-operator 0.17.1 0.17.1 A Helm chart for the AWX Operator
|
||||
|
||||
$ helm install my-awx-operator awx-operator/awx-operator
|
||||
NAME: my-awx-operator
|
||||
LAST DEPLOYED: Thu Feb 17 22:09:05 2022
|
||||
NAMESPACE: default
|
||||
STATUS: deployed
|
||||
REVISION: 1
|
||||
TEST SUITE: None
|
||||
NOTES:
|
||||
Helm Chart 0.17.1
|
||||
```
|
||||
|
||||
### Admin user account configuration
|
||||
|
||||
There are three variables that are customizable for the admin user account creation.
|
||||
|
||||
| Name | Description | Default |
|
||||
| --------------------------- | -------------------------------------------- | ---------------- |
|
||||
| admin_user | Name of the admin user | admin |
|
||||
| admin_email | Email of the admin user | test@example.com |
|
||||
| admin_password_secret | Secret that contains the admin user password | Empty string |
|
||||
| Name | Description | Default |
|
||||
| --------------------- | -------------------------------------------- | ---------------- |
|
||||
| admin_user | Name of the admin user | admin |
|
||||
| admin_email | Email of the admin user | test@example.com |
|
||||
| admin_password_secret | Secret that contains the admin user password | Empty string |
|
||||
|
||||
|
||||
> :warning: **admin_password_secret must be a Kubernetes secret and not your text clear password**.
|
||||
@@ -230,6 +314,41 @@ stringData:
|
||||
```
|
||||
|
||||
|
||||
### Secret Key Configuration
|
||||
|
||||
This key is used to encrypt sensitive data in the database.
|
||||
|
||||
| Name | Description | Default |
|
||||
| ----------------- | ----------------------------------------------------- | ---------------- |
|
||||
| secret_key_secret | Secret that contains the symmetric key for encryption | Generated |
|
||||
|
||||
|
||||
> :warning: **secret_key_secret must be a Kubernetes secret and not your text clear secret value**.
|
||||
|
||||
If `secret_key_secret` is not provided, the operator will look for a secret named `<resourcename>-secret-key` for the secret key. If it is not present, the operator will generate a password and create a Secret from it named `<resourcename>-secret-key`. It is important to not delete this secret as it will be needed for upgrades and if the pods get scaled down at any point. If you are using a GitOps flow, you will want to pass a secret key secret.
|
||||
|
||||
The secret should be formatted as follow:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: custom-awx-secret-key
|
||||
namespace: <target namespace>
|
||||
stringData:
|
||||
secret_key: supersecuresecretkey
|
||||
```
|
||||
|
||||
Then specify the secret name on the AWX spec:
|
||||
|
||||
```yaml
|
||||
---
|
||||
spec:
|
||||
...
|
||||
secret_key_secret: custom-awx-secret-key
|
||||
```
|
||||
|
||||
### Network and TLS Configuration
|
||||
|
||||
#### Service Type
|
||||
@@ -240,15 +359,18 @@ The `service_type` supported options are: `ClusterIP`, `LoadBalancer` and `NodeP
|
||||
|
||||
The following variables are customizable for any `service_type`
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------------------------- | --------------------------------------------- | --------------------------------- |
|
||||
| service_labels | Add custom labels | Empty string |
|
||||
| Name | Description | Default |
|
||||
| ------------------- | ----------------------- | ------------ |
|
||||
| service_labels | Add custom labels | Empty string |
|
||||
| service_annotations | Add service annotations | Empty string |
|
||||
|
||||
```yaml
|
||||
---
|
||||
spec:
|
||||
...
|
||||
service_type: ClusterIP
|
||||
service_annotations: |
|
||||
environment: testing
|
||||
service_labels: |
|
||||
environment: testing
|
||||
```
|
||||
@@ -257,11 +379,10 @@ spec:
|
||||
|
||||
The following variables are customizable only when `service_type=LoadBalancer`
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------------------ | ---------------------------------------- | ------------- |
|
||||
| loadbalancer_annotations | LoadBalancer annotations | Empty string |
|
||||
| loadbalancer_protocol | Protocol to use for Loadbalancer ingress | http |
|
||||
| loadbalancer_port | Port used for Loadbalancer ingress | 80 |
|
||||
| Name | Description | Default |
|
||||
| --------------------- | ---------------------------------------- | ------- |
|
||||
| loadbalancer_protocol | Protocol to use for Loadbalancer ingress | http |
|
||||
| loadbalancer_port | Port used for Loadbalancer ingress | 80 |
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -270,7 +391,7 @@ spec:
|
||||
service_type: LoadBalancer
|
||||
loadbalancer_protocol: https
|
||||
loadbalancer_port: 443
|
||||
loadbalancer_annotations: |
|
||||
service_annotations: |
|
||||
environment: testing
|
||||
service_labels: |
|
||||
environment: testing
|
||||
@@ -284,9 +405,9 @@ The HTTPS Load Balancer also uses SSL termination at the Load Balancer level and
|
||||
|
||||
The following variables are customizable only when `service_type=NodePort`
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------------------ | ---------------------------------------- | ------------- |
|
||||
| nodeport_port | Port used for NodePort | 30080 |
|
||||
| Name | Description | Default |
|
||||
| ------------- | ---------------------- | ------- |
|
||||
| nodeport_port | Port used for NodePort | 30080 |
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -314,12 +435,13 @@ spec:
|
||||
|
||||
The following variables are customizable when `ingress_type=ingress`. The `ingress` type creates an Ingress resource as [documented](https://kubernetes.io/docs/concepts/services-networking/ingress/) which can be shared with many other Ingress Controllers as [listed](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/).
|
||||
|
||||
| Name | Description | Default |
|
||||
| -------------------------- | ---------------------------------------- | ---------------------------- |
|
||||
| ingress_annotations | Ingress annotations | Empty string |
|
||||
| ingress_tls_secret | Secret that contains the TLS information | Empty string |
|
||||
| hostname | Define the FQDN | {{ meta.name }}.example.com |
|
||||
| ingress_path | Define the ingress path to the service | / |
|
||||
| Name | Description | Default |
|
||||
| ------------------- | ---------------------------------------- | --------------------------- |
|
||||
| ingress_annotations | Ingress annotations | Empty string |
|
||||
| ingress_tls_secret | Secret that contains the TLS information | Empty string |
|
||||
| hostname | Define the FQDN | {{ meta.name }}.example.com |
|
||||
| ingress_path | Define the ingress path to the service | / |
|
||||
| ingress_path_type | Define the type of the path (for LBs) | Prefix |
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -335,8 +457,8 @@ spec:
|
||||
|
||||
The following variables are customizable when `ingress_type=route`
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------------------------- | --------------------------------------------- | --------------------------------------------------------|
|
||||
| Name | Description | Default |
|
||||
| ------------------------------- | --------------------------------------------- | ------------------------------------------------------- |
|
||||
| route_host | Common name the route answers for | `<instance-name>-<namespace>-<routerCanonicalHostname>` |
|
||||
| route_tls_termination_mechanism | TLS Termination mechanism (Edge, Passthrough) | Edge |
|
||||
| route_tls_secret | Secret that contains the TLS information | Empty string |
|
||||
@@ -355,7 +477,7 @@ spec:
|
||||
|
||||
#### External PostgreSQL Service
|
||||
|
||||
In order for the AWX instance to rely on an external database, the Custom Resource needs to know about the connection details. Those connection details should be stored as a secret and either specified as `postgres_configuration_secret` at the CR spec level, or simply be present on the namespace under the name `<resourcename>-postgres-configuration`.
|
||||
To configure AWX to use an external database, the Custom Resource needs to know about the connection details. To do this, create a k8s secret with those connection details and specify the name of the secret as `postgres_configuration_secret` at the CR spec level.
|
||||
|
||||
|
||||
The secret should be formatted as follows:
|
||||
@@ -378,12 +500,21 @@ stringData:
|
||||
type: Opaque
|
||||
```
|
||||
|
||||
> Please ensure that the value for the variable "password" is wrapped in quotes if the password contains any special characters.
|
||||
> Please ensure that the value for the variable `password` should _not_ contain single or double quotes (`'`, `"`) or backslashes (`\`) to avoid any issues during deployment, backup or restoration.
|
||||
|
||||
> It is possible to set a specific username, password, port, or database, but still have the database managed by the operator. In this case, when creating the postgres-configuration secret, the `type: managed` field should be added.
|
||||
|
||||
**Note**: The variable `sslmode` is valid for `external` databases only. The allowed values are: `prefer`, `disable`, `allow`, `require`, `verify-ca`, `verify-full`.
|
||||
|
||||
Once the secret is created, you can specify it on your spec:
|
||||
|
||||
```yaml
|
||||
---
|
||||
spec:
|
||||
...
|
||||
postgres_configuration_secret: <name-of-your-secret>
|
||||
```
|
||||
|
||||
#### Migrating data from an old AWX instance
|
||||
|
||||
For instructions on how to migrate from an older version of AWX, see [migration.md](./docs/migration.md).
|
||||
@@ -394,13 +525,15 @@ If you don't have access to an external PostgreSQL service, the AWX operator can
|
||||
|
||||
The following variables are customizable for the managed PostgreSQL service
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------------------------ | ------------------------------------------ | --------------------------------- |
|
||||
| postgres_image | Path of the image to pull | postgres:12 |
|
||||
| postgres_resource_requirements | PostgreSQL container resource requirements | Empty object |
|
||||
| postgres_storage_requirements | PostgreSQL container storage requirements | requests: {storage: 8Gi} |
|
||||
| postgres_storage_class | PostgreSQL PV storage class | Empty string |
|
||||
| postgres_data_path | PostgreSQL data path | `/var/lib/postgresql/data/pgdata` |
|
||||
| Name | Description | Default |
|
||||
| --------------------------------------------- | --------------------------------------------- | ---------------------------------- |
|
||||
| postgres_image | Path of the image to pull | postgres:12 |
|
||||
| postgres_init_container_resource_requirements | Database init container resource requirements | requests: {cpu: 10m, memory: 64Mi} |
|
||||
| postgres_resource_requirements | PostgreSQL container resource requirements | requests: {cpu: 10m, memory: 64Mi} |
|
||||
| postgres_storage_requirements | PostgreSQL container storage requirements | requests: {storage: 8Gi} |
|
||||
| postgres_storage_class | PostgreSQL PV storage class | Empty string |
|
||||
| postgres_data_path | PostgreSQL data path | `/var/lib/postgresql/data/pgdata` |
|
||||
| postgres_priority_class | Priority class used for PostgreSQL pod | Empty string |
|
||||
|
||||
Example of customization could be:
|
||||
|
||||
@@ -421,6 +554,9 @@ spec:
|
||||
limits:
|
||||
storage: 50Gi
|
||||
postgres_storage_class: fast-ssd
|
||||
postgres_extra_args:
|
||||
- '-c'
|
||||
- 'max_connections=1000'
|
||||
```
|
||||
|
||||
**Note**: If `postgres_storage_class` is not defined, Postgres will store it's data on a volume using the default storage class for your cluster.
|
||||
@@ -431,15 +567,15 @@ spec:
|
||||
|
||||
There are a few variables that are customizable for awx the image management.
|
||||
|
||||
| Name | Description |
|
||||
| --------------------------| -------------------------- |
|
||||
| image | Path of the image to pull |
|
||||
| image_version | Image version to pull |
|
||||
| image_pull_policy | The pull policy to adopt |
|
||||
| image_pull_secret | The pull secret to use |
|
||||
| ee_images | A list of EEs to register |
|
||||
| redis_image | Path of the image to pull |
|
||||
| redis_image_version | Image version to pull |
|
||||
| Name | Description | Default |
|
||||
| ------------------- | ------------------------- | -------------------------------------- |
|
||||
| image | Path of the image to pull | quay.io/ansible/awx |
|
||||
| image_version | Image version to pull | value of DEFAULT_AWX_VERSION or latest |
|
||||
| image_pull_policy | The pull policy to adopt | IfNotPresent |
|
||||
| image_pull_secrets | The pull secrets to use | None |
|
||||
| ee_images | A list of EEs to register | quay.io/ansible/awx-ee:latest |
|
||||
| redis_image | Path of the image to pull | docker.io/redis |
|
||||
| redis_image_version | Image version to pull | latest |
|
||||
|
||||
Example of customization could be:
|
||||
|
||||
@@ -450,7 +586,8 @@ spec:
|
||||
image: myorg/my-custom-awx
|
||||
image_version: latest
|
||||
image_pull_policy: Always
|
||||
image_pull_secret: pull_secret_name
|
||||
image_pull_secrets:
|
||||
- pull_secret_name
|
||||
ee_images:
|
||||
- name: my-custom-awx-ee
|
||||
image: myorg/my-custom-awx-ee
|
||||
@@ -458,6 +595,20 @@ spec:
|
||||
|
||||
**Note**: The `image` and `image_version` are intended for local mirroring scenarios. Please note that using a version of AWX other than the one bundled with the `awx-operator` is **not** supported. For the default values, check the [main.yml](https://github.com/ansible/awx-operator/blob/devel/roles/installer/defaults/main.yml) file.
|
||||
|
||||
#### Redis container capabilities
|
||||
|
||||
Depending on your kubernetes cluster and settings you might need to grant some capabilities to the redis container so it can start. Set the `redis_capabilities` option so the capabilities are added in the deployment.
|
||||
|
||||
```yaml
|
||||
---
|
||||
spec:
|
||||
...
|
||||
redis_capabilities:
|
||||
- CHOWN
|
||||
- SETUID
|
||||
- SETGID
|
||||
```
|
||||
|
||||
#### Privileged Tasks
|
||||
|
||||
Depending on the type of tasks that you'll be running, you may find that you need the task pod to run as `privileged`. This can open yourself up to a variety of security concerns, so you should be aware (and verify that you have the privileges) to do this if necessary. In order to toggle this feature, you can add the following to your custom resource:
|
||||
@@ -482,11 +633,11 @@ Again, this is the most relaxed SCC that is provided by OpenShift, so be sure to
|
||||
|
||||
The resource requirements for both, the task and the web containers are configurable - both the lower end (requests) and the upper end (limits).
|
||||
|
||||
| Name | Description | Default |
|
||||
| -------------------------------- | ------------------------------------------------ | ----------------------------------- |
|
||||
| web_resource_requirements | Web container resource requirements | requests: {cpu: 1000m, memory: 2Gi} |
|
||||
| task_resource_requirements | Task container resource requirements | requests: {cpu: 500m, memory: 1Gi} |
|
||||
| ee_resource_requirements | EE control plane container resource requirements | requests: {cpu: 500m, memory: 1Gi} |
|
||||
| Name | Description | Default |
|
||||
| -------------------------- | ------------------------------------------------ | ------------------------------------ |
|
||||
| web_resource_requirements | Web container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
|
||||
| task_resource_requirements | Task container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
|
||||
| ee_resource_requirements | EE control plane container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
|
||||
|
||||
Example of customization could be:
|
||||
|
||||
@@ -496,42 +647,63 @@ spec:
|
||||
...
|
||||
web_resource_requirements:
|
||||
requests:
|
||||
cpu: 1000m
|
||||
cpu: 250m
|
||||
memory: 2Gi
|
||||
limits:
|
||||
cpu: 2000m
|
||||
cpu: 1000m
|
||||
memory: 4Gi
|
||||
task_resource_requirements:
|
||||
requests:
|
||||
cpu: 500m
|
||||
cpu: 250m
|
||||
memory: 1Gi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
ee_resource_requirements:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
cpu: 250m
|
||||
memory: 100Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
cpu: 500m
|
||||
memory: 2Gi
|
||||
```
|
||||
|
||||
#### Priority Classes
|
||||
|
||||
The AWX and Postgres pods can be assigned a custom PriorityClass to rank their importance compared to other pods in your cluster, which determines which pods get evicted first if resources are running low.
|
||||
First, [create your PriorityClass](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass) if needed.
|
||||
Then set the name of your priority class to the control plane and postgres pods as shown below.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: awx.ansible.com/v1beta1
|
||||
kind: AWX
|
||||
metadata:
|
||||
name: awx-demo
|
||||
spec:
|
||||
...
|
||||
control_plane_priority_class: awx-demo-high-priority
|
||||
postgres_priority_class: awx-demo-medium-priority
|
||||
```
|
||||
|
||||
#### Assigning AWX pods to specific nodes
|
||||
|
||||
You can constrain the AWX pods created by the operator to run on a certain subset of nodes. `node_selector` and `postgres_selector` constrains
|
||||
the AWX pods to run only on the nodes that match all the specified key/value pairs. `tolerations` and `postgres_tolerations` allow the AWX
|
||||
pods to be scheduled onto nodes with matching taints.
|
||||
The ability to specify topologySpreadConstraints is also allowed through `topology_spread_constraints`
|
||||
|
||||
|
||||
| Name | Description | Default |
|
||||
| -------------------------------| --------------------------- | ------- |
|
||||
| postgres_image | Path of the image to pull | 12 |
|
||||
| postgres_image_version | Image version to pull | 12 |
|
||||
| node_selector | AWX pods' nodeSelector | '' |
|
||||
| tolerations | AWX pods' tolerations | '' |
|
||||
| postgres_selector | Postgres pods' nodeSelector | '' |
|
||||
| postgres_tolerations | Postgres pods' tolerations | '' |
|
||||
| Name | Description | Default |
|
||||
| --------------------------- | ----------------------------------- | ------- |
|
||||
| postgres_image | Path of the image to pull | 12 |
|
||||
| postgres_image_version | Image version to pull | 12 |
|
||||
| node_selector | AWX pods' nodeSelector | '' |
|
||||
| topology_spread_constraints | AWX pods' topologySpreadConstraints | '' |
|
||||
| tolerations | AWX pods' tolerations | '' |
|
||||
| annotations | AWX pods' annotations | '' |
|
||||
| postgres_selector | Postgres pods' nodeSelector | '' |
|
||||
| postgres_tolerations | Postgres pods' tolerations | '' |
|
||||
|
||||
Example of customization could be:
|
||||
|
||||
@@ -543,6 +715,13 @@ spec:
|
||||
disktype: ssd
|
||||
kubernetes.io/arch: amd64
|
||||
kubernetes.io/os: linux
|
||||
topology_spread_constraints: |
|
||||
- maxSkew: 100
|
||||
topologyKey: "topology.kubernetes.io/zone"
|
||||
whenUnsatisfiable: "ScheduleAnyway"
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: "<resourcename>"
|
||||
tolerations: |
|
||||
- key: "dedicated"
|
||||
operator: "Equal"
|
||||
@@ -569,8 +748,8 @@ Trusting a custom Certificate Authority allows the AWX to access network service
|
||||
| Name | Description | Default |
|
||||
| -------------------------------- | ---------------------------------------- | --------|
|
||||
| ldap_cacert_secret | LDAP Certificate Authority secret name | '' |
|
||||
| ldap_password_secret | LDAP BIND DN Password secret name | '' |
|
||||
| bundle_cacert_secret | Certificate Authority secret name | '' |
|
||||
|
||||
Please note the `awx-operator` will look for the data field `ldap-ca.crt` in the specified secret when using the `ldap_cacert_secret`, whereas the data field `bundle-ca.crt` is required for `bundle_cacert_secret` parameter.
|
||||
|
||||
Example of customization could be:
|
||||
@@ -580,10 +759,13 @@ Example of customization could be:
|
||||
spec:
|
||||
...
|
||||
ldap_cacert_secret: <resourcename>-custom-certs
|
||||
ldap_password_secret: <resourcename>-ldap-password
|
||||
bundle_cacert_secret: <resourcename>-custom-certs
|
||||
```
|
||||
|
||||
To create the secret, you can use the command below:
|
||||
To create the secrets, you can use the commands below:
|
||||
|
||||
* Certificate Authority secret
|
||||
|
||||
```
|
||||
# kubectl create secret generic <resourcename>-custom-certs \
|
||||
@@ -591,17 +773,77 @@ To create the secret, you can use the command below:
|
||||
--from-file=bundle-ca.crt=<PATH/TO/YOUR/CA/PEM/FILE>
|
||||
```
|
||||
|
||||
* LDAP BIND DN Password secret
|
||||
|
||||
```
|
||||
# kubectl create secret generic <resourcename>-ldap-password \
|
||||
--from-literal=ldap-password=<your_ldap_dn_password>
|
||||
```
|
||||
|
||||
#### Enabling LDAP Integration at AWX bootstrap
|
||||
|
||||
A sample of extra settings can be found as below:
|
||||
|
||||
```yaml
|
||||
- setting: AUTH_LDAP_SERVER_URI
|
||||
value: >-
|
||||
"ldaps://ad01.abc.com:636 ldaps://ad02.abc.com:636"
|
||||
|
||||
- setting: AUTH_LDAP_BIND_DN
|
||||
value: >-
|
||||
"CN=LDAP User,OU=Service Accounts,DC=abc,DC=com"
|
||||
|
||||
- setting: AUTH_LDAP_USER_SEARCH
|
||||
value: 'LDAPSearch("DC=abc,DC=com",ldap.SCOPE_SUBTREE,"(sAMAccountName=%(user)s)",)'
|
||||
|
||||
- setting: AUTH_LDAP_GROUP_SEARCH
|
||||
value: 'LDAPSearch("OU=Groups,DC=abc,DC=com",ldap.SCOPE_SUBTREE,"(objectClass=group)",)'
|
||||
|
||||
- setting: AUTH_LDAP_USER_ATTR_MAP
|
||||
value: '{"first_name": "givenName","last_name": "sn","email": "mail"}'
|
||||
|
||||
- setting: AUTH_LDAP_REQUIRE_GROUP
|
||||
value: >-
|
||||
"CN=operators,OU=Groups,DC=abc,DC=com"
|
||||
- setting: AUTH_LDAP_USER_FLAGS_BY_GROUP
|
||||
value: {
|
||||
"is_superuser": [
|
||||
"CN=admin,OU=Groups,DC=abc,DC=com"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
- setting: AUTH_LDAP_ORGANIZATION_MAP
|
||||
value: {
|
||||
"abc": {
|
||||
"admins": "CN=admin,OU=Groups,DC=abc,DC=com",
|
||||
"remove_users": false,
|
||||
"remove_admins": false,
|
||||
"users": true
|
||||
}
|
||||
}
|
||||
|
||||
- setting: AUTH_LDAP_TEAM_MAP
|
||||
value: {
|
||||
"admin": {
|
||||
"remove": true,
|
||||
"users": "CN=admin,OU=Groups,DC=abc,DC=com",
|
||||
"organization": "abc"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Persisting Projects Directory
|
||||
|
||||
In cases which you want to persist the `/var/lib/projects` directory, there are few variables that are customizable for the `awx-operator`.
|
||||
|
||||
| Name | Description | Default |
|
||||
| -----------------------------------| ---------------------------------------------------------------------------------------------------- | ---------------|
|
||||
| projects_persistence | Whether or not the /var/lib/projects directory will be persistent | false |
|
||||
| projects_storage_class | Define the PersistentVolume storage class | '' |
|
||||
| projects_storage_size | Define the PersistentVolume size | 8Gi |
|
||||
| projects_storage_access_mode | Define the PersistentVolume access mode | ReadWriteMany |
|
||||
| projects_existing_claim | Define an existing PersistentVolumeClaim to use (cannot be combined with `projects_storage_*`) | '' |
|
||||
| Name | Description | Default |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------- | ------------- |
|
||||
| projects_persistence | Whether or not the /var/lib/projects directory will be persistent | false |
|
||||
| projects_storage_class | Define the PersistentVolume storage class | '' |
|
||||
| projects_storage_size | Define the PersistentVolume size | 8Gi |
|
||||
| projects_storage_access_mode | Define the PersistentVolume access mode | ReadWriteMany |
|
||||
| projects_existing_claim | Define an existing PersistentVolumeClaim to use (cannot be combined with `projects_storage_*`) | '' |
|
||||
|
||||
Example of customization when the `awx-operator` automatically handles the persistent volume could be:
|
||||
|
||||
@@ -618,14 +860,14 @@ spec:
|
||||
|
||||
In a scenario where custom volumes and volume mounts are required to either overwrite defaults or mount configuration files.
|
||||
|
||||
| Name | Description | Default |
|
||||
| --------------------------------- | -------------------------------------------------------- | ------- |
|
||||
| extra_volumes | Specify extra volumes to add to the application pod | '' |
|
||||
| web_extra_volume_mounts | Specify volume mounts to be added to Web container | '' |
|
||||
| task_extra_volume_mounts | Specify volume mounts to be added to Task container | '' |
|
||||
| ee_extra_volume_mounts | Specify volume mounts to be added to Execution container | '' |
|
||||
| init_container_extra_volume_mounts| Specify volume mounts to be added to Init container | '' |
|
||||
| init_container_extra_commands | Specify additional commands for Init container | '' |
|
||||
| Name | Description | Default |
|
||||
| ---------------------------------- | -------------------------------------------------------- | ------- |
|
||||
| extra_volumes | Specify extra volumes to add to the application pod | '' |
|
||||
| web_extra_volume_mounts | Specify volume mounts to be added to Web container | '' |
|
||||
| task_extra_volume_mounts | Specify volume mounts to be added to Task container | '' |
|
||||
| ee_extra_volume_mounts | Specify volume mounts to be added to Execution container | '' |
|
||||
| init_container_extra_volume_mounts | Specify volume mounts to be added to Init container | '' |
|
||||
| init_container_extra_commands | Specify additional commands for Init container | '' |
|
||||
|
||||
|
||||
> :warning: The `ee_extra_volume_mounts` and `extra_volumes` will only take effect to the globally available Execution Environments. For custom `ee`, please [customize the Pod spec](https://docs.ansible.com/ansible-tower/latest/html/administration/external_execution_envs.html#customize-the-pod-spec).
|
||||
@@ -720,7 +962,7 @@ type: Opaque
|
||||
```
|
||||
|
||||
##### Control plane ee from private registry
|
||||
The images listed in "ee_images" will be added as globally available Execution Environments. The "control_plane_ee_image" will be used to run project updates. In order to use a private image for any of these you'll need to use `image_pull_secret` to provide a k8s pull secret to access it. Currently the same secret is used for any of these images supplied at install time.
|
||||
The images listed in "ee_images" will be added as globally available Execution Environments. The "control_plane_ee_image" will be used to run project updates. In order to use a private image for any of these you'll need to use `image_pull_secrets` to provide a list of k8s pull secrets to access it. Currently the same secret is used for any of these images supplied at install time.
|
||||
|
||||
You can create `image_pull_secret`
|
||||
```
|
||||
@@ -746,11 +988,11 @@ type: kubernetes.io/dockerconfigjson
|
||||
|
||||
If you need to export custom environment variables to your containers.
|
||||
|
||||
| Name | Description | Default |
|
||||
| ----------------------------- | -------------------------------------------------------- | ------- |
|
||||
| task_extra_env | Environment variables to be added to Task container | '' |
|
||||
| web_extra_env | Environment variables to be added to Web container | '' |
|
||||
| ee_extra_env | Environment variables to be added to EE container | '' |
|
||||
| Name | Description | Default |
|
||||
| -------------- | --------------------------------------------------- | ------- |
|
||||
| task_extra_env | Environment variables to be added to Task container | '' |
|
||||
| web_extra_env | Environment variables to be added to Web container | '' |
|
||||
| ee_extra_env | Environment variables to be added to EE container | '' |
|
||||
|
||||
> :warning: The `ee_extra_env` will only take effect to the globally available Execution Environments. For custom `ee`, please [customize the Pod spec](https://docs.ansible.com/ansible-tower/latest/html/administration/external_execution_envs.html#customize-the-pod-spec).
|
||||
|
||||
@@ -769,13 +1011,43 @@ Example configuration of environment variables
|
||||
value: foo
|
||||
```
|
||||
|
||||
#### CSRF Cookie Secure Setting
|
||||
|
||||
With `csrf_cookie_secure`, you can pass the value for `CSRF_COOKIE_SECURE` to `/etc/tower/settings.py`
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------------------ | ------------------ | ------- |
|
||||
| csrf_cookie_secure | CSRF Cookie Secure | '' |
|
||||
|
||||
Example configuration of the `csrf_cookie_secure` setting:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
csrf_cookie_secure: 'False'
|
||||
```
|
||||
|
||||
#### Session Cookie Secure Setting
|
||||
|
||||
With `session_cookie_secure`, you can pass the value for `SESSION_COOKIE_SECURE` to `/etc/tower/settings.py`
|
||||
|
||||
| Name | Description | Default |
|
||||
| --------------------- | --------------------- | ------- |
|
||||
| session_cookie_secure | Session Cookie Secure | '' |
|
||||
|
||||
Example configuration of the `session_cookie_secure` setting:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
session_cookie_secure: 'False'
|
||||
```
|
||||
|
||||
#### Extra Settings
|
||||
|
||||
With`extra_settings`, you can pass multiple custom settings via the `awx-operator`. The parameter `extra_settings` will be appended to the `/etc/tower/settings.py` and can be an alternative to the `extra_volumes` parameter.
|
||||
|
||||
| Name | Description | Default |
|
||||
| ----------------------------- | -------------------------------------------------------- | ------- |
|
||||
| extra_settings | Extra settings | '' |
|
||||
| Name | Description | Default |
|
||||
| -------------- | -------------- | ------- |
|
||||
| extra_settings | Extra settings | '' |
|
||||
|
||||
Example configuration of `extra_settings` parameter
|
||||
|
||||
@@ -789,13 +1061,64 @@ Example configuration of `extra_settings` parameter
|
||||
value: "cn=admin,dc=example,dc=com"
|
||||
```
|
||||
|
||||
#### No Log
|
||||
Configure no_log for tasks with no_log
|
||||
|
||||
| Name | Description | Default |
|
||||
| ------ | -------------------- | ------- |
|
||||
| no_log | No log configuration | 'true' |
|
||||
|
||||
Example configuration of `no_log` parameter
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
no_log: 'true'
|
||||
```
|
||||
|
||||
#### Auto upgrade
|
||||
With this parameter you can influence the behaviour during an operator upgrade.
|
||||
If set to `true`, the operator will upgrade the specific instance directly.
|
||||
When the value is set to `false`, and we have a running deployment, the operator will not update the AWX instance.
|
||||
This can be useful when you have multiple AWX instances which you want to upgrade step by step instead of all at once.
|
||||
|
||||
|
||||
| Name | Description | Default |
|
||||
| -------------| ---------------------------------- | ------- |
|
||||
| auto_upgrade | Automatic upgrade of AWX instances | true |
|
||||
|
||||
Example configuration of `auto_upgrade` parameter
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
auto_upgrade: true
|
||||
```
|
||||
|
||||
##### Upgrade of instances without auto upgrade
|
||||
|
||||
There are two ways to upgrade instances which are marked with the 'auto_upgrade: false' flag.
|
||||
|
||||
Changing flags:
|
||||
|
||||
- change the auto_upgrade flag on your AWX object to true
|
||||
- wait until the upgrade process of that instance is finished
|
||||
- change the auto_upgrade flag on your AWX object back to false
|
||||
|
||||
Delete the deployment:
|
||||
|
||||
- delete the deployment object of your AWX instance
|
||||
```
|
||||
$ kubectl -n awx delete deployment <yourInstanceName>
|
||||
```
|
||||
- wait until the instance gets redeployed
|
||||
|
||||
|
||||
#### Service Account
|
||||
|
||||
If you need to modify some `ServiceAccount` proprieties
|
||||
|
||||
| Name | Description | Default |
|
||||
| ----------------------------- | -------------------------------------------------------- | ------- |
|
||||
| service_account_annotations | Annotations to the ServiceAccount | '' |
|
||||
| Name | Description | Default |
|
||||
| --------------------------- | --------------------------------- | ------- |
|
||||
| service_account_annotations | Annotations to the ServiceAccount | '' |
|
||||
|
||||
Example configuration of environment variables
|
||||
|
||||
@@ -834,6 +1157,21 @@ delete your existing `awx-operator` service account, role and role binding.
|
||||
|
||||
Starting with awx-operator 0.14.0, the project is now based on operator-sdk 1.x. You may need to manually delete your old operator Deployment to avoid issues.
|
||||
|
||||
##### Steps to upgrade
|
||||
|
||||
Delete your old AWX Operator and existing `awx-operator` service account, role and role binding in `default` namespace first:
|
||||
|
||||
```
|
||||
$ kubectl -n default delete deployment awx-operator
|
||||
$ kubectl -n default delete serviceaccount awx-operator
|
||||
$ kubectl -n default delete clusterrolebinding awx-operator
|
||||
$ kubectl -n default delete clusterrole awx-operator
|
||||
```
|
||||
|
||||
Then install the new AWX Operator by following the instructions in [Basic Install](#basic-install-on-existing-cluster). The `NAMESPACE` environment variable have to be the name of the namespace in which your old AWX instance resides.
|
||||
|
||||
Once the new AWX Operator is up and running, your AWX deployment will also be upgraded.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please visit [our contributing guidelines](https://github.com/ansible/awx-operator/blob/devel/CONTRIBUTING.md).
|
||||
@@ -841,47 +1179,26 @@ Please visit [our contributing guidelines](https://github.com/ansible/awx-operat
|
||||
|
||||
## Release Process
|
||||
|
||||
### Update version and files
|
||||
The first step is to create a draft release. Typically this will happen in the [Stage Release](https://github.com/ansible/awx/blob/devel/.github/workflows/stage.yml) workflow for AWX and you dont need to do it as a separate step.
|
||||
|
||||
Update the awx-operator version:
|
||||
If you need to do an independent release of the operator, you can run the [Stage Release](https://github.com/ansible/awx-operator/blob/devel/.github/workflows/stage.yml) in the awx-operator repo. Both of these workflows will run smoke tests, so there is no need to do this manually.
|
||||
|
||||
- `Makefile`
|
||||
After the draft release is created, publish it and the [Promote AWX Operator image](https://github.com/ansible/awx-operator/blob/devel/.github/workflows/promote.yaml) will run, which will:
|
||||
|
||||
### Verify Functionality
|
||||
|
||||
Run the following command inside this directory:
|
||||
|
||||
```
|
||||
$ IMAGE_TAG_BASE=quay.io/<user>/awx-operator make docker-build docker-push
|
||||
```
|
||||
|
||||
After it is built, test it on a local cluster:
|
||||
|
||||
```
|
||||
$ minikube start --memory 6g --cpus 4
|
||||
$ minikube addons enable ingress
|
||||
$ export NAMESPACE=example-awx
|
||||
$ make deploy
|
||||
$ ansible-playbook ansible/instantiate-awx-deployment.yml -e namespace=$NAMESPACE -e image=quay.io/<user>/awx -e service_type=nodeport
|
||||
$ # Verify that the awx-task and awx-web containers are launched
|
||||
$ # with the right version of the awx image
|
||||
$ # Launch a job at `minikube service awx-demo-service --url -n $NAMESPACE`
|
||||
$ minikube delete
|
||||
```
|
||||
|
||||
### Update changelog
|
||||
|
||||
Generate a list of commits between the versions and add it to the [changelog](./CHANGELOG.md).
|
||||
```
|
||||
$ git log --no-merges --pretty="- %s (%an) - %h " <old_tag>..<new_tag>
|
||||
```
|
||||
|
||||
### Commit / Create Release
|
||||
|
||||
If everything works, commit the updated version, then [publish a new release](https://github.com/ansible/awx-operator/releases/new) using the same version you used in `ansible/group_vars/all`.
|
||||
|
||||
After creating the release, [this GitHub Workflow](https://github.com/ansible/awx-operator/blob/devel/.github/workflows/release.yaml) will run and publish the new image to quay.io.
|
||||
- Publish image to Quay
|
||||
- Release Helm chart
|
||||
|
||||
## Author
|
||||
|
||||
This operator was originally built in 2019 by [Jeff Geerling](https://www.jeffgeerling.com) and is now maintained by the Ansible Team
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
We ask all of our community members and contributors to adhere to the [Ansible code of conduct](http://docs.ansible.com/ansible/latest/community/code_of_conduct.html). If you have questions or need assistance, please reach out to our community team at [codeofconduct@ansible.com](mailto:codeofconduct@ansible.com)
|
||||
|
||||
## Get Involved
|
||||
|
||||
We welcome your feedback and ideas. The AWX operator uses the same mailing list and IRC chanel as AWX itself. Here's how to reach us with feedback and questions:
|
||||
|
||||
- Join the `#ansible-awx` channel on irc.libera.chat
|
||||
- Join the [mailing list](https://groups.google.com/forum/#!forum/awx-project)
|
||||
|
||||
3
SECURITY.md
Normal file
3
SECURITY.md
Normal file
@@ -0,0 +1,3 @@
|
||||
For all security related bugs, email security@ansible.com instead of using this issue tracker and you will receive a prompt response.
|
||||
|
||||
For more information on the Ansible community's practices regarding responsible disclosure, see https://www.ansible.com/security
|
||||
47
ansible/helm-release.yml
Normal file
47
ansible/helm-release.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
vars:
|
||||
chart_repo: awx-operator
|
||||
tasks:
|
||||
- name: Look up release
|
||||
uri:
|
||||
url: "https://api.github.com/repos/{{ chart_owner }}/{{ chart_repo }}/releases/tags/{{ tag }}"
|
||||
register: release
|
||||
ignore_errors: yes
|
||||
|
||||
- fail:
|
||||
msg: |
|
||||
Release must exist before running this playbook
|
||||
when: release is not success
|
||||
|
||||
- name: Build and package helm chart
|
||||
command: |
|
||||
make helm-chart helm-package
|
||||
environment:
|
||||
VERSION: "{{ tag }}"
|
||||
IMAGE_TAG_BASE: "{{ operator_image }}"
|
||||
args:
|
||||
chdir: "{{ playbook_dir }}/../"
|
||||
|
||||
# Move to chart releaser after https://github.com/helm/chart-releaser/issues/122 exists
|
||||
- name: Upload helm chart
|
||||
uri:
|
||||
url: "https://uploads.github.com/repos/{{ chart_owner }}/{{ chart_repo }}/releases/{{ release.json.id }}/assets?name=awx-operator-{{ tag }}.tgz"
|
||||
src: "{{ playbook_dir }}/../.cr-release-packages/awx-operator-{{ tag }}.tgz"
|
||||
headers:
|
||||
Authorization: "token {{ gh_token }}"
|
||||
Content-Type: "application/octet-stream"
|
||||
status_code:
|
||||
- 200
|
||||
- 201
|
||||
register: asset_upload
|
||||
changed_when: asset_upload.json.state == "uploaded"
|
||||
|
||||
- name: Publish helm index
|
||||
command: |
|
||||
make helm-index
|
||||
environment:
|
||||
CHART_OWNER: "{{ chart_owner }}"
|
||||
CR_TOKEN: "{{ gh_token }}"
|
||||
args:
|
||||
chdir: "{{ playbook_dir }}/../"
|
||||
@@ -67,6 +67,9 @@ spec:
|
||||
extra_volumes:
|
||||
description: Specify extra volumes to add to the application pod
|
||||
type: string
|
||||
service_annotations:
|
||||
description: Annotations to add to the service
|
||||
type: string
|
||||
service_type:
|
||||
description: The service type to be used on the deployed instance
|
||||
type: string
|
||||
@@ -89,15 +92,15 @@ spec:
|
||||
ingress_path:
|
||||
description: The ingress path used to reach the deployed service
|
||||
type: string
|
||||
ingress_path_type:
|
||||
description: The ingress path type for the deployed service
|
||||
type: string
|
||||
ingress_annotations:
|
||||
description: Annotations to add to the Ingress Controller
|
||||
type: string
|
||||
ingress_tls_secret:
|
||||
description: Secret where the Ingress TLS secret can be found
|
||||
type: string
|
||||
loadbalancer_annotations:
|
||||
description: Annotations to add to the loadbalancer
|
||||
type: string
|
||||
loadbalancer_protocol:
|
||||
description: Protocol to use for the loadbalancer
|
||||
type: string
|
||||
@@ -131,9 +134,15 @@ spec:
|
||||
node_selector:
|
||||
description: nodeSelector for the pods
|
||||
type: string
|
||||
topology_spread_constraints:
|
||||
description: topology rule(s) for the pods
|
||||
type: string
|
||||
service_labels:
|
||||
description: Additional labels to apply to the service
|
||||
type: string
|
||||
annotations:
|
||||
description: annotations for the pods
|
||||
type: string
|
||||
tolerations:
|
||||
description: node tolerations for the pods
|
||||
type: string
|
||||
@@ -156,6 +165,9 @@ spec:
|
||||
control_plane_ee_image:
|
||||
description: Registry path to the Execution Environment container image to use on control plane pods
|
||||
type: string
|
||||
control_plane_priority_class:
|
||||
description: Assign a preexisting priority class to the control plane pods
|
||||
type: string
|
||||
ee_pull_credentials_secret:
|
||||
description: Secret where pull credentials for registered ees can be found
|
||||
type: string
|
||||
@@ -170,8 +182,13 @@ spec:
|
||||
- never
|
||||
- IfNotPresent
|
||||
- ifnotpresent
|
||||
image_pull_secret:
|
||||
description: The image pull secret
|
||||
image_pull_secrets:
|
||||
description: Image pull secrets for app and database containers
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
image_pull_secret: # deprecated
|
||||
description: (Deprecated) Image pull secret for app and database containers
|
||||
type: string
|
||||
task_resource_requirements:
|
||||
description: Resource requirements for the task container
|
||||
@@ -239,6 +256,50 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
postgres_init_container_resource_requirements:
|
||||
description: Resource requirements for the postgres init container
|
||||
properties:
|
||||
requests:
|
||||
properties:
|
||||
cpu:
|
||||
type: string
|
||||
memory:
|
||||
type: string
|
||||
storage:
|
||||
type: string
|
||||
type: object
|
||||
limits:
|
||||
properties:
|
||||
cpu:
|
||||
type: string
|
||||
memory:
|
||||
type: string
|
||||
storage:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
redis_resource_requirements:
|
||||
description: Resource requirements for the redis container
|
||||
properties:
|
||||
requests:
|
||||
properties:
|
||||
cpu:
|
||||
type: string
|
||||
memory:
|
||||
type: string
|
||||
storage:
|
||||
type: string
|
||||
type: object
|
||||
limits:
|
||||
properties:
|
||||
cpu:
|
||||
type: string
|
||||
memory:
|
||||
type: string
|
||||
storage:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
service_account_annotations:
|
||||
description: ServiceAccount annotations
|
||||
type: string
|
||||
@@ -292,6 +353,11 @@ spec:
|
||||
redis_image_version:
|
||||
description: Redis container image version to use
|
||||
type: string
|
||||
redis_capabilities:
|
||||
description: Redis container capabilities
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
init_container_image:
|
||||
description: Registry path to the init container to use
|
||||
type: string
|
||||
@@ -351,9 +417,16 @@ spec:
|
||||
postgres_storage_class:
|
||||
description: Storage class to use for the PostgreSQL PVC
|
||||
type: string
|
||||
postgres_priority_class:
|
||||
description: Assign a preexisting priority class to the postgres pod
|
||||
type: string
|
||||
postgres_data_path:
|
||||
description: Path where the PostgreSQL data are located
|
||||
type: string
|
||||
postgres_extra_args:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
ca_trust_bundle:
|
||||
description: Path where the trusted CA bundle is available
|
||||
type: string
|
||||
@@ -363,6 +436,9 @@ spec:
|
||||
ldap_cacert_secret:
|
||||
description: Secret where can be found the LDAP trusted Certificate Authority Bundle
|
||||
type: string
|
||||
ldap_password_secret:
|
||||
description: Secret where can be found the LDAP bind password
|
||||
type: string
|
||||
bundle_cacert_secret:
|
||||
description: Secret where can be found the trusted Certificate Authority Bundle
|
||||
type: string
|
||||
@@ -390,6 +466,12 @@ spec:
|
||||
description: AccessMode for the /var/lib/projects PersistentVolumeClaim
|
||||
default: ReadWriteMany
|
||||
type: string
|
||||
csrf_cookie_secure:
|
||||
description: Set csrf cookie secure mode for web
|
||||
type: string
|
||||
session_cookie_secure:
|
||||
description: Set session cookie secure mode for web
|
||||
type: string
|
||||
extra_settings:
|
||||
description: Extra settings to specify for the API
|
||||
items:
|
||||
@@ -400,6 +482,17 @@ spec:
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
no_log:
|
||||
description: Configure no_log for no_log tasks
|
||||
type: string
|
||||
security_context_settings:
|
||||
description: Key/values that will be set under the pod-level securityContext field
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
auto_upgrade:
|
||||
description: Should AWX instances be automatically upgraded when operator gets upgraded
|
||||
type: boolean
|
||||
default: true
|
||||
type: object
|
||||
status:
|
||||
properties:
|
||||
|
||||
@@ -43,6 +43,9 @@ spec:
|
||||
backup_storage_class:
|
||||
description: Storage class to use when creating PVC for backup
|
||||
type: string
|
||||
clean_backup_on_delete:
|
||||
description: Flag to indicate if backup should be deleted on PVC if AWXBackup object is deleted
|
||||
type: boolean
|
||||
postgres_label_selector:
|
||||
description: Label selector used to identify postgres pod for backing up data
|
||||
type: string
|
||||
@@ -52,6 +55,9 @@ spec:
|
||||
postgres_image_version:
|
||||
description: PostgreSQL container image version to use
|
||||
type: string
|
||||
no_log:
|
||||
description: Configure no_log for no_log tasks
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -56,6 +56,9 @@ spec:
|
||||
postgres_image_version:
|
||||
description: PostgreSQL container image version to use
|
||||
type: string
|
||||
no_log:
|
||||
description: Configure no_log for no_log tasks
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -21,7 +21,7 @@ spec:
|
||||
- containerPort: 8443
|
||||
protocol: TCP
|
||||
name: https
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
args:
|
||||
- "--health-probe-bind-address=:6789"
|
||||
- "--metrics-bind-address=127.0.0.1:8080"
|
||||
|
||||
@@ -8,14 +8,14 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
args:
|
||||
- "--config=controller_manager_config.yaml"
|
||||
volumeMounts:
|
||||
- name: manager-config
|
||||
- name: awx-manager-config
|
||||
mountPath: /controller_manager_config.yaml
|
||||
subPath: controller_manager_config.yaml
|
||||
volumes:
|
||||
- name: manager-config
|
||||
- name: awx-manager-config
|
||||
configMap:
|
||||
name: manager-config
|
||||
name: awx-manager-config
|
||||
|
||||
@@ -5,10 +5,10 @@ generatorOptions:
|
||||
configMapGenerator:
|
||||
- files:
|
||||
- controller_manager_config.yaml
|
||||
name: manager-config
|
||||
name: awx-manager-config
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: controller
|
||||
newName: quay.io/ansible/awx-operator
|
||||
newTag: 0.14.0
|
||||
newTag: latest
|
||||
|
||||
@@ -30,10 +30,12 @@ spec:
|
||||
- --leader-elect
|
||||
- --leader-election-id=awx-operator
|
||||
image: controller:latest
|
||||
name: manager
|
||||
name: awx-manager
|
||||
env:
|
||||
- name: ANSIBLE_GATHERING
|
||||
value: explicit
|
||||
- name: ANSIBLE_DEBUG_LOGS
|
||||
value: 'false'
|
||||
- name: WATCH_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
@@ -52,5 +54,14 @@ spec:
|
||||
port: 6789
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
requests:
|
||||
memory: "32Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "4096Mi"
|
||||
cpu: "2000m"
|
||||
serviceAccountName: controller-manager
|
||||
imagePullSecrets:
|
||||
- name: redhat-operators-pull-secret
|
||||
terminationGracePeriodSeconds: 10
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@ apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: manager-role
|
||||
name: awx-manager-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- route.openshift.io
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: manager-rolebinding
|
||||
name: awx-manager-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: manager-role
|
||||
name: awx-manager-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
|
||||
@@ -4,21 +4,15 @@ kind: AWX
|
||||
metadata:
|
||||
name: example-awx
|
||||
spec:
|
||||
service_account_annotations: |
|
||||
foo: bar
|
||||
deployment_type: awx
|
||||
ingress_type: ingress
|
||||
ingress_annotations: |
|
||||
kubernetes.io/ingress.class: nginx
|
||||
web_resource_requirements:
|
||||
requests:
|
||||
cpu: 250m
|
||||
cpu: 50m
|
||||
memory: 128M
|
||||
task_resource_requirements:
|
||||
requests:
|
||||
cpu: 250m
|
||||
cpu: 50m
|
||||
memory: 128M
|
||||
ee_resource_requirements:
|
||||
requests:
|
||||
cpu: 200m
|
||||
cpu: 50m
|
||||
memory: 64M
|
||||
|
||||
@@ -8,7 +8,7 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
env:
|
||||
- name: ANSIBLE_DEBUG_LOGS
|
||||
value: "TRUE"
|
||||
|
||||
@@ -8,5 +8,5 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
image: testing
|
||||
|
||||
@@ -8,5 +8,5 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
imagePullPolicy: Always
|
||||
|
||||
@@ -8,5 +8,5 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
||||
@@ -8,5 +8,5 @@ spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
- name: awx-manager
|
||||
imagePullPolicy: Never
|
||||
|
||||
51
docs/debugging.md
Normal file
51
docs/debugging.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Iterating on the installer without deploying the operator
|
||||
|
||||
Go through the [normal basic install](https://github.com/ansible/awx-operator/blob/devel/README.md#basic-install) steps.
|
||||
|
||||
Install some dependencies:
|
||||
|
||||
```
|
||||
$ ansible-galaxy collection install -r molecule/requirements.yml
|
||||
$ pip install -r molecule/requirements.txt
|
||||
```
|
||||
|
||||
To prevent the changes we're about to make from being overwritten, scale down any running instance of the operator:
|
||||
|
||||
```
|
||||
$ kubectl scale deployment awx-operator-controller-manager --replicas=0
|
||||
```
|
||||
|
||||
Create a playbook that invokes the installer role (the operator uses ansible-runner's role execution feature):
|
||||
|
||||
```yaml
|
||||
# run.yml
|
||||
---
|
||||
- hosts: localhost
|
||||
roles:
|
||||
- installer
|
||||
```
|
||||
|
||||
Create a vars file:
|
||||
|
||||
```yaml
|
||||
# vars.yml
|
||||
---
|
||||
ansible_operator_meta:
|
||||
name: awx
|
||||
namespace: awx
|
||||
service_type: nodeport
|
||||
```
|
||||
|
||||
Run the installer:
|
||||
|
||||
```
|
||||
$ ansible-playbook run.yml -e @vars.yml -v
|
||||
```
|
||||
|
||||
Grab the URL and admin password:
|
||||
|
||||
```
|
||||
$ minikube service awx-service --url -n awx
|
||||
$ minikube kubectl get secret awx-admin-password -- -o jsonpath="{.data.password}" | base64 --decode
|
||||
LU6lTfvnkjUvDwL240kXKy1sNhjakZmT
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: Build kustomize testing overlay
|
||||
# load_restrictor must be set to none so we can load patch files from the default overlay
|
||||
command: '{{ kustomize }} build --load_restrictor none .'
|
||||
command: '{{ kustomize }} build --load-restrictor LoadRestrictionsNone .'
|
||||
args:
|
||||
chdir: '{{ config_dir }}/testing'
|
||||
register: resources
|
||||
|
||||
@@ -21,6 +21,9 @@ provisioner:
|
||||
namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test}
|
||||
host_vars:
|
||||
localhost:
|
||||
awx_image: ${AWX_TEST_IMAGE:-""}
|
||||
awx_version: ${AWX_TEST_VERSION:-""}
|
||||
default_awx_version: "{{ lookup('url', 'https://api.github.com/repos/ansible/awx/releases/latest') | from_json | json_query('tag_name') }}"
|
||||
ansible_python_interpreter: '{{ ansible_playbook_python }}'
|
||||
config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config
|
||||
samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
k8s:
|
||||
state: present
|
||||
namespace: '{{ namespace }}'
|
||||
definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}"
|
||||
definition: "{{ lookup('template', 'awx_cr_molecule.yml.j2') | from_yaml }}"
|
||||
wait: yes
|
||||
wait_timeout: 900
|
||||
wait_condition:
|
||||
type: Running
|
||||
reason: Successful
|
||||
status: "True"
|
||||
vars:
|
||||
cr_file: 'awx_v1beta1_awx.yaml'
|
||||
|
||||
- name: Obtain generated admin password
|
||||
k8s_info:
|
||||
@@ -20,11 +18,68 @@
|
||||
name: example-awx-admin-password
|
||||
register: admin_pw_secret
|
||||
|
||||
- name: Launch Demo Job Template
|
||||
awx.awx.job_launch:
|
||||
name: Demo Job Template
|
||||
wait: yes
|
||||
validate_certs: no
|
||||
controller_host: localhost
|
||||
controller_username: admin
|
||||
controller_password: "{{ admin_pw_secret.resources[0].data.password | b64decode }}"
|
||||
- block:
|
||||
- name: Get pod details
|
||||
k8s_info:
|
||||
namespace: '{{ namespace }}'
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app.kubernetes.io/name = example-awx
|
||||
register: awx_pod
|
||||
when: not awx_version
|
||||
|
||||
- name: Exract tags from images
|
||||
set_fact:
|
||||
image_tags: |
|
||||
{{ awx_pod.resources[0].spec.containers |
|
||||
map(attribute='image') |
|
||||
map('regex_search', default_awx_version) }}
|
||||
when: not awx_version
|
||||
|
||||
- fail:
|
||||
msg: |
|
||||
It looks like you may have broken the DEFAULT_AWX_VERSION functionality.
|
||||
This is an environment variable that is set via build arg when releasing awx-operator.
|
||||
when:
|
||||
- not awx_version
|
||||
- default_awx_version not in image_tags
|
||||
|
||||
- name: Launch Demo Job Template
|
||||
awx.awx.job_launch:
|
||||
name: Demo Job Template
|
||||
wait: yes
|
||||
validate_certs: no
|
||||
controller_host: localhost/awx/
|
||||
controller_username: admin
|
||||
controller_password: "{{ admin_pw_secret.resources[0].data.password | b64decode }}"
|
||||
rescue:
|
||||
- name: Get list of project updates and jobs
|
||||
uri:
|
||||
url: "http://localhost/awx/api/v2/{{ resource }}/"
|
||||
user: admin
|
||||
password: "{{ admin_pw_secret.resources[0].data.password | b64decode }}"
|
||||
force_basic_auth: yes
|
||||
register: job_lists
|
||||
loop:
|
||||
- project_updates
|
||||
- jobs
|
||||
loop_control:
|
||||
loop_var: resource
|
||||
|
||||
- name: Get all job and project details
|
||||
uri:
|
||||
url: "http://localhost{{ endpoint }}"
|
||||
user: admin
|
||||
password: "{{ admin_pw_secret.resources[0].data.password | b64decode }}"
|
||||
force_basic_auth: yes
|
||||
loop: |
|
||||
{{ job_lists.results | map(attribute='json') | map(attribute='results') | flatten | map(attribute='url') }}
|
||||
loop_control:
|
||||
loop_var: endpoint
|
||||
|
||||
- name: Re-emit failure
|
||||
vars:
|
||||
failed_task:
|
||||
result: '{{ ansible_failed_result }}'
|
||||
fail:
|
||||
msg: '{{ failed_task }}'
|
||||
|
||||
31
molecule/default/templates/awx_cr_molecule.yml.j2
Normal file
31
molecule/default/templates/awx_cr_molecule.yml.j2
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
apiVersion: awx.ansible.com/v1beta1
|
||||
kind: AWX
|
||||
metadata:
|
||||
name: example-awx
|
||||
spec:
|
||||
{% if awx_image %}
|
||||
image: {{ awx_image }}
|
||||
{% endif %}
|
||||
{% if awx_version %}
|
||||
image_version: {{ awx_version }}
|
||||
{% endif %}
|
||||
ingress_type: ingress
|
||||
ingress_path: /awx
|
||||
ingress_annotations: |
|
||||
kubernetes.io/ingress.class: nginx
|
||||
web_resource_requirements:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32M
|
||||
task_resource_requirements:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32M
|
||||
ee_resource_requirements:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 16M
|
||||
postgres_resource_requirements: {}
|
||||
postgres_init_container_resource_requirements: {}
|
||||
redis_resource_requirements: {}
|
||||
@@ -36,7 +36,7 @@
|
||||
k8s_log:
|
||||
name: '{{ item.metadata.name }}'
|
||||
namespace: '{{ namespace }}'
|
||||
container: manager
|
||||
container: awx-manager
|
||||
loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}"
|
||||
register: debug_logs
|
||||
|
||||
|
||||
@@ -10,15 +10,25 @@
|
||||
build:
|
||||
path: '{{ project_dir }}'
|
||||
pull: no
|
||||
args:
|
||||
DEFAULT_AWX_VERSION: '{{ default_awx_version }}'
|
||||
name: '{{ operator_image }}'
|
||||
tag: latest
|
||||
push: no
|
||||
source: build
|
||||
force_source: yes
|
||||
|
||||
- name: Load image into kind cluster
|
||||
- name: Load operator image into kind cluster
|
||||
command: kind load docker-image --name osdk-test '{{ operator_image }}'
|
||||
register: result
|
||||
changed_when: '"not yet present" in result.stdout'
|
||||
|
||||
- name: Load awx image into kind cluster
|
||||
command: kind load docker-image --name osdk-test '{{ awx_image }}:{{ awx_version }}'
|
||||
register: result
|
||||
changed_when: '"not yet present" in result.stdout'
|
||||
when:
|
||||
- awx_image is defined
|
||||
- awx_image != ''
|
||||
|
||||
- import_playbook: ../default/converge.yml
|
||||
|
||||
@@ -23,7 +23,10 @@ provisioner:
|
||||
namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test}
|
||||
host_vars:
|
||||
localhost:
|
||||
awx_image: ${AWX_TEST_IMAGE:-""}
|
||||
awx_version: ${AWX_TEST_VERSION:-""}
|
||||
ansible_python_interpreter: '{{ ansible_playbook_python }}'
|
||||
default_awx_version: "{{ lookup('url', 'https://api.github.com/repos/ansible/awx/releases/latest') | from_json | json_query('tag_name') }}"
|
||||
config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config
|
||||
samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples
|
||||
project_dir: ${MOLECULE_PROJECT_DIRECTORY}
|
||||
|
||||
@@ -2,6 +2,6 @@ molecule
|
||||
molecule-docker
|
||||
yamllint
|
||||
ansible-lint
|
||||
openshift
|
||||
openshift!=0.13.0
|
||||
jmespath
|
||||
ansible-core
|
||||
|
||||
@@ -74,7 +74,12 @@ To check the name of this secret, look at the postgresConfigurationSecret status
|
||||
The postgresql pod for the old deployment is used when backing up data to the new postgresql pod. If your postgresql pod has a custom label,
|
||||
you can pass that via the `postgres_label_selector` variable to make sure the postgresql pod can be found.
|
||||
|
||||
It is also possible to tie the lifetime of the backup files to that of the AWXBackup resource object. To do that you can set the
|
||||
`clean_backup_on_delete` value to true. This will delete the `backupDirectory` on the pvc associated with the AWXBackup object deleted.
|
||||
|
||||
```
|
||||
clean_backup_on_delete: true
|
||||
```
|
||||
Testing
|
||||
----------------
|
||||
|
||||
|
||||
@@ -10,3 +10,15 @@ backup_pvc_namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
|
||||
# Size of backup PVC if created dynamically
|
||||
backup_storage_requirements: ''
|
||||
|
||||
# Set no_log settings on certain tasks
|
||||
no_log: 'true'
|
||||
|
||||
# Variable to set when you want backups to be cleaned up when the CRD object is deleted
|
||||
clean_backup_on_delete: false
|
||||
|
||||
# Variable to signal that this role is being run as a finalizer
|
||||
finalizer_run: false
|
||||
|
||||
# Allow additional parameters to be added to the pg_dump backup command
|
||||
pg_dump_suffix: ''
|
||||
|
||||
47
roles/backup/tasks/creation.yml
Normal file
47
roles/backup/tasks/creation.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
- name: Patching labels to {{ kind }} kind
|
||||
k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: "{{ api_version }}"
|
||||
kind: "{{ kind }}"
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
metadata:
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
labels:
|
||||
app.kubernetes.io/name: "{{ ansible_operator_meta.name }}"
|
||||
app.kubernetes.io/part-of: "{{ ansible_operator_meta.name }}"
|
||||
app.kubernetes.io/managed-by: "{{ deployment_type }}-operator"
|
||||
app.kubernetes.io/component: "{{ deployment_type }}"
|
||||
app.kubernetes.io/operator-version: '{{ lookup("env", "OPERATOR_VERSION") }}'
|
||||
|
||||
- name: Look up details for this backup object
|
||||
k8s_info:
|
||||
api_version: "{{ api_version }}"
|
||||
kind: "{{ kind }}"
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
register: this_backup
|
||||
|
||||
- block:
|
||||
- include_tasks: init.yml
|
||||
|
||||
- include_tasks: postgres.yml
|
||||
|
||||
- include_tasks: awx-cro.yml
|
||||
|
||||
- include_tasks: secrets.yml
|
||||
|
||||
- name: Set flag signifying this backup was successful
|
||||
set_fact:
|
||||
backup_complete: true
|
||||
|
||||
- include_tasks: cleanup.yml
|
||||
|
||||
when:
|
||||
- this_backup['resources'][0]['status']['backupDirectory'] is not defined
|
||||
|
||||
- name: Update status variables
|
||||
include_tasks: update_status.yml
|
||||
7
roles/backup/tasks/delete_backup.yml
Normal file
7
roles/backup/tasks/delete_backup.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Cleanup backup associated with this option if enabled
|
||||
k8s_exec:
|
||||
namespace: "{{ backup_pvc_namespace }}"
|
||||
pod: "{{ ansible_operator_meta.name }}-db-management"
|
||||
command: >-
|
||||
bash -c 'rm -rf {{ backup_dir }}'
|
||||
@@ -25,15 +25,15 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: "{{ _name }}"
|
||||
register: _secret
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set secret data
|
||||
set_fact:
|
||||
_data: "{{ _secret['resources'][0]['data'] }}"
|
||||
_type: "{{ _secret['resources'][0]['type'] }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Create and Add secret names and data to dictionary
|
||||
set_fact:
|
||||
secret_dict: "{{ secret_dict | default({}) | combine({ item: {'name': _name, 'data': _data, 'type': _type }}) }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: "{{ _name }}"
|
||||
register: _secret
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set secret key
|
||||
set_fact:
|
||||
_data: "{{ _secret['resources'][0]['data'] }}"
|
||||
_type: "{{ _secret['resources'][0]['type'] }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Create and Add secret names and data to dictionary
|
||||
set_fact:
|
||||
secret_dict: "{{ secret_dict | default({}) | combine({item: { 'name': _name, 'data': _data, 'type': _type }}) }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: _name != ''
|
||||
|
||||
19
roles/backup/tasks/finalizer.yml
Normal file
19
roles/backup/tasks/finalizer.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Look up details for this backup object
|
||||
k8s_info:
|
||||
api_version: "{{ api_version }}"
|
||||
kind: "{{ kind }}"
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
register: this_backup
|
||||
|
||||
- block:
|
||||
- include_tasks: init.yml
|
||||
|
||||
- include_tasks: delete_backup.yml
|
||||
|
||||
- include_tasks: cleanup.yml
|
||||
vars:
|
||||
backup_dir: "{{ this_backup['resources'][0]['status']['backupDirectory'] }}"
|
||||
when:
|
||||
- clean_backup_on_delete and backup_dir is defined
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
|
||||
- name: Delete any existing management pod
|
||||
k8s:
|
||||
name: "{{ ansible_operator_meta.name }}-db-management"
|
||||
@@ -57,12 +56,27 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: '{{ deployment_name }}-backup-claim'
|
||||
namespace: '{{ backup_pvc_namespace }}'
|
||||
name: "{{ deployment_name }}-backup-claim"
|
||||
namespace: "{{ backup_pvc_namespace }}"
|
||||
ownerReferences: null
|
||||
when:
|
||||
- backup_pvc == '' or backup_pvc is not defined
|
||||
|
||||
- name: Set default postgres image
|
||||
set_fact:
|
||||
_default_postgres_image: "{{ _postgres_image }}:{{_postgres_image_version }}"
|
||||
|
||||
- name: Set user provided postgres image
|
||||
set_fact:
|
||||
_custom_postgres_image: "{{ postgres_image }}:{{ postgres_image_version }}"
|
||||
when:
|
||||
- postgres_image | default([]) | length
|
||||
- postgres_image_version is defined and postgres_image_version != ''
|
||||
|
||||
- name: Set Postgres image URL
|
||||
set_fact:
|
||||
_postgres_image: "{{ _custom_postgres_image | default(lookup('env', 'RELATED_IMAGE_AWX_POSTGRES')) | default(_default_postgres_image, true) }}"
|
||||
|
||||
- name: Create management pod from templated deployment config
|
||||
k8s:
|
||||
name: "{{ ansible_operator_meta.name }}-db-management"
|
||||
|
||||
@@ -1,47 +1,8 @@
|
||||
---
|
||||
- name: Patching labels to {{ kind }} kind
|
||||
k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: '{{ api_version }}'
|
||||
kind: '{{ kind }}'
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
metadata:
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
labels:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
app.kubernetes.io/operator-version: '{{ lookup("env", "OPERATOR_VERSION") }}'
|
||||
- name: Run creation tasks
|
||||
include_tasks: creation.yml
|
||||
when: not finalizer_run
|
||||
|
||||
- name: Look up details for this backup object
|
||||
k8s_info:
|
||||
api_version: "{{ api_version }}"
|
||||
kind: "{{ kind }}"
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
register: this_backup
|
||||
|
||||
- block:
|
||||
- include_tasks: init.yml
|
||||
|
||||
- include_tasks: postgres.yml
|
||||
|
||||
- include_tasks: awx-cro.yml
|
||||
|
||||
- include_tasks: secrets.yml
|
||||
|
||||
- name: Set flag signifying this backup was successful
|
||||
set_fact:
|
||||
backup_complete: true
|
||||
|
||||
- include_tasks: cleanup.yml
|
||||
|
||||
when:
|
||||
- this_backup['resources'][0]['status']['backupDirectory'] is not defined
|
||||
|
||||
- name: Update status variables
|
||||
include_tasks: update_status.yml
|
||||
- name: Run finalizer tasks
|
||||
include_tasks: finalizer.yml
|
||||
when: finalizer_run
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: "{{ this_awx['resources'][0]['status']['postgresConfigurationSecret'] }}"
|
||||
register: pg_config
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Fail if postgres configuration secret status does not exist
|
||||
fail:
|
||||
@@ -21,7 +21,7 @@
|
||||
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
|
||||
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
|
||||
awx_postgres_type: "{{ pg_config['resources'][0]['data']['type'] | default('unmanaged'|b64encode) | b64decode }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- block:
|
||||
- name: Delete pod to reload a resource configuration
|
||||
@@ -39,6 +39,7 @@
|
||||
until:
|
||||
- "postgres_pod['resources'] | length"
|
||||
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
|
||||
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
|
||||
delay: 5
|
||||
retries: 60
|
||||
|
||||
@@ -79,7 +80,7 @@
|
||||
- name: Set full resolvable host name for postgres pod
|
||||
set_fact:
|
||||
resolvable_db_host: '{{ (awx_postgres_type == "managed") | ternary(awx_postgres_host + "." + ansible_operator_meta.namespace + ".svc.cluster.local", awx_postgres_host) }}' # yamllint disable-line rule:line-length
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set pg_dump command
|
||||
set_fact:
|
||||
@@ -90,7 +91,8 @@
|
||||
-d {{ awx_postgres_database }}
|
||||
-p {{ awx_postgres_port }}
|
||||
-F custom
|
||||
no_log: true
|
||||
{{ pg_dump_suffix }}
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Write pg_dump to backup on PVC
|
||||
k8s_exec:
|
||||
@@ -99,9 +101,9 @@
|
||||
command: |
|
||||
bash -c """
|
||||
set -e -o pipefail
|
||||
PGPASSWORD={{ awx_postgres_pass }} {{ pgdump }} > {{ backup_dir }}/tower.db
|
||||
PGPASSWORD='{{ awx_postgres_pass }}' {{ pgdump }} > {{ backup_dir }}/tower.db
|
||||
echo 'Successful'
|
||||
"""
|
||||
register: data_migration
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
failed_when: "'Successful' not in data_migration.stdout"
|
||||
|
||||
@@ -21,13 +21,25 @@
|
||||
- ingress_tls_secret
|
||||
- ldap_cacert_secret
|
||||
- bundle_cacert_secret
|
||||
- image_pull_secret
|
||||
- ee_pull_credentials_secret
|
||||
|
||||
# image_pull_secret is deprecated in favor of image_pull_secrets
|
||||
- name: Dump image_pull_secret into file
|
||||
include_tasks: dump_secret.yml
|
||||
with_items:
|
||||
- image_pull_secret
|
||||
when: image_pull_secret is defined
|
||||
|
||||
- name: Dump image_pull_secrets into file
|
||||
include_tasks: dump_secret.yml
|
||||
with_items:
|
||||
- image_pull_secrets
|
||||
when: image_pull_secrets | default([]) | length
|
||||
|
||||
- name: Nest secrets under a single variable
|
||||
set_fact:
|
||||
secrets: {"secrets": '{{ secret_dict }}'}
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Write postgres configuration to pvc
|
||||
k8s_exec:
|
||||
@@ -35,4 +47,4 @@
|
||||
pod: "{{ ansible_operator_meta.name }}-db-management"
|
||||
command: >-
|
||||
bash -c "echo '{{ secrets | to_yaml }}' > {{ backup_dir }}/secrets.yml"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
@@ -13,7 +13,7 @@ metadata:
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ ansible_operator_meta.name }}-db-management
|
||||
image: "{{ postgres_image }}:{{ postgres_image_version }}"
|
||||
image: "{{ _postgres_image }}"
|
||||
imagePullPolicy: Always
|
||||
command: ["sleep", "infinity"]
|
||||
volumeMounts:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
deployment_type: "awx"
|
||||
postgres_image: postgres
|
||||
postgres_image_version: 12
|
||||
_postgres_image: postgres
|
||||
_postgres_image_version: 12
|
||||
backup_complete: false
|
||||
database_type: "unmanaged"
|
||||
|
||||
@@ -10,6 +10,7 @@ task_privileged: false
|
||||
service_type: ClusterIP
|
||||
ingress_type: none
|
||||
ingress_path: '/'
|
||||
ingress_path_type: 'Prefix'
|
||||
# Add annotations to the service account. Specify as literal block. E.g.:
|
||||
# service_account_annotations: |
|
||||
# eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/<IAM_ROLE_NAME>
|
||||
@@ -35,7 +36,7 @@ ingress_tls_secret: ''
|
||||
|
||||
loadbalancer_protocol: 'http'
|
||||
loadbalancer_port: '80'
|
||||
loadbalancer_annotations: ''
|
||||
service_annotations: ''
|
||||
|
||||
nodeport_port: '30080'
|
||||
# The TLS termination mechanism to use to access
|
||||
@@ -63,6 +64,17 @@ hostname: ''
|
||||
# kubernetes.io/os: linux
|
||||
node_selector: ''
|
||||
|
||||
# Add a topologySpreadConstraints for the AWX pods.
|
||||
# Specify as literal block. E.g.:
|
||||
# topology_spread_constraints: |
|
||||
# - maxSkew: 100
|
||||
# topologyKey: "topology.kubernetes.io/zone"
|
||||
# whenUnsatisfiable: "ScheduleAnyway"
|
||||
# labelSelector:
|
||||
# matchLabels:
|
||||
# app.kubernetes.io/name: "<resourcename>"
|
||||
topology_spread_constraints: ''
|
||||
|
||||
# Add node tolerations for the AWX pods. Specify as literal block. E.g.:
|
||||
# tolerations: |
|
||||
# - key: "dedicated"
|
||||
@@ -71,6 +83,12 @@ node_selector: ''
|
||||
# effect: "NoSchedule"
|
||||
tolerations: ''
|
||||
|
||||
# Add annotations to awx pods. Specify as literal block. E.g.:
|
||||
# annotations: |
|
||||
# my.annotation/1: value
|
||||
# my.annotation/2: value2
|
||||
annotations: ''
|
||||
|
||||
admin_user: admin
|
||||
admin_email: test@example.com
|
||||
|
||||
@@ -106,16 +124,16 @@ extra_volumes: ''
|
||||
|
||||
# Use these image versions for Ansible AWX.
|
||||
|
||||
image: quay.io/ansible/awx
|
||||
image_version: 19.4.0
|
||||
redis_image: docker.io/redis
|
||||
redis_image_version: latest
|
||||
postgres_image: postgres
|
||||
postgres_image_version: 12
|
||||
init_container_image: quay.io/centos/centos
|
||||
init_container_image_version: 8
|
||||
_image: quay.io/ansible/awx
|
||||
_image_version: "{{ lookup('env', 'DEFAULT_AWX_VERSION') or 'latest' }}"
|
||||
_redis_image: docker.io/redis
|
||||
_redis_image_version: 7
|
||||
_postgres_image: postgres
|
||||
_postgres_image_version: 12
|
||||
_init_container_image: quay.io/centos/centos
|
||||
_init_container_image_version: stream8
|
||||
image_pull_policy: IfNotPresent
|
||||
image_pull_secret: ''
|
||||
image_pull_secrets: []
|
||||
|
||||
# Extra commands which will be appended to the initContainer
|
||||
# Make sure that each command entered return an exit code 0
|
||||
@@ -137,7 +155,7 @@ ee_images:
|
||||
- name: AWX EE (latest)
|
||||
image: quay.io/ansible/awx-ee:latest
|
||||
|
||||
control_plane_ee_image: quay.io/ansible/awx-ee:latest
|
||||
_control_plane_ee_image: quay.io/ansible/awx-ee:latest
|
||||
|
||||
create_preload_data: true
|
||||
|
||||
@@ -146,24 +164,36 @@ replicas: "1"
|
||||
task_args:
|
||||
- /usr/bin/launch_awx_task.sh
|
||||
task_command: []
|
||||
web_args: []
|
||||
web_args:
|
||||
- /usr/bin/launch_awx.sh
|
||||
web_command: []
|
||||
|
||||
task_resource_requirements:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
|
||||
web_resource_requirements:
|
||||
requests:
|
||||
cpu: 1000m
|
||||
memory: 2Gi
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
|
||||
ee_resource_requirements:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
|
||||
# Customize CSRF options
|
||||
csrf_cookie_secure: False
|
||||
session_cookie_secure: False
|
||||
|
||||
# Assign a preexisting priority class to the control plane pods
|
||||
control_plane_priority_class: ''
|
||||
|
||||
redis_resource_requirements:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
# Add extra environment variables to the AWX task/web containers. Specify as
|
||||
# literal block. E.g.:
|
||||
# task_extra_env: |
|
||||
@@ -204,7 +234,16 @@ postgres_tolerations: ''
|
||||
postgres_storage_requirements:
|
||||
requests:
|
||||
storage: 8Gi
|
||||
postgres_resource_requirements: {}
|
||||
postgres_resource_requirements:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
postgres_init_container_resource_requirements:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
# Assign a preexisting priority class to the postgres pod
|
||||
postgres_priority_class: ''
|
||||
postgres_data_path: '/var/lib/postgresql/data/pgdata'
|
||||
|
||||
# Persistence to the AWX project data folder
|
||||
@@ -214,6 +253,9 @@ projects_persistence: false
|
||||
# Define an existing PersistentVolumeClaim to use
|
||||
projects_existing_claim: ''
|
||||
#
|
||||
# Define postgres configuration arguments to use
|
||||
postgres_extra_args: ''
|
||||
|
||||
# Define the storage_class, size and access_mode
|
||||
# when not using an existing claim
|
||||
projects_storage_size: 8Gi
|
||||
@@ -225,6 +267,9 @@ ca_trust_bundle: "/etc/pki/tls/certs/ca-bundle.crt"
|
||||
#
|
||||
ldap_cacert_secret: ''
|
||||
|
||||
# Secret to lookup that provides the LDAP bind password
|
||||
ldap_password_secret: ''
|
||||
|
||||
# Secret to lookup that provides the custom CA trusted bundle
|
||||
bundle_cacert_secret: ''
|
||||
|
||||
@@ -234,3 +279,12 @@ bundle_cacert_secret: ''
|
||||
garbage_collect_secrets: false
|
||||
|
||||
development_mode: false
|
||||
|
||||
security_context_settings: {}
|
||||
|
||||
# Set no_log settings on certain tasks
|
||||
no_log: 'true'
|
||||
|
||||
# Should AWX instances be automatically upgraded when operator gets upgraded
|
||||
#
|
||||
auto_upgrade: true
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ admin_password_secret }}'
|
||||
register: _custom_admin_password
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: admin_password_secret | length
|
||||
|
||||
- name: Check for default admin password configuration
|
||||
@@ -14,19 +14,19 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-admin-password'
|
||||
register: _default_admin_password
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set admin password secret
|
||||
set_fact:
|
||||
_admin_password_secret: '{{ _custom_admin_password["resources"] | default([]) | length | ternary(_custom_admin_password, _default_admin_password) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- block:
|
||||
- name: Create admin password secret
|
||||
k8s:
|
||||
apply: true
|
||||
definition: "{{ lookup('template', 'admin_password_secret.yaml.j2') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Read admin password secret
|
||||
k8s_info:
|
||||
@@ -34,16 +34,16 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-admin-password'
|
||||
register: _generated_admin_password
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
when: not _admin_password_secret['resources'] | default([]) | length
|
||||
|
||||
- name: Set admin password secret
|
||||
set_fact:
|
||||
__admin_password_secret: '{{ _generated_admin_password["resources"] | default([]) | length | ternary(_generated_admin_password, _admin_password_secret) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Store admin password
|
||||
set_fact:
|
||||
admin_password: "{{ __admin_password_secret['resources'][0]['data']['password'] | b64decode }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ broadcast_websocket_secret }}'
|
||||
register: _custom_broadcast_websocket
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: broadcast_websocket_secret | length
|
||||
|
||||
- name: Check for default broadcast websocket secret configuration
|
||||
@@ -14,20 +14,20 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-broadcast-websocket'
|
||||
register: _default_broadcast_websocket
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set broadcast websocket secret
|
||||
set_fact:
|
||||
# yamllint disable-line rule:line-length
|
||||
_broadcast_websocket_secret: '{{ _custom_broadcast_websocket["resources"] | default([]) | length | ternary(_custom_broadcast_websocket, _default_broadcast_websocket) }}' # noqa 204
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- block:
|
||||
- name: Create broadcast websocket secret
|
||||
k8s:
|
||||
apply: true
|
||||
definition: "{{ lookup('template', 'broadcast_websocket_secret.yaml.j2') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Read broadcast websocket secret
|
||||
k8s_info:
|
||||
@@ -35,7 +35,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-broadcast-websocket'
|
||||
register: _generated_broadcast_websocket
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
when: not _broadcast_websocket_secret['resources'] | default([]) | length
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
set_fact:
|
||||
# yamllint disable-line rule:line-length
|
||||
__broadcast_websocket_secret: '{{ _generated_broadcast_websocket["resources"] | default([]) | length | ternary(_generated_broadcast_websocket, _broadcast_websocket_secret) }}' # noqa 204
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Store broadcast websocket secret name
|
||||
set_fact:
|
||||
broadcast_websocket_secret_value: "{{ __broadcast_websocket_secret['resources'][0]['data']['secret'] | b64decode }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
- '{{ _secret_key }}'
|
||||
- '{{ _postgres_configuration }}'
|
||||
- '{{ _broadcast_websocket_secret }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
when: not garbage_collect_secrets | bool
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
name: '{{ postgres_configuration_secret }}'
|
||||
register: _custom_pg_config_resources
|
||||
when: postgres_configuration_secret | length
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Check for default PostgreSQL configuration
|
||||
k8s_info:
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-postgres-configuration'
|
||||
register: _default_pg_config_resources
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Check for specified old PostgreSQL configuration secret
|
||||
k8s_info:
|
||||
@@ -23,7 +23,7 @@
|
||||
name: '{{ old_postgres_configuration_secret }}'
|
||||
register: _custom_old_pg_config_resources
|
||||
when: old_postgres_configuration_secret | length
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Check for default old PostgreSQL configuration
|
||||
k8s_info:
|
||||
@@ -31,7 +31,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-old-postgres-configuration'
|
||||
register: _default_old_pg_config_resources
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set old PostgreSQL configuration
|
||||
set_fact:
|
||||
@@ -45,19 +45,34 @@
|
||||
when:
|
||||
- old_pg_config['resources'] is defined
|
||||
- old_pg_config['resources'] | length
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set default postgres image
|
||||
set_fact:
|
||||
_default_postgres_image: "{{ _postgres_image }}:{{_postgres_image_version }}"
|
||||
|
||||
- name: Set PostgreSQL configuration
|
||||
set_fact:
|
||||
_pg_config: '{{ _custom_pg_config_resources["resources"] | default([]) | length | ternary(_custom_pg_config_resources, _default_pg_config_resources) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set user provided postgres image
|
||||
set_fact:
|
||||
_custom_postgres_image: "{{ postgres_image }}:{{ postgres_image_version }}"
|
||||
when:
|
||||
- postgres_image | default([]) | length
|
||||
- postgres_image_version is defined and postgres_image_version != ''
|
||||
|
||||
- name: Set Postgres image URL
|
||||
set_fact:
|
||||
_postgres_image: "{{ _custom_postgres_image | default(lookup('env', 'RELATED_IMAGE_AWX_POSTGRES')) | default(_default_postgres_image, true) }}"
|
||||
|
||||
- block:
|
||||
- name: Create Database configuration
|
||||
k8s:
|
||||
apply: true
|
||||
definition: "{{ lookup('template', 'postgres_secret.yaml.j2') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Read Database Configuration
|
||||
k8s_info:
|
||||
@@ -65,13 +80,13 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-postgres-configuration'
|
||||
register: _generated_pg_config_resources
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: not _pg_config['resources'] | default([]) | length
|
||||
|
||||
- name: Set PostgreSQL Configuration
|
||||
set_fact:
|
||||
pg_config: '{{ _generated_pg_config_resources["resources"] | default([]) | length | ternary(_generated_pg_config_resources, _pg_config) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set actual postgres configuration secret used
|
||||
set_fact:
|
||||
@@ -84,6 +99,10 @@
|
||||
definition: "{{ lookup('template', 'postgres.yaml.j2') }}"
|
||||
register: create_statefulset_result
|
||||
|
||||
- name: Scale down Deployment for migration
|
||||
include_tasks: scale_down_deployment.yml
|
||||
when: create_statefulset_result.changed
|
||||
|
||||
rescue:
|
||||
- name: Scale down Deployment for migration
|
||||
include_tasks: scale_down_deployment.yml
|
||||
@@ -121,7 +140,27 @@
|
||||
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
|
||||
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
|
||||
awx_postgres_sslmode: "{{ pg_config['resources'][0]['data']['sslmode'] | default('prefer'|b64encode) | b64decode }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Wait for Database to initialize if managed DB
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-postgres-0' # using name to keep compatibility
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
register: postgres_pod
|
||||
until:
|
||||
- "postgres_pod['resources'] | length"
|
||||
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
|
||||
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
|
||||
delay: 5
|
||||
retries: 60
|
||||
when: pg_config['resources'][0]['data']['type'] | default('') | b64decode == 'managed'
|
||||
|
||||
- name: Set database as managed
|
||||
set_fact:
|
||||
managed_database: "{{ pg_config['resources'][0]['data']['type'] | default('') | b64decode == 'managed' }}"
|
||||
|
||||
- name: Look up details for this deployment
|
||||
k8s_info:
|
||||
|
||||
@@ -13,18 +13,6 @@
|
||||
register: users_result
|
||||
changed_when: users_result.return_code > 0
|
||||
|
||||
- name: Update super user password via Django if it does exist (same password is a noop)
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage update_password --username '{{ admin_user }}' --password '{{ admin_password }}'"
|
||||
register: update_pw_result
|
||||
changed_when: users_result.stdout == 'Password not updated'
|
||||
no_log: true
|
||||
when: users_result.return_code == 0
|
||||
|
||||
- name: Create super user via Django if it doesn't exist.
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
@@ -34,20 +22,9 @@
|
||||
bash -c "echo \"from django.contrib.auth.models import User;
|
||||
User.objects.create_superuser('{{ admin_user }}', '{{ admin_email }}', '{{ admin_password }}')\"
|
||||
| awx-manage shell"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: users_result.return_code > 0
|
||||
|
||||
- name: Create preload data if necessary. # noqa 305
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage create_preload_data"
|
||||
register: cdo
|
||||
changed_when: "'added' in cdo.stdout"
|
||||
when: create_preload_data | bool
|
||||
|
||||
- name: Check if legacy queue is present
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
@@ -80,7 +57,7 @@
|
||||
_execution_environments_pull_credentials: >-
|
||||
{{ _custom_execution_environments_pull_credentials["resources"] | default([]) | length
|
||||
| ternary(_custom_execution_environments_pull_credentials, []) }}
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Register default execution environments (without authentication)
|
||||
k8s_exec:
|
||||
@@ -101,7 +78,7 @@
|
||||
default_execution_environment_pull_credentials_url: "{{ _execution_environments_pull_credentials['resources'][0]['data']['url'] | b64decode }}"
|
||||
default_execution_environment_pull_credentials_url_verify: >-
|
||||
{{ _execution_environments_pull_credentials['resources'][0]['data']['ssl_verify'] | default("True"|b64encode) | b64decode }}
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Register default execution environments (with authentication)
|
||||
k8s_exec:
|
||||
@@ -116,5 +93,16 @@
|
||||
--verify-ssl='{{ default_execution_environment_pull_credentials_url_verify }}'"
|
||||
register: ree
|
||||
changed_when: "'changed: True' in ree.stdout"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: _execution_environments_pull_credentials['resources'] | default([]) | length
|
||||
|
||||
- name: Create preload data if necessary. # noqa 305
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage create_preload_data"
|
||||
register: cdo
|
||||
changed_when: "'added' in cdo.stdout"
|
||||
when: create_preload_data | bool
|
||||
|
||||
88
roles/installer/tasks/install.yml
Normal file
88
roles/installer/tasks/install.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
- name: Patching labels to AWX kind
|
||||
k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: '{{ api_version }}'
|
||||
kind: '{{ kind }}'
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
metadata:
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
labels:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
app.kubernetes.io/operator-version: '{{ lookup("env", "OPERATOR_VERSION") }}'
|
||||
|
||||
- name: Include secret key configuration tasks
|
||||
include_tasks: secret_key_configuration.yml
|
||||
|
||||
- name: Load LDAP CAcert certificate
|
||||
include_tasks: load_ldap_cacert_secret.yml
|
||||
when:
|
||||
- ldap_cacert_secret != ''
|
||||
|
||||
- name: Load ldap bind password
|
||||
include_tasks: load_ldap_password_secret.yml
|
||||
when:
|
||||
- ldap_password_secret != ''
|
||||
|
||||
- name: Load bundle certificate authority certificate
|
||||
include_tasks: load_bundle_cacert_secret.yml
|
||||
when:
|
||||
- bundle_cacert_secret != ''
|
||||
|
||||
- name: Include admin password configuration tasks
|
||||
include_tasks: admin_password_configuration.yml
|
||||
|
||||
- name: Include broadcast websocket configuration tasks
|
||||
include_tasks: broadcast_websocket_configuration.yml
|
||||
|
||||
- name: Include set_images tasks
|
||||
include_tasks: set_images.yml
|
||||
|
||||
- name: Include database configuration tasks
|
||||
include_tasks: database_configuration.yml
|
||||
|
||||
- name: Load Route TLS certificate
|
||||
include_tasks: load_route_tls_secret.yml
|
||||
when:
|
||||
- ingress_type | lower == 'route'
|
||||
- route_tls_secret != ''
|
||||
|
||||
- name: Include resources configuration tasks
|
||||
include_tasks: resources_configuration.yml
|
||||
|
||||
- name: Check for pending migrations
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
|
||||
changed_when: false
|
||||
register: database_check
|
||||
|
||||
- name: Migrate the database if the K8s resources were updated. # noqa 305
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage migrate --noinput"
|
||||
register: migrate_result
|
||||
when:
|
||||
- database_check is defined
|
||||
- (database_check.stdout|trim) != '0'
|
||||
|
||||
- name: Initialize Django
|
||||
include_tasks: initialize_django.yml
|
||||
|
||||
- name: Update status variables
|
||||
include_tasks: update_status.yml
|
||||
|
||||
- name: Cleanup & Set garbage collection refs
|
||||
include_tasks: cleanup.yml
|
||||
@@ -5,10 +5,10 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ bundle_cacert_secret }}'
|
||||
register: bundle_cacert
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Load bundle Certificate Authority Secret content
|
||||
set_fact:
|
||||
bundle_ca_crt: '{{ bundle_cacert["resources"][0]["data"]["bundle-ca.crt"] | b64decode }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: '"bundle-ca.crt" in bundle_cacert["resources"][0]["data"]'
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ldap_cacert_secret }}'
|
||||
register: ldap_cacert
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Load LDAP CA Certificate Secret content
|
||||
set_fact:
|
||||
ldap_cacert_ca_crt: '{{ ldap_cacert["resources"][0]["data"]["ldap-ca.crt"] | b64decode }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: '"ldap-ca.crt" in ldap_cacert["resources"][0]["data"]'
|
||||
|
||||
14
roles/installer/tasks/load_ldap_password_secret.yml
Normal file
14
roles/installer/tasks/load_ldap_password_secret.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Retrieve LDAP bind password Secret
|
||||
k8s_info:
|
||||
kind: Secret
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ldap_password_secret }}'
|
||||
register: ldap_password
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Load LDAP bind password Secret content
|
||||
set_fact:
|
||||
ldap_bind_password: '{{ ldap_password["resources"][0]["data"]["ldap-password"] | b64decode }}'
|
||||
no_log: "{{ no_log }}"
|
||||
when: '"ldap-password" in ldap_password["resources"][0]["data"]'
|
||||
@@ -5,16 +5,16 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ route_tls_secret }}'
|
||||
register: route_tls
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Load Route TLS Secret content
|
||||
set_fact:
|
||||
route_tls_key: '{{ route_tls["resources"][0]["data"]["tls.key"] | b64decode }}'
|
||||
route_tls_crt: '{{ route_tls["resources"][0]["data"]["tls.crt"] | b64decode }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Load Route TLS Secret content
|
||||
set_fact:
|
||||
route_ca_crt: '{{ route_tls["resources"][0]["data"]["ca.crt"] | b64decode }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: '"ca.crt" in route_tls["resources"][0]["data"]'
|
||||
|
||||
@@ -1,80 +1,13 @@
|
||||
---
|
||||
- name: Patching labels to AWX kind
|
||||
k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: '{{ api_version }}'
|
||||
kind: '{{ kind }}'
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
metadata:
|
||||
name: '{{ ansible_operator_meta.name }}'
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
labels:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
app.kubernetes.io/operator-version: '{{ lookup("env", "OPERATOR_VERSION") }}'
|
||||
|
||||
- name: Include secret key configuration tasks
|
||||
include_tasks: secret_key_configuration.yml
|
||||
|
||||
- name: Load LDAP CAcert certificate
|
||||
include_tasks: load_ldap_cacert_secret.yml
|
||||
when:
|
||||
- ldap_cacert_secret != ''
|
||||
|
||||
- name: Load bundle certificate authority certificate
|
||||
include_tasks: load_bundle_cacert_secret.yml
|
||||
when:
|
||||
- bundle_cacert_secret != ''
|
||||
|
||||
- name: Include admin password configuration tasks
|
||||
include_tasks: admin_password_configuration.yml
|
||||
|
||||
- name: Include broadcast websocket configuration tasks
|
||||
include_tasks: broadcast_websocket_configuration.yml
|
||||
|
||||
- name: Include database configuration tasks
|
||||
include_tasks: database_configuration.yml
|
||||
|
||||
- name: Load Route TLS certificate
|
||||
include_tasks: load_route_tls_secret.yml
|
||||
when:
|
||||
- ingress_type | lower == 'route'
|
||||
- route_tls_secret != ''
|
||||
|
||||
- name: Include resources configuration tasks
|
||||
include_tasks: resources_configuration.yml
|
||||
|
||||
- name: Check for pending migrations
|
||||
k8s_exec:
|
||||
- name: Check for presence of Deployment
|
||||
k8s_info:
|
||||
api_version: v1
|
||||
kind: Deployment
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
|
||||
changed_when: false
|
||||
register: database_check
|
||||
register: tower_deployment
|
||||
|
||||
- name: Migrate the database if the K8s resources were updated. # noqa 305
|
||||
k8s_exec:
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ ansible_operator_meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage migrate --noinput"
|
||||
register: migrate_result
|
||||
when:
|
||||
- database_check is defined
|
||||
- (database_check.stdout|trim) != '0'
|
||||
|
||||
- name: Initialize Django
|
||||
include_tasks: initialize_django.yml
|
||||
|
||||
- name: Update status variables
|
||||
include_tasks: update_status.yml
|
||||
|
||||
- name: Cleanup & Set garbage collection refs
|
||||
include_tasks: cleanup.yml
|
||||
# Just execute deployment steps when auto_upgrade is true or when no deployment exists
|
||||
- name: Start installation
|
||||
include_tasks: install.yml
|
||||
when: (tower_deployment['resources'] | length > 0 and auto_upgrade | bool ) or (tower_deployment['resources'] | length == 0)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
awx_old_postgres_database: "{{ old_pg_config['resources'][0]['data']['database'] | b64decode }}"
|
||||
awx_old_postgres_port: "{{ old_pg_config['resources'][0]['data']['port'] | b64decode }}"
|
||||
awx_old_postgres_host: "{{ old_pg_config['resources'][0]['data']['host'] | b64decode }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Default label selector to custom resource generated postgres
|
||||
set_fact:
|
||||
@@ -29,6 +29,7 @@
|
||||
until:
|
||||
- "postgres_pod['resources'] | length"
|
||||
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
|
||||
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
|
||||
delay: 5
|
||||
retries: 60
|
||||
|
||||
@@ -48,7 +49,7 @@
|
||||
-d {{ awx_old_postgres_database }}
|
||||
-p {{ awx_old_postgres_port }}
|
||||
-F custom
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set pg_restore command
|
||||
set_fact:
|
||||
@@ -56,7 +57,7 @@
|
||||
pg_restore --clean --if-exists
|
||||
-U {{ database_username }}
|
||||
-d {{ database_name }}
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Stream backup from pg_dump to the new postgresql container
|
||||
k8s_exec:
|
||||
@@ -65,10 +66,10 @@
|
||||
command: |
|
||||
bash -c """
|
||||
set -e -o pipefail
|
||||
PGPASSWORD={{ awx_old_postgres_pass }} {{ pgdump }} | PGPASSWORD={{ awx_postgres_pass }} {{ pg_restore }}
|
||||
PGPASSWORD='{{ awx_old_postgres_pass }}' {{ pgdump }} | PGPASSWORD='{{ awx_postgres_pass }}' {{ pg_restore }}
|
||||
echo 'Successful'
|
||||
"""
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
register: data_migration
|
||||
failed_when: "'Successful' not in data_migration.stdout"
|
||||
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
set_fact:
|
||||
tower_pod_name: "{{ tower_pods['resources'][0]['metadata']['name'] | default('') }}"
|
||||
|
||||
- name: Set user provided control plane ee image
|
||||
set_fact:
|
||||
_custom_control_plane_ee_image: "{{ control_plane_ee_image }}"
|
||||
when:
|
||||
- control_plane_ee_image | default([]) | length
|
||||
|
||||
- name: Set Control Plane EE image URL
|
||||
set_fact:
|
||||
_control_plane_ee_image: "{{ _custom_control_plane_ee_image | default(lookup('env', 'RELATED_IMAGE_CONTROL_PLANE_EE')) | default(_control_plane_ee_image, true) }}"
|
||||
|
||||
- name: Apply Resources
|
||||
k8s:
|
||||
apply: yes
|
||||
@@ -30,7 +40,37 @@
|
||||
- 'persistent'
|
||||
- 'service'
|
||||
- 'ingress'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set default awx app image
|
||||
set_fact:
|
||||
_default_image: "{{ _image }}:{{ _image_version }}"
|
||||
|
||||
- name: Set user provided awx app image
|
||||
set_fact:
|
||||
_custom_image: "{{ image }}:{{ image_version }}"
|
||||
when:
|
||||
- image | default([]) | length
|
||||
- image_version is defined or image_version != ''
|
||||
|
||||
- name: Set AWX app image URL
|
||||
set_fact:
|
||||
_image: "{{ _custom_image | default(lookup('env', 'RELATED_IMAGE_AWX')) | default(_default_image, true) }}"
|
||||
|
||||
- name: Set default redis image
|
||||
set_fact:
|
||||
_default_redis_image: "{{ _redis_image }}:{{ _redis_image_version }}"
|
||||
|
||||
- name: Set user provided redis image
|
||||
set_fact:
|
||||
_custom_redis_image: "{{ redis_image }}:{{ redis_image_version }}"
|
||||
when:
|
||||
- redis_image | default([]) | length
|
||||
- redis_image_version is defined or redis_image_version != ''
|
||||
|
||||
- name: Set Redis image URL
|
||||
set_fact:
|
||||
_redis_image: "{{ _custom_redis_image | default(lookup('env', 'RELATED_IMAGE_AWX_REDIS')) | default(_default_redis_image, true) }}"
|
||||
|
||||
- name: Apply deployment resources
|
||||
k8s:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ secret_key_secret }}'
|
||||
register: _custom_secret_key
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: secret_key_secret | length
|
||||
|
||||
- name: Check for default secret key configuration
|
||||
@@ -14,19 +14,19 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-secret-key'
|
||||
register: _default_secret_key
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set secret key secret
|
||||
set_fact:
|
||||
_secret_key_secret: '{{ _custom_secret_key["resources"] | default([]) | length | ternary(_custom_secret_key, _default_secret_key) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- block:
|
||||
- name: Create secret key secret
|
||||
k8s:
|
||||
apply: true
|
||||
definition: "{{ lookup('template', 'secret_key.yaml.j2') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Read secret key secret
|
||||
k8s_info:
|
||||
@@ -34,16 +34,16 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ ansible_operator_meta.name }}-secret-key'
|
||||
register: _generated_secret_key
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
when: not _secret_key_secret['resources'] | default([]) | length
|
||||
|
||||
- name: Set secret key secret
|
||||
set_fact:
|
||||
__secret_key_secret: '{{ _generated_secret_key["resources"] | default([]) | length | ternary(_generated_secret_key, _secret_key_secret) }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Store secret key secret name
|
||||
set_fact:
|
||||
secret_key_secret_name: "{{ __secret_key_secret['resources'][0]['metadata']['name'] }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
19
roles/installer/tasks/set_images.yml
Normal file
19
roles/installer/tasks/set_images.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
# For disconnected environments, images must be set based on the values of `RELATED_IMAGE_` variables
|
||||
---
|
||||
- name: Set default awx init container image
|
||||
set_fact:
|
||||
_default_init_container_image: "{{ _init_container_image }}:{{ _init_container_image_version }}"
|
||||
|
||||
- name: Set user provided awx init image
|
||||
set_fact:
|
||||
_custom_init_container_image: "{{ init_container_image }}:{{ init_container_image_version }}"
|
||||
when:
|
||||
- init_container_image | default([]) | length
|
||||
- init_container_image_version is defined or init_container_image_version != ''
|
||||
|
||||
- name: Set Init image URL
|
||||
set_fact:
|
||||
_init_container_image: >-
|
||||
{{ _custom_init_container_image |
|
||||
default(lookup('env', 'RELATED_IMAGE_AWX_INIT_CONTAINER')) |
|
||||
default(_default_init_container_image, true) }}
|
||||
@@ -70,7 +70,7 @@
|
||||
name: "{{ ansible_operator_meta.name }}"
|
||||
namespace: "{{ ansible_operator_meta.namespace }}"
|
||||
status:
|
||||
image: "{{ image }}"
|
||||
image: "{{ _custom_image | default(lookup('env', 'RELATED_IMAGE_AWX')) | default(_default_image, true) }}"
|
||||
|
||||
- block:
|
||||
- name: Retrieve route URL
|
||||
|
||||
@@ -18,6 +18,7 @@ data:
|
||||
settings: |
|
||||
import os
|
||||
import socket
|
||||
from django_auth_ldap.config import LDAPSearch
|
||||
|
||||
def get_secret():
|
||||
if os.path.exists("/etc/tower/SECRET_KEY"):
|
||||
@@ -25,11 +26,22 @@ data:
|
||||
|
||||
ADMINS = ()
|
||||
STATIC_ROOT = '/var/lib/awx/public/static'
|
||||
STATIC_URL = '{{ (ingress_path + '/static/').replace('//', '/') }}'
|
||||
PROJECTS_ROOT = '/var/lib/awx/projects'
|
||||
JOBOUTPUT_ROOT = '/var/lib/awx/job_status'
|
||||
|
||||
IS_K8S = True
|
||||
|
||||
# Set memory available based off of resource request/limit for the task pod
|
||||
memory_limit = '{{ task_resource_requirements["limits"]["memory"] if "limits" in task_resource_requirements and "memory" in task_resource_requirements["limits"] }}'
|
||||
if memory_limit:
|
||||
SYSTEM_TASK_ABS_MEM = memory_limit
|
||||
|
||||
# Set cpu available based off of resource request/limit for the task pod
|
||||
cpu_limit = '{{ task_resource_requirements["limits"]["cpu"] if "limits" in task_resource_requirements and "cpu" in task_resource_requirements["limits"] }}'
|
||||
if cpu_limit:
|
||||
SYSTEM_TASK_ABS_CPU = cpu_limit
|
||||
|
||||
SECRET_KEY = get_secret()
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
@@ -48,8 +60,8 @@ data:
|
||||
CLUSTER_HOST_ID = socket.gethostname()
|
||||
SYSTEM_UUID = os.environ.get('MY_POD_UID', '00000000-0000-0000-0000-000000000000')
|
||||
|
||||
CSRF_COOKIE_SECURE = False
|
||||
SESSION_COOKIE_SECURE = False
|
||||
CSRF_COOKIE_SECURE = {{ csrf_cookie_secure | bool }}
|
||||
SESSION_COOKIE_SECURE = {{ session_cookie_secure | bool }}
|
||||
|
||||
SERVER_EMAIL = 'root@localhost'
|
||||
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
|
||||
@@ -133,6 +145,7 @@ data:
|
||||
{% if route_tls_termination_mechanism | lower == 'passthrough' %}
|
||||
server {
|
||||
listen 8052 default_server;
|
||||
listen [::]:8052 default_server;
|
||||
server_name _;
|
||||
|
||||
# Redirect all HTTP links to the matching HTTPS page
|
||||
@@ -143,6 +156,7 @@ data:
|
||||
server {
|
||||
{% if route_tls_termination_mechanism | lower == 'passthrough' %}
|
||||
listen 8053 ssl;
|
||||
listen [::]:8053 ssl;
|
||||
|
||||
ssl_certificate /etc/nginx/pki/web.crt;
|
||||
ssl_certificate_key /etc/nginx/pki/web.key;
|
||||
@@ -153,6 +167,7 @@ data:
|
||||
ssl_prefer_server_ciphers on;
|
||||
{% else %}
|
||||
listen 8052 default_server;
|
||||
listen [::]:8052 default_server;
|
||||
{% endif %}
|
||||
|
||||
# If you have a domain name, this is where to add it
|
||||
@@ -164,6 +179,8 @@ data:
|
||||
|
||||
# Protect against click-jacking https://www.owasp.org/index.php/Testing_for_Clickjacking_(OTG-CLIENT-009)
|
||||
add_header X-Frame-Options "DENY";
|
||||
# Protect against MIME content sniffing https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
@@ -172,15 +189,15 @@ data:
|
||||
deny all;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
location {{ (ingress_path + '/static').replace('//', '/') }} {
|
||||
alias /var/lib/awx/public/static/;
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
location {{ (ingress_path + '/favicon.ico').replace('//', '/') }} {
|
||||
alias /var/lib/awx/public/static/media/favicon.ico;
|
||||
}
|
||||
|
||||
location /websocket {
|
||||
location {{ (ingress_path + '/websocket').replace('//', '/') }} {
|
||||
# Pass request to the upstream alias
|
||||
proxy_pass http://daphne;
|
||||
# Require http version 1.1 to allow for upgrade requests
|
||||
@@ -202,7 +219,7 @@ data:
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
}
|
||||
|
||||
location / {
|
||||
location {{ ingress_path }} {
|
||||
# Add trailing / if missing
|
||||
rewrite ^(.*)$http_host(.*[^/])$ $1$http_host$2/ permanent;
|
||||
uwsgi_read_timeout 120s;
|
||||
@@ -217,6 +234,7 @@ data:
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
# Protect against click-jacking https://www.owasp.org/index.php/Testing_for_Clickjacking_(OTG-CLIENT-009)
|
||||
add_header X-Frame-Options "DENY";
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Expires "0";
|
||||
add_header Pragma "no-cache";
|
||||
|
||||
@@ -7,7 +7,7 @@ metadata:
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
labels:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/version: '{{ image_version }}'
|
||||
app.kubernetes.io/version: '{{ _image.split(':')[-1] | truncate(63, True, '') }}'
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
@@ -23,20 +23,32 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/version: '{{ image_version }}'
|
||||
app.kubernetes.io/version: '{{ _image.split(':')[-1] | truncate(63, True, '') }}'
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
{% if annotations %}
|
||||
annotations:
|
||||
{{ annotations | indent(width=8) }}
|
||||
{% endif %}
|
||||
spec:
|
||||
serviceAccountName: '{{ ansible_operator_meta.name }}'
|
||||
{% if image_pull_secret %}
|
||||
{% if image_pull_secret is defined %}
|
||||
imagePullSecrets:
|
||||
- name: {{ image_pull_secret }}
|
||||
{% elif image_pull_secrets | length > 0 %}
|
||||
imagePullSecrets:
|
||||
{% for secret in image_pull_secrets %}
|
||||
- name: {{ secret }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if control_plane_priority_class is defined %}
|
||||
priorityClassName: '{{ control_plane_priority_class }}'
|
||||
{% endif %}
|
||||
{% if bundle_ca_crt or projects_persistence|bool or init_container_extra_commands %}
|
||||
initContainers:
|
||||
{% if bundle_ca_crt or projects_persistence|bool or init_container_extra_commands %}
|
||||
- name: init
|
||||
image: '{{ init_container_image }}:{{ init_container_image_version }}'
|
||||
image: '{{ _init_container_image }}'
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
command:
|
||||
- /bin/sh
|
||||
@@ -71,9 +83,14 @@ spec:
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
containers:
|
||||
- image: '{{ redis_image }}:{{ redis_image_version }}'
|
||||
- image: '{{ _redis_image }}'
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
name: redis
|
||||
{% if redis_capabilities is defined and redis_capabilities %}
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: {{ redis_capabilities }}
|
||||
{% endif %}
|
||||
args: ["redis-server", "/etc/redis.conf"]
|
||||
volumeMounts:
|
||||
- name: {{ ansible_operator_meta.name }}-redis-config
|
||||
@@ -84,7 +101,8 @@ spec:
|
||||
mountPath: "/var/run/redis"
|
||||
- name: "{{ ansible_operator_meta.name }}-redis-data"
|
||||
mountPath: "/data"
|
||||
- image: '{{ image }}:{{ image_version }}'
|
||||
resources: {{ redis_resource_requirements }}
|
||||
- image: '{{ _image }}'
|
||||
name: '{{ ansible_operator_meta.name }}-web'
|
||||
{% if web_command %}
|
||||
command: {{ web_command }}
|
||||
@@ -164,6 +182,8 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: UWSGI_MOUNT_PATH
|
||||
value: "{{ ingress_path }}"
|
||||
{% if development_mode | bool %}
|
||||
- name: AWX_KUBE_DEVEL
|
||||
value: "1"
|
||||
@@ -172,7 +192,7 @@ spec:
|
||||
{{ web_extra_env | indent(width=12, indentfirst=True) }}
|
||||
{% endif %}
|
||||
resources: {{ web_resource_requirements }}
|
||||
- image: '{{ image }}:{{ image_version }}'
|
||||
- image: '{{ _image }}'
|
||||
name: '{{ ansible_operator_meta.name }}-task'
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
{% if task_privileged == true %}
|
||||
@@ -262,7 +282,7 @@ spec:
|
||||
{{ task_extra_env | indent(width=12, indentfirst=True) }}
|
||||
{% endif %}
|
||||
resources: {{ task_resource_requirements }}
|
||||
- image: '{{ control_plane_ee_image }}'
|
||||
- image: '{{ _control_plane_ee_image }}'
|
||||
name: '{{ ansible_operator_meta.name }}-ee'
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
resources: {{ ee_resource_requirements }}
|
||||
@@ -301,13 +321,22 @@ spec:
|
||||
nodeSelector:
|
||||
{{ node_selector | indent(width=8) }}
|
||||
{% endif %}
|
||||
{% if topology_spread_constraints %}
|
||||
topologySpreadConstraints:
|
||||
{{ topology_spread_constraints | indent(width=8) }}
|
||||
{% endif %}
|
||||
{% if tolerations %}
|
||||
tolerations:
|
||||
{{ tolerations | indent(width=8) }}
|
||||
{% endif %}
|
||||
{% if projects_persistence|bool %}
|
||||
{% if projects_persistence|bool or (security_context_settings|length) %}
|
||||
securityContext:
|
||||
{% if projects_persistence|bool %}
|
||||
fsGroup: 1000
|
||||
{% endif %}
|
||||
{% if security_context_settings|length %}
|
||||
{{ security_context_settings | to_nice_yaml | indent(8) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
volumes:
|
||||
{% if bundle_ca_crt %}
|
||||
|
||||
@@ -3,4 +3,4 @@ GLOBAL_JOB_EXECUTION_ENVIRONMENTS = [
|
||||
{'name': '{{ item.name }}' , 'image': '{{ item.image }}'},
|
||||
{% endfor %}
|
||||
]
|
||||
CONTROL_PLANE_EXECUTION_ENVIRONMENT = '{{ control_plane_ee_image }}'
|
||||
CONTROL_PLANE_EXECUTION_ENVIRONMENT = "{{ _custom_control_plane_ee_image | default(lookup('env', 'RELATED_IMAGE_CONTROL_PLANE_EE')) | default(_control_plane_ee_image, true) }}"
|
||||
|
||||
@@ -20,7 +20,7 @@ spec:
|
||||
- http:
|
||||
paths:
|
||||
- path: '{{ ingress_path }}'
|
||||
pathType: Prefix
|
||||
pathType: '{{ ingress_path_type }}'
|
||||
backend:
|
||||
service:
|
||||
name: '{{ ansible_operator_meta.name }}-service'
|
||||
|
||||
@@ -4,3 +4,8 @@ AUTH_LDAP_GLOBAL_OPTIONS = {
|
||||
ldap.OPT_X_TLS_CACERTFILE: "/etc/openldap/certs/ldap-ca.crt"
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
# Load LDAP BIND password from Kubernetes secret if define
|
||||
{% if ldap_password_secret -%}
|
||||
AUTH_LDAP_BIND_PASSWORD = "{{ ldap_bind_password }}"
|
||||
{% endif %}
|
||||
|
||||
@@ -33,14 +33,39 @@ spec:
|
||||
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
spec:
|
||||
{% if image_pull_secret %}
|
||||
{% if image_pull_secret is defined %}
|
||||
imagePullSecrets:
|
||||
- name: {{ image_pull_secret }}
|
||||
{% elif image_pull_secrets | length > 0 %}
|
||||
imagePullSecrets:
|
||||
{% for secret in image_pull_secrets %}
|
||||
- name: {{ secret }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if postgres_priority_class is defined %}
|
||||
priorityClassName: '{{ postgres_priority_class }}'
|
||||
{% endif %}
|
||||
initContainers:
|
||||
- name: database-check
|
||||
image: '{{ _init_container_image }}'
|
||||
resources: {{ postgres_init_container_resource_requirements }}
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
[[ -d /check-db/pgsql/data ]] && rm -rf /check-db/data && mv /check-db/pgsql/data/ /check-db/data/ && rm -rf /check-db/pgsql || exit 0
|
||||
volumeMounts:
|
||||
- name: postgres
|
||||
mountPath: /check-db
|
||||
subPath: ''
|
||||
containers:
|
||||
- image: '{{ postgres_image }}:{{ postgres_image_version }}'
|
||||
- image: '{{ _postgres_image }}'
|
||||
imagePullPolicy: '{{ image_pull_policy }}'
|
||||
name: postgres
|
||||
{% if postgres_extra_args %}
|
||||
args: {{ postgres_extra_args }}
|
||||
{% endif %}
|
||||
env:
|
||||
# For postgres_image based on rhel8/postgresql-12
|
||||
- name: POSTGRESQL_DATABASE
|
||||
|
||||
@@ -11,13 +11,20 @@ metadata:
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
app.kubernetes.io/operator-version: '{{ lookup("env", "OPERATOR_VERSION") }}'
|
||||
{{ service_labels | indent(width=4) }}
|
||||
{% if service_type | lower == 'loadbalancer' and loadbalancer_annotations %}
|
||||
{% if service_annotations %}
|
||||
annotations:
|
||||
{{ loadbalancer_annotations | indent(width=4) }}
|
||||
{{ service_annotations | indent(width=4) }}
|
||||
{% endif %}
|
||||
spec:
|
||||
ports:
|
||||
{% if service_type | lower != 'loadbalancer' and loadbalancer_protocol | lower != 'https' %}
|
||||
|
||||
{% if service_type | lower == "nodeport" %}
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 8052
|
||||
name: http
|
||||
nodePort: {{ nodeport_port }}
|
||||
{% elif service_type | lower != 'loadbalancer' and loadbalancer_protocol | lower != 'https' %}
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 8052
|
||||
@@ -44,10 +51,10 @@ spec:
|
||||
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
|
||||
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
|
||||
app.kubernetes.io/component: '{{ deployment_type }}'
|
||||
{% if service_type | lower == "loadbalancer" %}
|
||||
type: LoadBalancer
|
||||
{% elif service_type | lower == "nodeport" %}
|
||||
{% if service_type | lower == "nodeport" %}
|
||||
type: NodePort
|
||||
{% elif service_type | lower == "loadbalancer" %}
|
||||
type: LoadBalancer
|
||||
{% else %}
|
||||
type: ClusterIP
|
||||
{% endif %}
|
||||
|
||||
@@ -10,3 +10,6 @@ backup_pvc_namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
|
||||
# Required: backup name, found on the awxbackup object
|
||||
backup_dir: ''
|
||||
|
||||
# Set no_log settings on certain tasks
|
||||
no_log: 'true'
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- '{{ admin_password_secret }}'
|
||||
- '{{ broadcast_websocket_secret }}'
|
||||
- '{{ postgres_configuration_secret }}'
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Cleanup temp spec file
|
||||
file:
|
||||
|
||||
@@ -71,6 +71,21 @@
|
||||
force: true
|
||||
wait: true
|
||||
|
||||
- name: Set default postgres image
|
||||
set_fact:
|
||||
_default_postgres_image: "{{ _postgres_image }}:{{_postgres_image_version }}"
|
||||
|
||||
- name: Set user provided postgres image
|
||||
set_fact:
|
||||
_custom_postgres_image: "{{ postgres_image }}:{{ postgres_image_version }}"
|
||||
when:
|
||||
- postgres_image | default([]) | length
|
||||
- postgres_image_version is defined and postgres_image_version != ''
|
||||
|
||||
- name: Set Postgres image URL
|
||||
set_fact:
|
||||
_postgres_image: "{{ _custom_postgres_image | default(lookup('env', 'RELATED_IMAGE_AWX_POSTGRES')) | default(_default_postgres_image, true) }}"
|
||||
|
||||
- name: Create management pod from templated deployment config
|
||||
k8s:
|
||||
name: "{{ ansible_operator_meta.name }}-db-management"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
name: '{{ postgres_configuration_secret }}'
|
||||
register: pg_config
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Store Database Configuration
|
||||
set_fact:
|
||||
@@ -20,7 +20,7 @@
|
||||
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
|
||||
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
|
||||
awx_postgres_type: "{{ pg_config['resources'][0]['data']['type'] | b64decode | default('unmanaged') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Default label selector to custom resource generated postgres
|
||||
set_fact:
|
||||
@@ -37,6 +37,7 @@
|
||||
until:
|
||||
- "postgres_pod['resources'] | length"
|
||||
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
|
||||
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
|
||||
delay: 5
|
||||
retries: 60
|
||||
|
||||
@@ -65,7 +66,7 @@
|
||||
- name: Set full resolvable host name for postgres pod
|
||||
set_fact:
|
||||
resolvable_db_host: "{{ awx_postgres_host }}.{{ ansible_operator_meta.namespace }}.svc.cluster.local"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: awx_postgres_type == 'managed'
|
||||
|
||||
- name: Set pg_restore command
|
||||
@@ -77,7 +78,7 @@
|
||||
-U {{ awx_postgres_user }}
|
||||
-d {{ awx_postgres_database }}
|
||||
-p {{ awx_postgres_port }}
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Restore database dump to the new postgresql container
|
||||
k8s_exec:
|
||||
@@ -86,9 +87,9 @@
|
||||
command: |
|
||||
bash -c """
|
||||
set -e -o pipefail
|
||||
cat {{ backup_dir }}/tower.db | PGPASSWORD={{ awx_postgres_pass }} {{ pg_restore }}
|
||||
cat {{ backup_dir }}/tower.db | PGPASSWORD='{{ awx_postgres_pass }}' {{ pg_restore }}
|
||||
echo 'Successful'
|
||||
"""
|
||||
register: data_migration
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
failed_when: "'Successful' not in data_migration.stdout"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
command: >-
|
||||
bash -c "cat '{{ backup_dir }}/secrets.yml'"
|
||||
register: _secrets
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Create Temporary secrets file
|
||||
tempfile:
|
||||
@@ -20,38 +20,38 @@
|
||||
dest: "{{ tmp_secrets.path }}"
|
||||
content: "{{ _secrets.stdout }}"
|
||||
mode: 0640
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Include secret vars from backup
|
||||
include_vars: "{{ tmp_secrets.path }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: If deployment is managed, set the database_host in the pg config secret
|
||||
block:
|
||||
- name: Set new database host
|
||||
set_fact:
|
||||
database_host: "{{ deployment_name }}-postgres"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Set tmp postgres secret dict
|
||||
set_fact:
|
||||
_pg_secret: "{{ secrets['postgresConfigurationSecret'] }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Change postgres host value
|
||||
set_fact:
|
||||
_pg_data: "{{ _pg_secret['data'] | combine({'host': database_host | b64encode }) }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Create a postgres secret with the new host value
|
||||
set_fact:
|
||||
_pg_secret: "{{ _pg_secret | combine({'data': _pg_data}) }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Create a new dict of secrets with the new postgres secret
|
||||
set_fact:
|
||||
secrets: "{{ secrets | combine({'postgresConfigurationSecret': _pg_secret}) }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
when: secrets['postgresConfigurationSecret']['data']['type'] | b64decode == 'managed'
|
||||
|
||||
- name: Apply secret
|
||||
@@ -61,7 +61,7 @@
|
||||
apply: yes
|
||||
wait: yes
|
||||
definition: "{{ lookup('template', 'secrets.yml.j2') }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
- name: Remove ownerReference on restored secrets
|
||||
k8s:
|
||||
@@ -73,4 +73,4 @@
|
||||
namespace: '{{ ansible_operator_meta.namespace }}'
|
||||
ownerReferences: null
|
||||
loop: "{{ secrets | dict2items }}"
|
||||
no_log: true
|
||||
no_log: "{{ no_log }}"
|
||||
|
||||
@@ -13,7 +13,7 @@ metadata:
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ ansible_operator_meta.name }}-db-management
|
||||
image: "{{ postgres_image }}:{{ postgres_image_version }}"
|
||||
image: "{{ _postgres_image }}"
|
||||
imagePullPolicy: Always
|
||||
command: ["sleep", "infinity"]
|
||||
volumeMounts:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
|
||||
deployment_type: "awx"
|
||||
postgres_image: postgres
|
||||
postgres_image_version: 12
|
||||
_postgres_image: postgres
|
||||
_postgres_image_version: 12
|
||||
|
||||
backup_api_version: '{{ deployment_type }}.ansible.com/v1beta1'
|
||||
backup_kind: 'AWXBackup'
|
||||
|
||||
@@ -4,14 +4,22 @@
|
||||
group: awx.ansible.com
|
||||
kind: AWX
|
||||
role: installer
|
||||
snakeCaseParameters: False
|
||||
|
||||
- version: v1beta1
|
||||
group: awx.ansible.com
|
||||
kind: AWXBackup
|
||||
role: backup
|
||||
snakeCaseParameters: False
|
||||
finalizer:
|
||||
name: awx.ansible.com/finalizer
|
||||
role: backup
|
||||
vars:
|
||||
finalizer_run: true
|
||||
|
||||
- version: v1beta1
|
||||
group: awx.ansible.com
|
||||
kind: AWXRestore
|
||||
role: restore
|
||||
snakeCaseParameters: False
|
||||
# +kubebuilder:scaffold:watch
|
||||
|
||||
Reference in New Issue
Block a user