Compare commits

...

42 Commits

Author SHA1 Message Date
Hao Liu
d2818931c9 Update Matrix section with CI-TEST channel
Added CI-TEST channel to Matrix section.
2025-10-30 10:44:26 -04:00
Rebeccah Hunter
7ead166ca0 set client_request_timeout from annotation in the CR (#2077)
add the functionality to accept an annotation in the awx-cr to be able to override the default client_request_timeout value.

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
2025-10-15 18:13:12 -04:00
Christian M. Adams
c5533f47c1 Use --no-acl flag when restoring to exclude GRANT and REVOKE commands
This avoids running in to the following error when pg_restore is run as
  the application db user from the db-management pod:

  pg_restore: error: could not execute query: ERROR: must be member of role postgres
  Command was: ALTER SCHEMA public OWNER TO postgres;
2025-10-15 13:54:21 -04:00
lucas-benedito
78864b3653 fix: Correct the image_version conditional (#2082)
* fix: Correct the image_version conditional

When image is set and image_version is unset, the conditional is failing
due to the unset variable causes and error.
Implemented the correct conditional and added an assert to validate that
both variables are set properly when image is set.

Signed-off-by: Lucas Benedito <lbenedit@redhat.com>
2025-10-09 18:34:50 +01:00
Sharvesh
bed4aff4cc Fix: Redis ERR max number of clients reached (#2041)
Add timeout to Redis Config

Co-authored-by: Christian Adams <chadams@redhat.com>
2025-09-10 09:44:30 -04:00
jamesmarshall24
e0a8a88243 Add postgres_extra_settings (#2071)
* Add hacking/ directory to .gitignore as it is commonly used for dev scripts
* Add postgres_extra_settings
* Add postgres_configuration_secret checksum to DB statefulset
* Docs for postgres_extra_settings, CI coverage, and examples
---------
Co-authored-by: Christian M. Adams <chadams@redhat.com>
2025-09-03 12:36:34 -04:00
Christian Adams
1c3c5d430d Guard against missing version status on existing CR (#2076) 2025-08-27 16:53:01 -04:00
Joel
6e47dc62c2 Fix installer update-ca-trust command (#1985)
The latest release of the update-ca-trust requires the --output param
if you run as non-root user.

See: 81a090f89a
And: https://github.com/ansible/awx-ee/issues/258#issuecomment-2439742296

Fixes: https://github.com/ansible/awx-ee/issues/258
2025-08-25 14:38:18 +02:00
Christian Adams
2e9615aa1e Add configurable pull secret file support to up.sh (#2073)
- Applies a pull-secret yaml file if it exists at hacking/awx-cr.yml
- The operator will look for a pull secret called
  redhat-operators-pull-secret
- This makes it possible to use a private operator image on your quay.io
  registry out of the box with the up.sh
- Add PULL_SECRET_FILE environment variable with default hacking/pull-secret.yml
2025-08-19 11:50:19 -04:00
lucas-benedito
e2aef8330e Update the default crd example for the up.sh (#2061) 2025-08-13 17:09:31 -04:00
Ricardo Carrillo Cruz
883baeb16b Revert "Run import_auth_config_to_gateway when public_url is defined … (#2068)
Revert "Run import_auth_config_to_gateway when public_url is defined (#2066)"

This reverts commit ba1bb878f1.
2025-07-31 12:59:43 -04:00
Dimitri Savineau
ba1bb878f1 Run import_auth_config_to_gateway when public_url is defined (#2066)
Signed-off-by: Dimitri Savineau <dsavinea@redhat.com>
Co-authored-by: Ricardo Carrillo Cruz <ricarril@redhat.com>
2025-07-30 23:23:49 -04:00
aknochow
45ce8185df Reverting #2064 and Updating descriptions in backup and restore roles (#2060)
* updating task descriptions in backup and restore roles

* Revert "Run import_auth_config_to_gateway when public_url is defined (#2064)"

This reverts commit 54293a0efb.
2025-07-29 23:21:38 +00:00
lucas-benedito
a55829e5d5 Fixes for passwords for FIPS compliance (#2062)
Set password_encryption to scram-sha-256 and re-encrypt db user passwords for FIPS compliance

(cherry picked from commit 0e76404357a77a5f773aee6e2b3a5b85d1f514b7)

Co-authored-by: Christian M. Adams <chadams@redhat.com>
2025-07-28 18:52:59 +01:00
Ricardo Carrillo Cruz
54293a0efb Run import_auth_config_to_gateway when public_url is defined (#2064) 2025-07-24 10:25:07 +02:00
Rebeccah Hunter
e506466d08 set api timeout to match proxy timeout (#2056)
feat: set api timeout to match proxy timeout

Timeout before the openshift route times out
not timing out before undercuts usefulness of our log-traceback-middleware in
django-ansible-base that logs a traceback from requests that get timed
out -- because uwsgi or gunicorn has to send the timeout signal to the
worker handling the request. Also leads to issues where requests that
envoy has already timed out are filling up queues of the workers of the
components.

Also, configure nginx to return a 503 if WSGI server doesn't respond.

Co-authored-by: Elijah DeLee <kdelee@redhat.com>
2025-07-03 20:19:50 +00:00
Albert Daunis
e9750b489e Update migrate_schema to use check_migrations (#2025)
Update migrate schema showmigrations conditional
2025-06-25 15:59:23 -04:00
Christian Adams
0a89fc87a6 Update kubernetes.core to 3.2.0 and sdk to v1.36.1 (#2052)
* Update collections to match the other ansible operators

* Update the ansible-operator base image to v1.36.1
2025-06-18 18:12:58 -04:00
Dimitri Savineau
65a82f706c Fix jquery version in redirect page
Other installer uses 3.7.1 and the file on disk is also using 3.7.1
from the rest framework directory.

Signed-off-by: Dimitri Savineau <dsavinea@redhat.com>
2025-06-04 12:17:08 -04:00
Sharvari Khedkar
e8f0306ec2 Add route_annotations feature to mesh ingress CRD (#2045)
* Add route_annotations feature to mesh ingress CRD
* update route_annotations type to string
* display Route Annotations only when ingress_type=route
2025-05-12 18:07:21 -04:00
Bruno Rocha
f1660c8bd1 Address review comments 2025-05-09 15:08:17 -04:00
Bruno Rocha
f967c7d341 fix: explicitly import ldap on config file
File "/etc/tower/conf.d/ldap.py", line 2, in <module>
ldap.OPT_X_TLS_REQUIRE_CERT: True,
^^^^
NameError: name 'ldap' is not defined
2025-05-09 15:08:17 -04:00
aknochow
54072d6a46 fixing backup pvc namespace quotes (#2042) 2025-04-28 08:14:50 -04:00
Christian Adams
fb13011aad Check if pg_isready before trying to restore to new postgresql pod (#2039) 2025-04-24 17:08:50 -04:00
Ricardo Carrillo Cruz
24cb6006f6 Grant postgres to awx user on migrate_data (#2038)
This is needed in case customers move to
operator platform.

Fixes https://issues.redhat.com/browse/AAP-41592
2025-04-24 09:58:48 +02:00
Christian Adams
4c05137fb8 Update kubernetes.core to 2.4.2 to fix k8s_cp module usage against OCP with virt (#2031) 2025-03-17 12:12:32 -04:00
aknochow
07540c29da fixing quotes on namespace to support namespace names with only numbers (#2030) 2025-03-17 09:19:02 -04:00
jamesmarshall24
5bb2b2ac87 Add deployment type shortname for legacy API url (#2026)
* Add deployment type shortname for legacy API url

* Add trailing slash to legacy API url

Co-authored-by: Christian Adams <rooftopcellist@gmail.com>

---------

Co-authored-by: Christian Adams <rooftopcellist@gmail.com>
2025-03-05 15:04:01 -05:00
shellclear
039157d070 Parameterization of the client_max_body_size directive in Nginx (#2014)
Enables users to customize client_max_body_size in Nginx conf to allow
for larger file uploads. This is useful in cases when users need to upload
large subscription manifest files.

---------

Co-authored-by: Seth Foster <fosterseth@users.noreply.github.com>
2025-02-24 12:50:08 -05:00
Christian Adams
bb4f4c2eb4 Fail early if postgres_configuration_secret is specified by does not exist (#2015) 2025-02-17 12:38:06 -05:00
Christian Adams
97efcab2a2 Accepts new status conditions from the operator on the CR object (#2016) 2025-02-17 12:36:43 -05:00
aknochow
c08c1027a1 idle_deployment - Scale down deployments to put AWX into an idle state (#2012)
- separating database_configuration and deployment tasks into separate files to add ability to call configuration independently
2025-02-11 11:01:18 -05:00
Yuval Lahav
3d1ecc19f4 AAP-38745 Increase limits in manager.py (#2006)
* AAP-38745 Increase limits in manager.py

Closes https://issues.redhat.com/browse/AAP-38745

* Update manager.yaml
2025-01-20 11:32:49 -05:00
aknochow
5d0f91ec13 adding conditional to checksum template and removing default for public_base_url to fix undefined variable 2024-12-02 11:54:13 -05:00
Christian Adams
6ab32a42cf Add up.sh and down.sh development scripts for consistency with other ansible operators (#1991) 2024-11-26 11:25:24 -05:00
Chris Meyers
9718424483 Point at awx devel collection
* awx.awx collection on galaxy is ooooold at this point. Releases are
  paused, so point at awx collection in devel to get that new bleeding
  edge hotness.
2024-11-07 12:53:53 -05:00
aknochow
d5683adaf8 adding redirect page (#1982) 2024-10-29 17:47:41 -04:00
Christian Adams
1bc342258a Only set upgradedFrom status if previous_version is explicitly set (#1980) 2024-10-23 13:51:18 -04:00
Hao Liu
79ab6f0b5e Fix disable reverse sync on mgmt command (#1977) 2024-10-18 15:02:28 +00:00
Christian Adams
3822e32755 Add upgradedFrom status for check-version changes (#1975) 2024-10-17 19:28:43 +00:00
Christian Adams
c30d4c174d Compare gating version against existing deployment versions (#1972)
* Compare gating version against existing deployment versions and set upgradeFrom status
* Add quotes to default version

Co-authored-by: Dimitri Savineau <savineau.dimitri@gmail.com>
2024-10-16 17:43:26 -04:00
Christian Adams
8a5ec6e19c Fix Label PR check by using python venv for requests library (#1973) 2024-10-16 13:00:50 -04:00
61 changed files with 1118 additions and 229 deletions

View File

@@ -13,9 +13,17 @@ jobs:
name: Label PR - Community
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- name: Install python requests
run: pip install requests
- name: Create a virtual environment
run: python3 -m venv venv
- name: Activate virtual environment and install dependencies
run: |
source venv/bin/activate
pip3 install requests
- name: Check if user is a member of Ansible org
uses: jannekem/run-python-script-action@v1
id: check_user
@@ -32,6 +40,7 @@ jobs:
print("User is member")
else:
print("User is community")
- name: Add community label if not a member
if: contains(steps.check_user.outputs.stdout, 'community')
uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ gh-pages/
__pycache__
/site
venv/*
hacking/

View File

@@ -10,6 +10,7 @@ Have questions about this document or anything not covered here? Please file a n
- [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)
- [Development](#development)
- [Testing](#testing)
- [Testing in Kind](#testing-in-kind)
- [Testing in Minikube](#testing-in-minikube)
@@ -42,7 +43,8 @@ Have questions about this document or anything not covered here? Please file a n
**Note**: If you have multiple commits, make sure to `squash` your commits into a single commit which will facilitate our release process.
## Development
The development environment consists of running an [`up.sh`](./up.sh) and a [`down.sh`](./down.sh) script, which applies or deletes yaml on the Openshift or K8s cluster you are connected to. See the [development.md](docs/development.md) for information on how to deploy and test changes from your branch.
## Testing

View File

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

View File

@@ -161,7 +161,7 @@ ifeq (,$(shell which operator-sdk 2>/dev/null))
@{ \
set -e ;\
mkdir -p $(dir $(OPERATOR_SDK)) ;\
curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/v1.34.2/operator-sdk_$(OS)_$(ARCHA) ;\
curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/v1.36.1/operator-sdk_$(OS)_$(ARCHA) ;\
chmod +x $(OPERATOR_SDK) ;\
}
else
@@ -177,7 +177,7 @@ ifeq (,$(shell which ansible-operator 2>/dev/null))
@{ \
set -e ;\
mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\
curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/ansible-operator-plugins/releases/download/v1.34.0/ansible-operator_$(OS)_$(ARCHA) ;\
curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/ansible-operator-plugins/releases/download/v1.36.1/ansible-operator_$(OS)_$(ARCHA) ;\
chmod +x $(ANSIBLE_OPERATOR) ;\
}
else

View File

@@ -20,6 +20,8 @@ Please visit [our contributing guidelines](https://github.com/ansible/awx-operat
For docs changes, create PRs on the appropriate files in the `/docs` folder.
The development environment consists of running an [`up.sh`](https://github.com/ansible/awx-operator/blob/devel/up.sh) and a [`down.sh`](https://github.com/ansible/awx-operator/blob/devel/down.sh) script, which applies or deletes yaml on the Openshift or K8s cluster you are connected to. See the [development.md](https://github.com/ansible/awx-operator/blob/devel/docs/development.md) for information on how to deploy and test changes from your branch.
## Author
This operator was originally built in 2019 by [Jeff Geerling](https://www.jeffgeerling.com) and is now maintained by the Ansible Team
@@ -48,6 +50,8 @@ For more information on the forum navigation, see [Navigating the Ansible forum]
For real-time interactions, conversations in the community happen over the Matrix protocol in the following channels:
<CI-TEST>
* [#awx:ansible.com](https://matrix.to/#/#awx:ansible.com): AWX and AWX-Operator project-related discussions.
* [#docs:ansible.im](https://matrix.to/#/#docs:ansible.im): Ansible, AWX and AWX-Operator documentation-related discussions.

View File

@@ -69,6 +69,9 @@ spec:
ingress_annotations:
description: Annotations to add to the Ingress Controller
type: string
route_annotations:
description: Annotations to add to the OpenShift Route
type: string
ingress_class_name:
description: The name of ingress class to use instead of the cluster default.
type: string

View File

@@ -36,6 +36,17 @@ spec:
metadata:
type: object
spec:
x-kubernetes-validations:
- rule: "has(self.image) && has(self.image_version) || !has(self.image) && !has(self.image_version)"
message: "Both image and image_version must be set when required"
- rule: "has(self.redis_image) && has(self.redis_image_version) || !has(self.redis_image) && !has(self.redis_image_version)"
message: "Both redis_image and redis_image_version must be set when required"
- rule: "has(self.postgres_image) && has(self.postgres_image_version) || !has(self.postgres_image) && !has(self.postgres_image_version)"
message: "Both postgres_image and postgres_image_version must be set when required"
- rule: >-
has(self.metrics_utility_image) && has(self.metrics_utility_image_version) ||
!has(self.metrics_utility_image) && !has(self.metrics_utility_image_version)
message: "Both metrics_utility_image and metrics_utility_image_version must be set when required"
properties:
deployment_type:
description: Name of the deployment type
@@ -1736,6 +1747,9 @@ spec:
nginx_worker_connections:
description: Set the number of connections per worker for nginx
type: integer
nginx_client_max_body_size:
description: Sets the maximum allowed size of the client request body in megabytes (defaults to 5M)
type: integer
nginx_worker_cpu_affinity:
description: Set the CPU affinity for nginx workers
type: string
@@ -1825,9 +1839,25 @@ spec:
description: Assign a preexisting priority class to the postgres pod
type: string
postgres_extra_args:
description: "(Deprecated, use postgres_extra_settings parameter) Define postgres configuration arguments to use"
type: array
items:
type: string
postgres_extra_settings:
description: "PostgreSQL configuration settings to be added to postgresql.conf"
type: array
items:
type: object
properties:
setting:
description: "PostgreSQL configuration parameter name"
type: string
value:
description: "PostgreSQL configuration parameter value"
type: string
required:
- setting
- value
postgres_data_volume_init:
description: Sets permissions on the /var/lib/pgdata/data for postgres container using an init container (not Openshift)
type: boolean
@@ -1965,6 +1995,9 @@ spec:
description: Disable web container's nginx ipv6 listener
type: boolean
default: false
idle_deployment:
description: Scale down deployments to put AWX into an idle state
type: boolean
metrics_utility_enabled:
description: Enable metrics utility
type: boolean
@@ -2009,8 +2042,12 @@ spec:
description: Enable metrics utility shipping to Red Hat Hybrid Cloud Console
type: boolean
default: false
public_base_url:
description: Public base URL
type: string
type: object
status:
x-kubernetes-preserve-unknown-fields: true
properties:
URL:
description: URL to access the deployed instance
@@ -2042,6 +2079,9 @@ spec:
image:
description: URL of the image used for the deployed instance
type: string
upgradedFrom:
description: Last gated version
type: string
conditions:
description: The resulting conditions when a Service Telemetry is instantiated
items:
@@ -2056,5 +2096,6 @@ spec:
type: string
type: object
type: array
x-kubernetes-preserve-unknown-fields: true
type: object
type: object

View File

@@ -73,8 +73,8 @@ spec:
memory: "32Mi"
cpu: "50m"
limits:
memory: "960Mi"
cpu: "1500m"
memory: "4000Mi"
cpu: "2000m"
serviceAccountName: controller-manager
imagePullSecrets:
- name: redhat-operators-pull-secret

View File

@@ -50,6 +50,12 @@ spec:
path: ingress_annotations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Route Annotations
path: route_annotations
x-descriptors:
- 'urn:alm:descriptor:com.tectonic.ui:advanced'
- 'urn:alm:descriptor:com.tectonic.ui:text'
- 'urn:alm:descriptor:com.tectonic.ui:fieldDependency:ingress_type:Route'
- displayName: Ingress Class Name
path: ingress_class_name
x-descriptors:
@@ -173,6 +179,12 @@ spec:
path: db_management_pod_node_selector
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- displayName: Public Base URL
path: public_base_url
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
statusDescriptors:
- description: Persistent volume claim name used during backup
displayName: Backup Claim
@@ -578,6 +590,11 @@ spec:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:number
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Set the maximum allowed size of the client request body in megabytes for nginx
path: nginx_client_max_body_size
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:number
- displayName: Task Replicas
path: task_replicas
x-descriptors:
@@ -680,11 +697,16 @@ spec:
x-descriptors:
- urn:alm:descriptor:io.kubernetes:StorageClass
- urn:alm:descriptor:com.tectonic.ui:advanced
- displayName: Postgres Extra Arguments
- displayName: Postgres Extra Arguments (Deprecated)
path: postgres_extra_args
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Postgres Extra Settings
path: postgres_extra_settings
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: Specify extra volumes to add to the postgres pod
displayName: Postgres Extra Volumes
path: postgres_extra_volumes
@@ -1149,6 +1171,13 @@ spec:
- 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
- description: Scale down deployments to put AWX into an idle state
displayName: Idle AWX
path: idle_deployment
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- urn:alm:descriptor:com.tectonic.ui:hidden
statusDescriptors:
- description: Route to access the instance deployed
displayName: URL

View File

@@ -0,0 +1,24 @@
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
service_type: clusterip
ingress_type: route
no_log: false
# Secrets
admin_password_secret: custom-admin-password
postgres_configuration_secret: custom-pg-configuration
secret_key_secret: custom-secret-key
# Resource Requirements
postgres_storage_requirements:
requests:
storage: 10Gi
# Extra Settings
extra_settings:
- setting: MAX_PAGE_SIZE
value: "500"

View File

@@ -0,0 +1,30 @@
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
service_type: clusterip
ingress_type: Route
postgres_extra_settings:
- setting: max_connections
value: "999"
- setting: ssl_ciphers
value: "HIGH:!aNULL:!MD5"
# requires custom-postgres-configuration secret to be pre-created
# postgres_configuration_secret: custom-postgres-configuration
postgres_resource_requirements:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 800m
memory: 1Gi
postgres_storage_requirements:
requests:
storage: 20Gi
limits:
storage: 100Gi

View File

@@ -0,0 +1,13 @@
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
service_type: nodeport
ingress_type: ingress
# Secrets
admin_password_secret: custom-admin-password
postgres_configuration_secret: custom-pg-configuration
secret_key_secret: custom-secret-key

View File

@@ -0,0 +1,13 @@
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
service_type: clusterip
ingress_type: Route
# # Secrets
# admin_password_secret: custom-admin-password
# postgres_configuration_secret: custom-pg-configuration
# secret_key_secret: custom-secret-key

View File

@@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Secret
metadata:
name: custom-admin-password
stringData:
password: 'password'

View File

@@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Secret
metadata:
name: custom-secret-key
stringData:
secret_key: 'awxsecret'

View File

@@ -0,0 +1,12 @@
---
apiVersion: v1
kind: Secret
metadata:
name: external-pg-secret
stringData:
database: 'awx'
host: 'awx-postgres'
password: 'test'
port: '5432'
type: 'managed'
username: 'awx'

104
docs/development.md Normal file
View File

@@ -0,0 +1,104 @@
# Development Guide
There are development scripts and yaml exaples in the [`dev/`](../dev) directory that, along with the up.sh and down.sh scripts in the root of the repo, can be used to build, deploy and test changes made to the awx-operator.
## Prerequisites
You will need to have the following tools installed:
* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [podman](https://podman.io/docs/installation) or [docker](https://docs.docker.com/get-docker/)
* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
* [oc](https://docs.openshift.com/container-platform/4.11/cli_reference/openshift_cli/getting-started-cli.html) (if using Openshift)
You will also need to have a container registry account. This guide uses quay.io, but any container registry will work. You will need to create a robot account and login at the CLI with `podman login` or `docker login`.
## Quay.io Setup for Development
Before using the development scripts, you'll need to set up a Quay.io repository and pull secret:
### 1. Create a Private Quay.io Repository
- Go to [quay.io](https://quay.io) and create a private repository named `awx-operator` under your username
- The repository URL should be `quay.io/username/awx-operator`
### 2. Create a Bot Account
- In your Quay.io repository, go to Settings → Robot Accounts
- Create a new robot account with write permissions to your repository
- Click on the robot account name to view its credentials
### 3. Generate Kubernetes Pull Secret
- In the robot account details, click "Kubernetes Secret"
- Copy the generated YAML content from the pop-up
### 4. Create Local Pull Secret File
- Create a file at `hacking/pull-secret.yml` in your awx-operator checkout
- Paste the Kubernetes secret YAML content into this file
- **Important**: Change the `name` field in the secret from the default to `redhat-operators-pull-secret`
- The `hacking/` directory is in `.gitignore`, so this file won't be committed to git
Example `hacking/pull-secret.yml`:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: redhat-operators-pull-secret # Change this name
namespace: awx
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-credentials>
```
## Build and Deploy
If you clone the repo, and make sure you are logged in at the CLI with oc and your cluster, you can run:
```
export QUAY_USER=username
export NAMESPACE=awx
export TAG=test
./up.sh
```
You can add those variables to your .bashrc file so that you can just run `./up.sh` in the future.
> Note: the first time you run this, it will create quay.io repos on your fork. If you followed the Quay.io setup steps above and created the `hacking/pull-secret.yml` file, the script will automatically handle the pull secret. Otherwise, you will need to either make those repos public, or create a global pull secret on your cluster.
To get the URL, if on **Openshift**, run:
```
$ oc get route
```
On **k8s with ingress**, run:
```
$ kubectl get ing
```
On **k8s with nodeport**, run:
```
$ kubectl get svc
```
The URL is then `http://<Node-IP>:<NodePort>`
> Note: NodePort will only work if you expose that port on your underlying k8s node, or are accessing it from localhost.
By default, the usename and password will be admin and password if using the `up.sh` script because it pre-creates a custom admin password k8s secret and specifies it on the AWX custom resource spec. Without that, a password would have been generated and stored in a k8s secret named <deployment-name>-admin-password.
## Clean up
Same thing for cleanup, just run ./down.sh and it will clean up your namespace on that cluster
```
./down.sh
```
## Running CI tests locally
More tests coming soon...

View File

@@ -115,6 +115,7 @@ configuration.
* [worker_cpu_affinity](http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity) with `nginx_worker_cpu_affinity` (default "auto")
* [worker_connections](http://nginx.org/en/docs/ngx_core_module.html#worker_connections) with `nginx_worker_connections` (minimum of 1024)
* [listen](https://nginx.org/en/docs/http/ngx_http_core_module.html#listen) with `nginx_listen_queue_size` (default same as uwsgi listen queue size)
* [client_max_body_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) with `nginx_client_max_body_size` (default of 5M)
## Custom Logos

View File

@@ -69,6 +69,7 @@ The following variables are customizable for the managed PostgreSQL service
| 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 |
| postgres_extra_settings | PostgreSQL configuration settings to be added to postgresql.conf | `[]` |
Example of customization could be:
@@ -89,14 +90,78 @@ spec:
limits:
storage: 50Gi
postgres_storage_class: fast-ssd
postgres_extra_args:
- '-c'
- 'max_connections=1000'
postgres_extra_settings:
- setting: max_connections
value: "1000"
```
!!! 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.
## PostgreSQL Extra Settings
!!! warning "Deprecation Notice"
The `postgres_extra_args` parameter is **deprecated** and should no longer be used. Use `postgres_extra_settings` instead for configuring PostgreSQL parameters. The `postgres_extra_args` parameter will be removed in a future version of the AWX operator.
You can customize PostgreSQL configuration by adding settings to the `postgresql.conf` file using the `postgres_extra_settings` parameter. This allows you to tune PostgreSQL performance, security, and behavior according to your specific requirements.
The `postgres_extra_settings` parameter accepts an array of setting objects, where each object contains a `setting` name and its corresponding `value`.
!!! note
The `postgres_extra_settings` parameter replaces the deprecated `postgres_extra_args` parameter and provides a more structured way to configure PostgreSQL settings.
### Configuration Format
```yaml
spec:
postgres_extra_settings:
- setting: max_connections
value: "499"
- setting: ssl_ciphers
value: "HIGH:!aNULL:!MD5"
```
**Common PostgreSQL settings you might want to configure:**
| Setting | Description | Example Value |
|---------|-------------|---------------|
| `max_connections` | Maximum number of concurrent connections | `"200"` |
| `ssl_ciphers` | SSL cipher suites to use | `"HIGH:!aNULL:!MD5"` |
| `shared_buffers` | Amount of memory for shared memory buffers | `"256MB"` |
| `effective_cache_size` | Planner's assumption about effective cache size | `"1GB"` |
| `work_mem` | Amount of memory for internal sort operations | `"4MB"` |
| `maintenance_work_mem` | Memory for maintenance operations | `"64MB"` |
| `checkpoint_completion_target` | Target for checkpoint completion | `"0.9"` |
| `wal_buffers` | Amount of memory for WAL buffers | `"16MB"` |
### Important Notes
!!! warning
- Changes to `postgres_extra_settings` require a PostgreSQL pod restart to take effect.
- Some settings may require specific PostgreSQL versions or additional configuration.
- Always test configuration changes in a non-production environment first.
!!! tip
- String values should be quoted in the YAML configuration.
- Numeric values can be provided as strings or numbers.
- Boolean values should be provided as strings ("on"/"off" or "true"/"false").
For a complete list of available PostgreSQL configuration parameters, refer to the [PostgreSQL documentation](https://www.postgresql.org/docs/current/runtime-config.html).
**Verification:**
You can verify that your settings have been applied by connecting to the PostgreSQL database and running:
```bash
kubectl exec -it <postgres-pod-name> -n <namespace> -- psql
```
Then run the following query:
```sql
SELECT name, setting FROM pg_settings;
```
## 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).

36
down.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
# AWX Operator down.sh
# Purpose:
# Cleanup and delete the namespace you deployed in
# -- Usage
# NAMESPACE=awx ./down.sh
# -- Variables
TAG=${TAG:-dev}
AWX_CR=${AWX_CR:-awx}
CLEAN_DB=${CLEAN_DB:-false}
# -- Check for required variables
# Set the following environment variables
# export NAMESPACE=awx
if [ -z "$NAMESPACE" ]; then
echo "Error: NAMESPACE env variable is not set. Run the following with your namespace:"
echo " export NAMESPACE=developer"
exit 1
fi
# -- Delete Backups
kubectl delete awxbackup --all
# -- Delete Restores
kubectl delete awxrestore --all
# Deploy Operator
make undeploy NAMESPACE=$NAMESPACE
# Remove PVCs
kubectl delete pvc postgres-15-$AWX_CR-postgres-15-0

View File

@@ -49,3 +49,8 @@ spec:
{% if additional_fields is defined %}
{{ additional_fields | to_nice_yaml | indent(2) }}
{% endif %}
postgres_extra_settings:
- setting: max_connections
value: "499"
- setting: ssl_ciphers
value: "HIGH:!aNULL:!MD5"

View File

@@ -4,4 +4,6 @@ collections:
- name: kubernetes.core
- name: operator_sdk.util
- name: community.docker
- name: awx.awx
- name: https://github.com/ansible/awx.git#/awx_collection/
type: git
version: devel

View File

@@ -1,6 +1,6 @@
---
collections:
- name: kubernetes.core
version: '>=2.3.2'
- name: operator_sdk.util
version: "0.5.0"
- name: kubernetes.core
version: "3.2.0"

View File

@@ -72,7 +72,7 @@
command: >-
touch {{ backup_dir }}/tower.db
- name: Set full resolvable host name for postgres pod
- name: Set resolvable_db_host
set_fact:
resolvable_db_host: '{{ (awx_postgres_type == "managed") | ternary(awx_postgres_host + "." + ansible_operator_meta.namespace + ".svc", awx_postgres_host) }}' # yamllint disable-line rule:line-length
no_log: "{{ no_log }}"

View File

@@ -3,7 +3,7 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ deployment_name }}-backup-claim
namespace: {{ backup_pvc_namespace }}
namespace: "{{ backup_pvc_namespace }}"
ownerReferences: null
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}

View File

@@ -3,12 +3,12 @@ apiVersion: v1
kind: Event
metadata:
name: backup-error.{{ now }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
involvedObject:
apiVersion: awx.ansible.com/v1beta1
kind: {{ kind }}
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
message: {{ error_msg }}
reason: BackupFailed
type: Warning

View File

@@ -3,7 +3,7 @@ apiVersion: v1
kind: Pod
metadata:
name: {{ ansible_operator_meta.name }}-db-management
namespace: {{ backup_pvc_namespace }}
namespace: "{{ backup_pvc_namespace }}"
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
spec:

View File

@@ -1,5 +1,6 @@
---
deployment_type: awx
deployment_type_shortname: awx
kind: 'AWX'
api_version: '{{ deployment_type }}.ansible.com/v1beta1'
@@ -421,14 +422,20 @@ projects_persistence: false
# Define an existing PersistentVolumeClaim to use
projects_existing_claim: ''
#
# Define postgres configuration arguments to use
# Define postgres configuration arguments to use (Deprecated)
postgres_extra_args: ''
#
# Define postgresql.conf configurations
postgres_extra_settings: []
postgres_data_volume_init: false
postgres_init_container_commands: |
chown 26:0 /var/lib/pgsql/data
chmod 700 /var/lib/pgsql/data
# Enable PostgreSQL SCRAM-SHA-256 migration
postgres_scram_migration_enabled: true
# Configure postgres connection keepalive
postgres_keepalives: true
postgres_keepalives_idle: 5
@@ -488,8 +495,12 @@ ipv6_disabled: false
# - hostname
host_aliases: ''
# receptor default values
receptor_log_level: info
# common default values
client_request_timeout: 30
# UWSGI default values
uwsgi_processes: 5
# NOTE: to increase this value, net.core.somaxconn must also be increased
@@ -497,11 +508,19 @@ uwsgi_processes: 5
# Also see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls for how
# to allow setting this sysctl, which requires kubelet configuration to add to allowlist
uwsgi_listen_queue_size: 128
uwsgi_timeout: "{{ (([(client_request_timeout | int), 10] | max) / 3) | int }}"
uwsgi_timeout_grace_period: 2
# NGINX default values
nginx_worker_processes: 1
nginx_worker_connections: "{{ uwsgi_listen_queue_size }}"
nginx_worker_cpu_affinity: 'auto'
nginx_listen_queue_size: "{{ uwsgi_listen_queue_size }}"
nginx_client_max_body_size: 5
nginx_read_timeout: "{{ (([(client_request_timeout | int), 10] | max) / 2) | int }}" # used in nginx config
extra_settings_files: {}
# idle_deployment - Scale down deployments to put AWX into an idle state
idle_deployment: false

View File

@@ -0,0 +1,38 @@
---
- name: Check for presence of Deployment
kubernetes.core.k8s_info:
api_version: apps/v1
kind: Deployment
namespace: "{{ ansible_operator_meta.namespace }}"
label_selectors:
- 'app.kubernetes.io/part-of={{ ansible_operator_meta.name }}'
- 'app.kubernetes.io/managed-by={{ deployment_type }}-operator'
- 'app.kubernetes.io/component={{ deployment_type }}'
register: _deployments
- name: Set previous_version if deployment exists
when: _deployments.resources | length > 0
block:
- name: Check for existing deployment
kubernetes.core.k8s_info:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
namespace: "{{ ansible_operator_meta.namespace }}"
name: "{{ ansible_operator_meta.name }}"
register: existing_cr
- name: Set previous_version version based on AWX CR version status
ansible.builtin.set_fact:
previous_version: "{{ existing_cr.resources[0].status.version }}"
when:
- existing_cr.resources | length
- existing_cr.resources[0].status is defined
- existing_cr.resources[0].status.version is defined
- name: If previous_version is less than or equal to gating_version, set upgraded_from to previous_version
ansible.builtin.set_fact:
upgraded_from: "{{ previous_version }}"
when:
- previous_version is defined
- previous_version is version_compare(gating_version, '<')

View File

@@ -0,0 +1,189 @@
---
- name: Get database configuration
include_tasks: database_configuration.yml
- name: Create postgresql.conf ConfigMap
k8s:
apply: true
definition: "{{ lookup('template', 'configmaps/postgres_extra_settings.yaml.j2') }}"
when: postgres_extra_settings | length
# 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 }}"
field_selectors:
- status.phase=Running
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:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
# 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:
- this_awx['resources'][0] is defined
- "'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: "{{ old_postgres_pod['metadata']['name'] }}"
command: |
bash -c """
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
- debug:
msg: "--- Upgrading from {{ old_postgres_pod['metadata']['name'] | default('NONE')}} Pod ---"
- name: Migrate from md5 to scram-sha-256
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ old_postgres_pod['metadata']['name'] }}"
command: |
bash -c "
psql -U postgres -c \"ALTER SYSTEM SET password_encryption = 'scram-sha-256';\" &&
psql -U postgres -c \"SELECT pg_reload_conf();\" &&
psql -U postgres -c \"ALTER USER \\\"{{ awx_postgres_user }}\\\" WITH PASSWORD '{{ awx_postgres_pass }}';\"
"
register: _migration_output
no_log: "{{ no_log }}"
when:
- postgres_scram_migration_enabled
- (_old_pg_version.stdout | default(0) | int ) == 13
- 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) | int ) < supported_pg_version
when:
- managed_database
- (_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
k8s:
apply: true
definition: "{{ lookup('template', 'statefulsets/postgres.yaml.j2') }}"
register: create_statefulset_result
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
when: create_statefulset_result.changed
rescue:
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
- name: Scale down PostgreSQL statefulset for migration
kubernetes.core.k8s_scale:
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
replicas: 0
wait: yes
- name: Remove PostgreSQL statefulset for upgrade
k8s:
state: absent
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
wait: yes
when: create_statefulset_result.error == 422
- name: Recreate PostgreSQL statefulset with updated values
k8s:
apply: true
definition: "{{ lookup('template', 'statefulsets/postgres.yaml.j2') }}"
when: managed_database
- name: Set Default label selector for custom resource generated postgres
set_fact:
postgres_label_selector: "app.kubernetes.io/instance=postgres-{{ supported_pg_version }}-{{ ansible_operator_meta.name }}"
when: postgres_label_selector is not defined
- name: Get the postgres pod information
k8s_info:
kind: Pod
namespace: "{{ ansible_operator_meta.namespace }}"
label_selectors:
- "{{ postgres_label_selector }}"
field_selectors:
- status.phase=Running
register: postgres_pod
- name: Wait for Database to initialize if managed DB
k8s_info:
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "{{ postgres_label_selector }}"
field_selectors:
- status.phase=Running
register: postgres_pod
until:
- "postgres_pod['resources'] | length"
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
delay: 5
retries: 60
when: managed_database
- name: Look up details for this deployment
k8s_info:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
- name: Migrate data from old Openshift instance
import_tasks: migrate_data.yml
when:
- old_pg_config['resources'] is defined
- old_pg_config['resources'] | length
- this_awx['resources'][0]['status']['migratedFromSecret'] is not defined

View File

@@ -51,6 +51,14 @@
set_fact:
_default_postgres_image: "{{ _postgres_image }}:{{_postgres_image_version }}"
- name: Fail if PostgreSQL secret is specified, but not found
fail:
msg: "PostgreSQL configuration {{ postgres_configuration_secret }} not found in namespace {{ ansible_operator_meta.namespace }}"
when:
- postgres_configuration_secret | length
- _custom_pg_config_resources is defined
- _custom_pg_config_resources['resources'] | length == 0
- name: Set PostgreSQL configuration
set_fact:
_pg_config: '{{ _custom_pg_config_resources["resources"] | default([]) | length | ternary(_custom_pg_config_resources, _default_pg_config_resources) }}'
@@ -106,167 +114,3 @@
- name: Set database as managed
set_fact:
managed_database: "{{ pg_config['resources'][0]['data']['type'] | default('') | b64decode == 'managed' }}"
# 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 }}"
field_selectors:
- status.phase=Running
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:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
# 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:
- this_awx['resources'][0] is defined
- "'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: "{{ old_postgres_pod['metadata']['name'] }}"
command: |
bash -c """
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
- 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) | int ) < supported_pg_version
when:
- managed_database
- (_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
k8s:
apply: true
definition: "{{ lookup('template', 'statefulsets/postgres.yaml.j2') }}"
register: create_statefulset_result
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
when: create_statefulset_result.changed
rescue:
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
- name: Scale down PostgreSQL statefulset for migration
kubernetes.core.k8s_scale:
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
replicas: 0
wait: yes
- name: Remove PostgreSQL statefulset for upgrade
k8s:
state: absent
api_version: apps/v1
kind: StatefulSet
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
wait: yes
when: create_statefulset_result.error == 422
- name: Recreate PostgreSQL statefulset with updated values
k8s:
apply: true
definition: "{{ lookup('template', 'statefulsets/postgres.yaml.j2') }}"
when: managed_database
- name: Set Default label selector for custom resource generated postgres
set_fact:
postgres_label_selector: "app.kubernetes.io/instance=postgres-{{ supported_pg_version }}-{{ ansible_operator_meta.name }}"
when: postgres_label_selector is not defined
- name: Get the postgres pod information
k8s_info:
kind: Pod
namespace: "{{ ansible_operator_meta.namespace }}"
label_selectors:
- "{{ postgres_label_selector }}"
field_selectors:
- status.phase=Running
register: postgres_pod
- name: Wait for Database to initialize if managed DB
k8s_info:
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "{{ postgres_label_selector }}"
field_selectors:
- status.phase=Running
register: postgres_pod
until:
- "postgres_pod['resources'] | length"
- "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
- "postgres_pod['resources'][0]['status']['containerStatuses'][0]['ready'] == true"
delay: 5
retries: 60
when: managed_database
- name: Look up details for this deployment
k8s_info:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
- name: Migrate data from old Openshift instance
import_tasks: migrate_data.yml
when:
- old_pg_config['resources'] is defined
- old_pg_config['resources'] | length
- this_awx['resources'][0]['status']['migratedFromSecret'] is not defined

View File

@@ -0,0 +1,34 @@
---
- name: Scale down AWX Deployments
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ item }}"
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
replicas: 0
loop:
- '{{ ansible_operator_meta.name }}-task'
- '{{ ansible_operator_meta.name }}-web'
- name: Get database configuration
include_tasks: database_configuration.yml
- name: Scale down PostgreSQL Statefulset
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: "{{ ansible_operator_meta.name }}-postgres-{{ supported_pg_version }}"
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
replicas: 0
when: managed_database
- name: End Playbook
ansible.builtin.meta: end_play

View File

@@ -18,13 +18,11 @@
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: awx-manage createsuperuser --username={{ admin_user | quote }} --email={{ admin_email | quote }} --noinput
command: bash -c "ANSIBLE_REVERSE_RESOURCE_SYNC=false 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"
failed_when: "'That username is already taken' not in result.stderr and 'Superuser created successfully' not in result.stdout"
no_log: "{{ no_log }}"
environment:
ANSIBLE_REVERSE_RESOURCE_SYNC: "false"
when: users_result.return_code > 0
- name: Update Django super user password
@@ -116,9 +114,7 @@
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage create_preload_data"
bash -c "ANSIBLE_REVERSE_RESOURCE_SYNC=false awx-manage create_preload_data"
register: cdo
changed_when: "'added' in cdo.stdout"
environment:
ANSIBLE_REVERSE_RESOURCE_SYNC: "false"
when: create_preload_data | bool

View File

@@ -44,6 +44,12 @@
- name: Include secret key configuration tasks
include_tasks: secret_key_configuration.yml
- name: Apply Redirect Page Configmap
k8s:
apply: true
definition: "{{ lookup('template', 'configmaps/redirect-page.configmap.html.j2') }}"
when: public_base_url is defined
- name: Load LDAP CAcert certificate (Deprecated)
include_tasks: load_ldap_cacert_secret.yml
when:
@@ -68,8 +74,8 @@
- name: Include set_images tasks
include_tasks: set_images.yml
- name: Include database configuration tasks
include_tasks: database_configuration.yml
- name: Include Database tasks
include_tasks: database.yml
- name: Load Route TLS certificate
include_tasks: load_route_tls_secret.yml

View File

@@ -1,4 +1,33 @@
---
- name: Idle AWX
include_tasks: idle_deployment.yml
when: idle_deployment | bool
- name: Look up details for this deployment
k8s_info:
api_version: "{{ api_version }}"
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_awx
- name: set annotations based on this_awx
set_fact:
this_annotations: "{{ this_awx['resources'][0]['metadata']['annotations'] | default({}) }}"
- name: set client_request_timeout based on annotation
set_fact:
client_request_timeout: "{{ (this_annotations['aap.ansible.io/client-request-timeout'][:-1]) | int }}"
client_request_timeout_overidden: true
when:
- "'aap.ansible.io/client-request-timeout' in this_annotations"
- this_annotations['aap.ansible.io/client-request-timeout'] is match('^\\d+s$')
- name: client_request_timeout has been changed
debug:
msg: "client_request_timeout's default 30s value has been overriden by the annotation 'aap.ansible.io/client-request-timeout' to {{ client_request_timeout }}s"
when: client_request_timeout_overidden | default(false)
- name: Check for presence of old awx Deployment
k8s_info:
api_version: apps/v1
@@ -23,6 +52,10 @@
namespace: "{{ ansible_operator_meta.namespace }}"
register: awx_web_deployment
- name: Check for existing deployment for previous version
include_tasks: check_existing.yml
when: gating_version | length
- name: Start installation if auto_upgrade is true
include_tasks: install.yml
when:

View File

@@ -77,7 +77,9 @@
trap 'end_keepalive \"$keepalive_file\" \"$keepalive_pid\"' EXIT SIGINT SIGTERM
echo keepalive_pid: $keepalive_pid
set -e -o pipefail
psql -c 'GRANT postgres TO {{ awx_postgres_user }}'
PGPASSWORD=\"$PGPASSWORD_OLD\" {{ pgdump }} | PGPASSWORD=\"$POSTGRES_PASSWORD\" {{ pg_restore }}
psql -c 'REVOKE postgres FROM {{ awx_postgres_user }}'
set +e +o pipefail
echo 'Successful'
"

View File

@@ -6,7 +6,7 @@
pod: "{{ awx_web_pod_name }}"
container: "{{ ansible_operator_meta.name }}-web"
command: >-
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
bash -c "awx-manage showmigrations | grep -v '(no migrations)' | grep -v '[X]' | grep '[ ]' | wc -l"
changed_when: false
when: awx_web_pod_name != ''
register: database_check

View File

@@ -224,7 +224,7 @@
_custom_image: "{{ image }}:{{ image_version }}"
when:
- image | default([]) | length
- image_version is defined or image_version != ''
- image_version is defined and image_version != ''
- name: Set AWX app image URL
set_fact:
@@ -239,7 +239,7 @@
_custom_redis_image: "{{ redis_image }}:{{ redis_image_version }}"
when:
- redis_image | default([]) | length
- redis_image_version is defined or redis_image_version != ''
- redis_image_version is defined and redis_image_version != ''
- name: Set Redis image URL
set_fact:

View File

@@ -55,6 +55,16 @@
changed_when: false
when: awx_web_pod_name != ''
- name: Update upgradedFrom status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
status:
upgradedFrom: "{{ upgraded_from }}"
when: upgraded_from is defined
- name: Update version status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'

View File

@@ -72,7 +72,7 @@
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
register: old_postgres_svc
- name: Set full resolvable host name for postgres pod
- name: Set resolvable_db_host
set_fact:
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 }}"

View File

@@ -109,7 +109,7 @@ data:
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
client_max_body_size 5M;
client_max_body_size {{ nginx_client_max_body_size }}M;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
@@ -187,7 +187,7 @@ data:
allow 127.0.0.1;
deny all;
}
location {{ (ingress_path + '/static').replace('//', '/') }} {
alias /var/lib/awx/public/static/;
}
@@ -229,7 +229,7 @@ data:
location {{ ingress_path }} {
# Add trailing / if missing
rewrite ^(.*)$http_host(.*[^/])$ $1$http_host$2/ permanent;
uwsgi_read_timeout 125s;
uwsgi_read_timeout {{ nginx_read_timeout }}s;
uwsgi_pass uwsgi;
include /etc/nginx/uwsgi_params;
include /etc/nginx/conf.d/*.conf;
@@ -243,6 +243,23 @@ data:
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Expires "0";
add_header Pragma "no-cache";
# Return 503 Service Unavailable with JSON response if uWSGI fails to respond
error_page 504 =503 /json_503;
error_page 502 =503 /json_503; # Optional, in case uWSGI is completely down
}
location = /json_503 {
# Custom JSON response for 503 Service Unavailable
internal;
add_header Content-Type application/json;
# Check if X-Request-ID is set and include it in the response
if ($http_x_request_id) {
return 503 '{"status": "error", "message": "Service Unavailable", "code": 503, "request_id": "$http_x_request_id"}';
}
# If X-Request-ID is not set, just return the basic JSON response
return 503 '{"status": "error", "message": "Service Unavailable", "code": 503}';
}
}
}
@@ -251,6 +268,7 @@ data:
unixsocketperm 777
port 0
bind 127.0.0.1
timeout 300
receptor_conf: |
---
- log-level: {{ receptor_log_level }}
@@ -304,8 +322,8 @@ data:
max-requests = 1000
buffer-size = 32768
harakiri = 120
harakiri-graceful-timeout = 115
harakiri = {{ uwsgi_timeout }}
harakiri-graceful-timeout = {{ uwsgi_timeout_grace_period }}
harakiri-graceful-signal = 6
py-call-osafterfork = true

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: '{{ ansible_operator_meta.name }}-postgres-extra-settings'
namespace: '{{ ansible_operator_meta.namespace }}'
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
data:
99-overrides.conf: |
{% for pg_setting in postgres_extra_settings %}
{% if pg_setting.value is string %}
{{ pg_setting.setting }} = '{{ pg_setting.value }}'
{% else %}
{{ pg_setting.setting }} = {{ pg_setting.value }}
{% endif %}
{% endfor %}

View File

@@ -0,0 +1,76 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ ansible_operator_meta.name }}-redirect-page
namespace: "{{ ansible_operator_meta.namespace }}"
data:
redirect-page.html: |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="15; url={{ public_base_url }}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redirecting to Ansible Automation Platform</title>
<!-- Favicon links -->
<link rel="icon" type="image/x-icon" href="static/media/favicon.ico">
<!-- Link to DRF's CSS -->
<link rel="stylesheet" type="text/css" href="static/rest_framework/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="static/rest_framework/css/bootstrap-theme.min.css">
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding-top: 0px;
/* background-color: rgb(34, 34, 34); */
}
.banner {
background-color: #151414;
color: rgb(255, 255, 255);
padding: 20px;
margin-bottom: 20px;
min-height: 70px; /* Ensure the banner is tall enough to fit the logo */
text-align: left;
}
.logo {
width: 150px;
margin-bottom: 20px;
}
a {
color: #007BFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.doc-note {
font-size: 0.7em; /* Makes the text smaller */
color: #555; /* Optional: Change text color to a lighter shade */
background-color: #f9f9f9; /* Optional: Light background color */
padding: 10px; /* Optional: Add some padding */
margin: 10px 0; /* Optional: Add some margin */
}
</style>
</head>
<body>
<!-- Banner Section with Brand Logo -->
<div class="banner">
<img src="/static/media/aap-logo.svg" alt="Brand Logo">
</div>
<h2>Redirecting to Ansible Automation Platform...</h2>
<p>If you are not redirected automatically, <a href="{{ public_base_url }}">click here</a> to go to AAP.</p>
<p class="doc-note">
The API endpoints for this platform service will temporarily remain available at the URL for this service.
Please use the Ansible Automation Platform API endpoints corresponding to this component in the future.
These can be found at <a href="{{ public_base_url }}/api/{{ deployment_type_shortname }}" target="_blank">{{ public_base_url }}/api/{{ deployment_type_shortname }}/</a>.
</p>
<!-- Include any additional scripts if needed -->
<script src="static/rest_framework/js/jquery-3.7.1.min.js"></script>
<script src="static/rest_framework/js/bootstrap.min.js"></script>
</body>
</html>

View File

@@ -84,7 +84,7 @@ spec:
- -c
- |
mkdir -p /etc/pki/ca-trust/extracted/{java,pem,openssl,edk2}
update-ca-trust extract
update-ca-trust extract --output /etc/pki/ca-trust/extracted
volumeMounts:
- name: "ca-trust-extracted"
mountPath: "/etc/pki/ca-trust/extracted"

View File

@@ -28,12 +28,15 @@ spec:
annotations:
kubectl.kubernetes.io/default-container: '{{ ansible_operator_meta.name }}-web'
{% for template in [
"configmaps/config",
"secrets/app_credentials",
"storage/persistent",
"configmaps/config.yaml",
"secrets/app_credentials.yaml",
"storage/persistent.yaml",
] %}
checksum-{{ template | replace('/', '-') }}: "{{ lookup('template', template + '.yaml.j2') | sha1 }}"
checksum-{{ template | replace('/', '-') }}: "{{ lookup('template', template + '.j2') | sha1 }}"
{% endfor %}
{% if public_base_url is defined %}
checksum-configmaps-redirect-page.configmap.html: "{{ lookup('template', 'configmaps/redirect-page.configmap.html.j2') | sha1 }}"
{% endif %}
{% for secret in [
"bundle_cacert",
"route_tls",
@@ -90,7 +93,7 @@ spec:
- -c
- |
mkdir -p /etc/pki/ca-trust/extracted/{java,pem,openssl,edk2}
update-ca-trust extract
update-ca-trust extract --output /etc/pki/ca-trust/extracted
volumeMounts:
- name: "ca-trust-extracted"
mountPath: "/etc/pki/ca-trust/extracted"
@@ -197,6 +200,11 @@ spec:
timeoutSeconds: {{ web_readiness_timeout }}
{% endif %}
volumeMounts:
{% if public_base_url is defined %}
- name: redirect-page
mountPath: '/var/lib/awx/venv/awx/lib/python3.11/site-packages/awx/ui/build/index.html'
subPath: redirect-page.html
{% endif %}
{% if bundle_ca_crt %}
- name: "ca-trust-extracted"
mountPath: "/etc/pki/ca-trust/extracted"
@@ -375,6 +383,14 @@ spec:
{{ security_context_settings | to_nice_yaml | indent(8) }}
{% endif %}
volumes:
{% if public_base_url is defined %}
- name: redirect-page
configMap:
name: '{{ ansible_operator_meta.name }}-redirect-page'
items:
- key: redirect-page.html
path: redirect-page.html
{% endif %}
- name: "{{ ansible_operator_meta.name }}-receptor-ca"
secret:
secretName: "{{ ansible_operator_meta.name }}-receptor-ca"

View File

@@ -24,7 +24,7 @@ spec:
- -c
- |
mkdir -p /etc/pki/ca-trust/extracted/{java,pem,openssl,edk2}
update-ca-trust extract
update-ca-trust extract --output /etc/pki/ca-trust/extracted
volumeMounts:
- name: "ca-trust-extracted"
mountPath: "/etc/pki/ca-trust/extracted"

View File

@@ -1,9 +1,13 @@
AUTH_LDAP_GLOBAL_OPTIONS = {
{% if ldap_cacert_ca_crt %}
import ldap
AUTH_LDAP_GLOBAL_OPTIONS = {
ldap.OPT_X_TLS_REQUIRE_CERT: True,
ldap.OPT_X_TLS_CACERTFILE: "/etc/openldap/certs/ldap-ca.crt"
{% endif %}
}
{% else %}
AUTH_LDAP_GLOBAL_OPTIONS = {}
{% endif %}
# Load LDAP BIND password from Kubernetes secret if define
{% if ldap_password_secret -%}

View File

@@ -34,6 +34,11 @@ spec:
app.kubernetes.io/component: 'database'
app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
annotations:
{% if postgres_extra_settings | length > 0 %}
checksum-postgres_extra_settings: "{{ lookup('template', 'configmaps/postgres_extra_settings.yaml.j2') | sha1 }}"
{% endif %}
checksum-secret-postgres_configuration_secret: "{{ lookup('ansible.builtin.vars', 'pg_config', default='')["resources"][0]["data"] | default('') | sha1 }}"
{% if postgres_annotations %}
{{ postgres_annotations | indent(width=8) }}
{% endif %}
@@ -137,6 +142,11 @@ spec:
- name: postgres-{{ supported_pg_version }}
mountPath: '{{ _postgres_data_path | dirname }}'
subPath: '{{ _postgres_data_path | dirname | basename }}'
{% if postgres_extra_settings | length > 0 %}
- name: pg-overrides
mountPath: /opt/app-root/src/postgresql-cfg
readOnly: true
{% endif %}
{% if postgres_extra_volume_mounts %}
{{ postgres_extra_volume_mounts | indent(width=12, first=True) }}
{% endif %}
@@ -149,9 +159,19 @@ spec:
tolerations:
{{ postgres_tolerations | indent(width=8) }}
{% endif %}
{% if postgres_extra_volumes %}
{% if (postgres_extra_volumes | length + postgres_extra_settings | length) > 0 %}
volumes:
{% if postgres_extra_volumes %}
{{ postgres_extra_volumes | indent(width=8, first=False) }}
{% endif %}
{% if postgres_extra_settings | length > 0 %}
- name: pg-overrides
configMap:
name: '{{ ansible_operator_meta.name }}-postgres-extra-settings'
items:
- key: 99-overrides.conf
path: 99-overrides.conf
{% endif %}
{% endif %}
volumeClaimTemplates:
- metadata:

View File

@@ -3,7 +3,7 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ _metrics_utility_pvc_claim }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
ownerReferences: null
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}

View File

@@ -21,3 +21,6 @@ _metrics_utility_pvc_claim: "{{ metrics_utility_pvc_claim | default(deployment_t
_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') }}"
# version check
gating_version: ''

View File

@@ -6,6 +6,7 @@ ingress_api_version: 'networking.k8s.io/v1'
ingress_annotations: ''
ingress_class_name: ''
ingress_controller: ''
route_annotations: ''
set_self_owneref: true

View File

@@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
selector:
matchLabels:

View File

@@ -6,7 +6,7 @@ apiVersion: '{{ ingress_api_version }}'
kind: Ingress
metadata:
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
annotations:
{% if ingress_annotations %}
{{ ingress_annotations | indent(width=4) }}
@@ -41,7 +41,7 @@ apiVersion: '{{ ingress_api_version }}'
kind: IngressRouteTCP
metadata:
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
annotations:
{% if ingress_annotations %}
{{ ingress_annotations | indent(width=4) }}
@@ -67,8 +67,11 @@ kind: Route
metadata:
annotations:
openshift.io/host.generated: "true"
{% if route_annotations %}
{{ route_annotations | indent(width=4) }}
{% endif %}
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
{% if external_hostname is defined %}
host: {{ external_hostname }}

View File

@@ -3,7 +3,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: {{ ansible_operator_meta.name }}-receptor-config
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
data:
receptor_conf: |
---

View File

@@ -5,7 +5,7 @@
postgres_configuration_secret: "{{ spec['postgres_configuration_secret'] | default(postgres_configuration_secret) }}"
- name: Check for specified PostgreSQL configuration
k8s_info:
kubernetes.core.k8s_info:
kind: Secret
namespace: '{{ ansible_operator_meta.namespace }}'
name: '{{ postgres_configuration_secret }}'
@@ -29,7 +29,7 @@
- block:
- name: Get the postgres pod information
k8s_info:
kubernetes.core.k8s_info:
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
@@ -47,7 +47,7 @@
when: awx_postgres_type == 'managed'
- name: Check for presence of AWX Deployment
k8s_info:
kubernetes.core.k8s_info:
api_version: apps/v1
kind: Deployment
name: "{{ deployment_name }}-task"
@@ -55,7 +55,7 @@
register: this_deployment
- name: Scale down Deployment for migration
k8s_scale:
kubernetes.core.k8s_scale:
api_version: apps/v1
kind: Deployment
name: "{{ item }}"
@@ -67,15 +67,23 @@
- "{{ deployment_name }}-web"
when: this_deployment['resources'] | length
- name: Set full resolvable host name for postgres pod
- name: Set resolvable_db_host
set_fact:
resolvable_db_host: '{{ (awx_postgres_type == "managed") | ternary(awx_postgres_host + "." + ansible_operator_meta.namespace + ".svc." + cluster_name, awx_postgres_host) }}' # yamllint disable-line rule:line-length
no_log: "{{ no_log }}"
- name: Set pg_isready command
ansible.builtin.set_fact:
pg_isready: >-
pg_isready
-h {{ resolvable_db_host }}
-p {{ awx_postgres_port }}
no_log: "{{ no_log }}"
- name: Set pg_restore command
set_fact:
pg_restore: >-
pg_restore --clean --if-exists
pg_restore --clean --if-exists --no-owner --no-acl
-U {{ awx_postgres_user }}
-h {{ resolvable_db_host }}
-d {{ awx_postgres_database }}
@@ -111,8 +119,8 @@
{{ pg_create_db }}
when: force_drop_db
- name: Restore database dump to the new postgresql container
k8s_exec:
- name: Restore Postgres database
kubernetes.core.k8s_exec:
namespace: "{{ backup_pvc_namespace }}"
pod: "{{ ansible_operator_meta.name }}-db-management"
container: "{{ ansible_operator_meta.name }}-db-management"
@@ -126,6 +134,11 @@
exit $rc
}
keepalive_file=\"$(mktemp)\"
until {{ pg_isready }} &> /dev/null
do
echo \"Waiting until Postgres is accepting connections...\"
sleep 2
done
while [[ -f \"$keepalive_file\" ]]; do
echo 'Migrating data from old database...'
sleep 60

View File

@@ -3,12 +3,12 @@ apiVersion: v1
kind: Event
metadata:
name: restore-error.{{ now }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
involvedObject:
apiVersion: awx.ansible.com/v1beta1
kind: {{ kind }}
name: {{ ansible_operator_meta.name }}
namespace: {{ ansible_operator_meta.namespace }}
namespace: "{{ ansible_operator_meta.namespace }}"
message: {{ error_msg }}
reason: RestoreFailed
type: Warning

View File

@@ -3,7 +3,7 @@ apiVersion: v1
kind: Pod
metadata:
name: {{ ansible_operator_meta.name }}-db-management
namespace: {{ backup_pvc_namespace }}
namespace: "{{ backup_pvc_namespace }}"
labels:
{{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }}
spec:

140
up.sh Executable file
View File

@@ -0,0 +1,140 @@
#!/bin/bash
# AWX Operator up.sh
# Purpose:
# Build operator image from your local checkout, push to quay.io/youruser/awx-operator:dev, and deploy operator
# -- Usage
# NAMESPACE=awx TAG=dev QUAY_USER=developer ./up.sh
# NAMESPACE=awx TAG=dev QUAY_USER=developer PULL_SECRET_FILE=my-secret.yml ./up.sh
# -- User Variables
NAMESPACE=${NAMESPACE:-awx}
QUAY_USER=${QUAY_USER:-developer}
TAG=${TAG:-$(git rev-parse --short HEAD)}
DEV_TAG=${DEV_TAG:-dev}
DEV_TAG_PUSH=${DEV_TAG_PUSH:-true}
PULL_SECRET_FILE=${PULL_SECRET_FILE:-hacking/pull-secret.yml}
# -- Check for required variables
# Set the following environment variables
# export NAMESPACE=awx
# export QUAY_USER=developer
if [ -z "$QUAY_USER" ]; then
echo "Error: QUAY_USER env variable is not set."
echo " export QUAY_USER=developer"
exit 1
fi
if [ -z "$NAMESPACE" ]; then
echo "Error: NAMESPACE env variable is not set. Run the following with your namespace:"
echo " export NAMESPACE=developer"
exit 1
fi
# -- Container Build Engine (podman or docker)
ENGINE=${ENGINE:-podman}
# -- Variables
IMG=quay.io/$QUAY_USER/awx-operator
KUBE_APPLY="kubectl apply -n $NAMESPACE -f"
# -- Wait for existing project to be deleted
# Function to check if the namespace is in terminating state
is_namespace_terminating() {
kubectl get namespace $NAMESPACE 2>/dev/null | grep -q 'Terminating'
return $?
}
# Check if the namespace exists and is in terminating state
if kubectl get namespace $NAMESPACE 2>/dev/null; then
echo "Namespace $NAMESPACE exists."
if is_namespace_terminating; then
echo "Namespace $NAMESPACE is in terminating state. Waiting for it to be fully terminated..."
while is_namespace_terminating; do
sleep 5
done
echo "Namespace $NAMESPACE has been terminated."
fi
fi
# -- Create namespace
kubectl create namespace $NAMESPACE
# -- Prepare
# Set imagePullPolicy to Always
files=(
config/manager/manager.yaml
)
for file in "${files[@]}"; do
if grep -qF 'imagePullPolicy: IfNotPresent' ${file}; then
sed -i -e "s|imagePullPolicy: IfNotPresent|imagePullPolicy: Always|g" ${file};
fi
done
# Create redhat-operators-pull-secret if pull credentials file exists
if [ -f "$PULL_SECRET_FILE" ]; then
$KUBE_APPLY $PULL_SECRET_FILE
fi
# Delete old operator deployment
kubectl delete deployment awx-operator-controller-manager
# Create secrets
$KUBE_APPLY dev/secrets/custom-secret-key.yml
$KUBE_APPLY dev/secrets/admin-password-secret.yml
# (Optional) Create external-pg-secret
# $KUBE_APPLY dev/secrets/external-pg-secret.yml
# -- Login to Quay.io
$ENGINE login quay.io
if [ $ENGINE = 'podman' ]; then
if [ -f "$XDG_RUNTIME_DIR/containers/auth.json" ] ; then
REGISTRY_AUTH_CONFIG=$XDG_RUNTIME_DIR/containers/auth.json
echo "Found registry auth config: $REGISTRY_AUTH_CONFIG"
elif [ -f $HOME/.config/containers/auth.json ] ; then
REGISTRY_AUTH_CONFIG=$HOME/.config/containers/auth.json
echo "Found registry auth config: $REGISTRY_AUTH_CONFIG"
elif [ -f "/home/$USER/.docker/config.json" ] ; then
REGISTRY_AUTH_CONFIG=/home/$USER/.docker/config.json
echo "Found registry auth config: $REGISTRY_AUTH_CONFIG"
else
echo "No Podman configuration files were found."
fi
fi
if [ $ENGINE = 'docker' ]; then
if [ -f "/home/$USER/.docker/config.json" ] ; then
REGISTRY_AUTH_CONFIG=/home/$USER/.docker/config.json
echo "Found registry auth config: $REGISTRY_AUTH_CONFIG"
else
echo "No Docker configuration files were found."
fi
fi
# -- Build & Push Operator Image
echo "Preparing to build $IMG:$TAG ($IMG:$DEV_TAG) with $ENGINE..."
sleep 3
make docker-build docker-push IMG=$IMG:$TAG
# Tag and Push DEV_TAG Image when DEV_TAG_PUSH is 'True'
if $DEV_TAG_PUSH ; then
$ENGINE tag $IMG:$TAG $IMG:$DEV_TAG
make docker-push IMG=$IMG:$DEV_TAG
fi
# -- Deploy Operator
make deploy IMG=$IMG:$TAG NAMESPACE=$NAMESPACE
# -- Create CR
# uncomment the CR you want to use
$KUBE_APPLY dev/awx-cr/awx-openshift-cr.yml
# $KUBE_APPLY dev/awx-cr/awx-cr-settings.yml
# $KUBE_APPLY dev/awx-cr/awx-k8s-ingress.yml

Binary file not shown.