Compare commits

...

56 Commits

Author SHA1 Message Date
Dimitri Savineau
3fa60853a2 backup: Remove default parameter from jinja map (#1839)
The default paramater from the jinja map filter has been added in the
2.11.0 release.
However, the downstream ansible operator is still using ansible 2.9
with jinja 2.10.x so using the default parameter leads to the
following error:

TASK [Dump ingress tls secret names from awx spec and data into file]
********************************
The error was: jinja2.exceptions.FilterArgumentError: Unexpected
keyword argument 'default'
fatal: [localhost]: FAILED! => {
  "msg": "Unexpected failure during module execution.",
  "stdout": ""
}

Rather than using the default parameter with the map filter then add the
selectattr filter to get only the items with tls_secret defined and then
get the tls_secret attribute with the map filter.

This also gets rid of the when statement since we always get an empty
list when no tls_secret are present in ingress_hosts so the loop statement
will be skipped on the empty list.

Finally this changes the default value from the ingress_hosts field because
it's a list rather than a string.

https://jinja.palletsprojects.com/en/latest/templates/#jinja-filters.map

Signed-off-by: Dimitri Savineau <dsavinea@redhat.com>
2024-04-23 10:36:42 -04:00
Florian Sey
f8bbe9f55a Format Markdown list properly in upgrading.md (#1825)
Ensures the list is properly rendered in readthedocs website.
Improves the documentation to build and serve the docs locally.

Co-authored-by: Florian Sey <florian.sey@neofacto.com>
2024-04-17 19:15:03 +00:00
dependabot[bot]
c7c7171110 Bump the dependencies group in /docs with 1 update (#1802)
Bumps the dependencies group in /docs with 1 update: [mkdocs-ansible](https://github.com/ansible/mkdocs-ansible).

Updates `mkdocs-ansible` from 24.2.1 to 24.3.0
- [Release notes](https://github.com/ansible/mkdocs-ansible/releases)
- [Commits](https://github.com/ansible/mkdocs-ansible/compare/v24.2.1...v24.3.0)

---
updated-dependencies:
- dependency-name: mkdocs-ansible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-17 14:36:32 -04:00
kurokobo
b7370d0e48 docs: add a tip to add extra settings through configmaps or secrets and improve an example for that (#1824)
* docs: add a tip to add extra settings through configmaps or secrets and improve an example for that
2024-04-17 14:33:43 -04:00
Hao Liu
0b37f76225 Output debug resource to file in molecule test (#1823)
- output all relevant k8s resource to file on failure
- output awx job list and job details to file on failure
- output all pod logs to file on failure
- added STORE_DEBUG_OUTPUT to enable debug output gathering
- added DEBUG_OUTPUT_DIR to control where the debug output files will be stored
- when molecule test fail in CI trigger artifact gathering
2024-04-12 13:52:48 -04:00
aknochow
e6e1025206 adding new variables for redhat hybrid cloud console to metrics-utility (#1816)
adding new variables for redhat hybrid cloud console shipping
simplifying configmap and secret setup
making pvc creation conditional on ship_target type being directory
2024-04-11 19:30:39 -04:00
Hao Liu
a5d5028dae Add AWX_EE_TEST_IMAGE option to molecule test (#1819) 2024-04-10 17:43:08 +00:00
kurokobo
413b7003a2 docs: fix incorrect command for getting ingressroutetcp resources (#1778) 2024-04-05 23:07:46 -04:00
Christian Adams
7b02b5df04 Set default for -iness probe parameters and add docs (#1808) 2024-04-03 14:26:41 -04:00
Christian Adams
a5211fe511 Add postgres init container to resolve permissions for some k3s deployments (#1805)
Add postgres init container if
postgres_data_volume_init is true

This is aimed to solve the issue where users may
need to chmod or chown the postgres
data volume for user 26, which is the user
that is running postgres in the sclorg image.

For example, one can now set the follow on the AWX spec:
spec:
  postgres_init_container_commands: |
    chown 26:0 /var/lib/pgsql/data
    chmod 700 /var/lib/pgsql/data

Deprecate postgres_init_container_resource_requirements param in favor
of postgres_resource_requirements param.

Signed-off-by: Seth Foster <fosterbseth@gmail.com>
Co-authored-by: craph <14820052+craph@users.noreply.github.com>
Co-authored-by: kurokobo <kuro664@gmail.com>
Co-authored-by: Christian M. Adams <chadams@redhat.com>
2024-04-03 13:19:57 -04:00
Hao Liu
fcbf394272 Fix "external_hostname" should not be required while using Route ingress (#1807)
Fix "external_hostname" required on OCP
2024-04-03 16:16:16 +00:00
Christian Adams
7bf49c207a Remove the ability to customize the postgres_data_dir (#1798)
* in the sclorg Postgresql 15 image, the PGDATA directory is hardcoded
* if users were to modify this directory, they would only change the
  directory the pvc is mounted to, not the directory PostgreSQL uses.
  This would result in loss of data.
* switch from /var/lib/pgsql/data/pgdata to /var/lib/pgsql/data/userdata
2024-03-31 21:58:33 -04:00
aknochow
3c70598704 setting Metrics-Utility Image to only display when enabled (#1796) 2024-03-27 21:39:11 +00:00
Dimitri Savineau
80a9e8c156 postgresql: Cast sorted_old_postgres_pods as list (#1791)
With ansible 2.9.27 (operator-sdk v1.27.0) then the reverse filter
returns an iterator so we need to cast it to list.
The behavior doesn't exist when using a more recent operator-sdk
version like v1.34.0 (ansible-core 2.15.8) but using the list
filter on that version works too (even if not needed)

"sorted_old_postgres_pods": "<list_reverseiterator object at 0x7f539eaa5610>"

Signed-off-by: Dimitri Savineau <dsavinea@redhat.com>
2024-03-27 14:31:53 -04:00
Don Naro
dc0e86b823 Add noxfile and workflow to test docsite PRs (#1794)
* add noxfile with mkdocs build session

* add nox build check

* include reusable nox in ci workflow
2024-03-27 14:29:38 -04:00
kurokobo
07b8120788 fix: add retries to find running web pod (#1787) 2024-03-27 14:25:10 -04:00
kurokobo
a6e7a1bec3 fix: correct readinessProbe for web pod (#1786)
fix: correct readinesProbe for web pod
2024-03-27 14:21:23 -04:00
zaki-lknr
809491bce0 docs: add description of init container image definition (#1779)
* docs: add description of init container image definition

Co-authored-by: kurokobo <kuro664@gmail.com>
2024-03-27 14:19:48 -04:00
Dimitri Savineau
5e66b6aeb0 csv: Fix metrics utility fields (#1783)
The metrics utility fields were configured under the statusDescriptors
section rather than specDescriptors so displaying those fields in the
UI wasn't done correctly (not under the Advanced section nor using the
correct field type).

This also changes the `metrics_utility_configmap` descriptor from
`urn:alm:descriptor:com.tectonic.ui:selector:core:v1:ConfigMap` to
`urn:alm:descriptor:io.kubernetes:ConfigMap` because the first value
doesn't work.

Finally, all metrics utility fields are only displayed (in the Advanced
section) when `metrics_utility_enabled` is enabled (not default).

Signed-off-by: Dimitri Savineau <dsavinea@redhat.com>
2024-03-26 09:16:27 -04:00
aknochow
c6fe038fe4 Adding support for ansible metrics-utility (#1754)
- Adding metadata, storage_class, and pullsecret for metrics-utility
- Updating crd, csv and defaults
- Adding metrics-utility cronjob
2024-03-20 11:05:13 -04:00
kurokobo
49d7a566b2 docs: add tips about traefik api groups (#1757) 2024-03-14 16:25:44 +00:00
Don Naro
3cf912c998 Add dependabot config to bump doc dependencies (#1758) 2024-03-14 12:13:18 -04:00
Hao Liu
0dbf3ddff8 Add ServiceAccount and ImagePullSecet to migration job (#1763)
Add ServiceAccount and ImagePullSecet to migration pod
2024-03-13 20:56:56 +00:00
aknochow
af16e9e73f Updating image pull policy for awx-operator to IfNotPresent (#1761) 2024-03-13 16:51:06 -04:00
Seth Foster
154b801cfc Change default value for postgres_data_path (#1766)
* Change default value for postgres_data_path

/var/lib/postgresql/data/pgdata
to
/var/lib/pgsql/data/pgdata

postgres 15 uses a different location for
postgres data directory.

Fixes issue were database was not being written
to the mounted in volume, and if the postgres
container restarted, data would be lost.

Signed-off-by: Seth Foster <fosterbseth@gmail.com>
---------

Signed-off-by: Seth Foster <fosterbseth@gmail.com>
Co-authored-by: Hao Liu <44379968+TheRealHaoLiu@users.noreply.github.com>
2024-03-13 16:17:49 -04:00
Hao Liu
a8acae4af5 Don't delete old postgres 13 volume automatically (#1767)
Leave old postgres-13 volume alone in case of unforseen upgrade failure for restore purposes

User can manually delete old PVC after verifying upgrade is completed
2024-03-13 15:23:10 -04:00
Hao Liu
6e31feaa20 Add command when specifying args for postgres (#1765)
When using args the container defaults to the entrypoint instead of command

causing postgres to be in a crashloop
2024-03-13 15:16:05 -04:00
Hao Liu
a53a10ad33 Whitelist test and enforce test order (#1762)
also reduce replica count during test to save CPU/memory
2024-03-13 13:50:33 -04:00
Christian Adams
d5a3cb7519 Revert change to cast settings values to strings as they could be nested (#1756)
- We cast the settings value to a string so that it would display
  properly in the Openshift UI. Unfortunately, the k8s validator will no
  longer allow arrays for settings values.
2024-03-12 11:58:00 -04:00
Christian Adams
ed6ac1a11a Create a new postgres configuration secret when restoring a new instance (#1733)
- This will avoid the operator changing the host value of the original
  deployments postgres_configuration_secret. As it was, restores broke
  the original deployment if it was still around before this change.

Signed-off-by: Christian M. Adams <chadams@redhat.com>
2024-03-11 16:34:43 -04:00
Hao Liu
b5d81b8e5d Fix awx_kube_devel (#1759)
* Fix awx_kube_devel
* Sanitize version name for kube_dev

When in development mode, awx version may look
like 23.9.1.dev18+gee9eac15dc.d20240311

k8s job to the migration can only have
a name with alphanumeric, and '.', '-'

so we can just drop off the +

Signed-off-by: Seth Foster <fosterbseth@gmail.com>

---------

Signed-off-by: Seth Foster <fosterbseth@gmail.com>
Co-authored-by: Seth Foster <fosterbseth@gmail.com>
2024-03-11 19:01:00 +00:00
bartowl
3abeec518a Bind EE images version with DEFAULT_AWX_VERSION (#1740)
* bind ee_images, control_plane_ee_image and init_container_image with DEFAULT_AWX_VERSION instead of "latest"

* fix when condition on init_container_image_version check

* Use DEFAULT_AWX_VERSION for AWXMeshIngress

* Add back AWX EE latest for backward compatibility

---------

Co-authored-by: Hao Liu <44379968+TheRealHaoLiu@users.noreply.github.com>
2024-03-11 14:12:10 -04:00
Christian Adams
d2c4b9c8a4 The pg service label_selector now uses the deployment_type variable (#1755) 2024-03-08 09:02:31 -05:00
Christian Adams
2ad1d25120 Update PostgreSQL docs about finding default version (#1747) 2024-03-07 21:47:18 -05:00
Hao Liu
26e72b4e1d Fix undefined external_hostname when using Route (#1753) 2024-03-07 22:53:48 +00:00
Hao Liu
3434cbef96 AWXMeshIngress route respect external_hostname (#1752)
* AwxMeshIngress route respect external_hostname
* Set host in AWXMeshIngress route if external_hostname is defined
2024-03-07 15:43:06 -05:00
David Hageman
256d84a42a Add imagePullSecrets option to Mesh Ingress (#1750) 2024-03-07 13:17:39 -05:00
kurokobo
03cfe14c07 fix: extend expiration date for the certs for receptor nodes to 10 years (#1744) 2024-03-06 19:52:04 +00:00
Tyler Muir
82c7dd2f44 add support for defining loadbalancer class (#1746) 2024-03-06 14:35:16 -05:00
Erez Samimi
818b3682fa Fix table format in container-probes.md (#1748) 2024-03-06 19:28:46 +00:00
David Hageman
ffba1b4712 Add -ness checks and refactor migrations (#1674) 2024-03-05 19:54:22 -05:00
kurokobo
dba934daa0 fix: revert type of status.upgradedPostgresVersion to string (#1745) 2024-03-04 15:55:16 -05:00
aknochow
d0827ba426 Fixing postgres upgrade conditional (#1741) 2024-03-01 17:09:15 -05:00
kurokobo
16b2f2a34f fix: correct unsafe conditional (#1737) 2024-03-01 20:54:40 +00:00
John Westcott IV
607a7ca58c Upgrading to PostgreSQL 15 and moving to sclorg images (#1486)
* Upgrading to postgres:15
* Changing image from postgres to sclorg
* Handle scenario where upgrade status is not defined & correct pg tag
* Rework the upgrade logic to be more resiliant for multiple upgrades

---------

Co-authored-by: john-westcott-iv <john-westcott-iv@users.noreply.github.com>
Co-authored-by: Christian M. Adams <chadams@redhat.com>
2024-02-29 17:02:11 -05:00
kurokobo
d11d66e81d docs: enable search feature (#1725) 2024-02-28 19:46:04 +00:00
Christian Adams
7a937b0932 Expose extra_settings in OLM UI form (#1732)
Expose extra_settings in olm UI form

Signed-off-by: Christian M. Adams <chadams@redhat.com>
2024-02-28 14:35:05 -05:00
Don Naro
e1c0e33b4f Use pip tools to generate the full dependency tree (#1727)
* add venv to gitignore

* use pip compiled docs requirements
2024-02-28 14:33:29 -05:00
Neev Geffen
cf905ca5d0 CSV Change Descriptor of StorageClass From Text to StorageClass (#1729)
Update awx-operator.clusterserviceversion.yaml:
Some Descriptors for StorageClasses were set as text and not Storage Class
2024-02-28 19:19:24 +00:00
Hao Liu
630a5ee1f3 Fix bug where uppercase Route fails (#1731) 2024-02-26 17:17:37 +00:00
Matt Miller
3d78e90ab1 Update Dockerfile operator-framework/ansible-operator to v1.34.0 (#1714)
Update Dockerfile base image

* Vulnerability scans against this image when deployed shows: CVE-2023-4911
* https://quay.io/repository/operator-framework/ansible-operator/manifest/sha256:f08f675976f42dc3a8ebbb8482acea153a8f57232e2ee48940e3d40ca40d24d9?tab=vulnerabilities
* It appears if 5f3d9ed96f/Dockerfile (L1C14-L1C49) is updated to `v1.34.0` this vulnerability is mitigated.
2024-02-21 14:50:08 -05:00
kurokobo
3981e6ba5e fix: correct indentation for annotations for awxmeshingress (#1723)
fix: correct indentation for annotations
2024-02-21 19:46:34 +00:00
kurokobo
ac682a9c05 docs: improve documentation for awxmeshingress (#1724)
* add descriptions and examples for awxmeshingress
* convert list to table
* add note for image
* correct minor wording issues
* apply suggested changes from code review for docs/user-guide/advanced-configuration/mesh-ingress.md

Co-authored-by: Seth Foster <fosterseth@users.noreply.github.com>
2024-02-21 14:36:50 -05:00
kurokobo
7bdf48ffc0 docs: add description for --force-conflicts option to upgrade crds (#1717) 2024-02-21 14:31:32 -05:00
Seth Foster
fc11db4ece Fix syntax error in mesh ingress docs (#1720)
Signed-off-by: Seth Foster <fosterbseth@gmail.com>
2024-02-16 17:16:28 +00:00
TVo
148309325e Separate out the custom receptor CA section to its own section. (#1707) 2024-02-16 10:06:05 -07:00
69 changed files with 1889 additions and 610 deletions

13
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/docs"
groups:
dependencies:
patterns:
- "*"
schedule:
interval: "weekly"
labels:
- "component:docs"
- "dependencies"

View File

@@ -17,6 +17,7 @@ jobs:
- -t replicas
env:
DOCKER_API_VERSION: "1.41"
DEBUG_OUTPUT_DIR: /tmp/awx_operator_molecule_test
steps:
- uses: actions/checkout@v3
@@ -37,10 +38,18 @@ jobs:
MOLECULE_VERBOSITY: 3
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
STORE_DEBUG_OUTPUT: true
run: |
sudo rm -f $(which kustomize)
make kustomize
KUSTOMIZE_PATH=$(readlink -f bin/kustomize) molecule test -s kind -- ${{ matrix.ansible_args }}
- name: Upload artifacts for failed tests if Run Molecule fails
if: failure()
uses: actions/upload-artifact@v2
with:
name: awx_operator_molecule_test
path: ${{ env.DEBUG_OUTPUT_DIR }}
helm:
runs-on: ubuntu-latest
name: helm
@@ -99,3 +108,5 @@ jobs:
echo "${no_log}"
exit 1
fi
nox-sessions:
uses: ./.github/workflows/reusable-nox.yml

26
.github/workflows/reusable-nox.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
---
name: nox
"on":
workflow_call:
jobs:
nox:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- session: build
python-versions: "3.11"
name: "Run nox ${{ matrix.session }} session"
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Setup nox
uses: wntrblm/nox@2024.03.02
with:
python-versions: "${{ matrix.python-versions }}"
- name: "Run nox -s ${{ matrix.session }}"
run: |
nox -s "${{ matrix.session }}"

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@ gh-pages/
.vscode/
__pycache__
/site
venv/*

View File

@@ -36,6 +36,29 @@ When upgrading to releases with CRD changes use the following command to update
kubectl apply --server-side -k github.com/ansible/awx-operator/config/crd?ref=<VERSION>
```
If running above command results in an error like below:
```text
Apply failed with 1 conflict: conflict with "helm" using apiextensions.k8s.io/v1: .spec.versions
Please review the fields above--they currently have other managers. Here
are the ways you can resolve this warning:
* If you intend to manage all of these fields, please re-run the apply
command with the `--force-conflicts` flag.
* If you do not intend to manage all of the fields, please edit your
manifest to remove references to the fields that should keep their
current managers.
* You may co-own fields by updating your manifest to match the existing
value; in this case, you'll become the manager if the other manager(s)
stop managing the field (remove it from their configuration).
See https://kubernetes.io/docs/reference/using-api/server-side-apply/#conflicts
```
Use `--force-conflicts` flag to resolve the conflict.
```bash
kubectl apply --server-side --force-conflicts -k github.com/ansible/awx-operator/config/crd?ref=<VERSION>
```
## Configuration
The goal of adding helm configurations is to abstract out and simplify the creation of multi-resource configs. The `AWX.spec` field maps directly to the spec configs of the `AWX` resource that the operator provides, which are detailed in the [main README](https://github.com/ansible/awx-operator/blob/devel/README.md). Other sub-config can be added with the goal of simplifying more involved setups that require additional resources to be specified.

View File

@@ -13,7 +13,7 @@ spec:
storage: {{ default "8Gi" .size | quote }}
storageClassName: {{ include "postgres.storageClassName" $ }}
hostPath:
path: {{ required "customVolumes.postgres.hostPath or spec.postgres_data_path are required!" (default ($.Values.AWX.spec).postgres_data_path .hostPath) | quote }}
path: /var/lib/pgsql/data/userdata
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -6,13 +6,15 @@ Have questions about this document or anything not covered here? Please file a n
## Table of contents
* [Things to know prior to submitting code](#things-to-know-prior-to-submitting-code)
* [Submmiting your Work](#submitting-your-work)
* [Testing](#testing)
* [Testing in Docker](#testing-in-docker)
* [Testing in Minikube](#testing-in-minikube)
* [Generating a bundle](#generating-a-bundle)
* [Reporting Issues](#reporting-issues)
- [AWX-Operator Contributing Guidelines](#awx-operator-contributing-guidelines)
- [Table of contents](#table-of-contents)
- [Things to know prior to submitting code](#things-to-know-prior-to-submitting-code)
- [Submmiting your work](#submmiting-your-work)
- [Testing](#testing)
- [Testing in Kind](#testing-in-kind)
- [Testing in Minikube](#testing-in-minikube)
- [Generating a bundle](#generating-a-bundle)
- [Reporting Issues](#reporting-issues)
## Things to know prior to submitting code
@@ -44,12 +46,12 @@ Have questions about this document or anything not covered here? Please file a n
## Testing
This Operator includes a [Molecule](https://molecule.readthedocs.io/en/stable/)-based test environment, which can be executed standalone in Docker (e.g. in CI or in a single Docker container anywhere), or inside any kind of Kubernetes cluster (e.g. Minikube).
This Operator includes a [Molecule](https://ansible.readthedocs.io/projects/molecule/)-based test environment, which can be executed standalone in Docker (e.g. in CI or in a single Docker container anywhere), or inside any kind of Kubernetes cluster (e.g. Minikube).
You need to make sure you have Molecule installed before running the following commands. You can install Molecule with:
```sh
#> pip install 'molecule[docker]'
#> python -m pip install molecule-plugins[docker]
```
Running `molecule test` sets up a clean environment, builds the operator, runs all configured tests on an example operator instance, then tears down the environment (at least in the case of Docker).

View File

@@ -1,4 +1,4 @@
FROM quay.io/operator-framework/ansible-operator:v1.32.0
FROM quay.io/operator-framework/ansible-operator:v1.34.0
USER root
RUN dnf update --security --bugfix -y && \

View File

@@ -41,6 +41,11 @@ spec:
deployment_name:
description: Name of the AWX deployment to create the Mesh Ingress for.
type: string
image_pull_secrets:
description: Image pull secrets for Mesh Ingress containers.
type: array
items:
type: string
external_hostname:
description: External hostname to use for the Mesh Ingress.
type: string

View File

@@ -159,6 +159,10 @@ spec:
description: Assign LoadBalancer IP address
type: string
default: ''
loadbalancer_class:
description: Class of LoadBalancer to use
type: string
default: ''
route_host:
description: The DNS to use to points to the instance
type: string
@@ -1456,7 +1460,7 @@ spec:
type: object
type: object
postgres_init_container_resource_requirements:
description: Resource requirements for the postgres init container
description: (Deprecated, use postgres_resource_requirements parameter) Resource requirements for the postgres init container
properties:
requests:
properties:
@@ -1571,6 +1575,86 @@ spec:
description: Number of task instance replicas
type: integer
format: int32
web_liveness_initial_delay:
description: Initial delay before starting liveness checks on web pod
type: integer
default: 5
format: int32
task_liveness_initial_delay:
description: Initial delay before starting liveness checks on task pod
type: integer
default: 5
format: int32
web_liveness_period:
description: Time period in seconds between each liveness check for the web pod
type: integer
default: 0
format: int32
task_liveness_period:
description: Time period in seconds between each liveness check for the task pod
type: integer
default: 0
format: int32
web_liveness_failure_threshold:
description: Number of consecutive failure events to identify failure of web pod
type: integer
default: 3
format: int32
task_liveness_failure_threshold:
description: Number of consecutive failure events to identify failure of task pod
type: integer
default: 3
format: int32
web_liveness_timeout:
description: Number of seconds to wait for a probe response from web pod
type: integer
default: 1
format: int32
task_liveness_timeout:
description: Number of seconds to wait for a probe response from task pod
type: integer
default: 1
format: int32
web_readiness_initial_delay:
description: Initial delay before starting readiness checks on web pod
type: integer
default: 20
format: int32
task_readiness_initial_delay:
description: Initial delay before starting readiness checks on task pod
type: integer
default: 20
format: int32
web_readiness_period:
description: Time period in seconds between each readiness check for the web pod
type: integer
default: 0
format: int32
task_readiness_period:
description: Time period in seconds between each readiness check for the task pod
type: integer
default: 0
format: int32
web_readiness_failure_threshold:
description: Number of consecutive failure events to identify failure of web pod
type: integer
default: 3
format: int32
task_readiness_failure_threshold:
description: Number of consecutive failure events to identify failure of task pod
type: integer
default: 3
format: int32
web_readiness_timeout:
description: Number of seconds to wait for a probe response from web pod
type: integer
default: 1
format: int32
task_readiness_timeout:
description: Number of seconds to wait for a probe response from task pod
type: integer
default: 1
format: int32
garbage_collect_secrets:
description: Whether or not to remove secrets upon instance removal
default: false
@@ -1723,13 +1807,16 @@ spec:
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
postgres_data_volume_init:
description: Sets permissions on the /var/lib/pgdata/data for postgres container using an init container (not Openshift)
type: boolean
postgres_init_container_commands:
description: Customize the postgres init container commands (Non Openshift)
type: string
postgres_extra_volumes:
description: Specify extra volumes to add to the application pod
type: string
@@ -1805,7 +1892,7 @@ spec:
description: Set log level of receptor service
type: string
extra_settings:
description: Extra settings to specify for the API
description: Extra settings to specify for AWX
items:
properties:
setting:
@@ -1839,6 +1926,50 @@ spec:
description: Disable web container's nginx ipv6 listener
type: boolean
default: false
metrics_utility_enabled:
description: Enable metrics utility
type: boolean
default: false
metrics_utility_image:
description: Metrics-Utility Image
type: string
metrics_utility_image_version:
description: Metrics-Utility Image Version
type: string
metrics_utility_image_pull_policy:
description: Metrics-Utility Image PullPolicy
type: string
metrics_utility_configmap:
description: Metrics-Utility ConfigMap
type: string
metrics_utility_secret:
description: Metrics-Utility Secret
type: string
metrics_utility_cronjob_gather_schedule:
description: Metrics-Utility Gather Data CronJob Schedule
type: string
default: '@hourly'
metrics_utility_cronjob_report_schedule:
description: Metrics-Utility Report CronJob Schedule
type: string
default: '@monthly'
metrics_utility_ship_target:
description: Metrics-Utility Ship Target
type: string
metrics_utility_pvc_claim:
description: Metrics-Utility PVC Claim
type: string
metrics_utility_pvc_claim_size:
description: Metrics-Utility PVC Claim Size
type: string
default: 5Gi
metrics_utility_pvc_claim_storage_class:
description: Metrics-Utility PVC Claim Storage Class
type: string
metrics_utility_console_enabled:
description: Enable metrics utility shipping to Red Hat Hybrid Cloud Console
type: boolean
default: false
type: object
status:
properties:

View File

@@ -5,9 +5,9 @@ generatorOptions:
disableNameSuffixHash: true
configMapGenerator:
- name: awx-manager-config
files:
- files:
- controller_manager_config.yaml
name: awx-manager-config
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

View File

@@ -39,7 +39,7 @@ spec:
- --leader-elect
- --leader-election-id=awx-operator
image: controller:latest
imagePullPolicy: Always
imagePullPolicy: IfNotPresent
name: awx-manager
env:
- name: ANSIBLE_GATHERING

View File

@@ -58,6 +58,11 @@ spec:
path: ingress_controller
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Image Pull Secrets
path: image_pull_secrets
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
version: v1alpha1
- description: Back up a deployment of the awx, including jobs, inventories, and
credentials
@@ -91,7 +96,7 @@ spec:
- displayName: Backup PVC Storage Class
path: backup_storage_class
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:io.kubernetes:StorageClass
- urn:alm:descriptor:com.tectonic.ui:advanced
- displayName: Precreate Partition Hours
path: precreate_partition_hours
@@ -387,6 +392,12 @@ spec:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:string
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:service_type:LoadBalancer
- displayName: LoadBalancer Class
path: loadbalancer_class
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:string
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:service_type:LoadBalancer
- displayName: Route API Version
path: route_api_version
x-descriptors:
@@ -445,12 +456,21 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- description: The PostgreSQL init container is not used when an external DB
is configured
- description: Sets permissions on the /var/lib/pgsql/data for postgres container using an init container (not Openshift)
displayName: PostgreSQL initialize data volume
path: postgres_data_volume_init
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: Customize the postgres init container commands (Non Openshift)
displayName: PostgreSQL Init Container Commands
path: postgres_init_container_commands
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: (Deprecated, use postgres_resource_requirements parameter instead)
displayName: PostgreSQL Init Container Resource Requirements
path: postgres_init_container_resource_requirements
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- displayName: Redis Container Resource Requirements
path: redis_resource_requirements
@@ -626,11 +646,6 @@ spec:
x-descriptors:
- urn:alm:descriptor:io.kubernetes:StorageClass
- urn:alm:descriptor:com.tectonic.ui:advanced
- displayName: Postgres Datapath
path: postgres_data_path
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Postgres Extra Arguments
path: postgres_extra_args
x-descriptors:
@@ -713,7 +728,7 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:projects_use_existing_claim:_No_
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:io.kubernetes:StorageClass
- description: Projects Storage Size
displayName: Projects Storage Size
path: projects_storage_size
@@ -937,7 +952,7 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: API Extra Settings
- displayName: Extra Settings
path: extra_settings
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
@@ -1013,6 +1028,83 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- displayName: Metrics-Utility Enabled
path: metrics_utility_enabled
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- displayName: Metrics-Utility Image
path: metrics_utility_image
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Image Version
path: metrics_utility_image_version
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Image PullPolicy
path: metrics_utility_image_pull_policy
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:imagePullPolicy
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility ConfigMap
path: metrics_utility_configmap
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:ConfigMap
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Secret
path: metrics_utility_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Gather Data CronJob Schedule
path: metrics_utility_cronjob_gather_schedule
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Report CronJob Schedule
path: metrics_utility_cronjob_report_schedule
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Ship Target
path: metrics_utility_ship_target
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility PVC Claim
path: metrics_utility_pvc_claim
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility PVC Claim Size
path: metrics_utility_pvc_claim_size
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility PVC Claim Storage Class
path: metrics_utility_pvc_claim_storage_class
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:StorageClass
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
- displayName: Metrics-Utility Enabled Shipping to Red Hat Hybrid Cloud Console
path: metrics_utility_console_enabled
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:metrics_utility_enabled:true
statusDescriptors:
- description: Route to access the instance deployed
displayName: URL

View File

@@ -78,6 +78,18 @@ rules:
- patch
- update
- watch
- apiGroups:
- batch
resources:
- cronjobs
- jobs
verbs:
- get
- list
- create
- patch
- update
- watch
- apiGroups:
- monitoring.coreos.com
resources:

View File

@@ -46,10 +46,3 @@ spec:
limits:
cpu: 1000m
memory: 2Gi
postgres_init_container_resource_requirements:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 1000m
memory: 2Gi

View File

@@ -2,9 +2,15 @@
To build the AWX Operator docs locally:
1. Clone the AWX operator repository.
2. From the root directory:
a. pip install --user -r docs/requirements.txt
b. mkdocs build
1. Clone the AWX operator repository.
1. Preferrably, create a virtual environment for installing the dependencies.
a. `python3 -m venv venv`
b. `source venv/bin/activate`
1. From the root directory:
a. `pip install -r docs/requirements.txt`
b. `mkdocs build`
1. View the docs in your browser:
a. `mkdocs serve`
b. Open your browser and navigate to `http://127.0.0.1:8000/`
This will create a new directory called `site/` in the root of your clone containing the index.html and static files. To view the docs in your browser, navigate there in your file explorer and double-click on the `index.html` file. This should open the docs site in your browser.
This will create a new directory called `site/` in the root of your clone containing the index.html and static files.

3
docs/requirements.in Normal file
View File

@@ -0,0 +1,3 @@
# This requirements file is used for AWX Operator latest doc builds.
mkdocs-ansible

View File

@@ -1,12 +1,193 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --allow-unsafe --output-file=docs/requirements.txt --strip-extras docs/requirements.in
#
babel==2.14.0
# via mkdocs-material
beautifulsoup4==4.12.3
# via
# linkchecker
# mkdocs-htmlproofer-plugin
# readtime
cairocffi==1.6.1
# via cairosvg
cairosvg==2.7.0
markdown-exec>=1.6.0
mkdocs-ansible>=0.1.6
mkdocs-gen-files>=0.4.0
mkdocs-material-extensions>=1.1.1
mkdocs-material>=9.1.18
mkdocs
mkdocstrings-python>=1.1.0
mkdocstrings>=0.22.0
# via mkdocs-ansible
certifi==2024.2.2
# via requests
cffi==1.16.0
# via cairocffi
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via
# mkdocs
# mkdocstrings
colorama==0.4.6
# via
# griffe
# mkdocs-material
csscompressor==0.9.5
# via mkdocs-minify-plugin
cssselect==1.2.0
# via pyquery
cssselect2==0.7.0
# via cairosvg
defusedxml==0.7.1
# via cairosvg
dnspython==2.6.1
# via linkchecker
ghp-import==2.1.0
# via mkdocs
griffe==0.40.1
# via mkdocstrings-python
htmlmin2==0.1.13
# via mkdocs-minify-plugin
idna==3.6
# via requests
jinja2==3.1.3
# via
# mkdocs
# mkdocs-macros-plugin
# mkdocs-material
# mkdocstrings
jsmin==3.0.1
# via mkdocs-minify-plugin
linkchecker==10.4.0
# via mkdocs-ansible
lxml==5.1.0
# via
# mkdocs-material
# pyquery
markdown==3.5.2
# via
# markdown-include
# mkdocs
# mkdocs-autorefs
# mkdocs-htmlproofer-plugin
# mkdocs-material
# mkdocstrings
# pymdown-extensions
markdown-exec==1.8.0
# via mkdocs-ansible
markdown-include==0.8.1
# via mkdocs-ansible
markdown2==2.4.12
# via readtime
markupsafe==2.1.5
# via
# jinja2
# mkdocs
# mkdocstrings
mergedeep==1.3.4
# via mkdocs
mkdocs==1.5.3
# via
# mkdocs-ansible
# mkdocs-autorefs
# mkdocs-gen-files
# mkdocs-htmlproofer-plugin
# mkdocs-macros-plugin
# mkdocs-material
# mkdocs-minify-plugin
# mkdocs-monorepo-plugin
# mkdocstrings
mkdocs-ansible==24.3.0
# via -r requirements.in
mkdocs-autorefs==0.5.0
# via mkdocstrings
mkdocs-gen-files==0.5.0
# via mkdocs-ansible
mkdocs-htmlproofer-plugin==1.0.0
# via mkdocs-ansible
mkdocs-macros-plugin==1.0.5
# via mkdocs-ansible
mkdocs-material==9.2.6
# via mkdocs-ansible
mkdocs-material-extensions==1.3.1
# via
# mkdocs-ansible
# mkdocs-material
mkdocs-minify-plugin==0.8.0
# via mkdocs-ansible
mkdocs-monorepo-plugin==1.1.0
# via mkdocs-ansible
mkdocstrings==0.24.0
# via
# mkdocs-ansible
# mkdocstrings-python
mkdocstrings-python==1.8.0
# via mkdocs-ansible
packaging==23.2
# via mkdocs
paginate==0.5.6
# via mkdocs-material
pathspec==0.12.1
# via mkdocs
pillow==10.0.1
# via
# cairosvg
# mkdocs-ansible
pipdeptree==2.7.1
# via mkdocs-ansible
platformdirs==4.2.0
# via
# mkdocs
# mkdocstrings
pycparser==2.21
# via cffi
pygments==2.17.2
# via mkdocs-material
pymdown-extensions==10.0.1
# via
# markdown-exec
# mkdocs-ansible
# mkdocs-material
# mkdocstrings
pyquery==2.0.0
# via readtime
python-dateutil==2.8.2
# via
# ghp-import
# mkdocs-macros-plugin
python-slugify==8.0.4
# via mkdocs-monorepo-plugin
pyyaml==6.0.1
# via
# mkdocs
# mkdocs-macros-plugin
# pymdown-extensions
# pyyaml-env-tag
pyyaml-env-tag==0.1
# via mkdocs
readtime==3.0.0
# via mkdocs-material
regex==2023.12.25
# via mkdocs-material
requests==2.31.0
# via
# linkchecker
# mkdocs-htmlproofer-plugin
# mkdocs-material
six==1.16.0
# via python-dateutil
soupsieve==2.5
# via beautifulsoup4
termcolor==2.4.0
# via mkdocs-macros-plugin
text-unidecode==1.3
# via python-slugify
tinycss2==1.2.1
# via
# cairosvg
# cssselect2
urllib3==2.2.1
# via requests
watchdog==4.0.0
# via mkdocs
webencodings==0.5.1
# via
# cssselect2
# tinycss2

View File

@@ -1,6 +1,7 @@
### Upgrading
To upgrade AWX, it is recommended to upgrade the awx-operator to the version that maps to the desired version of AWX. To find the version of AWX that will be installed by the awx-operator by default, check the version specified in the `DEFAULT_AWX_VERSION` variable for that particular release. You can do so by running the following command
To upgrade AWX, it is recommended to upgrade the awx-operator to the version that maps to the desired version of AWX. To find the version of AWX that will be installed by the awx-operator by default, check the version specified in the `DEFAULT_AWX_VERSION` variable for that particular release. You can do so by running the following command
```shell
AWX_OPERATOR_VERSION=2.8.0
docker run --entrypoint="" quay.io/ansible/awx-operator:$AWX_OPERATOR_VERSION bash -c "env | grep DEFAULT_AWX_VERSION"
@@ -12,26 +13,23 @@ Apply the awx-operator.yml for that release to upgrade the operator, and in turn
The first part of any upgrade should be a backup. Note, there are secrets in the pod which work in conjunction with the database. Having just a database backup without the required secrets will not be sufficient for recovering from an issue when upgrading to a new version. See the [backup role documentation](https://github.com/ansible/awx-operator/tree/devel/roles/backup) for information on how to backup your database and secrets.
In the event you need to recover the backup see the [restore role documentation](https://github.com/ansible/awx-operator/tree/devel/roles/restore). *Before Restoring from a backup*, be sure to:
* delete the old existing AWX CR
* delete the persistent volume claim (PVC) for the database from the old deployment, which has a name like `postgres-13-<deployment-name>-postgres-13-0`
In the event you need to recover the backup see the [restore role documentation](https://github.com/ansible/awx-operator/tree/devel/roles/restore). _Before Restoring from a backup_, be sure to:
- delete the old existing AWX CR
- delete the persistent volume claim (PVC) for the database from the old deployment, which has a name like `postgres-15-<deployment-name>-postgres-15-0`
**Note**: Do not delete the namespace/project, as that will delete the backup and the backup's PVC as well.
#### PostgreSQL Upgrade Considerations
If there is a PostgreSQL major version upgrade, after the data directory on the PVC is migrated to the new version, the old PVC is kept by default.
This provides the ability to roll back if needed, but can take up extra storage space in your cluster unnecessarily. You can configure it to be deleted automatically
after a successful upgrade by setting the following variable on the AWX spec.
This provides the ability to roll back if needed, but can take up extra storage space in your cluster unnecessarily. You can configure it to be deleted automatically after a successful upgrade by setting the following variable on the AWX spec.
```yaml
spec:
postgres_keep_pvc_after_upgrade: False
spec:
postgres_keep_pvc_after_upgrade: False
```
#### v0.14.0
##### Cluster-scope to Namespace-scope considerations

View File

@@ -1,26 +1,4 @@
### Adding Execution Nodes
Starting with AWX Operator v0.30.0 and AWX v21.7.0, standalone execution nodes can be added to your deployments.
See [AWX execution nodes docs](https://github.com/ansible/awx/blob/devel/docs/execution_nodes.md) for information about this feature.
See [Managing Capacity With Instances](https://ansible.readthedocs.io/projects/awx/en/latest/administration/instances.html) chapter of the AWX Administration Guide for information about this feature.
#### Custom Receptor CA
The control nodes on the K8S cluster will communicate with execution nodes via mutual TLS TCP connections, running via Receptor.
Execution nodes will verify incoming connections by ensuring the x509 certificate was issued by a trusted Certificate Authority (CA).
A user may wish to provide their own CA for this validation. If no CA is provided, AWX Operator will automatically generate one using OpenSSL.
Given custom `ca.crt` and `ca.key` stored locally, run the following,
```bash
kubectl create secret tls awx-demo-receptor-ca \
--cert=/path/to/ca.crt --key=/path/to/ca.key
```
The secret should be named `{AWX Custom Resource name}-receptor-ca`. In the above the AWX CR name is "awx-demo". Please replace "awx-demo" with your AWX Custom Resource name.
If this secret is created after AWX is deployed, run the following to restart the deployment,
```bash
kubectl rollout restart deployment awx-demo
```
**Important Note**, changing the receptor CA will break connections to any existing execution nodes. These nodes will enter an `unavailable` state, and jobs will not be able to run on them. Users will need to download and re-run the install bundle for each execution node. This will replace the TLS certificate files with those signed by the new CA. The execution nodes should then appear in a `ready` state after a few minutes.

View File

@@ -9,25 +9,25 @@ If you want to use affinity rules for your AWX pod you can use the `affinity` op
If you want to constrain the web and task pods individually, you can do so by specificying the deployment type before the specific setting. For
example, specifying `task_tolerations` will allow the AWX task pod to be scheduled onto nodes with matching taints.
| Name | Description | Default |
| -------------------------------- | ---------------------------------------- | ------- |
| postgres_image | Path of the image to pull | postgres |
| postgres_image_version | Image version to pull | 13 |
| node_selector | AWX pods' nodeSelector | '' |
| web_node_selector | AWX web pods' nodeSelector | '' |
| task_node_selector | AWX task pods' nodeSelector | '' |
| topology_spread_constraints | AWX pods' topologySpreadConstraints | '' |
| web_topology_spread_constraints | AWX web pods' topologySpreadConstraints | '' |
| task_topology_spread_constraints | AWX task pods' topologySpreadConstraints | '' |
| affinity | AWX pods' affinity rules | '' |
| web_affinity | AWX web pods' affinity rules | '' |
| task_affinity | AWX task pods' affinity rules | '' |
| tolerations | AWX pods' tolerations | '' |
| web_tolerations | AWX web pods' tolerations | '' |
| task_tolerations | AWX task pods' tolerations | '' |
| annotations | AWX pods' annotations | '' |
| postgres_selector | Postgres pods' nodeSelector | '' |
| postgres_tolerations | Postgres pods' tolerations | '' |
| Name | Description | Default |
| -------------------------------- | ---------------------------------------- | -------------------------------- |
| postgres_image | Path of the image to pull | quay.io/sclorg/postgresql-15-c9s |
| postgres_image_version | Image version to pull | latest |
| node_selector | AWX pods' nodeSelector | '' |
| web_node_selector | AWX web pods' nodeSelector | '' |
| task_node_selector | AWX task pods' nodeSelector | '' |
| topology_spread_constraints | AWX pods' topologySpreadConstraints | '' |
| web_topology_spread_constraints | AWX web pods' topologySpreadConstraints | '' |
| task_topology_spread_constraints | AWX task pods' topologySpreadConstraints | '' |
| affinity | AWX pods' affinity rules | '' |
| web_affinity | AWX web pods' affinity rules | '' |
| task_affinity | AWX task pods' affinity rules | '' |
| tolerations | AWX pods' tolerations | '' |
| web_tolerations | AWX web pods' tolerations | '' |
| task_tolerations | AWX task pods' tolerations | '' |
| annotations | AWX pods' annotations | '' |
| postgres_selector | Postgres pods' nodeSelector | '' |
| postgres_tolerations | Postgres pods' tolerations | '' |
Example of customization could be:

View File

@@ -0,0 +1,52 @@
#### Container Probes
These parameters control the usage of liveness and readiness container probes for
the web and task containers.
> [!ALERT]
> All of probes are disabled by default for now, to enable it, set the *_period parameters. For example:
```
web_liveness_period: 15
web_readiness_period: 15
task_liveness_period: 15
task_readiness_period: 15
```
#### Web / Task Container Liveness Check
The liveness probe queries the status of the supervisor daemon of the container. The probe will fail if it
detects one of the services in a state other than "RUNNING".
| Name | Description | Default |
| -------------| -----------------------------------|---------|
| web_liveness_period | Time period in seconds between each probe check. The value of 0 disables the probe. | 0 |
| web_liveness_initial_delay | Initial delay before starting probes in seconds | 5 |
| web_liveness_failure_threshold| Number of consecutive failure events to identify failure of container | 3 |
| web_liveness_timeout | Number of seconds to wait for a probe response from container | 1 |
| task_liveness_period | Time period in seconds between each probe check. The value of 0 disables the probe. | 0 |
| task_liveness_initial_delay | Initial delay before starting probes in seconds | 5 |
| task_liveness_failure_threshold| Number of consecutive failure events to identify failure of container | 3 |
| task_liveness_timeout | Number of seconds to wait for a probe response from container | 1 |
#### Web Container Readiness Check
This is an HTTP check against the status endpoint to confirm the system is still able to respond to web requests.
| Name | Description | Default |
| -------------| ---------------------------------- | ------- |
| web_readiness_period | Time period in seconds between each probe check. The value of 0 disables the probe. | 0 |
| web_readiness_initial_delay | Initial delay before starting probes in seconds | 5 |
| web_readiness_failure_threshold| Number of consecutive failure events to identify failure of container | 3 |
| web_readiness_timeout | Number of seconds to wait for a probe response from container | 1 |
#### Task Container Readiness Check
This is a command probe using the builtin check command of the awx-manage utility.
| Name | Description | Default |
| -------------| ---------------------------------- | ------- |
| task_readiness_period | Time period in seconds between each probe check. The value of 0 disables the probe. | 0 |
| task_readiness_initial_delay | Initial delay before starting probes in seconds | 5 |
| task_readiness_failure_threshold| Number of consecutive failure events to identify failure of container | 3 |
| task_readiness_timeout | Number of seconds to wait for a probe response from container | 1 |

View File

@@ -22,16 +22,15 @@ spec:
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: 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: 50m, memory: 64Mi} |
| redis_resource_requirements | Redis container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
| postgres_resource_requirements | Postgres container resource requirements | requests: {cpu: 10m, memory: 64Mi} |
| rsyslog_resource_requirements | Rsyslog container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
| init_container_resource_requirements | Init Container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
| postgres_init_container_resource_requirements | Postgres Init Container resource requirements | requests: {cpu: 10m, memory: 64Mi} |
| 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: 50m, memory: 64Mi} |
| redis_resource_requirements | Redis container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
| postgres_resource_requirements | Postgres container (and initContainer) resource requirements | requests: {cpu: 10m, memory: 64Mi} |
| rsyslog_resource_requirements | Rsyslog container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
| init_container_resource_requirements | Init Container resource requirements | requests: {cpu: 100m, memory: 128Mi} |
Example of customization could be:
@@ -85,13 +84,6 @@ spec:
limits:
cpu: 1000m
memory: 2Gi
postgres_init_container_resource_requirements:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 1000m
memory: 2Gi
```

View File

@@ -0,0 +1,24 @@
### Custom Receptor CA
The control nodes on the K8S cluster will communicate with execution nodes via mutual TLS TCP connections, running via Receptor.
Execution nodes will verify incoming connections by ensuring the x509 certificate was issued by a trusted Certificate Authority (CA).
A user may wish to provide their own CA for this validation. If no CA is provided, AWX Operator will automatically generate one using OpenSSL.
Given custom `ca.crt` and `ca.key` stored locally, run the following,
```bash
kubectl create secret tls awx-demo-receptor-ca \
--cert=/path/to/ca.crt --key=/path/to/ca.key
```
The secret should be named `{AWX Custom Resource name}-receptor-ca`. In the above the AWX CR name is "awx-demo". Please replace "awx-demo" with your AWX Custom Resource name.
If this secret is created after AWX is deployed, run the following to restart the deployment,
```bash
kubectl rollout restart deployment awx-demo
```
**Important Note**, changing the receptor CA will break connections to any existing execution nodes. These nodes will enter an `unavailable` state, and jobs will not be able to run on them. Users will need to download and re-run the install bundle for each execution node. This will replace the TLS certificate files with those signed by the new CA. The execution nodes should then appear in a `ready` state after a few minutes.

View File

@@ -13,7 +13,8 @@ In a scenario where custom volumes and volume mounts are required to either over
| 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).
!!! 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).
Example configuration for ConfigMap
@@ -26,62 +27,68 @@ metadata:
namespace: <target namespace>
data:
ansible.cfg: |
[defaults]
remote_tmp = /tmp
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
[defaults]
remote_tmp = /tmp
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
custom.py: |
INSIGHTS_URL_BASE = "example.org"
AWX_CLEANUP_PATHS = True
INSIGHTS_URL_BASE = "example.org"
AWX_CLEANUP_PATHS = True
```
Example spec file for volumes and volume mounts
```yaml
---
spec:
...
extra_volumes: |
- name: ansible-cfg
configMap:
defaultMode: 420
items:
- key: ansible.cfg
path: ansible.cfg
name: <resourcename>-extra-config
- name: custom-py
configMap:
defaultMode: 420
items:
- key: custom.py
path: custom.py
name: <resourcename>-extra-config
- name: shared-volume
persistentVolumeClaim:
claimName: my-external-volume-claim
spec:
...
extra_volumes: |
- name: ansible-cfg
configMap:
defaultMode: 420
items:
- key: ansible.cfg
path: ansible.cfg
name: <resourcename>-extra-config
- name: custom-py
configMap:
defaultMode: 420
items:
- key: custom.py
path: custom.py
name: <resourcename>-extra-config
- name: shared-volume
persistentVolumeClaim:
claimName: my-external-volume-claim
init_container_extra_volume_mounts: |
- name: shared-volume
mountPath: /shared
init_container_extra_volume_mounts: |
- name: shared-volume
mountPath: /shared
init_container_extra_commands: |
# set proper permissions (rwx) for the awx user
chmod 775 /shared
chgrp 1000 /shared
init_container_extra_commands: |
# set proper permissions (rwx) for the awx user
chmod 775 /shared
chgrp 1000 /shared
ee_extra_volume_mounts: |
- name: ansible-cfg
mountPath: /etc/ansible/ansible.cfg
subPath: ansible.cfg
ee_extra_volume_mounts: |
- name: ansible-cfg
mountPath: /etc/ansible/ansible.cfg
subPath: ansible.cfg
task_extra_volume_mounts: |
- name: custom-py
mountPath: /etc/tower/conf.d/custom.py
subPath: custom.py
- name: shared-volume
mountPath: /shared
web_extra_volume_mounts: |
- name: custom-py
mountPath: /etc/tower/conf.d/custom.py
subPath: custom.py
task_extra_volume_mounts: |
- name: custom-py
mountPath: /etc/tower/conf.d/custom.py
subPath: custom.py
- name: shared-volume
mountPath: /shared
```
> :warning: **Volume and VolumeMount names cannot contain underscores(_)**
!!! warning
**Volume and VolumeMount names cannot contain underscores(_)**
##### Custom UWSGI Configuration
We allow the customization of two UWSGI parameters:
@@ -143,7 +150,9 @@ $ oc create configmap favicon-configmap --from-file favicon.ico
Then specify the extra_volume and web_extra_volume_mounts on your AWX CR spec
```yaml
---
spec:
...
extra_volumes: |
- name: favicon
configMap:

View File

@@ -2,15 +2,19 @@
There are a few variables that are customizable for awx the image management.
| 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 |
| 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:DEFAULT_AWX_VERSION |
| redis_image | Path of the image to pull | docker.io/redis |
| redis_image_version | Image version to pull | latest |
| control_plane_ee_image | Image version to pull | quay.io/ansible/awx-ee:DEFAULT_AWX_VERSION |
| init_container_image | Path of the image to pull | quay.io/ansible/awx-ee |
| init_container_image_version | Image version to pull | value of DEFAULT_AWX_VERSION or latest |
| init_projects_container_image | Image version to pull | quay.io/centos/centos:stream9 |
Example of customization could be:
@@ -26,6 +30,10 @@ spec:
ee_images:
- name: my-custom-awx-ee
image: myorg/my-custom-awx-ee
control_plane_ee_image: myorg/my-custom-awx-ee:latest
init_container_image: myorg/my-custom-awx-ee
init_container_image_version: latest
init_projects_container_image: myorg/my-mirrored-centos:stream9
```
**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.

View File

@@ -24,3 +24,7 @@ Example configuration of `extra_settings` parameter
```
Note for some settings, such as `LOG_AGGREGATOR_LEVEL`, the value may need double quotes.
!!! tip
Alternatively, you can pass any additional settings by mounting ConfigMaps or Secrets of the python files (`*.py`) that contain custom settings to under `/etc/tower/conf.d/` in the web and task pods.
See the example of `custom.py` in the [Custom Volume and Volume Mount Options](custom-volume-and-volume-mount-options.md) section.

View File

@@ -11,9 +11,14 @@ For more information about remote execution and hop nodes and how to create them
## Deploy and configure AWXMeshIngress
### On Red Hat OpenShift with operator managed Route
!!! note
The mesh ingress uses the `control_plane_ee_image` and `image_pull_policy` fields of the AWX instance to determine image and policy to be adopted.
Defaulted to `quay.io/ansible/awx-ee:latest` and `Always`.
Currently there are no dedicated parameters to specify the image and policy.
To deploy an mesh ingress on OpenShift create the AWXMeshIngress resource.
### On Red Hat OpenShift with Operator managed Route
To deploy a mesh ingress on OpenShift, create the AWXMeshIngress resource on the namespace where your AWX instance is running on.
Example:
@@ -27,21 +32,141 @@ spec:
deployment_name: <awx instance name>
```
### User managed Ingress
### On Kubernetes with Operator managed Ingress (NGINX)
UNDER CONSTRUCTION (contribution welcome)
To deploy a mesh ingress on Kubernetes cluster which has [NGINX Ingress Controller](https://www.nginx.com/products/nginx-ingress-controller/), create the AWXMeshIngress resource on the namespace where your AWX instance is running on.
### Operator managed Ingress
Note that AWXMeshIngress requires [SSL Passthrough](https://kubernetes.github.io/ingress-nginx/user-guide/tls/#ssl-passthrough) enabled which is disabled by default. Ensure it is enabled on your NGINX Ingress Controller.
UNDER CONSTRUCTION (contribution welcome)
By specifying `ingress_controller` as `nginx`, AWX Operator will generate Ingress resource that has `nginx.ingress.kubernetes.io/ssl-passthrough` annotation set to `"true"`.
### Deploy and configure AWXMeshIngress via IngressRouteTCP
Example:
UNDER CONSTRUCTION (contribution welcome)
```yaml
---
apiVersion: awx.ansible.com/v1alpha1
kind: AWXMeshIngress
metadata:
name: <mesh ingress name>
spec:
deployment_name: <awx instance name>
ingress_type: Ingress
ingress_controller: nginx
ingress_class_name: nginx
external_hostname: <fqdn for mesh ingress>
```
### On Kubernetes with Operator managed Ingress (Traefik)
To deploy a mesh ingress on Kubernetes cluster which has [Traefik Kubernetes Ingress provider](https://doc.traefik.io/traefik/providers/kubernetes-ingress/), create the AWXMeshIngress resource on the namespace where your AWX instance is running on.
Note that by deploying following AWXMeshIngress, AWX Operator will generate IngressRouteTCP resource that has `websecure` as an `entryPoints`. If this does not satisfy your requirement, refer to [User managed Ingress section](#on-kubernetes-with-user-managed-ingress) and create an IngressRouteTCP resource manually.
Example:
```yaml
---
apiVersion: awx.ansible.com/v1alpha1
kind: AWXMeshIngress
metadata:
name: <mesh ingress name>
spec:
deployment_name: <awx instance name>
ingress_type: IngressRouteTCP
ingress_controller: traefik
ingress_class_name: traefik
ingress_api_version: traefik.io/v1alpha1
external_hostname: <fqdn for mesh ingress>
```
!!! tip
AWX Operator supports both API groups `traefik.io` and `traefik.containo.us` in `ingress_api_version` for Traefik, but it is recommended to use `traefik.io` since `traefik.containo.us` is deprecated in Traefik v2.10 and is removed in Traefik v3. Refer to [Traefik documentation](https://doc.traefik.io/traefik/migration/v2/#v210) for more information about deprecation.
If you can't see any IngressRouteTCP resources by `kubectl` command after deploying mesh ingress, you should fully qualify the resource name with API group, `kubectl get ingressroutetcp.traefik.io` or `kubectl get ingressroutetcp.traefik.containo.us` for example.
### On Kubernetes with User managed Ingress
To deploy a mesh ingress on Kubernetes cluster, create the AWXMeshIngress resource on the namespace where your AWX instance is running on.
Alternatively, if you wish to create your own Ingress resource, you can deploy a mesh ingress with `ingress_type` set to `none` and then manually create an Ingress resource with any configuration.
In this case, the `external_hostname` is still required as it is used to generate the certificate that will be used by Receptor.
Example:
```yaml
---
apiVersion: awx.ansible.com/v1alpha1
kind: AWXMeshIngress
metadata:
name: <mesh ingress name>
spec:
deployment_name: <awx instance name>
ingress_type: none # This line can be omitted since this is the default value
external_hostname: <fqdn for mesh ingress>
```
The requirements for user managed Ingress resource are as follows:
- Supports WebSocket
- SSL/TLS Passthrough enabled
- Accessible over port `443`
- Having the same hostname as `external_hostname` in the AWXMeshIngress resource
- Routing the traffic to port `27199` of the Service of the same name as the AWXMeshIngress resource
These are example Ingress resources for NGINX and Traefik.
```yaml
# Ingress for NGINX Ingress Controller
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: <mesh ingress name>
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
ingressClassName: nginx
rules:
- host: <fqdn for mesh ingress>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <mesh ingress name>
port:
number: 27199
```
```yaml
# Ingress for Traefik Kubernetes Ingress provider
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: <mesh ingress name>
spec:
entryPoints:
- websecure
routes:
- match: HostSNI(`<fqdn for mesh ingress>`)
services:
- name: <mesh ingress name>
port: 27199
tls:
passthrough: true
```
## Validating setup of Mesh Ingress
After AWXMeshIngress has been successfully created a new Instance with the same name will show up in AWX Instance UI
After AWXMeshIngress has been successfully created, a new Instance with the same name will be registered to AWX and will be visible on the Instance UI page
![mesh ingress instance on AWX UI](mesh-ingress-instance-on-awx-ui.png)
@@ -57,92 +182,48 @@ In this example, the mesh ingress has two listener addresses:
When selecting peer for new instance the mesh ingress instance should now be present as a option.
![peering to mesh ingress on awx ui](peering-to-mesh-ingress-on-awx-ui.png)
For more information about how to create external remote execution and hop node and configuring the mesh. See AWX Documentation on [Add a instance](https://ansible.readthedocs.io/projects/awx/en/latest/administration/instances.html#add-an-instance).
For more information about how to create external remote execution and hop nodes and configuring the mesh, see AWX Documentation on [Add a instance](https://ansible.readthedocs.io/projects/awx/en/latest/administration/instances.html#add-an-instance).
## AWXMeshIngress
## Custom Resource Definitions
### AWXMeshIngress
AWXMeshIngress controls the deployment and configuration of mesh ingress on AWX
- **apiVersion**: awx.ansible.com/v1alpha1
| Name | Description |
| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`apiVersion`** | awx.ansible.com/v1alpha1 |
| **`kind`** | AWXMeshIngress |
| **`metadata`** ([ObjectMeta](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/object-meta/#ObjectMeta)) | Standard object's metadata. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata) |
| **`spec`** ([AWXMeshIngressSpec](#awxmeshingressspec)) | Spec is the desired state of the AWXMeshIngress. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status) |
| **`status`** ([AWXMeshIngressStatus](#awxmeshingressstatus)) | Status is the current state of the AWXMeshIngress. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status) |
- **kind**: AWXMeshIngress
#### AWXMeshIngressSpec
- **metadata**: ([ObjectMeta](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/object-meta/#ObjectMeta))
AWXMeshIngressSpec is the description of the configuration for AWXMeshIngress.
Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
| Name | Description | Default |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| **`deployment_name`** (string), required | Name of the AWX deployment to create the Mesh Ingress for. | `awx` |
| **`ingress_type`** (string) | Ingress type for ingress managed by the operator. Options: `none`, `Ingress`, `IngressRouteTCP`, `Route` | `Route` (on OpenShift), `none` (on Kubernetes) |
| **`external_hostname`** (string) | External hostname is an optional field used for specifying the external hostname defined in an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). This parameter is automatically generated on OpenShift | N/A |
| **`external_ipaddress`** (string) | External IP Address is an optional field used for specifying the external IP address defined in an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | N/A |
| **`ingress_api_version`** (string) | API Version for ingress managed by the operator. This parameter is ignored when `ingress_type` is `Route` | `networking.k8s.io/v1` |
| **`ingress_annotations`** (string) | Additional annotation on the ingress managed by the operator. This parameter is ignored when `ingress_type` is `Route` | `""` |
| **`ingress_controller`** (string) | Special configuration for specific Ingress Controllers. This parameter is ignored when `ingress_type` is `Route` | `""` |
| **`ingress_class_name`** (string) | The name of ingress class to use instead of the cluster default. see [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec). This parameter is ignored when `ingress_type` is `Route` | `""` |
- **spec**: ([AWXMeshIngressSpec](#awxmeshingressspec))
spec is the desired state of the AWXMeshIngress. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
- **status**: ([AWXMeshIngressStatus](#awxmeshingressstatus))
status is the current state of the AWXMeshIngress. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
### AWXMeshIngressSpec
AWXMeshIngress is the description of the configuration for AWXMeshIngress.
- **deployment_name** (string), required
Name of the AWX deployment to create the Mesh Ingress for.
- **external_hostname** (string)
External hostname is an optional field used for specifying the external hostname defined in an user managed [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- **external_ipaddress** (string)
External IP Address is an optional field used for specifying the external IP address defined in an user managed [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- **ingress_type** (string)
Ingress type for ingress managed by the operator
Options:
- none (default)
- Ingress
- IngressRouteTCP
- Route (default when deploy on OpenShift)
- **ingress_api_version** (string)
API Version for ingress managed by the operator
This parameter is ignored when ingress_type=Route
- **ingress_annotations** (string)
Annotation on the ingress managed by the operator
- **ingress_class_name** (string)
The name of ingress class to use instead of the cluster default. see [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec)
This parameter is ignored when `ingress_type=Route`
- **ingress_controller** (string)
Special configuration for specific Ingress Controllers
This parameter is ignored when ingress_type=Route
### AWXMeshIngressStatus
#### AWXMeshIngressStatus
AWXMeshIngressStatus describe the current state of the AWXMeshIngress.
## AWXMeshIngressList
### AWXMeshIngressList
AWXMeshIngressList is a collection of AWXMeshIngress.
- **items** ([][AWXMeshIngress](#awxmeshingress))
items is the list of Ingress.
- **apiVersion** (string)
APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
- **kind** (string)
Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
- **metadata** ([ListMeta](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/list-meta/#ListMeta))
Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
| Name | Description |
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`items`** ([AWXMeshIngress](#awxmeshingress)) | items is the list of Ingress. |
| **`apiVersion`** (string) | APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources) |
| **`kind`** (string) | Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds) |
| **`metadata`** ([ListMeta](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/list-meta/#ListMeta)) | Standard object's metadata. [More info](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata) |

View File

@@ -1,10 +1,10 @@
### Database Configuration
#### Postgres Version
#### PostgreSQL Version
The default Postgres version for the version of AWX bundled with the latest version of the awx-operator is Postgres 13. You can find this default for a given version by at the default value for [_postgres_image_version](https://github.com/ansible/awx-operator/blob/devel/roles/installer/defaults/main.yml#L243).
The default PostgreSQL version for the version of AWX bundled with the latest version of the awx-operator is PostgreSQL 15. You can find this default for a given version by at the default value for [supported_pg_version](https://github.com/ansible/awx-operator/blob/ffba1b4712a0b03f1faedfa70e3a9ef0d443e4a6/roles/installer/vars/main.yml#L7).
We only have coverage for the default version of Postgres. Newer versions of Postgres (14+) will likely work, but should only be configured as an external database. If your database is managed by the awx-operator (default if you don't specify a `postgres_configuration_secret`), then you should not override the default version as this may cause issues when awx-operator tries to upgrade your postgresql pod.
We only have coverage for the default version of PostgreSQL. Newer versions of PostgreSQL will likely work, but should only be configured as an external database. If your database is managed by the awx-operator (default if you don't specify a `postgres_configuration_secret`), then you should not override the default version as this may cause issues when awx-operator tries to upgrade your postgresql pod.
#### External PostgreSQL Service
@@ -56,15 +56,14 @@ 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_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 |
| Name | Description | Default |
| --------------------------------------------- | --------------------------------------------------------------- | --------------------------------------- |
| postgres_image | Path of the image to pull | quay.io/sclorg/postgresql-15-c9s |
| postgres_image_version | Image version to pull | latest |
| postgres_resource_requirements | PostgreSQL container (and initContainer) 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_priority_class | Priority class used for PostgreSQL pod | Empty string |
Example of customization could be:
@@ -90,4 +89,31 @@ spec:
- '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.
**Note**: If `postgres_storage_class` is not defined, PostgreSQL will store it's data on a volume using the default storage class for your cluster.
#### Note about overriding the postgres image
We recommend you use the default image sclorg image. If you are coming from a deployment using the old postgres image from dockerhub (postgres:13), upgrading from awx-operator version 2.12.2 and below to 2.15.0+ will handle migrating your data to the new postgresql image (postgresql-15-c9s).
You can no longer configure a custom `postgres_data_path` because it is hardcoded in the quay.io/sclorg/postgresql-15-c9s image.
If you override the postgres image to use a custom postgres image like postgres:15 for example, the default data directory path may be different. These images cannot be used interchangeably.
#### Initialize Postgres data volume
When using a hostPath backed PVC and some other storage classes like longhorn storagfe, the postgres data directory needs to be accessible by the user in the postgres pod (UID 26).
To initialize this directory with the correct permissions, configure the following setting, which will use an init container to set the permissions in the postgres volume.
```yaml
spec:
postgres_data_volume_init: true
```
Should you need to modify the init container commands, there is an example below.
```yaml
postgres_init_container_commands: |
chown 26:0 /var/lib/pgsql/data
chmod 700 /var/lib/pgsql/data
```

View File

@@ -33,6 +33,7 @@ The following variables are customizable only when `service_type=LoadBalancer`
| loadbalancer_protocol | Protocol to use for Loadbalancer ingress | http |
| loadbalancer_port | Port used for Loadbalancer ingress | 80 |
| loadbalancer_ip | Assign Loadbalancer IP | '' |
| loadbalancer_class | LoadBalancer class to use | '' |
```yaml
---
@@ -42,6 +43,7 @@ spec:
loadbalancer_ip: '192.168.10.25'
loadbalancer_protocol: https
loadbalancer_port: 443
loadbalancer_class: service.k8s.aws/nlb
service_annotations: |
environment: testing
service_labels: |

View File

@@ -18,6 +18,9 @@ theme:
- navigation.indexes
- navigation.tracking
- toc.integrate
- search.highlight
- search.share
- search.suggest
palette:
- media: "(prefers-color-scheme: light)"
primary: teal
@@ -67,6 +70,7 @@ nav:
- user-guide/advanced-configuration/scaling-the-web-and-task-pods-independently.md
- user-guide/advanced-configuration/assigning-awx-pods-to-specific-nodes.md
- user-guide/advanced-configuration/trusting-a-custom-certificate-authority.md
- user-guide/advanced-configuration/custom-receptor-certs.md
- user-guide/advanced-configuration/enabling-ldap-integration-at-awx-bootstrap.md
- user-guide/advanced-configuration/persisting-projects-directory.md
- user-guide/advanced-configuration/custom-volume-and-volume-mount-options.md
@@ -91,7 +95,8 @@ exclude_docs:
plugins:
- autorefs
- markdown-exec
- search
- material/search:
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
- mkdocstrings:
handlers:
python:

View File

@@ -21,6 +21,7 @@ provisioner:
namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test}
host_vars:
localhost:
awx_ee_image: ${AWX_EE_TEST_IMAGE:-""}
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') }}"
@@ -30,6 +31,8 @@ provisioner:
operator_image: ${OPERATOR_IMAGE:-""}
operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"}
kustomize: ${KUSTOMIZE_PATH:-kustomize}
store_debug_output: ${STORE_DEBUG_OUTPUT:-false}
debug_output_dir: ${DEBUG_OUTPUT_DIR:-"/tmp/awx_operator_molecule_test"}
env:
K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"}
verifier:

View File

@@ -1,5 +1,5 @@
---
- name: Create or update the awx.ansible.com/v1alpha1.AWX
- name: Create or update the awx.ansible.com/v1beta1.AWX
k8s:
state: present
namespace: '{{ namespace }}'

View File

@@ -49,16 +49,16 @@
####
- debug:
msg: test - replicas=3 should give 3 of each
msg: test - replicas=2 should give 2 of each
- include_tasks: apply_awx_spec.yml
vars:
additional_fields:
replicas: 3
replicas: 2
- include_tasks: _test_case_replicas.yml
vars:
expected_web_replicas: 3
expected_task_replicas: 3
expected_web_replicas: 2
expected_task_replicas: 2
tags:
- replicas

View File

@@ -1,98 +1,8 @@
---
- include_tasks: apply_awx_spec.yml
- name: Obtain generated admin password
k8s_info:
namespace: '{{ namespace }}'
kind: Secret
name: example-awx-admin-password
register: admin_pw_secret
- block:
- name: Get web pod details
k8s_info:
namespace: '{{ namespace }}'
kind: Pod
label_selectors:
- app.kubernetes.io/name = example-awx-web
register: awx_web_pod
when: not awx_version
- name: Get task pod details
k8s_info:
namespace: '{{ namespace }}'
kind: Pod
label_selectors:
- app.kubernetes.io/name = example-awx-task
register: awx_task_pod
when: not awx_version
- name: Extract tags from images from web pod
set_fact:
web_image_tags: |
{{ awx_web_pod.resources[0].spec.containers |
map(attribute='image') |
map('regex_search', default_awx_version) }}
when: not awx_version
- name: Extract tags from images from task pod
set_fact:
task_image_tags: |
{{ awx_task_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 web_image_tags
- default_awx_version not in task_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 }}'
- block:
- name: Validate AWX deployment
block:
- name: Look up details for this AWX instance
k8s_info:
namespace: "{{ namespace }}"
@@ -117,65 +27,90 @@
- app.kubernetes.io/name = example-awx-task
register: awx_task_pod
- name: Extract additional_labels from AWX spec
set_fact:
awx_additional_labels: >-
{{ this_awx.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', this_awx.resources[0].spec.additional_labels)
| list
}}
- name: Validate DEFAULT_AWX_VERSION
block:
- name: Extract tags from images from web pod
set_fact:
web_image_tags: |
{{ awx_web_pod.resources[0].spec.containers |
map(attribute='image') |
map('regex_search', default_awx_version) }}
- name: Extract tags from images from task pod
set_fact:
task_image_tags: |
{{ awx_task_pod.resources[0].spec.containers |
map(attribute='image') |
map('regex_search', default_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:
- default_awx_version not in web_image_tags
- default_awx_version not in task_image_tags
when: not awx_version
- name: Extract additional_labels from AWX web Pod
set_fact:
awx_web_pod_additional_labels: >-
{{ awx_web_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', this_awx.resources[0].spec.additional_labels)
| list
}}
- name: Extract additional_labels from AWX task Pod
set_fact:
awx_task_pod_additional_labels: >-
{{ awx_task_pod.resources[0].metadata.labels
- name: Validate additional_labels
block:
- name: Extract additional_labels from AWX spec
set_fact:
awx_additional_labels: >-
{{ this_awx.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', this_awx.resources[0].spec.additional_labels)
| list
}}
}}
- name: Assert AWX web Pod contains additional_labels
ansible.builtin.assert:
that:
- awx_web_pod_additional_labels == awx_additional_labels
- name: Extract additional_labels from AWX web Pod
set_fact:
awx_web_pod_additional_labels: >-
{{ awx_web_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', this_awx.resources[0].spec.additional_labels)
| list
}}
- name: Assert AWX task Pod contains additional_labels
ansible.builtin.assert:
that:
- awx_task_pod_additional_labels == awx_additional_labels
- name: Extract additional_labels from AWX task Pod
set_fact:
awx_task_pod_additional_labels: >-
{{ awx_task_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', this_awx.resources[0].spec.additional_labels)
| list
}}
- name: Extract web Pod labels which shouldn't have been propagated to it from AWX
set_fact:
awx_web_pod_extra_labels: >-
{{ awx_web_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', ["my/do-not-inherit"])
| list
}}
- name: Assert AWX web Pod contains additional_labels
ansible.builtin.assert:
that:
- awx_web_pod_additional_labels == awx_additional_labels
- name: AWX web Pod doesn't contain AWX labels not in additional_labels
ansible.builtin.assert:
that:
- awx_web_pod_extra_labels == []
- name: Assert AWX task Pod contains additional_labels
ansible.builtin.assert:
that:
- awx_task_pod_additional_labels == awx_additional_labels
- name: Extract task Pod labels which shouldn't have been propagated to it from AWX
set_fact:
awx_task_pod_extra_labels: >-
{{ awx_task_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', ["my/do-not-inherit"])
| list
}}
- name: Extract web Pod labels which shouldn't have been propagated to it from AWX
set_fact:
awx_web_pod_extra_labels: >-
{{ awx_web_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', ["my/do-not-inherit"])
| list
}}
- name: AWX task Pod doesn't contain AWX labels not in additional_labels
ansible.builtin.assert:
that:
- awx_task_pod_extra_labels == []
- name: AWX web Pod doesn't contain AWX labels not in additional_labels
ansible.builtin.assert:
that:
- awx_web_pod_extra_labels == []
- name: Extract task Pod labels which shouldn't have been propagated to it from AWX
set_fact:
awx_task_pod_extra_labels: >-
{{ awx_task_pod.resources[0].metadata.labels
| dict2items | selectattr('key', 'in', ["my/do-not-inherit"])
| list
}}
- name: AWX task Pod doesn't contain AWX labels not in additional_labels
ansible.builtin.assert:
that:
- awx_task_pod_extra_labels == []
rescue:
- name: Re-emit failure
@@ -184,3 +119,76 @@
result: '{{ ansible_failed_result }}'
fail:
msg: '{{ failed_task }}'
- name: Obtain generated admin password
k8s_info:
namespace: '{{ namespace }}'
kind: Secret
name: example-awx-admin-password
register: admin_pw_secret
- name: Validate demo job launch
block:
- 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: Store job_lists debug output
copy:
content: "{{ job_lists | to_nice_json }}"
dest: "{{ debug_output_dir }}/job_lists.json"
when: store_debug_output | default(false)
- 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
register: job_details
- name: Store job_details debug output
copy:
content: "{{ job_details | to_nice_json }}"
dest: "{{ debug_output_dir }}/job_details.json"
when: store_debug_output | default(false)
## TODO: figure out why this doesn't work
# - name: Store debug outputs
# copy:
# content: '{{ item }}'
# dest: "{{ debug_output_dir }}/{{ item }}.json"
# loop:
# - job_lists
# - job_details
# when: store_debug_output | default(false)
- name: Re-emit failure
vars:
failed_task:
result: '{{ ansible_failed_result }}'
fail:
msg: '{{ failed_task }}'

View File

@@ -13,6 +13,12 @@ spec:
{% endif %}
{% if awx_version %}
image_version: {{ awx_version }}
{% endif %}
{% if awx_ee_image %}
control_plane_ee_image: {{ awx_ee_image }}
ee_images:
- image: {{ awx_ee_image }}
name: AWX EE
{% endif %}
ingress_type: ingress
ingress_path: /awx
@@ -32,11 +38,10 @@ spec:
memory: 16M
no_log: false
postgres_resource_requirements: {}
postgres_init_container_resource_requirements: {}
redis_resource_requirements: {}
additional_labels:
- my/team
- my/service
{% if additional_fields is defined %}
{{ additional_fields | to_nice_yaml | indent(2) }}
{% endif %}
{% endif %}

View File

@@ -0,0 +1,15 @@
---
- name: Get all container log in pod
kubernetes.core.k8s_log:
namespace: '{{ namespace }}'
name: '{{ item.metadata.name }}'
all_containers: true
register: all_container_logs
- name: Store logs in file
ansible.builtin.copy:
content: "{{ all_container_logs.log_lines | join('\n') }}"
dest: '{{ debug_output_dir }}/{{ item.metadata.name }}.log'
# TODO: all_containser option dump all of the output in a single output make it hard to read we probably should iterate through each of the container to get specific logs
# also we should probably investigate toolings to do OpenShift style sosreport/must-gather for kind cluster or switch to microshift where sosreport is supported

View File

@@ -0,0 +1,29 @@
---
- name: Retrieve relevant k8s resources
kubernetes.core.k8s_info:
api_version: '{{ item.api_version }}'
kind: '{{ item.kind }}'
namespace: '{{ namespace }}'
loop:
- api_version: v1
kind: Pod
- api_version: apps/v1
kind: Deployment
- api_version: v1
kind: Secret
- api_version: v1
kind: ConfigMap
- api_version: "awx.ansible.com/v1beta1"
kind: AWX
register: debug_resources
- name: debug print item.kind and item.metadata.name
debug:
msg: '{{ item.kind }}-{{ item.metadata.name }}'
loop: "{{ debug_resources.results | map(attribute='resources') | flatten }}"
- name: Output gathered resource to files
ansible.builtin.copy:
content: '{{ item | to_nice_json }}'
dest: '{{ debug_output_dir }}/{{ item.kind }}-{{ item.metadata.name }}.json'
loop: "{{ debug_resources.results | map(attribute='resources') | flatten }}"

View File

@@ -10,52 +10,41 @@
ctrl_label: control-plane=controller-manager
tasks:
- block:
- name: Perform awx tests
block:
- name: Import all test files from tasks/
include_tasks: '{{ item }}'
ansible.builtin.include_tasks: '{{ item }}'
with_fileglob:
- tasks/*_test.yml
- tasks/awx_test.yml
- tasks/awx_replicas_test.yml
tags:
- always
rescue:
- name: Retrieve relevant resources
k8s_info:
api_version: '{{ item.api_version }}'
kind: '{{ item.kind }}'
- name: Create debug output directory
ansible.builtin.file:
path: '{{ debug_output_dir }}'
state: directory
tags:
- always
- name: Gather and output K8s resources
ansible.builtin.include_tasks: utils/output_k8s_resources.yml
tags:
- always
- name: Get all pods
kubernetes.core.k8s_info:
api_version: v1
kind: Pod
namespace: '{{ namespace }}'
loop:
- api_version: v1
kind: Pod
- api_version: apps/v1
kind: Deployment
- api_version: v1
kind: Secret
- api_version: v1
kind: ConfigMap
register: debug_resources
register: all_pods
tags:
- always
- name: Retrieve Pod logs
k8s_log:
name: '{{ item.metadata.name }}'
namespace: '{{ namespace }}'
container: awx-manager
loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}"
register: debug_logs
tags:
- always
- name: Output gathered resources
debug:
var: debug_resources
tags:
- always
- name: Output gathered logs
debug:
var: item.log_lines
loop: '{{ debug_logs.results }}'
- name: Get all container logs for all pods
ansible.builtin.include_tasks: utils/output_all_container_logs_for_pod.yml
loop: '{{ all_pods.resources }}'
ignore_errors: yes
tags:
- always
@@ -63,7 +52,7 @@
vars:
failed_task:
result: '{{ ansible_failed_result }}'
fail:
ansible.builtin.fail:
msg: '{{ failed_task }}'
tags:
- always

View File

@@ -23,6 +23,7 @@ provisioner:
namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test}
host_vars:
localhost:
awx_ee_image: ${AWX_EE_TEST_IMAGE:-""}
awx_image: ${AWX_TEST_IMAGE:-""}
awx_version: ${AWX_TEST_VERSION:-""}
ansible_python_interpreter: '{{ ansible_playbook_python }}'
@@ -34,6 +35,8 @@ provisioner:
operator_pull_policy: "Never"
kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}"
kustomize: ${KUSTOMIZE_PATH:-kustomize}
store_debug_output: ${STORE_DEBUG_OUTPUT:-false}
debug_output_dir: ${DEBUG_OUTPUT_DIR:-"/tmp/awx_operator_molecule_test"}
env:
K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig
KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig

20
noxfile.py Normal file
View File

@@ -0,0 +1,20 @@
import nox
@nox.session
def build(session: nox.Session):
"""
Build the AWX Operator docsite.
"""
session.install(
"-r",
"docs/requirements.in",
"-c",
"docs/requirements.txt",
)
session.run(
"mkdocs",
"build",
"--strict",
*session.posargs,
)

View File

@@ -20,9 +20,7 @@
- name: Dump ingress tls secret names from awx spec and data into file
include_tasks: dump_ingress_tls_secrets.yml
with_items:
- "{{ awx_spec.spec['ingress_hosts'] | default('') | map(attribute='tls_secret', default='') | select() | list }}"
when: "{{ awx_spec.spec['ingress_hosts'] | default('') | map(attribute='tls_secret', default='') | select() | list | length }}"
with_items: "{{ awx_spec.spec['ingress_hosts'] | default([]) | selectattr('tls_secret', 'defined') | map(attribute='tls_secret') | list }}"
- name: Dump receptor secret names and data into file
include_tasks: dump_receptor_secrets.yml

View File

@@ -1,8 +1,8 @@
---
deployment_type: "awx"
_postgres_image: postgres
_postgres_image_version: 13
_postgres_image: quay.io/sclorg/postgresql-15-c9s
_postgres_image_version: latest
backup_complete: false
database_type: "unmanaged"
supported_pg_version: 13
supported_pg_version: 15
image_pull_policy: IfNotPresent

View File

@@ -52,6 +52,7 @@ ingress_hosts: ''
loadbalancer_protocol: 'http'
loadbalancer_port: '80'
loadbalancer_class: ''
service_annotations: ''
# Port to be used for NodePort configuration, default is to auto-assign a port between 30000-32768
@@ -255,8 +256,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: 13
_postgres_image: quay.io/sclorg/postgresql-15-c9s
_postgres_image_version: latest
image_pull_policy: IfNotPresent
image_pull_secrets: []
@@ -277,10 +278,12 @@ init_container_extra_commands: ''
init_container_extra_volume_mounts: ''
ee_images:
- name: AWX EE (latest)
image: quay.io/ansible/awx-ee:latest
- name: "AWX EE (latest)"
image: "quay.io/ansible/awx-ee:latest"
- name: "AWX EE ({{ _image_version }})"
image: "quay.io/ansible/awx-ee:{{ _image_version }}"
_control_plane_ee_image: quay.io/ansible/awx-ee:latest
_control_plane_ee_image: "quay.io/ansible/awx-ee:{{ _image_version }}"
_init_container_image: "{{ _control_plane_ee_image.split(':')[0] }}"
_init_container_image_version: "{{ _control_plane_ee_image.split(':')[1] }}"
@@ -293,6 +296,11 @@ replicas: 1
web_replicas: ''
task_replicas: ''
web_liveness_period: 0
web_readiness_period: 0
task_liveness_period: 0
task_readiness_period: 0
task_args:
- /usr/bin/launch_awx_task.sh
task_command: []
@@ -392,13 +400,9 @@ 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
# Whether or not the /var/lib/projects directory will be persistent
@@ -410,6 +414,11 @@ projects_existing_claim: ''
# Define postgres configuration arguments to use
postgres_extra_args: ''
postgres_data_volume_init: false
postgres_init_container_commands: |
chown 26:0 /var/lib/pgsql/data
chmod 700 /var/lib/pgsql/data
# Configure postgres connection keepalive
postgres_keepalives: true
postgres_keepalives_idle: 5
@@ -481,3 +490,16 @@ nginx_worker_processes: 1
nginx_worker_connections: "{{ uwsgi_listen_queue_size }}"
nginx_worker_cpu_affinity: 'auto'
nginx_listen_queue_size: "{{ uwsgi_listen_queue_size }}"
# metrics-utility (github.com/ansible/metrics-utility)
_metrics_utility_enabled: "{{ metrics_utility_enabled | default(false) }}"
_metrics_utility_configmap: "{{ metrics_utility_configmap | default(deployment_type + '-metrics-utility-configmap') }}"
_metrics_utility_console_enabled: "{{ metrics_utility_console_enabled | default(false) }}"
_metrics_utility_image: "{{ metrics_utility_image | default(_image) }}"
_metrics_utility_image_version: "{{ metrics_utility_image_version | default(_image_version) }}"
_metrics_utility_image_pull_policy: "{{ metrics_utility_image_pull_policy | default('IfNotPresent') }}"
_metrics_utility_ship_target: "{{ metrics_utility_ship_target | default('directory') }}"
_metrics_utility_pvc_claim: "{{ metrics_utility_pvc_claim | default(deployment_type + '-metrics-utility') }}"
_metrics_utility_pvc_claim_size: "{{ metrics_utility_pvc_claim_size | default('5Gi') }}"
_metrics_utility_cronjob_gather_schedule: "{{ metrics_utility_cronjob_gather_schedule | default('@hourly') }}"
_metrics_utility_cronjob_report_schedule: "{{ metrics_utility_cronjob_report_schedule | default('@monthly') }}"

View File

@@ -106,14 +106,38 @@
set_fact:
managed_database: "{{ pg_config['resources'][0]['data']['type'] | default('') | b64decode == 'managed' }}"
- name: Get the old postgres pod information
# It is possible that N-2 postgres pods may still be present in the namespace from previous upgrades.
# So we have to take that into account and preferentially set the most recent one.
- name: Get the old postgres pod (N-1)
k8s_info:
kind: Pod
namespace: "{{ ansible_operator_meta.namespace }}"
name: "{{ ansible_operator_meta.name }}-postgres-0"
field_selectors:
- status.phase=Running
register: old_postgres_pod
register: _running_pods
- block:
- name: Filter pods by name
set_fact:
filtered_old_postgres_pods: "{{ _running_pods.resources |
selectattr('metadata.name', 'match', ansible_operator_meta.name + '-postgres.*-0') |
rejectattr('metadata.name', 'search', '-' + supported_pg_version | string + '-0') |
list }}"
# Sort pods by name in reverse order (most recent PG version first) and set
- name: Set info for previous postgres pod
set_fact:
sorted_old_postgres_pods: "{{ filtered_old_postgres_pods |
sort(attribute='metadata.name') |
reverse | list }}"
when: filtered_old_postgres_pods | length
- name: Set info for previous postgres pod
set_fact:
old_postgres_pod: "{{ sorted_old_postgres_pods | first }}"
when: filtered_old_postgres_pods | length
when: _running_pods.resources | length
- name: Look up details for this deployment
k8s_info:
@@ -123,30 +147,40 @@
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
- name: Check if postgres pod is running and version 12
block:
- name: Set path to PG_VERSION file for given container image
set_fact:
path_to_pg_version: '{{ postgres_data_path }}/PG_VERSION'
# If this deployment has been upgraded before or if upgrade has already been started, set this var
- name: Set previous PG version var
set_fact:
_previous_upgraded_pg_version: "{{ this_awx['resources'][0]['status']['upgradedPostgresVersion'] | default(false) }}"
when:
- "'upgradedPostgresVersion' in this_awx['resources'][0]['status']"
- name: Check if postgres pod is running an older version
block:
- name: Get old PostgreSQL version
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ ansible_operator_meta.name }}-postgres-0"
pod: "{{ old_postgres_pod['metadata']['name'] }}"
command: |
bash -c """
cat {{ path_to_pg_version }}
if [ -f "{{ _postgres_data_path }}/PG_VERSION" ]; then
cat "{{ _postgres_data_path }}/PG_VERSION"
elif [ -f '/var/lib/postgresql/data/pgdata/PG_VERSION' ]; then
cat '/var/lib/postgresql/data/pgdata/PG_VERSION'
fi
"""
register: _old_pg_version
- name: Upgrade data dir from Postgres 12 to 13 if applicable
- debug:
msg: "--- Upgrading from {{ old_postgres_pod['metadata']['name'] | default('NONE')}} Pod ---"
- name: Upgrade data dir from old Postgres to {{ supported_pg_version }} if applicable
include_tasks: upgrade_postgres.yml
when:
- _old_pg_version.stdout | default('0') | trim == '12'
- (_old_pg_version.stdout | default(0) | int ) < supported_pg_version
when:
- managed_database
- this_awx['resources'][0]['status']['upgradedPostgresVersion'] | default('none') != '12'
- old_postgres_pod['resources'] | length # upgrade is complete and old pg pod has been removed
- (_previous_upgraded_pg_version | default(false)) | ternary(_previous_upgraded_pg_version | int < supported_pg_version, true)
- old_postgres_pod | length # If empty, then old pg pod has been removed and we can assume the upgrade is complete
- block:
- name: Create Database if no database is specified
@@ -167,7 +201,7 @@
kubernetes.core.k8s_scale:
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-13"
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
replicas: 0
wait: yes
@@ -177,7 +211,7 @@
state: absent
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-13"
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
wait: yes
when: create_statefulset_result.error == 422

View File

@@ -0,0 +1,42 @@
---
- name: Setup PVC if using directory ship target
block:
# Check to make sure provided pvc exists
- name: Check provided PVC claim exists
kubernetes.core.k8s_info:
name: "{{ _metrics_utility_pvc_claim }}"
kind: PersistentVolumeClaim
namespace: "{{ ansible_operator_meta.namespace }}"
when:
- _metrics_utility_pvc_claim | length
- name: Create PVC for metrics-utility
kubernetes.core.k8s:
kind: PersistentVolumeClaim
definition: "{{ lookup('template', 'storage/metrics-utility.yaml.j2') }}"
when: _metrics_utility_ship_target == "directory"
- name: Create default metrics-utility Kubernetes CronJobs
kubernetes.core.k8s:
definition: "{{ lookup('template', item.template) }}"
apply: true
wait: true
vars:
cronjob_name: "{{ item.name }}"
loop:
- {name: 'metrics-utility-gather', template: 'cronjobs/metrics-utility-gather.yaml.j2'}
- {name: 'metrics-utility-report', template: 'cronjobs/metrics-utility-report.yaml.j2'}
- name: Create metrics-utility Kubernetes CronJob for Red Hat Hybrid Cloud Console
kubernetes.core.k8s:
definition: "{{ lookup('template', item.template) }}"
apply: true
wait: true
vars:
cronjob_name: "{{ item.name }}"
metrics_utility_ship_target: crc # TODO - Update to console when changed
loop:
- {name: 'metrics-utility-gather-console', template: 'cronjobs/metrics-utility-gather.yaml.j2'}
when: _metrics_utility_console_enabled

View File

@@ -2,8 +2,8 @@
- name: Check if there are any super users defined.
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "echo 'from django.contrib.auth.models import User;
nsu = User.objects.filter(is_superuser=True, username=\"{{ admin_user }}\").count();
@@ -16,8 +16,8 @@
- name: Create super user via Django if it doesn't exist.
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: awx-manage createsuperuser --username={{ admin_user | quote }} --email={{ admin_email | quote }} --noinput
register: result
changed_when: "'That username is already taken' not in result.stderr"
@@ -28,8 +28,8 @@
- name: Update Django super user password
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: awx-manage update_password --username='{{ admin_user }}' --password='{{ admin_password }}'
register: result
changed_when: "'Password updated' in result.stdout"
@@ -39,8 +39,8 @@
- name: Check if legacy queue is present
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage list_instances | grep '^\[tower capacity=[0-9]*\]'"
register: legacy_queue
@@ -50,8 +50,8 @@
- name: Unregister legacy queue
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage unregister_queue --queuename=tower"
when: "'[tower capacity=' in legacy_queue.stdout"
@@ -74,8 +74,8 @@
- name: Register default execution environments (without authentication)
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage register_default_execution_environments"
register: ree
@@ -95,8 +95,8 @@
- name: Register default execution environments (with authentication)
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage register_default_execution_environments
--registry-username='{{ default_execution_environment_pull_credentials_user }}'
@@ -111,8 +111,8 @@
- name: Create preload data if necessary. # noqa 305
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage create_preload_data"
register: cdo

View File

@@ -94,51 +94,17 @@
- name: Include resources configuration tasks
include_tasks: resources_configuration.yml
- name: Check for pending migrations
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: >-
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
changed_when: false
when: awx_task_pod_name != ''
register: database_check
- name: Migrate the database if the K8s resources were updated # noqa 305
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: |
bash -c "
function end_keepalive {
rc=$?
rm -f \"$1\"
kill $(cat /proc/$2/task/$2/children 2>/dev/null) 2>/dev/null || true
wait $2 || true
exit $rc
}
keepalive_file=\"$(mktemp)\"
while [[ -f \"$keepalive_file\" ]]; do
echo 'Database schema migration in progress...'
sleep 60
done &
keepalive_pid=$!
trap 'end_keepalive \"$keepalive_file\" \"$keepalive_pid\"' EXIT SIGINT SIGTERM
echo keepalive_pid: $keepalive_pid
awx-manage migrate --noinput
echo 'Successful'
"
register: migrate_result
when:
- awx_task_pod_name != ''
- database_check is defined
- (database_check.stdout|trim) != '0'
- name: Migrate database to the latest schema
include_tasks: migrate_schema.yml
when: awx_web_pod_name != ''
- name: Initialize Django
include_tasks: initialize_django.yml
when: awx_task_pod_name != ''
when: awx_web_pod_name != ''
- name: Enable optional metrics-utility
include_tasks: enable_metrics_utility.yml
when: metrics_utility_enabled | bool
- name: Update status variables
include_tasks: update_status.yml

View File

@@ -0,0 +1,57 @@
---
- name: Check for pending migrations
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
changed_when: false
when: awx_web_pod_name != ''
register: database_check
- block:
- name: Get version of controller for tracking
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage --version"
changed_when: false
register: version_check
- name: Sanitize instance version
set_fact:
version: "{{ version_check.stdout.split('+')[0] | trim }}"
# It is possible to do a wait on this task to create the job and wait
# until it completes. Unfortunately, if the job doesn't wait finish within
# the timeout period that is considered an error. We only want this to
# error if there is an issue with creating the job.
- name: Create kubernetes job to perform the migration
k8s:
apply: yes
definition: "{{ lookup('template', 'jobs/migration.yaml.j2') }}"
register: migrate_result
# This task is really only necessary for new installations. We need to
# ensure the database has a schema loaded before continuing with the
# initialization of admin user, etc.
- name: Watch for the migration job to finish
k8s_info:
kind: Job
namespace: "{{ ansible_operator_meta.namespace }}"
name: "{{ ansible_operator_meta.name }}-migration-{{ version }}"
register: result
until:
- result.resources[0].status.succeeded is defined
- result.resources[0].status.succeeded == 1
retries: 180
delay: 5
ignore_errors: true
when:
- database_check is defined
- (database_check.stdout|trim) != '0'

View File

@@ -1,28 +1,28 @@
---
- name: Get the current resource task pod information.
- name: Get the current resource web pod information.
k8s_info:
api_version: v1
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task"
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-web"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
- "app.kubernetes.io/component={{ deployment_type }}"
field_selectors:
- status.phase=Running
register: awx_task_pod
register: awx_web_pod
- name: Set the resource pod as a variable.
set_fact:
awx_task_pod: >-
{{ awx_task_pod['resources']
awx_web_pod: >-
{{ awx_web_pod['resources']
| rejectattr('metadata.deletionTimestamp', 'defined')
| sort(attribute='metadata.creationTimestamp')
| first | default({}) }}
- name: Set the resource pod name as a variable.
set_fact:
awx_task_pod_name: "{{ awx_task_pod['metadata']['name'] | default('') }}"
awx_web_pod_name: "{{ awx_web_pod['metadata']['name'] | default('') }}"
- name: Set user provided control plane ee image
set_fact:
@@ -249,11 +249,9 @@
k8s:
apply: yes
definition: "{{ lookup('template', 'deployments/{{ item }}.yaml.j2') }}"
wait: yes
wait_timeout: "{{ (120 * replicas) or 120 }}"
loop:
- task
- web
- task
register: this_deployment_result
- block:
@@ -262,16 +260,21 @@
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task"
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-web"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
- "app.kubernetes.io/component={{ deployment_type }}"
field_selectors:
- status.phase=Running
register: _new_pod
until:
- "_new_pod['resources'] | length"
- "_new_pod['resources'] | rejectattr('metadata.deletionTimestamp', 'defined') | length"
retries: 60
delay: 5
- name: Update new resource pod as a variable.
set_fact:
awx_task_pod: >-
awx_web_pod: >-
{{ _new_pod['resources']
| rejectattr('metadata.deletionTimestamp', 'defined')
| sort(attribute='metadata.creationTimestamp')
@@ -279,13 +282,13 @@
- name: Update new resource pod name as a variable.
set_fact:
awx_task_pod_name: '{{ awx_task_pod["metadata"]["name"] | default("")}}'
awx_web_pod_name: '{{ awx_web_pod["metadata"]["name"] | default("")}}'
when:
- this_deployment_result.changed
- name: Verify the resource pod name is populated.
assert:
that:
- awx_task_pod_name != ''
- awx_web_pod_name != ''
fail_msg: "Could not find the tower pod's name."
when: task_replicas | int > 0 or (task_replicas == '' and replicas > 0)
when: web_replicas | int > 0 or (web_replicas == '' and replicas > 0)

View File

@@ -8,8 +8,8 @@
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 != ''
- init_container_image | default('_undefined',true) != '_undefined'
- init_container_image_version | default('_undefined',true) != '_undefined'
- name: Set Init image URL
set_fact:

View File

@@ -47,13 +47,13 @@
- name: Retrieve instance version
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage --version"
register: instance_version
changed_when: false
when: awx_task_pod_name != ''
when: awx_web_pod_name != ''
- name: Update version status
operator_sdk.util.k8s_status:
@@ -111,5 +111,5 @@
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
status:
upgradedPostgresVersion: "{{ upgraded_postgres_version }}"
upgradedPostgresVersion: "{{ upgraded_postgres_version | string }}"
when: upgraded_postgres_version is defined

View File

@@ -1,9 +1,9 @@
---
# Upgrade Posgres (Managed Databases only)
# * If postgres version is not 12, and not an external postgres instance (when managed_database is yes),
# * If postgres version is not supported_pg_version, and not an external postgres instance (when managed_database is yes),
# then run this playbook with include_tasks from database_configuration.yml
# * Data will be streamed via a pg_dump from the postgres 12 pod to the postgres 13
# * Data will be streamed via a pg_dump from the postgres 12/13 pod to the postgres supported_pg_version
# pod via a pg_restore.
@@ -62,9 +62,19 @@
set_fact:
postgres_pod_name: "{{ postgres_pod['resources'][0]['metadata']['name'] }}"
- name: Get the name of the service for the old postgres pod
k8s_info:
kind: Service
namespace: "{{ ansible_operator_meta.namespace }}"
label_selectors:
- "app.kubernetes.io/component=database"
- "app.kubernetes.io/instance={{ old_postgres_pod.metadata.labels['app.kubernetes.io/instance'] }}"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
register: old_postgres_svc
- name: Set full resolvable host name for postgres pod
set_fact:
resolvable_db_host: "{{ ansible_operator_meta.name }}-postgres.{{ ansible_operator_meta.namespace }}.svc" # yamllint disable-line rule:line-length
resolvable_db_host: "{{ old_postgres_svc['resources'][0]['metadata']['name'] }}.{{ ansible_operator_meta.namespace }}.svc" # yamllint disable-line rule:line-length
no_log: "{{ no_log }}"
- name: Set pg_dump command
@@ -118,31 +128,28 @@
- name: Set flag signifying that this instance has been migrated
set_fact:
upgraded_postgres_version: '13'
upgraded_postgres_version: '{{ supported_pg_version }}'
# Cleanup old Postgres resources
- name: Remove old Postgres StatefulSet
# Cleanup old PostgreSQL resources
- name: Remove old PostgreSQL StatefulSet
k8s:
kind: StatefulSet
api_version: v1
namespace: "{{ ansible_operator_meta.namespace }}"
name: "{{ ansible_operator_meta.name }}-postgres"
name: "{{ item }}"
state: absent
wait: true
loop:
- "{{ ansible_operator_meta.name }}-postgres"
- "{{ ansible_operator_meta.name }}-postgres-13"
- name: Remove old Postgres Service
- name: Remove old PostgreSQL Service
k8s:
kind: Service
api_version: v1
namespace: "{{ ansible_operator_meta.namespace }}"
name: "{{ ansible_operator_meta.name }}-postgres"
name: "{{ item }}"
state: absent
- name: Remove old persistent volume claim
k8s:
kind: PersistentVolumeClaim
api_version: v1
namespace: "{{ ansible_operator_meta.namespace }}"
name: "postgres-{{ ansible_operator_meta.name }}-postgres-0"
state: absent
when: postgres_keep_pvc_after_upgrade
loop:
- "{{ ansible_operator_meta.name }}-postgres"
- "{{ ansible_operator_meta.name }}-postgres-13"

View File

@@ -0,0 +1,83 @@
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ ansible_operator_meta.name }}-{{ cronjob_name }}
namespace: '{{ ansible_operator_meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-{{ cronjob_name }}'
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
{{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=4) | trim }}
spec:
schedule: "{{ _metrics_utility_cronjob_gather_schedule }}"
jobTemplate:
spec:
backoffLimit: 2
template:
metadata:
labels:
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-{{ cronjob_name }}'
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=12) | trim }}
{{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=12) | trim }}
spec:
{% 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 %}
containers:
- name: {{ ansible_operator_meta.name }}-{{ cronjob_name }}
image: "{{ _metrics_utility_image }}"
imagePullPolicy: "{{ image_pull_policy }}"
resources:
requests:
memory: "100Mi"
cpu: "100m"
command:
- /bin/sh
- -c
- metrics-utility gather_automation_controller_billing_data --ship --until=10m
env:
- name: METRICS_UTILITY_SHIP_TARGET
value: "{{ _metrics_utility_ship_target }}"
envFrom:
- configMapRef:
name: {{ _metrics_utility_configmap }}
{% if _metrics_utility_secret is defined %}
- secretRef:
name: {{ _metrics_utility_secret }}
{% endif %}
volumeMounts:
- name: {{ ansible_operator_meta.name }}-metrics-utility
mountPath: /metrics-utility
readOnly: false
- name: "{{ ansible_operator_meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: {{ ansible_operator_meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
volumes:
- name: {{ ansible_operator_meta.name }}-metrics-utility
persistentVolumeClaim:
claimName: {{ _metrics_utility_pvc_claim }}
readOnly: false
- name: "{{ ansible_operator_meta.name }}-application-credentials"
secret:
secretName: "{{ ansible_operator_meta.name }}-app-credentials"
items:
- key: credentials.py
path: 'credentials.py'
- name: {{ ansible_operator_meta.name }}-settings
configMap:
name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap'
items:
- key: settings
path: settings.py
restartPolicy: OnFailure

View File

@@ -0,0 +1,80 @@
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ ansible_operator_meta.name }}-{{ cronjob_name }}
namespace: '{{ ansible_operator_meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-{{ cronjob_name }}'
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
{{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=4) | trim }}
spec:
schedule: "{{ _metrics_utility_cronjob_report_schedule }}"
jobTemplate:
spec:
backoffLimit: 2
template:
metadata:
labels:
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-{{ cronjob_name }}'
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=12) | trim }}
{{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=12) | trim }}
spec:
{% 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 %}
containers:
- name: {{ ansible_operator_meta.name }}-{{ cronjob_name }}
image: "{{ _metrics_utility_image }}"
imagePullPolicy: "{{ image_pull_policy }}"
resources:
requests:
memory: "100Mi"
cpu: "100m"
command:
- /bin/sh
- -c
- metrics-utility build_report
envFrom:
- configMapRef:
name: {{ _metrics_utility_configmap }}
{% if _metrics_utility_secret is defined %}
- secretRef:
name: {{ _metrics_utility_secret }}
{% endif %}
volumeMounts:
- name: {{ ansible_operator_meta.name }}-metrics-utility
mountPath: /metrics-utility
readOnly: false
- name: "{{ ansible_operator_meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: {{ ansible_operator_meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
volumes:
- name: {{ ansible_operator_meta.name }}-metrics-utility
persistentVolumeClaim:
claimName: {{ _metrics_utility_pvc_claim }}
readOnly: false
- name: "{{ ansible_operator_meta.name }}-application-credentials"
secret:
secretName: "{{ ansible_operator_meta.name }}-app-credentials"
items:
- key: credentials.py
path: 'credentials.py'
- name: {{ ansible_operator_meta.name }}-settings
configMap:
name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap'
items:
- key: settings
path: settings.py
restartPolicy: OnFailure

View File

@@ -74,7 +74,32 @@ spec:
priorityClassName: '{{ control_plane_priority_class }}'
{% endif %}
initContainers:
- name: init
- name: init-database
image: '{{ _image }}'
imagePullPolicy: '{{ image_pull_policy }}'
resources: {{ init_container_resource_requirements }}
command:
- /bin/sh
- -c
- wait-for-migrations
volumeMounts:
- name: {{ ansible_operator_meta.name }}-application-credentials
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: "{{ secret_key_secret_name }}"
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ ansible_operator_meta.name }}-settings
mountPath: "/etc/tower/settings.py"
subPath: settings.py
readOnly: true
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
- name: init-receptor
image: '{{ _init_container_image }}'
imagePullPolicy: '{{ image_pull_policy }}'
resources: {{ init_container_resource_requirements }}
@@ -83,8 +108,20 @@ spec:
- -c
- |
hostname=$MY_POD_NAME
receptor --cert-makereq bits=2048 commonname=$hostname dnsname=$hostname nodeid=$hostname outreq=/etc/receptor/tls/receptor.req outkey=/etc/receptor/tls/receptor.key
receptor --cert-signreq req=/etc/receptor/tls/receptor.req cacert=/etc/receptor/tls/ca/mesh-CA.crt cakey=/etc/receptor/tls/ca/mesh-CA.key outcert=/etc/receptor/tls/receptor.crt verify=yes
receptor --cert-makereq \
bits=2048 \
commonname=$hostname \
dnsname=$hostname \
nodeid=$hostname \
outreq=/etc/receptor/tls/receptor.req \
outkey=/etc/receptor/tls/receptor.key
receptor --cert-signreq \
req=/etc/receptor/tls/receptor.req \
cacert=/etc/receptor/tls/ca/mesh-CA.crt \
cakey=/etc/receptor/tls/ca/mesh-CA.key \
outcert=/etc/receptor/tls/receptor.crt \
notafter=$(date --iso-8601=seconds --utc --date "10 years") \
verify=yes
{% if bundle_ca_crt %}
mkdir -p /etc/pki/ca-trust/extracted/{java,pem,openssl,edk2}
update-ca-trust
@@ -188,6 +225,30 @@ spec:
{% endif %}
{% if task_args %}
args: {{ task_args }}
{% endif %}
{% if task_liveness_period|int > 0 %}
livenessProbe:
exec:
command:
- sh
- -c
- |
(exit $(/usr/bin/supervisorctl -c /etc/supervisord_task.conf status | grep -vc RUNNING))
initialDelaySeconds: {{ task_liveness_initial_delay }}
periodSeconds: {{ task_liveness_period }}
failureThreshold: {{ task_liveness_failure_threshold }}
timeoutSeconds: {{ task_liveness_timeout }}
{% endif %}
{% if task_readiness_period|int > 0 %}
readinessProbe:
exec:
command:
- /usr/bin/awx-manage
- check
initialDelaySeconds: {{ task_readiness_initial_delay }}
periodSeconds: {{ task_readiness_period }}
failureThreshold: {{ task_readiness_failure_threshold }}
timeoutSeconds: {{ task_readiness_timeout }}
{% endif %}
volumeMounts:
{% if bundle_ca_crt %}

View File

@@ -162,6 +162,30 @@ spec:
- containerPort: 8052
{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %}
- containerPort: 8053
{% endif %}
{% if web_liveness_period|int > 0 %}
livenessProbe:
exec:
command:
- sh
- -c
- |
(exit $(/usr/bin/supervisorctl -c /etc/supervisord_task.conf status | grep -vc RUNNING))
initialDelaySeconds: {{ web_liveness_initial_delay }}
periodSeconds: {{ web_liveness_period }}
failureThreshold: {{ web_liveness_failure_threshold }}
timeoutSeconds: {{ web_liveness_timeout }}
{% endif %}
{% if web_readiness_period|int > 0 %}
readinessProbe:
httpGet:
path: /api/v2/ping/
scheme: HTTP
port: 8052
initialDelaySeconds: {{ web_readiness_initial_delay }}
periodSeconds: {{ web_readiness_period }}
failureThreshold: {{ web_readiness_failure_threshold }}
timeoutSeconds: {{ web_readiness_timeout }}
{% endif %}
volumeMounts:
{% if bundle_ca_crt %}

View File

@@ -0,0 +1,76 @@
apiVersion: batch/v1
kind: Job
metadata:
name: '{{ ansible_operator_meta.name }}-migration-{{ version }}'
namespace: '{{ ansible_operator_meta.namespace }}'
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
{{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=4) | trim }}
spec:
template:
spec:
containers:
- name: "migration-job"
image: '{{ _image }}'
command:
- awx-manage
- migrate
- --noinput
volumeMounts:
- name: {{ ansible_operator_meta.name }}-application-credentials
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: "{{ secret_key_secret_name }}"
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ ansible_operator_meta.name }}-settings
mountPath: "/etc/tower/settings.py"
subPath: settings.py
readOnly: true
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
serviceAccountName: '{{ ansible_operator_meta.name }}'
{% 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 %}
volumes:
- name: "{{ ansible_operator_meta.name }}-application-credentials"
secret:
secretName: "{{ ansible_operator_meta.name }}-app-credentials"
items:
- key: credentials.py
path: 'credentials.py'
- key: ldap.py
path: 'ldap.py'
- key: execution_environments.py
path: 'execution_environments.py'
- name: "{{ secret_key_secret_name }}"
secret:
secretName: '{{ secret_key_secret_name }}'
items:
- key: secret_key
path: SECRET_KEY
- name: {{ ansible_operator_meta.name }}-settings
configMap:
name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap'
items:
- key: settings
path: settings.py
{% if development_mode | bool %}
- name: awx-devel
hostPath:
path: /awx_devel
{% endif %}
dnsPolicy: ClusterFirst
restartPolicy: Never
terminationGracePeriodSeconds: 30

View File

@@ -55,6 +55,9 @@ spec:
{% if loadbalancer_ip is defined and loadbalancer_ip | length %}
loadbalancerip: '{{ loadbalancer_ip }}'
{% endif %}
{% if loadbalancer_class is defined and loadbalancer_class | length %}
loadBalancerClass: {{ loadbalancer_class }}
{% endif %}
{% else %}
type: ClusterIP
{% endif %}

View File

@@ -46,6 +46,27 @@ spec:
{% endif %}
{% if postgres_priority_class is defined %}
priorityClassName: '{{ postgres_priority_class }}'
{% endif %}
{% if postgres_data_volume_init and not is_openshift %}
initContainers:
- name: init
image: '{{ _postgres_image }}'
imagePullPolicy: '{{ image_pull_policy }}'
securityContext:
runAsUser: 0
command:
- /bin/sh
- -c
- |
{{ postgres_init_container_commands | indent(width=14) }}
resources: {{ postgres_init_container_resource_requirements | default(postgres_resource_requirements) }}
volumeMounts:
- name: postgres-{{ supported_pg_version }}
mountPath: '{{ _postgres_data_path | dirname }}'
subPath: '{{ _postgres_data_path | dirname | basename }}'
{% if postgres_extra_volume_mounts %}
{{ postgres_extra_volume_mounts | indent(width=12, first=True) }}
{% endif %}
{% endif %}
containers:
- image: '{{ _postgres_image }}'
@@ -56,10 +77,11 @@ spec:
{{ postgres_security_context_settings | to_nice_yaml | indent(12) }}
{% endif %}
{% if postgres_extra_args %}
command: ["run-postgresql"]
args: {{ postgres_extra_args }}
{% endif %}
env:
# For postgres_image based on rhel8/postgresql-13
# For postgres_image based on rhel8/postgresql-{{ supported_pg_version }}
- name: POSTGRESQL_DATABASE
valueFrom:
secretKeyRef:
@@ -93,7 +115,7 @@ spec:
name: '{{ __postgres_configuration_secret }}'
key: password
- name: PGDATA
value: '{{ postgres_data_path }}'
value: '{{ _postgres_data_path }}'
- name: POSTGRES_INITDB_ARGS
value: '{{ postgres_initdb_args }}'
- name: POSTGRES_HOST_AUTH_METHOD
@@ -110,9 +132,9 @@ spec:
name: postgres-{{ supported_pg_version }}
volumeMounts:
- name: postgres-{{ supported_pg_version }}
mountPath: '{{ postgres_data_path | dirname }}'
subPath: '{{ postgres_data_path | dirname | basename }}'
{% if postgres_extra_volume_mounts -%}
mountPath: '{{ _postgres_data_path | dirname }}'
subPath: '{{ _postgres_data_path | dirname | basename }}'
{% if postgres_extra_volume_mounts %}
{{ postgres_extra_volume_mounts | indent(width=12, first=True) }}
{% endif %}
resources: {{ postgres_resource_requirements }}

View File

@@ -0,0 +1,18 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ _metrics_utility_pvc_claim }}
namespace: {{ ansible_operator_meta.namespace }}
ownerReferences: null
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ _metrics_utility_pvc_claim_size }}
{% if metrics_utility_pvc_claim_storage_class is defined %}
storageClassName: {{ metrics_utility_pvc_claim_storage_class }}
{% endif %}

View File

@@ -4,4 +4,7 @@ postgres_host_auth_method: 'scram-sha-256'
ldap_cacert_ca_crt: ''
bundle_ca_crt: ''
projects_existing_claim: ''
supported_pg_version: 13
supported_pg_version: 15
_previous_upgraded_pg_version: 0
old_postgres_pod: []
_postgres_data_path: '/var/lib/pgsql/data/userdata'

View File

@@ -9,7 +9,8 @@ ingress_controller: ''
set_self_owneref: true
_control_plane_ee_image: quay.io/ansible/awx-ee:latest
_control_plane_ee_image: "quay.io/ansible/awx-ee:{{ lookup('env', 'DEFAULT_AWX_VERSION') or 'latest' }}"
_image_pull_policy: Always
image_pull_secrets: []
finalizer_run: false

View File

@@ -61,7 +61,7 @@
- name: Default ingress_type to Route if OpenShift
set_fact:
ingress_type: route
when: is_openshift | bool and ingress_type == 'none'
when: is_openshift | bool and ingress_type | lower == 'none'
- name: Apply Ingress resource
k8s:
@@ -77,7 +77,7 @@
- name: Set external_hostname
set_fact:
external_hostname: "{{ ingress.result.status.ingress[0].host }}"
when: ingress_type == 'route'
when: ingress_type | lower == 'route'
- name: Create other resources
k8s:

View File

@@ -12,6 +12,12 @@ spec:
labels:
app.kubernetes.io/name: {{ ansible_operator_meta.name }}
spec:
{% if image_pull_secrets | length > 0 %}
imagePullSecrets:
{% for secret in image_pull_secrets %}
- name: {{ secret }}
{% endfor %}
{% endif %}
containers:
- args:
- /bin/sh
@@ -24,7 +30,8 @@ spec:
{% if external_ipaddress is defined %}
external_ipaddress={{ external_ipaddress }}
{% endif %}
receptor --cert-makereq bits=2048 \
receptor --cert-makereq \
bits=2048 \
commonname=$internal_hostname \
dnsname=$internal_hostname \
nodeid=$internal_hostname \
@@ -41,6 +48,7 @@ spec:
cacert=/etc/receptor/tls/ca/mesh-CA.crt \
cakey=/etc/receptor/tls/ca/mesh-CA.key \
outcert=/etc/receptor/tls/receptor.crt \
notafter=$(date --iso-8601=seconds --utc --date "10 years") \
verify=yes
exec receptor --config /etc/receptor/receptor.conf
image: '{{ _control_plane_ee_image }}'

View File

@@ -12,7 +12,7 @@ metadata:
{{ ingress_annotations | indent(width=4) }}
{% endif %}
{% if ingress_controller|lower == "nginx" %}
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
{% endif %}
spec:
{% if ingress_class_name %}
@@ -28,7 +28,7 @@ spec:
name: {{ ansible_operator_meta.name }}
port:
number: 27199
{% if external_hostname %}
{% if external_hostname is defined %}
host: {{ external_hostname }}
{% endif %}
{% endif %}
@@ -53,7 +53,7 @@ spec:
- services:
- name: {{ ansible_operator_meta.name }}
port: 27199
{% if external_hostname %}
{% if external_hostname is defined %}
match: HostSNI(`{{ external_hostname }}`)
{% endif %}
tls:
@@ -70,6 +70,9 @@ metadata:
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
spec:
{% if external_hostname is defined %}
host: {{ external_hostname }}
{% endif %}
port:
targetPort: ws
tls:

View File

@@ -19,7 +19,7 @@ This role assumes you are authenticated with an Openshift or Kubernetes cluster:
*Before Restoring from a backup*, be sure to:
- delete the old existing AWX CR
- delete the persistent volume claim (PVC) for the database from the old deployment, which has a name like `postgres-13-<deployment-name>-postgres-13-0`
- delete the persistent volume claim (PVC) for the database from the old deployment, which has a name like `postgres-<postgres version>-<deployment-name>-postgres-<postgres version>-0`
**Note**: Do not delete the namespace/project, as that will delete the backup and the backup's PVC as well.

View File

@@ -19,6 +19,18 @@
include_vars: "{{ tmp_secrets.path }}"
no_log: "{{ no_log }}"
- name: If deployment is managed, set the new postgres_configuration_secret name
block:
- name: Set new postgres_configuration_secret name
set_fact:
_generated_pg_secret_name: "{{ deployment_name }}-postgres-configuration"
- name: Override postgres_configuration_secret
set_fact:
spec:
"{{ spec | combine({'postgres_configuration_secret': _generated_pg_secret_name}, recursive=True) }}"
when: secrets['postgresConfigurationSecret']['data']['type'] | b64decode == 'managed'
- name: If deployment is managed, set the database_host in the pg config secret
block:
- name: Set new database host
@@ -31,12 +43,18 @@
_pg_secret: "{{ secrets['postgresConfigurationSecret'] }}"
no_log: "{{ no_log }}"
- name: Change postgres host value
- name: Change postgres host and name value
set_fact:
_pg_data: "{{ _pg_secret['data'] | combine({'host': database_host | b64encode }) }}"
_pg_secret_name: "{{ deployment_name }}-postgres-configuration"
no_log: "{{ no_log }}"
- name: Create a postgres secret with the new host value
- name: Override postgres secret name
set_fact:
_pg_secret: "{{ _pg_secret | combine({'name': _pg_secret_name}) }}"
no_log: "{{ no_log }}"
- name: Override postgres secret host with new Postgres service
set_fact:
_pg_secret: "{{ _pg_secret | combine({'data': _pg_data}) }}"
no_log: "{{ no_log }}"

View File

@@ -1,8 +1,8 @@
---
deployment_type: "awx"
_postgres_image: postgres
_postgres_image_version: 13
_postgres_image: quay.io/sclorg/postgresql-15-c9s
_postgres_image_version: latest
backup_api_version: '{{ deployment_type }}.ansible.com/v1beta1'
backup_kind: 'AWXBackup'
@@ -12,7 +12,7 @@ secret_key_secret: '{{ deployment_name }}-secret-key'
admin_password_secret: '{{ deployment_name }}-admin-password'
broadcast_websocket_secret: '{{ deployment_name }}-broadcast-websocket'
postgres_configuration_secret: '{{ deployment_name }}-postgres-configuration'
supported_pg_version: 13
supported_pg_version: 15
image_pull_policy: IfNotPresent
# If set to true, the restore process will delete the existing database and create a new one