Compare commits

..

274 Commits
0.6.0 ... 0.9.0

Author SHA1 Message Date
Shane McDonald
8772d0eec5 Merge pull request #266 from shanemcd/bump-19.1.0
Bump 19.1.0
2021-05-01 10:27:39 -04:00
Shane McDonald
ca20dcf053 Use 'admin' username in tests 2021-05-01 09:39:50 -04:00
Shane McDonald
67a650ce38 Remove isolated logger from configmap
Isolated nodes have been removed in upstream AWX
2021-05-01 09:32:09 -04:00
Shane McDonald
acb443432e Bump version 2021-05-01 08:18:30 -04:00
Shane McDonald
3f2bb3e5db Regenerate files 2021-05-01 08:18:13 -04:00
Shane McDonald
c318611561 Bump AWX version 2021-05-01 07:45:18 -04:00
Shane McDonald
77e7039a2e Update playbook to allow for deploying custom image version/tag 2021-05-01 07:44:53 -04:00
Marcelo Moreira de Mello
8656ee1a1d Merge pull request #263 from tchellomello/projects
Mounts /var/lib/awx/projects on awx-web container
2021-04-30 13:46:17 -04:00
Marcelo Moreira de Mello
f21ec4de61 Mounts /var/lib/awx/projects on awx-web container 2021-04-30 13:31:31 -04:00
Shane McDonald
5f668d76f0 Merge pull request #262 from Spredzy/extra_settings
Extra Settings: Allow one to pass extra API configuration settings.
2021-04-30 10:01:47 -04:00
Yanis Guenane
1d14ebccad Extra Settings: Allow one to pass extra API configuration settings.
For more advanced usage, a user can do the
extra_volumes/extra_volume_mounts dance. But for simple need adding this
parameter make it easy to just specify an extra parameter.
2021-04-30 11:06:40 +02:00
Yanis Guenane
06ab6d2dad Merge pull request #257 from Spredzy/rename_postgres_parameters
PostgreSQL: Properly handle variable name difference when using Red Hat containers
2021-04-30 09:35:35 +02:00
Yanis Guenane
6b0ecacc63 Merge pull request #258 from Spredzy/fix_tower_ee_images
Properly hide tower_ee_images
2021-04-30 09:35:20 +02:00
Yanis Guenane
2965a9091e PostgreSQL: Properly handle variable name difference when using Red Hat containers 2021-04-29 18:16:20 +02:00
Yanis Guenane
160209698c Properly hide tower_ee_images 2021-04-29 17:39:57 +02:00
Marcelo Moreira de Mello
7361defa17 Merge pull request #198 from tchellomello/ssl_pg
Added support to override PosgreSQL sslmode
2021-04-28 15:51:01 -04:00
Shane McDonald
68774a3ccc Merge pull request #250 from rooftopcellist/ee-vars
Add templated EE volume mount var to operator config
2021-04-28 11:33:13 -04:00
Shane McDonald
70b7991cdf Merge pull request #253 from Spredzy/base_component_on_deployment_type
Deployment type: Make more fields dynamic based on that field
2021-04-28 11:32:37 -04:00
Yanis Guenane
4706aa9a1e Deployment type: Make more fields dynamic based on that field 2021-04-28 12:12:06 +02:00
Marcelo Moreira de Mello
fb183f4eab Merge pull request #251 from tchellomello/redeploy-it
Handle statefulset updates
2021-04-27 23:29:19 -04:00
Marcelo Moreira de Mello
3d5a9eae31 Handle statefulset updates 2021-04-27 17:16:57 -04:00
Christian M. Adams
e55d83ffa0 Add templated EE volume mount var to operator config 2021-04-27 15:54:37 -04:00
Yanis Guenane
fd9ce8f0cb Merge pull request #249 from Spredzy/fix_wrong_indentation
olm manifests: fix wrong identation making file incorrect
2021-04-27 14:19:30 +02:00
Yanis Guenane
126228774c olm manifests: fix wrong identation making file incorrect
Currently the file is inacurrate and yaml parsing would fail on line 166
with

>  syntax error: expected <block end>, but found '<block mapping start>'
(syntax)
2021-04-27 13:24:52 +02:00
Marcelo Moreira de Mello
3c26af0cd7 Merge pull request #217 from tchellomello/crashing
Updated logic to validate changes on configmaps, deployments and statefulsets
2021-04-26 17:04:20 -04:00
Shane McDonald
b781300977 Merge pull request #248 from shanemcd/devel
Fix service type logic
2021-04-26 14:10:43 -04:00
Shane McDonald
c0e164d763 Fix service type logic 2021-04-26 13:58:44 -04:00
Marcelo Moreira de Mello
2fd737fbc2 Merge pull request #204 from TheStally/devel
Set Service to use type ClusterIP instead of NodePort when tower_ingress_type is Ingress
2021-04-25 21:59:25 -04:00
Shane McDonald
ee9800c258 Merge pull request #244 from ilijamt/ee-conf-wrong
added missing comma, to AWX execution_environments.py file
2021-04-24 11:58:41 -04:00
stal
5b38c85f8a Extra changes for new tower_ingress_type NodePort 2021-04-24 15:16:49 +01:00
Ilija Matoski
72c122dff9 added missing comma, to AWX execution_environets.py file 2021-04-24 14:34:19 +02:00
Shane McDonald
3e8834e057 Merge pull request #243 from ansible/shanemcd-patch-3
Update default ee version
2021-04-23 14:24:28 -04:00
Shane McDonald
5779afd858 Update default ee version 2021-04-23 13:58:01 -04:00
Shane McDonald
da43c5ba7d Merge pull request #226 from fust/fix_postgres_resources
Fix postgres resources
2021-04-22 13:33:11 -04:00
Marcelo Moreira de Mello
cd181bc1fd Merge pull request #235 from tchellomello/split_image_expr
Split container image and version in 2 variables
2021-04-22 13:31:46 -04:00
Marcelo Moreira de Mello
01f1321bd4 Merge branch 'devel' into split_image_expr 2021-04-22 10:28:32 -04:00
Marcelo Moreira de Mello
52768c9a65 updated coumentation 2021-04-22 10:18:46 -04:00
TheStally
96b878f049 Add NodePort to tower_ingress_type enum 2021-04-22 08:39:28 +01:00
TheStally
a00052a8ca Fix template logic 2021-04-22 08:37:31 +01:00
Thom Wijtenburg
4596c30e9d Make displayName for PostgreSQL parameters single line 2021-04-22 07:07:51 +02:00
Marcelo Moreira de Mello
051500fff1 updated documentation 2021-04-21 17:51:40 -04:00
Marcelo Moreira de Mello
bc34758c91 Split container image and version in 2 variables 2021-04-21 17:18:02 -04:00
Shane McDonald
e3f027d625 Merge pull request #212 from tchellomello/change_pull_policy_redis
Inherit imagePullPolicy to redis container
2021-04-21 16:44:07 -04:00
Marcelo Moreira de Mello
46fca2af5a updated 2021-04-21 15:41:18 -04:00
Marcelo Moreira de Mello
dc073c85ed updated 2021-04-21 15:02:33 -04:00
Marcelo Moreira de Mello
597356f317 Handles deleting and recreating statefulset and deployment when needed 2021-04-21 14:58:21 -04:00
Shane McDonald
0655122a57 Merge pull request #234 from shanemcd/stop-using-devel
Stop telling folks to use devel
2021-04-21 13:32:06 -04:00
Shane McDonald
51ea411a79 Stop telling folks to use devel 2021-04-21 13:19:43 -04:00
Shane McDonald
776dba5e23 Merge pull request #216 from gamuniz/document_env_config
added documentation around environment variables
2021-04-21 10:21:59 -04:00
Shane McDonald
6858dcfa7a Merge pull request #231 from daenney/migration-docs
migration: Clarify you can migrate in-place
2021-04-21 09:15:29 -04:00
Daniele Sluijters
ea018be298 migration: Clarify you can migrate in-place
Closes #213
2021-04-21 15:01:39 +02:00
Thom Wijtenburg
841d1f94f2 Change default resource requirement to object 2021-04-20 11:52:56 +02:00
Thom Wijtenburg
262b1cca34 Update variable table for PostgreSQL service 2021-04-20 11:33:24 +02:00
Thom Wijtenburg
378a33aaee Fix PostgreSQL resource requests 2021-04-20 11:14:48 +02:00
Marcelo Moreira de Mello
09652056b7 Added initial upgrade documentation 2021-04-20 00:23:10 -04:00
Marcelo Moreira de Mello
39ef816f5e Updated logic to avoid crash during upgrades 2021-04-19 23:19:13 -04:00
Gabe Muniz
f68dc77ea3 added documentation around environment variables 2021-04-15 17:33:31 -04:00
Shane McDonald
51b2a211cb Merge pull request #214 from gamuniz/expose_extra_volume_config
Expose extra volume config
2021-04-15 16:08:11 -04:00
Gabe Muniz
9de67ad898 added default value for ee extra mounts 2021-04-15 15:25:45 -04:00
Gabe Muniz
8922e9fe7d added warning about kubernetes api naming 2021-04-15 11:09:32 -04:00
Gabe Muniz
90f25ab20c added ability to mount to Execution container with example 2021-04-15 10:01:46 -04:00
Gabe Muniz
6c476a994e added ability to mount conf.d and fixed underscore api issue 2021-04-14 16:18:44 -04:00
stal
1b87616a11 Add tower_ingress_type NodePort 2021-04-14 20:15:15 +01:00
Gabe Muniz
8d65b84b89 expose settings to use custom volumes and volume mounts 2021-04-14 14:49:42 -04:00
Shane McDonald
125b6fbe58 Merge pull request #208 from a-eperez/devel
Include support for nodeSelector and tolerations in AWX Postgres pod
2021-04-14 11:25:34 -04:00
Ernesto Pérez
d4d9d2a982 Correction, replace tower_tolerations by tower_postgres_tolerations 2021-04-14 09:59:50 +02:00
Ernesto Pérez
1cc47f7570 Correction, replace tower_node_selector by tower_postgres_selector 2021-04-14 09:56:06 +02:00
Marcelo Moreira de Mello
83a85d15c0 Inherit imagePullPolicy to redis container 2021-04-13 21:28:55 -04:00
Ernesto Pérez
0ab33a17df Fix yaml missing starting space in comment 2021-04-13 14:33:47 +02:00
Ernesto Pérez
30e4ad0d3d Postgres selector and tolerations description included in README.md 2021-04-13 14:00:15 +02:00
Ernesto Pérez
151ff11745 Add nodeSelector and tolerations for Postgres pod 2021-04-13 13:50:14 +02:00
Shane McDonald
b942794179 Merge pull request #206 from tchellomello/pwd_quotes
Removed jinja2 filter 'quote' for db password
2021-04-12 16:36:53 -04:00
Marcelo Moreira de Mello
57071129bf Removed jinja2 filter 'quote' for db password 2021-04-12 16:23:21 -04:00
stal
0f90847c07 Add Service types to docs based on Ingress used 2021-04-12 21:14:54 +01:00
stal
e091b32c4b use ClusterIP service when ingress type is Ingress 2021-04-12 19:35:29 +01:00
Marcelo Moreira de Mello
298d39c57b Added support to override pg_sslmode 2021-04-12 12:48:00 -04:00
Shane McDonald
9503d3cf48 Merge pull request #197 from RylandDeGregory/rylanddegregory-patch-1
Update docs and service Template for LoadBalancer ingress type
2021-04-08 12:45:05 -04:00
Ryland DeGregory
95f04abdfd Added conditional to validate that tower_loadbalancer_annotations is defined 2021-04-08 12:24:56 -04:00
Ryland DeGregory
7e3f5047a1 Updated protocol var in LoadBalancer ingress spec 2021-04-08 12:20:08 -04:00
Shane McDonald
5c77cf004b Merge pull request #192 from shanemcd/gha-release-workflow
Add GHA workflow for pushing releases to Quay
2021-04-08 09:10:08 -04:00
Shane McDonald
295ed47c43 Add GHA workflow for pushing releases to Quay 2021-04-08 07:26:45 -04:00
Shane McDonald
d8b7ed81b5 Merge pull request #189 from shanemcd/bump-19
Version bump for AWX 19
2021-04-07 18:00:16 -04:00
Shane McDonald
f4980917d2 Merge pull request #186 from tchellomello/build
Added build.sh to facilitate local tests
2021-04-07 17:27:45 -04:00
Shane McDonald
1c9173f48a Regenerate OLM metadata 2021-04-07 17:24:14 -04:00
Shane McDonald
f6b7a32a33 Bump version 2021-04-07 17:24:08 -04:00
Shane McDonald
aa03a7f268 Ensure CRD exists before deploying Operator 2021-04-07 17:20:52 -04:00
Shane McDonald
136b2c47f8 Remove unnecessary variables from molecule CR 2021-04-07 17:20:04 -04:00
Shane McDonald
0043c375d8 Merge pull request #184 from no-12/devel
add tower_image_pull_secret as property of AWX resource
2021-04-07 16:30:05 -04:00
Shane McDonald
c44c3fb095 Merge pull request #176 from rooftopcellist/fix-mismatched-db-name
Fix data migrations when the database names do not match
2021-04-07 16:29:52 -04:00
Shane McDonald
cb70e97366 Merge pull request #180 from tchellomello/add_labels_to_awx_kind
Added expected labels to AWX kind
2021-04-07 16:29:37 -04:00
Marcelo Moreira de Mello
1d21dc7f20 Added build.sh to facilitate local tests 2021-04-07 16:28:10 -04:00
Marcelo Moreira de Mello
4d4ed3e827 Added labels to AWX kind resource 2021-04-07 14:24:34 -04:00
Nico Ohnezat
0eb4286b71 add tower_image_pull_secret as property of AWX resource 2021-04-07 17:55:18 +02:00
Shane McDonald
f73cff3cb3 Merge pull request #177 from tchellomello/persistent_vol
Introducing ability to mount /var/lib/projects
2021-04-07 11:14:30 -04:00
Marcelo Moreira de Mello
54c8a7beef Fixed webUI form drop-down 2021-04-06 22:52:00 -04:00
Marcelo Moreira de Mello
584d45d315 Introducing ability to mount /var/lib/projects 2021-04-06 12:53:08 -04:00
Christian M. Adams
43aa01ce5f Fix data migrations when the database names do not match 2021-04-05 17:14:47 -04:00
Shane McDonald
a0c6565e59 Merge pull request #174 from shanemcd/cleanup
Clean up instances of tower_ee_image
2021-04-05 16:30:28 -04:00
Shane McDonald
bac795a36a Clean up instances of tower_ee_image 2021-04-05 15:50:29 -04:00
Shane McDonald
c9acc30009 Merge pull request #170 from tylerauerbeck/update-actions
Update GH Actions to run on push to devel
2021-04-03 17:34:45 -04:00
Shane McDonald
0cf0fd52c7 Merge pull request #171 from shanemcd/tower-ee-images
More flexibility for customizing default EEs
2021-04-03 17:32:27 -04:00
Shane McDonald
2b8530b3e2 Update instantiate playbook to document tower_ee_images 2021-04-03 17:21:53 -04:00
Shane McDonald
550756c33c Update CRD stuff related to tower_ee_image -> tower_ee_images rename 2021-04-03 17:21:49 -04:00
Shane McDonald
4230120884 More flexibility for customizing default EEs 2021-04-03 17:15:56 -04:00
Tyler Auerbeck
90b88676c5 Update README; Update GHA to run on push to devel 2021-04-03 14:42:24 -04:00
Shane McDonald
862123e2d6 Merge pull request #169 from shanemcd/fix-instantiate
Fix instantiate playbook when development_mode var is not provided
2021-04-03 13:05:42 -04:00
Shane McDonald
c1a2f6e649 Fix instantiate playbook when development_mode var is not provided 2021-04-03 12:54:43 -04:00
Shane McDonald
c0d3047dab Merge pull request #166 from ilijamt/wrong-supervisor-conf
fix wrong conf file for SUPERVISOR_WEB_CONFIG_PATH in kubernetes deployment file
2021-04-03 12:45:52 -04:00
Shane McDonald
1a50cd339e Merge pull request #162 from Spredzy/add_bundle_dockerfile
bundle.Dockerfile: Add the Dockerfile so user can build their own bundle
2021-04-03 12:45:30 -04:00
Shane McDonald
30db53d250 Merge pull request #164 from tchellomello/unique_labels
Use k8s labels to create unique matchLabels for svc and deployments
2021-04-03 12:44:31 -04:00
Shane McDonald
1309cc63c9 Merge pull request #165 from TrueTickets/athak/add-nodeselector-and-tolerations
Add support for nodeSelector and tolerations
2021-04-03 12:42:17 -04:00
Shane McDonald
32b862c79b Update roles/installer/templates/tower_deployment.yaml.j2 2021-04-03 12:36:55 -04:00
Shane McDonald
e09a468d2c Merge pull request #168 from shanemcd/goodbye-travis
Remove usage of Travis CI
2021-04-03 12:35:51 -04:00
Shane McDonald
adb896f294 Remove usage of Travis CI 2021-04-03 12:26:13 -04:00
Shane McDonald
2fd3158c7b Merge pull request #167 from shanemcd/remove-environment-sh
Remove usage of environment.sh
2021-04-03 12:25:20 -04:00
Shane McDonald
ba2672a0b0 Remove usage of environment.sh
This is no longer sourced in the launch scripts.
2021-04-03 12:07:02 -04:00
Shane McDonald
7c02a9728a Merge pull request #136 from tylerauerbeck/gha
Intial GH Actions - Publish latest build and CI
2021-04-03 11:58:55 -04:00
Ilija Matoski
9b327f6ad5 fix wrong conf file 2021-04-03 13:30:55 +02:00
Atha Kouroussis
2a3f700fde Update README and OLM catalog manifests 2021-04-02 11:03:54 -03:00
Yanis Guenane
d221c64f62 README.md: Extend README.md to explain how to generate the bundle 2021-04-02 15:43:26 +02:00
Yanis Guenane
0f1cc494fe bundle.Dockerfile: Add the Dockerfile so user can build their own bundle 2021-04-02 15:34:42 +02:00
Atha Kouroussis
be68adbf01 Add support for nodeSelector and tolerations 2021-04-01 18:28:07 -03:00
Marcelo Moreira de Mello
185238c199 Use k8s labels on managed resources 2021-04-01 14:04:59 -04:00
Yanis Guenane
210ac2c419 Merge pull request #157 from tchellomello/ldaps
Added ability to specify LDAP CA cert
2021-04-01 09:56:52 +02:00
Marcelo Moreira de Mello
658cf92a3b Make sure we only proceed with ldap-ca.crt is a valid secret 2021-03-31 11:25:25 -04:00
Yanis Guenane
d3f7594aea Merge pull request #160 from tchellomello/warning_admin_pass
tower_admin_password_secret warning note @ docs
2021-03-31 14:24:21 +02:00
Marcelo Moreira de Mello
939dd0b295 Warning for tower_admin_password_secret 2021-03-30 22:34:27 -04:00
Shane McDonald
51e384292c Merge pull request #159 from tchellomello/typo
Fixed typo on migration docs
2021-03-30 12:00:02 -04:00
Marcelo Moreira de Mello
f27f1d188c Fixed typo on migration docs 2021-03-30 10:44:28 -04:00
Marcelo Moreira de Mello
8974e3446a Added ability to configure LDAP CA 2021-03-29 22:19:22 -04:00
Shane McDonald
57a408e384 Merge pull request #155 from shanemcd/update-awx-ee
Use newer awx-ee image
2021-03-29 13:04:36 -04:00
Shane McDonald
1fa391a9f1 Bump awx-ee version 2021-03-29 12:39:57 -04:00
Shane McDonald
7885f8e454 Merge pull request #154 from starcraft66/patch-1
Create kustomization.yaml
2021-03-29 09:39:19 -04:00
Yanis Guenane
32ac0941dc Merge pull request #156 from Spredzy/hidden_tower_ee_image
olm-catalog: Set tower_ee_image as hidden
2021-03-29 14:48:24 +02:00
Yanis Guenane
371d826dd4 olm-catalog: Set tower_ee_image as hidden 2021-03-29 14:09:39 +02:00
Shane McDonald
aeebe6cc4b Allow group to access receptor socket 2021-03-28 15:09:18 -04:00
Shane McDonald
257a3ba807 Allow tower_ee_image to be specified in CR 2021-03-28 15:09:03 -04:00
Shane McDonald
ecdfaf6c0d Pin version of awx-ee 2021-03-28 15:08:49 -04:00
Shane McDonald
bc28071205 Update variable name 2021-03-28 15:07:39 -04:00
Shane McDonald
8962d501b3 Delete unnecessary file 2021-03-28 15:07:14 -04:00
Shane McDonald
e91031fa73 Fix deployment playbook 2021-03-28 15:06:41 -04:00
Tristan
cb2a059e16 Update kustomization.yaml 2021-03-28 01:25:18 -04:00
Tristan
5e5c7bbdaf Create kustomization.yaml
Creating a kustomization.yaml file will allow awx-operator to be added as a remote resource in a Kustomize deployment.
e.g. :
```
resources:
- https://github.com/ansible/awx-operator/deploy?ref=0.7.0
```
2021-03-28 01:10:50 -04:00
Shane McDonald
8b241e7871 Merge pull request #153 from billett83/devel
Handling HTTP loadbalancer
2021-03-26 09:54:49 -04:00
cbillett83@outlook.com
0740fc2bc1 fixes #151 Handling HTTP loadbalancer 2021-03-26 11:20:13 +00:00
billett83
a3cf6c4ea8 Merge pull request #2 from ansible/devel
merge changes
2021-03-26 11:05:21 +00:00
Shane McDonald
697ff11fa7 Merge pull request #144 from rooftopcellist/more_unique_pg_pod
Name pg pod in a more unique way
2021-03-25 11:20:14 -04:00
Yanis Guenane
0d6980b9b4 Merge pull request #145 from Spredzy/liveliness
Update liveness probe defaults
2021-03-24 21:04:48 +01:00
Yanis Guenane
387932e960 Update liveness probe defaults
The liveness probes default are too agressive and can lead to
undeployable operators[1][2] - We are bumping them as per the
operator-sdk default in 1.0[3]

[1] https://github.com/operator-framework/operator-sdk/issues/3216
[2] https://github.com/operator-framework/operator-sdk/issues/3267
[3]
ea43495073

Fixes: https://github.com/ansible/awx-operator/issues/131
2021-03-24 20:33:07 +01:00
Yanis Guenane
79e62755b8 Merge pull request #143 from Spredzy/update_bundle_params
Update bundle variables to catchup with latest commits
2021-03-24 20:25:38 +01:00
Christian M. Adams
746dc2738f Name pg pod in a more unique way
- this is to make it possible to run migration with multiple deployments in the same pod
2021-03-24 13:37:39 -04:00
Shane McDonald
7e67838adb Merge pull request #137 from Zokormazo/backup-read-default-old-configuration
Check the default old PostgreSQL configuration
2021-03-24 11:53:53 -04:00
Shane McDonald
7010ab1fc6 Update deploy/olm-catalog/awx-operator/manifests/awx-operator.clusterserviceversion.yaml 2021-03-24 11:52:33 -04:00
Shane McDonald
4eb4abf4f5 Merge pull request #141 from billett83/devel
fixes #140 - Allow for private hosted awx-ee image
2021-03-24 09:14:21 -04:00
Yanis Guenane
451e2b6497 Update bundle variables to catchup with latest commits 2021-03-24 14:07:36 +01:00
cbillett83@outlook.com
60479971b8 resolve build failure 2021-03-24 10:19:14 +00:00
cbillett83@outlook.com
76092c366e alow private hosted awx-ee image 2021-03-24 10:02:33 +00:00
billett83
e09c48d67c Merge pull request #1 from ansible/devel
Merge changes
2021-03-23 16:44:07 +00:00
Shane McDonald
556cb23a14 Merge pull request #138 from shanemcd/bump-18
Bump version / update default AWX image / fix CRD
2021-03-23 11:31:52 -04:00
Shane McDonald
62ec946e4f Use latest version of quay.io/ansible/awx 2021-03-23 11:15:55 -04:00
Shane McDonald
693ce5a17e Fix CRD
Fallout from https://github.com/ansible/awx-operator/pull/128
2021-03-23 11:15:51 -04:00
Shane McDonald
385a4f65a1 Bump version 2021-03-23 11:15:47 -04:00
Shane McDonald
3df272da27 Merge pull request #128 from billett83/devel
fixes #127 Provided service type LoadBalancer
2021-03-23 09:49:34 -04:00
Julen Landa Alustiza
60199f79aa Check the default old PostgreSQL configuration
Signed-off-by: Julen Landa Alustiza <jlanda@redhat.com>
2021-03-23 12:59:29 +01:00
Tyler Auerbeck
d713dce7e0 Intial GH Actions 2021-03-21 20:42:19 -04:00
Yanis Guenane
b00de51fb9 Merge pull request #132 from Spredzy/add_display_name
olm-catalog: Add displayName for the resource
2021-03-19 11:30:50 +01:00
Yanis Guenane
c81266af66 olm-catalog: Add displayName for the resource 2021-03-19 11:14:27 +01:00
Shane McDonald
c320dc835b Fix image 2021-03-18 14:17:13 -04:00
Shane McDonald
f47604998e Merge pull request #116 from rooftopcellist/backup_restore
Optional data migration if source DB configuration is provided
2021-03-18 14:15:30 -04:00
Shane McDonald
7d6743c44d Fix linter 2021-03-18 13:58:26 -04:00
Shane McDonald
bb519664cd Add seperate docs for migration 2021-03-18 12:33:05 -04:00
Shane McDonald
92a7bf22a1 Tweak migration logic 2021-03-18 12:31:02 -04:00
Shane McDonald
851ff16c0f Allow for overriding namespace when deploying via playbook 2021-03-18 11:22:04 -04:00
Shane McDonald
79534a1465 Dont require database names to match when doing migration 2021-03-18 11:22:04 -04:00
Shane McDonald
64c10f29c4 Uncomment status tasks 2021-03-18 11:22:04 -04:00
Shane McDonald
94a4861d13 Bulk removal of no_log statements
The operator would be impossible to debug with these
2021-03-18 11:22:04 -04:00
Shane McDonald
da26472a03 Fix reconcilation loop after data migration changes 2021-03-18 11:22:00 -04:00
cbillett83@outlook.com
76acd335b9 removed extra space 2021-03-18 11:12:03 +00:00
cbillett83@outlook.com
1570c0a883 Minor Changes from Spredzy 2021-03-18 10:58:00 +00:00
Christian M. Adams
c22577bc80 Make data migration idempotent 2021-03-17 16:03:46 -04:00
billett83
a65834dbf3 Update README.md
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:27:40 +00:00
billett83
e990c6bed2 Update README.md
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:27:35 +00:00
billett83
4297b158dc Update ansible/instantiate-awx-deployment.yml
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:27:30 +00:00
billett83
f099b15ff8 Update ansible/templates/crd.yml.j2
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:21:11 +00:00
billett83
add62c2973 Update deploy/awx-operator.yaml
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:20:33 +00:00
billett83
084e0b38a8 Update deploy/crds/awx_v1beta1_crd.yaml
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:20:25 +00:00
billett83
c6c94ce48d Update deploy/olm-catalog/awx-operator/manifests/awx-operator.clusterserviceversion.yaml
Co-authored-by: Shane McDonald <me@shanemcd.com>
2021-03-17 15:20:16 +00:00
cbillett83@outlook.com
781d3e0ec7 Provided service type LoadBalancer 2021-03-17 11:59:57 +00:00
Yanis Guenane
1cd93c6752 Merge pull request #125 from Spredzy/fix_wrong_variable_name
tower_deployment: Use the proper conditional variable
2021-03-17 10:50:34 +01:00
Christian M. Adams
e83e54419a Add no_log where needed, scale down pods before migration 2021-03-16 13:32:16 -04:00
Christian M. Adams
5b89c5c433 Clean db on Tower data is restored to 2021-03-16 13:32:15 -04:00
Christian M. Adams
0e1b12f4b1 Data migration from 3.8 to 4.0 via pg_dump streamed to psql 2021-03-16 13:32:15 -04:00
Christian M. Adams
93d53c712c Use k8s_exec tasks 2021-03-16 13:32:15 -04:00
Christian M. Adams
6a5bdaf2f7 init backup & restore 2021-03-16 13:32:15 -04:00
Shane McDonald
6cc3c47e33 Merge pull request #126 from dericcrago/image_pull_secret
added 'tower_image_pull_secret'
2021-03-15 12:26:01 -04:00
Deric Crago
1beae86c1d added 'tower_image_pull_secret' to 'README.md' 2021-03-15 11:47:07 -04:00
Deric Crago
7a559b9f3b added 'tower_image_pull_secret' 2021-03-15 11:27:37 -04:00
Yanis Guenane
cc3a752550 Merge pull request #120 from Spredzy/scram-sha
PostgreSQL: Set scram-sha-256 as default host auth method
2021-03-15 13:16:59 +01:00
Yanis Guenane
7442555869 tower_deployment: Use the proper conditional variable
fixes: https://github.com/ansible/awx-operator/issues/118
2021-03-15 12:58:14 +01:00
Yanis Guenane
10566b46b1 PostgreSQL: Set scram-sha-256 as default host auth method 2021-03-09 11:40:23 +01:00
Yanis Guenane
d32cf447ea Merge pull request #119 from Spredzy/better_passwords
Rely on /dev/null to generate passwords
2021-03-09 10:19:39 +01:00
Yanis Guenane
07dda4c8ef Rely on /dev/null to generate passwords 2021-03-09 10:01:38 +01:00
Yanis Guenane
a860b0f459 Merge pull request #115 from Spredzy/move_to_secret_base
Move tower_broadcast_websocket_secret to a Secret
2021-03-04 20:56:48 +01:00
Yanis Guenane
9683dc23a4 Move tower_broadcast_websocket_secret to a Secret 2021-03-04 20:21:38 +01:00
Shane McDonald
e4fd5aeb32 Merge pull request #76 from shanemcd/new-deployment-model
New deployment model
2021-03-04 11:46:46 -05:00
Shane McDonald
b1788be272 Merge pull request #1 from rooftopcellist/patch-ee-receptor
Dynamically set the deployment type for the configmap name
2021-03-03 15:46:30 -05:00
Christian M. Adams
92efe37100 Dynamically set the deployment type for the configmap name 2021-03-03 15:39:37 -05:00
Shane McDonald
21f284fb49 Ignore olm-catalog in yamllint 2021-03-03 13:13:12 -05:00
Shane McDonald
d53245b984 Regenerate bundle info 2021-03-03 12:35:07 -05:00
Shane McDonald
9595c6c008 New deployment model 2021-03-03 12:30:17 -05:00
Shane McDonald
9545acd301 Merge pull request #113 from shanemcd/refactor-templates
Refactor templates
2021-03-01 14:14:38 -05:00
Shane McDonald
1ff4d8f6c9 Refactor templates 2021-03-01 13:58:49 -05:00
Yanis Guenane
d839088521 Merge pull request #103 from Spredzy/more_flexibility
Augment the OpenAPI schema at the CRD definition level
2021-03-01 15:24:11 +01:00
Yanis Guenane
32a53f3747 Merge pull request #112 from Spredzy/increase_debug_in_ci
Improve CI troubleshooting
2021-03-01 11:00:55 +01:00
Yanis Guenane
70690ccd50 Improve CI troubleshooting 2021-03-01 10:42:36 +01:00
Yanis Guenane
c579537d66 Update API and operator interface 2021-02-25 17:44:00 +01:00
Yanis Guenane
e589a999a8 kind,api_version: Dynamically retrieve those values 2021-02-25 13:56:42 +01:00
Shane McDonald
53f3f07645 Merge pull request #110 from rooftopcellist/docs_typo
Fix minor typo in README.md
2021-02-24 15:31:27 -05:00
Christian M. Adams
b8d12d93fb Fix minor typo in README.md 2021-02-24 14:09:29 -05:00
Yanis Guenane
5f60f6d004 Merge pull request #107 from Spredzy/update_readdme
Update README
2021-02-24 09:45:48 +01:00
Yanis Guenane
87a6db538a Merge pull request #106 from Spredzy/full_openapi_schema
OpenAPI: Extend the schema to all role variables
2021-02-24 09:45:36 +01:00
Yanis Guenane
733d739124 Update README 2021-02-23 15:02:14 +01:00
Yanis Guenane
c7abc4b8d6 Merge pull request #108 from ansible/add-license-1
Add LICENSE file
2021-02-23 14:56:21 +01:00
Yanis Guenane
9271cd464e Add LICENSE file 2021-02-23 14:39:14 +01:00
Yanis Guenane
f04017ca95 OpenAPI: Extend the schema to all role variables
This is the full implementation of the OpenAPI schema that maps to the
currently existing roles defaults variable.

Prior to this commit, all variables specified at the spec level that
didn't have an entry in the OpenAPI schema at the CRD level were simply
ignored, unless --validate=false was specified.

This commit fixes that and provide a mapping between the CRD level
OpenAPI schema and the variables availabe in <roles>/defaults/main.yml.

This commit is simply about ensuring one can provide all the available
variables. A follow up commit will come to add logic in the OpenAPI
schema definition as it can be shown here[1]

[1]
https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
2021-02-22 16:19:54 +01:00
Yanis Guenane
5690fa7cc1 Merge pull request #102 from Spredzy/templatize_api_version
Make the API version used for status update parametrable
2021-02-17 11:43:25 +01:00
Yanis Guenane
a44cfb676d Make the API version used for status update parametrable 2021-02-17 11:21:29 +01:00
Yanis Guenane
d3e7c308c4 Merge pull request #100 from Spredzy/improved_req_mems
Requirements: Improve CRD OpenAPI schema
2021-02-16 18:31:08 +01:00
Yanis Guenane
53fd88a4e1 Requirements: Improve CRD OpenAPI schema 2021-02-16 18:14:17 +01:00
Yanis Guenane
3b9b4225ae Merge pull request #96 from Spredzy/default_and_v1
Move to apiextensions.k8s.io/v1 and enable default value on CRD
2021-02-16 15:32:34 +01:00
Yanis Guenane
1a58392804 Merge pull request #98 from Spredzy/improve_local_test
Discard .cache from linting and commiting
2021-02-16 14:55:29 +01:00
Yanis Guenane
78eab6873e Merge pull request #99 from Spredzy/fix_logs
CI: Properly return logs when deployment fails
2021-02-16 14:55:19 +01:00
Yanis Guenane
25fc21a6cd Enum: allow various casing 2021-02-16 14:30:31 +01:00
Yanis Guenane
a39b914963 CI: Bump bsycorp/kind to v1.17.9 2021-02-16 14:30:31 +01:00
Yanis Guenane
a4ee609a76 CRD: Add default value to openAPIV3Schema 2021-02-16 14:30:31 +01:00
Yanis Guenane
fbae5cf590 CRD: Move to apiextensions.k8s.io/v1 2021-02-16 14:30:31 +01:00
Yanis Guenane
6f965c9180 CI: Properly return logs when deployment fails 2021-02-16 14:16:12 +01:00
Yanis Guenane
4e8308c90d Discard .cache from linting and commiting 2021-02-16 14:14:36 +01:00
Yanis Guenane
e5e996569c Merge pull request #93 from Spredzy/resource_requirements
Allow greater flexibility to specify resource requests/limits
2021-02-10 16:52:45 +01:00
Yanis Guenane
fd4e3b2d4c Allow greater flexibility to specify resource requests/limits 2021-02-10 15:58:48 +01:00
Yanis Guenane
025dfa54df Merge pull request #95 from Spredzy/tls_custom_passthrough
TLS: Enable passthrough termination mechanism
2021-02-10 15:34:51 +01:00
Yanis Guenane
1fe7c4dd20 TLS: Enable passthrough termination mechanism
Depends-On: https://github.com/ansible/awx-operator/pull/94
2021-02-10 15:20:27 +01:00
Yanis Guenane
b5536ffd80 Merge pull request #94 from Spredzy/tls_customization
TLS: Enable customization of TLS behavior on route when using edge mechanism
2021-02-10 15:19:56 +01:00
Yanis Guenane
c895ca0f6d TLS: Enable customization of TLS behavior on route 2021-02-10 12:11:29 +01:00
Yanis Guenane
121c034e6c Merge pull request #91 from Spredzy/improved_ux
Update CSV with richer fields
2021-02-09 22:43:54 +01:00
Yanis Guenane
452bb128c6 Update CSV with richer fields 2021-02-09 22:23:05 +01:00
Yanis Guenane
821198c05e Merge pull request #90 from Spredzy/standar_gc
Secret: Create a toggle to garbage collect secrets in finalizer
2021-02-09 22:22:37 +01:00
Yanis Guenane
8049dfac9c Secret: Create a toggle to garbage collect secrets in finalizer. 2021-02-09 22:08:24 +01:00
Yanis Guenane
8481390bac Merge pull request #92 from Spredzy/fix_ci
travis.yml: Explicitly list ansible as a dep
2021-02-09 22:07:52 +01:00
Yanis Guenane
0eab2f9686 travis.yml: Explicitly list ansible as a dep 2021-02-09 21:52:51 +01:00
Yanis Guenane
72fd95994b Merge pull request #88 from Spredzy/admin_password
Admin Password: Allow one to specify an admin password secret else generate it
2021-02-09 09:28:50 +01:00
Yanis Guenane
e858f34f2c Admin Password: Allow one to specify an admin password secret else generate it 2021-02-08 19:29:55 +01:00
Yanis Guenane
90bfe5073b Merge pull request #89 from Spredzy/secret_key
Secret Key: Allow one to specify a secret key else generate it
2021-02-08 19:25:43 +01:00
Yanis Guenane
dfb96d1e18 Secret Key: Allow one to specify a secret key else generate it 2021-02-08 19:11:44 +01:00
Yanis Guenane
5cf9f72f60 Merge pull request #84 from Spredzy/database_configuration
PostgreSQL: Allow one to provide her own db configuration secret
2021-02-08 19:08:03 +01:00
Yanis Guenane
e5f1041350 PostgreSQL: Allow one to provide her own db configuration secret
If a user provide its own secret by using the
`tower_postgres_configuration_secret` use this variable, else try to use
`<instance>-postgres-configuration` secret. Else create one and use a
local database.
2021-02-08 15:13:56 +01:00
Yanis Guenane
f5ac42dfe2 Merge pull request #87 from Spredzy/fix_yamlliny
yamllint: Fix warning
2021-02-08 14:23:43 +01:00
Yanis Guenane
0149afcd9e yamllint: Fix warning 2021-02-08 14:05:16 +01:00
Yanis Guenane
5efd45570e Merge pull request #85 from Spredzy/fix_creds
tower_config: Remove credential from tower_config.yml
2021-02-08 09:48:58 +01:00
Yanis Guenane
357e8ad2c9 tower_config: Remove credential from tower_config.yml 2021-02-08 09:34:56 +01:00
Yanis Guenane
c5cd12e662 Merge pull request #86 from Spredzy/change_role_names
Rename base roles
2021-02-08 09:31:17 +01:00
Yanis Guenane
ad476e4782 Rename base roles 2021-02-05 22:23:23 +01:00
Yanis Guenane
3a2d3d889a Merge pull request #82 from Spredzy/normalize
deployment_type: Introduce the new variable
2021-02-05 21:32:10 +01:00
Yanis Guenane
285be0faff deployment_type: Introduce the new variable. 2021-02-05 21:19:16 +01:00
Yanis Guenane
38c57a61d0 Merge pull request #83 from Spredzy/database_configuration
PostgreSQL: Remove unused/wrongly used variable
2021-02-05 18:33:26 +01:00
Yanis Guenane
7837db6e53 Merge pull request #81 from Spredzy/change_default_admin_username
tower_admin_user: default to admin
2021-02-05 18:32:43 +01:00
Yanis Guenane
2daae08790 PostgreSQL: Remove unused/wrongly used variable 2021-02-05 16:11:28 +01:00
Yanis Guenane
c378e0da9f Merge pull request #79 from Spredzy/toc_readme
README: Add a ToC at the top of the README
2021-02-05 16:01:21 +01:00
Yanis Guenane
470870526b tower_admin_user: default to admin 2021-02-05 15:38:44 +01:00
Yanis Guenane
ae7aae4048 README: Add a ToC at the top of the README 2021-02-05 12:19:21 +01:00
Yanis Guenane
90023b8d75 Merge pull request #74 from Spredzy/trim_csv
Remove boiler plated ao-logs run from CSV file
2021-01-28 16:24:14 +01:00
Yanis Guenane
9189333611 Remove boiler plated ao-logs run from CSV file 2021-01-28 16:00:27 +01:00
Yanis Guenane
4e11d45386 Merge pull request #73 from Spredzy/bump_csv
Bump awx-operator tag in CSV
2021-01-26 21:32:03 +01:00
Yanis Guenane
9c53c4067e Bump awx-operator tag in CSV 2021-01-26 21:17:23 +01:00
76 changed files with 4791 additions and 1186 deletions

View File

@@ -1,3 +1,4 @@
---
skip_list:
- '306'
- '602'
@@ -5,3 +6,4 @@ skip_list:
exclude_paths:
- deploy/
- .cache/

44
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,44 @@
---
name: CI
on:
pull_request:
branches: [devel]
push:
branches: [devel]
jobs:
pull_request:
runs-on: ubuntu-18.04
name: pull_request
env:
DOCKER_API_VERSION: "1.38"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: "3.8"
- name: Install Dependencies
run: |
pip install \
molecule \
molecule-docker \
yamllint \
ansible-lint \
openshift \
jmespath \
ansible
- name: Install Collections
run: |
ansible-galaxy collection install community.kubernetes operator_sdk.util
- name: Run Molecule
env:
MOLECULE_VERBOSITY: 3
run: |
molecule test -s test-local

34
.github/workflows/devel.yaml vendored Normal file
View File

@@ -0,0 +1,34 @@
---
name: Devel
on:
push:
branches: [devel]
jobs:
release:
runs-on: ubuntu-18.04
name: Push devel image
steps:
- uses: actions/checkout@v2
- name: Install Operator-SDK
run: |
mkdir -p $GITHUB_WORKSPACE/bin
wget -O $GITHUB_WORKSPACE/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v0.19.4/operator-sdk-v0.19.4-x86_64-linux-gnu
chmod +x $GITHUB_WORKSPACE/bin/operator-sdk
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- name: Build Image
run: |
operator-sdk build awx-operator:devel
- name: Push To Quay
uses: redhat-actions/push-to-registry@v2.1.1
with:
image: awx-operator
tags: devel
registry: quay.io/ansible/
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_TOKEN }}

35
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Release
on:
release:
types:
- created
jobs:
release:
runs-on: ubuntu-18.04
name: Push tagged image to Quay
steps:
- uses: actions/checkout@v2
- name: Install Operator-SDK
run: |
mkdir -p $GITHUB_WORKSPACE/bin
wget -O $GITHUB_WORKSPACE/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v0.19.4/operator-sdk-v0.19.4-x86_64-linux-gnu
chmod +x $GITHUB_WORKSPACE/bin/operator-sdk
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- name: Build Image
run: |
operator-sdk build awx-operator:${{ github.event.release.tag_name }}
- name: Push To Quay
uses: redhat-actions/push-to-registry@v2.1.1
with:
image: awx-operator
tags: ${{ github.event.release.tag_name }}
registry: quay.io/ansible/
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_TOKEN }}

1
.gitignore vendored
View File

@@ -1 +1,2 @@
*~
.cache/

View File

@@ -1,19 +0,0 @@
---
services: docker
language: python
before_install:
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- sudo apt-get update
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
env:
- DOCKER_API_VERSION=1.38
install:
- pip3 install docker molecule molecule-docker yamllint ansible-lint openshift jmespath
- ansible-galaxy collection install community.kubernetes
script:
- molecule test -s test-local

View File

@@ -1,7 +1,12 @@
---
extends: default
ignore: |
.cache/
deploy/olm-catalog
rules:
truthy: disable
line-length:
max: 160
max: 170
level: warning

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

686
README.md
View File

@@ -1,127 +1,540 @@
# AWX Operator
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Build Status](https://github.com/ansible/awx-operator/workflows/CI/badge.svg?event=push)](https://github.com/ansible/awx-operator/actions)
An [Ansible AWX](https://github.com/ansible/awx) operator for Kubernetes built with [Operator SDK](https://github.com/operator-framework/operator-sdk) and Ansible.
# Table of Contents
<!--ts-->
* [AWX Operator](#awx-operator)
* [Table of Contents](#table-of-contents)
* [Purpose](#purpose)
* [Usage](#usage)
* [Basic Install](#basic-install)
* [Admin user account configuration](#admin-user-account-configuration)
* [Network and TLS Configuration](#network-and-tls-configuration)
* [Ingress Type](#ingress-type)
* [TLS Termination](#tls-termination)
* [Database Configuration](#database-configuration)
* [External PostgreSQL Service](#external-postgresql-service)
* [Migrating data from an old AWX instance](#migrating-data-from-an-old-awx-instance)
* [Managed PostgreSQL Service](#managed-postgresql-service)
* [Advanced Configuration](#advanced-configuration)
* [Deploying a specific version of AWX](#deploying-a-specific-version-of-awx)
* [Privileged Tasks](#privileged-tasks)
* [Containers Resource Requirements](#containers-resource-requirements)
* [LDAP Certificate Authority](#ldap-certificate-authority)
* [Persisting Projects Directory](#persisting-projects-directory)
* [Custom Volume and Volume Mount Options](#custom-volume-and-volume-mount-options)
* [Exporting Environment Variables to Containers](#exporting-environment-variables-to-containers)
* [Development](#development)
* [Testing](#testing)
* [Testing in Docker](#testing-in-docker)
* [Testing in Minikube](#testing-in-minikube)
* [Generating a bundle](#generating-a-bundle)
* [Release Process](#release-process)
* [Build a new release](#build-a-new-release)
* [Build a new version of the operator yaml file](#build-a-new-version-of-the-operator-yaml-file)
* [Author](#author)
<!--te-->
## Purpose
This operator is meant to provide a more Kubernetes-native installation method for AWX via an AWX Custom Resource Definition (CRD).
Note that the operator is not supported by Red Hat, and is in alpha status. For now, use it at your own risk!
Note that the operator is not supported by Red Hat, and is in **alpha** status. For now, use it at your own risk!
## Usage
### Basic Install
This Kubernetes Operator is meant to be deployed in your Kubernetes cluster(s) and can manage one or more AWX instances in any namespace.
First you need to deploy AWX Operator into your cluster:
First, you need to deploy AWX Operator into your cluster. Start by going to https://github.com/ansible/awx-operator/releases and making note of the latest release.
kubectl apply -f https://raw.githubusercontent.com/ansible/awx-operator/devel/deploy/awx-operator.yaml
Replace `<tag>` in the URL below with the version you are deploying:
Then you can create instances of AWX, for example:
```bash
#> kubectl apply -f https://raw.githubusercontent.com/ansible/awx-operator/<tag>/deploy/awx-operator.yaml
```
1. Make sure the namespace you're deploying into already exists (e.g. `kubectl create namespace ansible-awx`).
2. Create a file named `my-awx.yml` with the following contents:
```
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
namespace: ansible-awx
spec:
tower_admin_user: test
tower_admin_email: test@example.com
tower_admin_password: changeme
tower_broadcast_websocket_secret: changeme
```
3. Use `kubectl` to create the awx instance in your cluster:
```
kubectl apply -f my-awx.yml
```
After a few minutes, your new AWX instance will be accessible at `http://awx.mycompany.com/` (assuming your cluster has an Ingress controller configured). Log in using the `tower_admin_` credentials configured in the `spec`.
### Deploying a specific version of AWX
To achieve this, please add the following variable under spec within your CR (Custom Resource) file:
Then create a file named `my-awx.yml` with the following contents:
```yaml
tower_image: ansible/awx:15.0.0 # replace this with desired image
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
```
You may also override any default variables from `roles/awx/defaults/main.yml` using the same process, i.e. by adding those variables within your CR spec.
### Ingress Types
> The metadata.name you provide, will be the name of the resulting AWX deployment. If you deploy more than one to the same namespace, be sure to use unique names.
Depending on the cluster that you're running on, you may wish to use an `Ingress` to access AWX, or you may wish to use a `Route` to access your AWX. To toggle between these two options, you can add the following to your AWX CR:
Finally, use `kubectl` to create the awx instance in your cluster:
---
spec:
...
tower_ingress_type: Route
```bash
#> kubectl apply -f my-awx.yml
```
OR
After a few minutes, the new AWX instance will be deployed. One can look at the operator pod logs in order to know where the installation process is at. This can be done by running the following command: `kubectl logs -f deployments/awx-operator`.
---
spec:
...
tower_ingress_type: Ingress
tower_hostname: awx.mycompany.com
Once deployed, the AWX instance will be accessible at `http://awx.mycompany.com/` (assuming your cluster has an Ingress controller configured).
By default, no ingress/route is deployed as the default is set to `none`.
By default, the admin user is `admin` and the password is available in the `<resourcename>-admin-password` secret. To retrieve the admin password, run `kubectl get secret <resourcename>-admin-password -o jsonpath="{.data.password}" | base64 --decode`
### Privileged Tasks
You just completed the most basic install of an AWX instance via this operator. Congratulations !
### Admin user account configuration
There are three variables that are customizable for the admin user account creation.
| Name | Description | Default |
| --------------------------- | -------------------------------------------- | ---------------- |
| tower_admin_user | Name of the admin user | admin |
| tower_admin_email | Email of the admin user | test@example.com |
| tower_admin_password_secret | Secret that contains the admin user password | Empty string |
> :warning: **tower_admin_password_secret must be a Kubernetes secret and not your text clear password**.
If `tower_admin_password_secret` is not provided, the operator will look for a secret named `<resourcename>-admin-password` for the admin password. If it is not present, the operator will generate a password and create a Secret from it named `<resourcename>-admin-password`.
To retrieve the admin password, run `kubectl get secret <resourcename>-admin-password -o jsonpath="{.data.password}" | base64 --decode`
The secret that is expected to be passed should be formatted as follow:
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: <resourcename>-admin-password
namespace: <target namespace>
stringData:
password: mysuperlongpassword
```
### Network and TLS Configuration
#### Ingress Type
By default, the AWX operator is not opinionated and won't force a specific ingress type on you. So, if `tower_ingress_type` is not specified as part of the Custom Resource specification, it will default to `none` and nothing ingress-wise will be created.
The AWX operator provides support for four kinds of `Ingress` to access AWX: `Ingress`, `Route`, `LoadBalancer` and `NodePort`, To toggle between these options, you can add the following to your AWX CR:
* Route
```yaml
---
spec:
...
tower_ingress_type: Route
```
* Ingress
```yaml
---
spec:
...
tower_ingress_type: Ingress
tower_hostname: awx.mycompany.com
```
* LoadBalancer
```yaml
---
spec:
...
tower_ingress_type: LoadBalancer
tower_loadbalancer_protocol: http
```
* NodePort
```yaml
---
spec:
...
tower_ingress_type: NodePort
```
The AWX `Service` that gets created will have a `type` set based on the `tower_ingress_type` being used:
| Ingress Type `tower_ingress_type` | Service Type |
| ------------------------------------- | -------------- |
| `LoadBalancer` | `LoadBalancer` |
| `NodePort` | `NodePort` |
| `Ingress` or `Route` or not specified | `ClusterIP` |
#### TLS Termination
* Route
The following variables are customizable to specify the TLS termination procedure when `Route` is picked as an Ingress
| Name | Description | Default |
| ------------------------------------- | --------------------------------------------- | --------------------------------- |
| tower_route_host | Common name the route answers for | Empty string |
| tower_route_tls_termination_mechanism | TLS Termination mechanism (Edge, Passthrough) | Edge |
| tower_route_tls_secret | Secret that contains the TLS information | Empty string |
* Ingress
The following variables are customizable to specify the TLS termination procedure when `Ingress` is picked as an Ingress
| Name | Description | Default |
| -------------------------- | ---------------------------------------- | ------------- |
| tower_ingress_annotations | Ingress annotations | Empty string |
| tower_ingress_tls_secret | Secret that contains the TLS information | Empty string |
* LoadBalancer
The following variables are customizable to specify the TLS termination procedure when `LoadBalancer` is picked as an Ingress
| Name | Description | Default |
| ------------------------------ | ---------------------------------------- | ------------- |
| tower_loadbalancer_annotations | LoadBalancer annotations | Empty string |
| tower_loadbalancer_protocol | Protocol to use for Loadbalancer ingress | http |
| tower_loadbalancer_port | Port used for Loadbalancer ingress | 80 |
When setting up a Load Balancer for HTTPS you will be required to set the `tower_loadbalancer_port` to move the port away from `80`.
The HTTPS Load Balancer also uses SSL termination at the Load Balancer level and will offload traffic to AWX over HTTP.
### Database Configuration
#### External PostgreSQL Service
In order for the AWX instance to rely on an external database, the Custom Resource needs to know about the connection details. Those connection details should be stored as a secret and either specified as `tower_postgres_configuration_secret` at the CR spec level, or simply be present on the namespace under the name `<resourcename>-postgres-configuration`.
The secret should be formatted as follows:
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: <resourcename>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
sslmode: prefer
type: Opaque
```
**Note**: The variable `sslmode` is valid for `external` databases only. The allowed values are: `prefer`, `disable`, `allow`, `require`, `verify-ca`, `verify-full`.
#### Migrating data from an old AWX instance
For instructions on how to migrate from an older version of AWX, see [migration.md](./docs/migration.md).
#### Managed PostgreSQL Service
If you don't have access to an external PostgreSQL service, the AWX operator can deploy one for you along side the AWX instance itself.
The following variables are customizable for the managed PostgreSQL service
| Name | Description | Default |
| ------------------------------------ | ------------------------------------------ | --------------------------------- |
| tower_postgres_image | Path of the image to pull | postgres:12 |
| tower_postgres_resource_requirements | PostgreSQL container resource requirements | Empty object |
| tower_postgres_storage_requirements | PostgreSQL container storage requirements | requests: {storage: 8Gi} |
| tower_postgres_storage_class | PostgreSQL PV storage class | Empty string |
| tower_postgres_data_path | PostgreSQL data path | `/var/lib/postgresql/data/pgdata` |
Example of customization could be:
```yaml
---
spec:
...
tower_postgres_resource_requirements:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 1
memory: 4Gi
tower_postgres_storage_requirements:
requests:
storage: 8Gi
limits:
storage: 50Gi
tower_postgres_storage_class: fast-ssd
```
**Note**: If `tower_postgres_storage_class` is not defined, Postgres will store it's data on a volume using the default storage class for your cluster.
### Advanced Configuration
#### Deploying a specific version of AWX
There are a few variables that are customizable for awx the image management.
| Name | Description |
| --------------------------| -------------------------- |
| tower_image | Path of the image to pull |
| tower_image_version | Image version to pull |
| tower_image_pull_policy | The pull policy to adopt |
| tower_image_pull_secret | The pull secret to use |
| tower_ee_images | A list of EEs to register |
| tower_redis_image | Path of the image to pull |
| tower_redis_image_version | Image version to pull |
Example of customization could be:
```yaml
---
spec:
...
tower_image: myorg/my-custom-awx
tower_image_version: latest
tower_image_pull_policy: Always
tower_image_pull_secret: pull_secret_name
tower_ee_images:
- name: my-custom-awx-ee
image: myorg/my-custom-awx-ee
```
**Note**: The `tower_image` and `tower_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.
#### Privileged Tasks
Depending on the type of tasks that you'll be running, you may find that you need the task pod to run as `privileged`. This can open yourself up to a variety of security concerns, so you should be aware (and verify that you have the privileges) to do this if necessary. In order to toggle this feature, you can add the following to your custom resource:
---
spec:
...
tower_task_privileged: true
```yaml
---
spec:
...
tower_task_privileged: true
```
If you are attempting to do this on an OpenShift cluster, you will need to grant the `awx` ServiceAccount the `privileged` SCC, which can be done with:
oc adm policy add-scc-to-user privileged -z awx
```sh
#> oc adm policy add-scc-to-user privileged -z awx
```
Again, this is the most relaxed SCC that is provided by OpenShift, so be sure to familiarize yourself with the security concerns that accompany this action.
### Connecting to an external Postgres Service
When the Operator installs the AWX services and generates a Postgres deployment it will lay down a config file to enable AWX to connect to that service. To use an external database you just need to create a `Secret` that the AWX deployment will use instead and then set a property in the CR:
#### Containers Resource Requirements
---
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 |
| -------------------------------- | ------------------------------------ | ----------------------------------- |
| tower_web_resource_requirements | Web container resource requirements | requests: {cpu: 1000m, memory: 2Gi} |
| tower_task_resource_requirements | Task container resource requirements | requests: {cpu: 500m, memory: 1Gi} |
Example of customization could be:
```yaml
---
spec:
...
tower_web_resource_requirements:
requests:
cpu: 1000m
memory: 2Gi
limits:
cpu: 2000m
memory: 4Gi
tower_task_resource_requirements:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 1000m
memory: 2Gi
```
#### Assigning AWX pods to specific nodes
You can constrain the AWX pods created by the operator to run on a certain subset of nodes. `tower_node_selector` and `tower_postgres_selector` constrains
the AWX pods to run only on the nodes that match all the specified key/value pairs. `tower_tolerations` and `tower_postgres_tolerations` allow the AWX
pods to be scheduled onto nodes with matching taints.
| Name | Description | Default |
| -------------------------------| --------------------------- | ------- |
| tower_postgres_image | Path of the image to pull | 12 |
| tower_postgres_image_version | Image version to pull | 12 |
| tower_node_selector | AWX pods' nodeSelector | '' |
| tower_tolerations | AWX pods' tolerations | '' |
| tower_postgres_selector | Postgres pods' nodeSelector | '' |
| tower_postgres_tolerations | Postgres pods' tolerations | '' |
Example of customization could be:
```yaml
---
spec:
...
tower_node_selector: |
disktype: ssd
kubernetes.io/arch: amd64
kubernetes.io/os: linux
tower_tolerations: |
- key: "dedicated"
operator: "Equal"
value: "AWX"
effect: "NoSchedule"
tower_postgres_selector: |
disktype: ssd
kubernetes.io/arch: amd64
kubernetes.io/os: linux
tower_postgres_tolerations: |
- key: "dedicated"
operator: "Equal"
value: "AWX"
effect: "NoSchedule"
```
#### LDAP Certificate Authority
If the variable `ldap_cacert_secret` is provided, the operator will look for a the data field `ldap-ca.crt` in the specified secret.
| Name | Description | Default |
| -------------------------------- | --------------------------------------- | --------|
| ldap_cacert_secret | LDAP Certificate Authority secret name | '' |
Example of customization could be:
```yaml
---
spec:
...
ldap_cacert_secret: <resourcename>-ldap-ca-cert
```
To create the secret, you can use the command below:
```sh
# kubectl create secret generic <resourcename>-ldap-ca-cert --from-file=ldap-ca.crt=<PATH/TO/YOUR/CA/PEM/FILE>
```
#### Persisting Projects Directory
In cases which you want to persist the `/var/lib/projects` directory, there are few variables that are customizable for the `awx-operator`.
| Name | Description | Default |
| -----------------------------------| ---------------------------------------------------------------------------------------------------- | ---------------|
| tower_projects_persistence | Whether or not the /var/lib/projects directory will be persistent | false |
| tower_projects_storage_class | Define the PersistentVolume storage class | '' |
| tower_projects_storage_size | Define the PersistentVolume size | 8Gi |
| tower_projects_storage_access_mode | Define the PersistentVolume access mode | ReadWriteMany |
| tower_projects_existing_claim | Define an existing PersistentVolumeClaim to use (cannot be combined with `tower_projects_storage_*`) | '' |
Example of customization when the `awx-operator` automatically handles the persistent volume could be:
```yaml
---
spec:
...
tower_projects_persistence: true
tower_projects_storage_class: rook-ceph
tower_projects_storage_size: 20Gi
```
#### Custom Volume and Volume Mount Options
In a scenario where custom volumes and volume mounts are required to either overwrite defaults or mount configuration files.
| Name | Description | Default |
| ------------------------------ | -------------------------------------------------------- | ------- |
| tower_extra_volumes | Specify extra volumes to add to the application pod | '' |
| tower_web_extra_volume_mounts | Specify volume mounts to be added to Web container | '' |
| tower_task_extra_volume_mounts | Specify volume mounts to be added to Task container | '' |
| tower_ee_extra_volume_mounts | Specify volume mounts to be added to Execution container | '' |
Example configuration for ConfigMap
```yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: <resourcename>-extra-config
namespace: <target namespace>
data:
ansible.cfg: |
[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
```
Example spec file for volumes and volume mounts
```yaml
---
spec:
...
external_database: true
...
tower_ee_extra_volume_mounts: |
- name: ansible-cfg
mountPath: /etc/ansible/ansible.cfg
subPath: ansible.cfg
The secret should have the name: *crname*-postgres-configuration and
should look like:
tower_task_extra_volume_mounts: |
- name: custom-py
mountPath: /etc/tower/conf.d/custom.py
subPath: custom.py
apiVersion: v1
kind: Secret
metadata:
name: <crname>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque
tower_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
### Persistent storage for Postgres
```
If you need to use a specific storage class for Postgres' storage, specify `tower_postgres_storage_class` in your AWX spec:
> :warning: **Volume and VolumeMount names cannot contain underscores(_)**
---
spec:
...
tower_postgres_storage_class: fast-ssd
#### Exporting Environment Variables to Containers
If you need to export custom environment variables to your containers.
| Name | Description | Default |
| ----------------------------- | -------------------------------------------------------- | ------- |
| tower_task_extra_env | Environment variables to be added to Task container | '' |
| tower_web_extra_env | Environment variables to be added to Web container | '' |
Example configuration of environment variables
```yaml
spec:
tower_task_extra_env: |
- name: MYCUSTOMVAR
value: foo
tower_web_extra_env: |
- name: MYCUSTOMVAR
value: foo
```
If it's not specified, Postgres will store it's data on a volume using the default storage class for your cluster.
## Development
@@ -131,23 +544,29 @@ This Operator includes a [Molecule](https://molecule.readthedocs.io/en/stable/)-
You need to make sure you have Molecule installed before running the following commands. You can install Molecule with:
pip install 'molecule[docker]'
```sh
#> pip install 'molecule[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).
If you want to actively develop the operator, use `molecule converge`, which does everything but tear down the environment at the end.
#### Testing in Docker (standalone)
#### Testing in Docker
molecule test -s test-local
```sh
#> molecule test -s test-local
```
This environment is meant for headless testing (e.g. in a CI environment, or when making smaller changes which don't need to be verified through a web interface). It is difficult to test things like AWX's web UI or to connect other applications on your local machine to the services running inside the cluster, since it is inside a Docker container with no static IP address.
#### Testing in Minikube
minikube start --memory 8g --cpus 4
minikube addons enable ingress
molecule test -s test-minikube
```sh
#> minikube start --memory 8g --cpus 4
#> minikube addons enable ingress
#> molecule test -s test-minikube
```
[Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/) is a more full-featured test environment running inside a full VM on your computer, with an assigned IP address. This makes it easier to test things like NodePort services and Ingress from outside the Kubernetes cluster (e.g. in a browser on your computer).
@@ -157,11 +576,61 @@ Once the operator is deployed, you can visit the AWX UI in your browser by follo
2. Visit `http://example-awx.test/` in your browser. (Default admin login is `test`/`changeme`.)
Alternatively, you can also update the service `awx-service` in your namespace to use the type `NodePort` and use following command to get the URL to access your AWX instance:
```sh
minikube service <serviceName> -n <namespaceName> --url
#> minikube service <serviceName> -n <namespaceName> --url
```
### Release Process
### Generating a bundle
> :warning: operator-sdk version 0.19.4 is needed to run the following commands
If one has the Operator Lifecycle Manager (OLM) installed, the following steps is the process to generate the bundle that would nicely display in the OLM interface.
At the root of this directory:
1. Build and publish the operator
```
#> operator-sdk build registry.example.com/ansible/awx-operator:mytag
#> podman push registry.example.com/ansible/awx-operator:mytag
```
2. Build and publish the bundle
```
#> podman build . -f bundle.Dockerfile -t registry.example.com/ansible/awx-operator-bundle:mytag
#> podman push registry.example.com/ansible/awx-operator-bundle:mytag
```
3. Build and publish an index with your bundle in it
```
#> opm index add --bundles registry.example.com/ansible/awx-operator-bundle:mytag --tag registry.example.com/ansible/awx-operator-catalog:mytag
#> podman push registry.example.com/ansible/awx-operator-catalog:mytag
```
4. In your Kubernetes create a new CatalogSource pointing to `registry.example.com/ansible/awx-operator-catalog:mytag`
```
---
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: <catalogsource-name>
namespace: <namespace>
spec:
displayName: 'myoperatorhub'
image: registry.example.com/ansible/awx-operator-catalog:mytag
publisher: 'myoperatorhub'
sourceType: grpc
```
Applying this template will do it. Once the CatalogSource is in a READY state, the bundle should be available on the OperatorHub tab (as part of the custom CatalogSource that just got added)
5. Enjoy
## Release Process
There are a few moving parts to this project:
@@ -170,17 +639,34 @@ There are a few moving parts to this project:
Each of these must be appropriately built in preparation for a new tag:
#### Build a new release of the Operator for Docker Hub
### Verify Functionality
Run the following command inside this directory:
operator-sdk build quay.io/ansible/awx-operator:$VERSION
```sh
#> operator-sdk build quay.io/<user>/awx-operator:test
```
Then push the generated image to Docker Hub:
docker push quay.io/ansible/awx-operator:$VERSION
```sh
#> docker push quay.io/<user>/awx-operator:test
```
#### Build a new version of the `awx-operator.yaml` file
After it is built, test it on a local cluster:
```sh
#> minikube start --memory 6g --cpus 4
#> minikube addons enable ingress
#> ansible-playbook ansible/deploy-operator.yml -e operator_image=quay.io/<user>/awx-operator -e operator_version=test
#> kubectl create namespace example-awx
#> ansible-playbook ansible/instantiate-awx-deployment.yml -e tower_namespace=example-awx
#> <test everything>
#> minikube delete
```
### Update version
Update the awx-operator version:
@@ -188,19 +674,15 @@ Update the awx-operator version:
Once the version has been updated, run from the root of the repo:
ansible-playbook ansible/chain-operator-files.yml
```sh
#> ansible-playbook ansible/chain-operator-files.yml
```
After it is built, test it on a local cluster:
### Commit / Create Release
minikube start --memory 6g --cpus 4
minikube addons enable ingress
kubectl apply -f deploy/awx-operator.yaml
kubectl create namespace example-awx
kubectl apply -f deploy/crds/awx_v1beta1_cr.yaml
<test everything>
minikube delete
If everything works, commit the updated version, then [publish a new release](https://github.com/ansible/awx-operator/releases/new) using the same version you used in `ansible/group_vars/all`.
If everything works, commit the updated version, then tag a new repository release with the same tag as the Docker image pushed earlier.
After creating the release, [this GitHub Workflow](https://github.com/ansible/awx-operator/blob/devel/.github/workflows/release.yaml) will run and publish the new image to quay.io.
## Author

View File

@@ -10,8 +10,10 @@
template:
src: crd.yml.j2
dest: "{{ playbook_dir }}/../deploy/crds/awx_v1beta1_crd.yaml"
mode: '0644'
- name: Template awx-operator.yaml
template:
src: awx-operator.yaml.j2
dest: ../deploy/awx-operator.yaml
mode: '0644'

View File

@@ -1,3 +1,3 @@
operator_image: quay.io/ansible/awx-operator
operator_version: 0.6.0
operator_version: 0.9.0
pull_policy: Always

View File

@@ -9,7 +9,7 @@
- name: Deploy AWX
k8s:
state: "{{ state | default('present') }}"
namespace: default
namespace: "{{ tower_namespace | default('default') }}"
apply: yes
wait: yes
definition:
@@ -18,11 +18,13 @@
metadata:
name: awx
spec:
tower_admin_user: test
tower_admin_email: test@example.com
tower_admin_password: changeme
tower_broadcast_websocket_secret: changeme
tower_ingress_type: "{{ tower_ingress_type | default(omit) }}" # Either Route or Ingress
tower_admin_user: admin
tower_admin_email: admin@localhost
tower_ingress_type: "{{ tower_ingress_type | default(omit) }}" # Either Route, Ingress or LoadBalancer
tower_image: "{{ tower_image | default(omit) }}"
development_mode: "{{ development_mode | default(omit) }}"
tower_image_version: "{{ tower_image_version | default(omit) }}"
development_mode: "{{ development_mode | default(omit) | bool }}"
tower_image_pull_policy: "{{ tower_image_pull_policy | default(omit) }}"
# tower_ee_images:
# - name: test-ee
# image: quay.io/<user>/awx-ee

View File

@@ -1,6 +1,8 @@
#jinja2: trim_blocks:False
# This file is generated by Ansible. Changes will be lost.
# Update templates under ansible/templates/
{% include 'crd.yml.j2' %}
{% include 'role.yml.j2' %}
{% include 'role_binding.yml.j2' %}
@@ -8,5 +10,3 @@
{% include 'service_account.yml.j2' %}
{% include 'operator.yml.j2' %}
{% include 'crd.yml.j2' %}

View File

@@ -1,5 +1,5 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: awxs.awx.ansible.com
@@ -11,40 +11,365 @@ spec:
plural: awxs
singular: awx
scope: Namespaced
subresources:
status: {}
version: v1beta1
versions:
- name: v1beta1
served: true
storage: true
validation:
openAPIV3Schema:
description: Schema validation for the AWX CRD
type: object
properties:
spec:
type: object
subresources:
status: {}
schema:
openAPIV3Schema:
description: Schema validation for the AWX CRD
properties:
external_database:
type: boolean
description: |
If true you must supply a secret containing the location and credentials for
connecting to the external database by a user who has permission to create
and apply a schema.
The secret should have the name: <custom resource name>-postgres-configuration and
should look like:
apiVersion: v1
kind: Secret
metadata:
name: <crname>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque
spec:
properties:
deployment_type:
description: Name of the deployment type
type: string
default: awx
kind:
description: Kind of the deployment type
type: string
default: AWX
api_version:
description: apiVersion of the deployment type
type: string
default: awx.ansible.com/v1beta1
tower_task_privileged:
description: If a privileged security context should be enabled
type: boolean
default: false
tower_admin_user:
description: Username to use for the admin account
type: string
default: admin
tower_hostname:
description: The hostname of the instance
type: string
tower_admin_email:
description: The admin user email
type: string
tower_admin_password_secret:
description: Secret where the admin password can be found
type: string
tower_postgres_configuration_secret:
description: Secret where the database configuration can be found
type: string
tower_old_postgres_configuration_secret:
description: Secret where the old database configuration can be found for data migration
type: string
tower_secret_key_secret:
description: Secret where the secret key can be found
type: string
tower_broadcast_websocket_secret:
description: Secret where the broadcast websocket secret can be found
type: string
tower_extra_volumes:
description: Specify extra volumes to add to the application pod
type: string
tower_ingress_type:
description: The ingress type to use to reach the deployed instance
type: string
enum:
- none
- Ingress
- ingress
- Route
- route
- LoadBalancer
- loadbalancer
- NodePort
- nodeport
tower_ingress_annotations:
description: Annotations to add to the ingress
type: string
tower_ingress_tls_secret:
description: Secret where the ingress TLS secret can be found
type: string
tower_loadbalancer_annotations:
description: Annotations to add to the loadbalancer
type: string
tower_loadbalancer_protocol:
description: Protocol to use for the loadbalancer
type: string
default: http
enum:
- http
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
type: string
tower_route_tls_termination_mechanism:
description: The secure TLS termination mechanism to use
type: string
default: Edge
enum:
- Edge
- edge
- Passthrough
- passthrough
tower_route_tls_secret:
description: Secret where the TLS related credentials are stored
type: string
tower_node_selector:
description: nodeSelector for the AWX pods
type: string
tower_tolerations:
description: node tolerations for the AWX pods
type: string
tower_image:
description: Registry path to the application container to use
type: string
tower_image_version:
description: Application container image version to use
type: string
tower_ee_images:
description: Registry path to the Execution Environment container to use
type: array
items:
type: object
properties:
name:
type: string
image:
type: string
tower_image_pull_policy:
description: The image pull policy
type: string
default: IfNotPresent
enum:
- Always
- always
- Never
- never
- IfNotPresent
- ifnotpresent
tower_image_pull_secret:
description: The image pull secret
type: string
tower_task_resource_requirements:
description: Resource requirements for the task container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_web_resource_requirements:
description: Resource requirements for the web container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_replicas:
description: Number of instance replicas
type: integer
default: 1
format: int32
tower_garbage_collect_secrets:
description: Whether or not to remove secrets upon instance removal
default: false
type: boolean
tower_create_preload_data:
description: Whether or not to preload data upon Tower instance creation
default: true
type: boolean
tower_task_args:
type: array
items:
type: string
tower_task_command:
type: array
items:
type: string
tower_web_args:
type: array
items:
type: string
tower_web_command:
type: array
items:
type: string
tower_task_extra_env:
type: string
tower_web_extra_env:
type: string
tower_ee_extra_volume_mounts:
description: Specify volume mounts to be added to Execution container
type: string
tower_task_extra_volume_mounts:
description: Specify volume mounts to be added to Task container
type: string
tower_web_extra_volume_mounts:
description: Specify volume mounts to be added to the Web container
type: string
tower_redis_image:
description: Registry path to the redis container to use
type: string
tower_redis_image_version:
description: Redis container image version to use
type: string
tower_postgres_image:
description: Registry path to the PostgreSQL container to use
type: string
tower_postgres_image_version:
description: PostgreSQL container image version to use
type: string
tower_postgres_selector:
description: nodeSelector for the Postgres pods
type: string
tower_postgres_tolerations:
description: node tolerations for the Postgres pods
type: string
tower_postgres_storage_requirements:
description: Storage requirements for the PostgreSQL container
properties:
requests:
properties:
storage:
type: string
type: object
limits:
properties:
storage:
type: string
type: object
type: object
tower_postgres_resource_requirements:
description: Resource requirements for the PostgreSQL container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
type: object
type: object
tower_postgres_storage_class:
description: Storage class to use for the PostgreSQL PVC
type: string
tower_postgres_data_path:
description: Path where the PostgreSQL data are located
type: string
ca_trust_bundle:
description: Path where the trusted CA bundle is available
type: string
development_mode:
description: If the deployment should be done in development mode
type: boolean
ldap_cacert_secret:
description: Secret where can be found the LDAP trusted Certificate Authority Bundle
type: string
tower_projects_persistence:
description: Whether or not the /var/lib/projects directory will be persistent
default: false
type: boolean
tower_projects_use_existing_claim:
description: Using existing PersistentVolumeClaim
type: string
enum:
- _Yes_
- _No_
tower_projects_existing_claim:
description: PersistentVolumeClaim to mount /var/lib/projects directory
type: string
tower_projects_storage_class:
description: Storage class for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_storage_size:
description: Size for the /var/lib/projects PersistentVolumeClaim
default: 8Gi
type: string
tower_projects_storage_access_mode:
description: AccessMode for the /var/lib/projects PersistentVolumeClaim
default: ReadWriteMany
type: string
extra_settings:
description: Extra settings to specify for the API
items:
properties:
setting:
type: string
value:
type: string
type: object
type: array
type: object
status:
properties:
towerURL:
description: URL to access the deployed instance
type: string
towerAdminUser:
description: Admin user of the deployed instance
type: string
towerAdminPasswordSecret:
description: Admin password of the deployed instance
type: string
towerMigratedFromSecret:
description: The secret used for migrating an old Tower.
type: string
towerVersion:
description: Version of the deployed instance
type: string
towerImage:
description: URL of the image used for the deployed instance
type: string
conditions:
description: The resulting conditions when a Service Telemetry is instantiated
items:
properties:
status:
type: string
type:
type: string
reason:
type: string
lastTransitionTime:
type: string
type: object
type: array
type: object
type: object

View File

@@ -37,8 +37,8 @@ spec:
httpGet:
path: /healthz
port: 6789
initialDelaySeconds: 5
periodSeconds: 3
initialDelaySeconds: 15
periodSeconds: 20
volumes:
- name: runner
emptyDir: {}

View File

@@ -9,19 +9,24 @@ rules:
- route.openshift.io
resources:
- routes
- routes/custom-host
verbs:
- '*'
- apiGroups:
- ""
- "rbac.authorization.k8s.io"
resources:
- pods
- services
- services/finalizers
- serviceaccounts
- endpoints
- persistentvolumeclaims
- events
- configmaps
- secrets
- roles
- rolebindings
verbs:
- '*'
- apiGroups:
@@ -50,6 +55,13 @@ rules:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments/scale
- statefulsets/scale
verbs:
- patch
- apiGroups:
- ""
resources:

14
bundle.Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM scratch
LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1
LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/
LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/
LABEL operators.operatorframework.io.bundle.package.v1=awx-operator
LABEL operators.operatorframework.io.bundle.channels.v1=alpha
LABEL operators.operatorframework.io.bundle.channel.default.v1=alpha
LABEL operators.operatorframework.io.metrics.project_layout=ansible
LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1
LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v0.19.4
COPY deploy/olm-catalog/awx-operator/manifests /manifests/
COPY deploy/olm-catalog/awx-operator/metadata /metadata/

View File

@@ -1,5 +1,381 @@
# This file is generated by Ansible. Changes will be lost.
# Update templates under ansible/templates/
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: awxs.awx.ansible.com
spec:
group: awx.ansible.com
names:
kind: AWX
listKind: AWXList
plural: awxs
singular: awx
scope: Namespaced
versions:
- name: v1beta1
served: true
storage: true
subresources:
status: {}
schema:
openAPIV3Schema:
description: Schema validation for the AWX CRD
properties:
spec:
properties:
deployment_type:
description: Name of the deployment type
type: string
default: awx
kind:
description: Kind of the deployment type
type: string
default: AWX
api_version:
description: apiVersion of the deployment type
type: string
default: awx.ansible.com/v1beta1
tower_task_privileged:
description: If a privileged security context should be enabled
type: boolean
default: false
tower_admin_user:
description: Username to use for the admin account
type: string
default: admin
tower_hostname:
description: The hostname of the instance
type: string
tower_admin_email:
description: The admin user email
type: string
tower_admin_password_secret:
description: Secret where the admin password can be found
type: string
tower_postgres_configuration_secret:
description: Secret where the database configuration can be found
type: string
tower_old_postgres_configuration_secret:
description: Secret where the old database configuration can be found for data migration
type: string
tower_secret_key_secret:
description: Secret where the secret key can be found
type: string
tower_broadcast_websocket_secret:
description: Secret where the broadcast websocket secret can be found
type: string
tower_extra_volumes:
description: Specify extra volumes to add to the application pod
type: string
tower_ingress_type:
description: The ingress type to use to reach the deployed instance
type: string
enum:
- none
- Ingress
- ingress
- Route
- route
- LoadBalancer
- loadbalancer
- NodePort
- nodeport
tower_ingress_annotations:
description: Annotations to add to the ingress
type: string
tower_ingress_tls_secret:
description: Secret where the ingress TLS secret can be found
type: string
tower_loadbalancer_annotations:
description: Annotations to add to the loadbalancer
type: string
tower_loadbalancer_protocol:
description: Protocol to use for the loadbalancer
type: string
default: http
enum:
- http
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
type: string
tower_route_tls_termination_mechanism:
description: The secure TLS termination mechanism to use
type: string
default: Edge
enum:
- Edge
- edge
- Passthrough
- passthrough
tower_route_tls_secret:
description: Secret where the TLS related credentials are stored
type: string
tower_node_selector:
description: nodeSelector for the AWX pods
type: string
tower_tolerations:
description: node tolerations for the AWX pods
type: string
tower_image:
description: Registry path to the application container to use
type: string
tower_image_version:
description: Application container image version to use
type: string
tower_ee_images:
description: Registry path to the Execution Environment container to use
type: array
items:
type: object
properties:
name:
type: string
image:
type: string
tower_image_pull_policy:
description: The image pull policy
type: string
default: IfNotPresent
enum:
- Always
- always
- Never
- never
- IfNotPresent
- ifnotpresent
tower_image_pull_secret:
description: The image pull secret
type: string
tower_task_resource_requirements:
description: Resource requirements for the task container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_web_resource_requirements:
description: Resource requirements for the web container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_replicas:
description: Number of instance replicas
type: integer
default: 1
format: int32
tower_garbage_collect_secrets:
description: Whether or not to remove secrets upon instance removal
default: false
type: boolean
tower_create_preload_data:
description: Whether or not to preload data upon Tower instance creation
default: true
type: boolean
tower_task_args:
type: array
items:
type: string
tower_task_command:
type: array
items:
type: string
tower_web_args:
type: array
items:
type: string
tower_web_command:
type: array
items:
type: string
tower_task_extra_env:
type: string
tower_web_extra_env:
type: string
tower_ee_extra_volume_mounts:
description: Specify volume mounts to be added to Execution container
type: string
tower_task_extra_volume_mounts:
description: Specify volume mounts to be added to Task container
type: string
tower_web_extra_volume_mounts:
description: Specify volume mounts to be added to the Web container
type: string
tower_redis_image:
description: Registry path to the redis container to use
type: string
tower_redis_image_version:
description: Redis container image version to use
type: string
tower_postgres_image:
description: Registry path to the PostgreSQL container to use
type: string
tower_postgres_image_version:
description: PostgreSQL container image version to use
type: string
tower_postgres_selector:
description: nodeSelector for the Postgres pods
type: string
tower_postgres_tolerations:
description: node tolerations for the Postgres pods
type: string
tower_postgres_storage_requirements:
description: Storage requirements for the PostgreSQL container
properties:
requests:
properties:
storage:
type: string
type: object
limits:
properties:
storage:
type: string
type: object
type: object
tower_postgres_resource_requirements:
description: Resource requirements for the PostgreSQL container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
type: object
type: object
tower_postgres_storage_class:
description: Storage class to use for the PostgreSQL PVC
type: string
tower_postgres_data_path:
description: Path where the PostgreSQL data are located
type: string
ca_trust_bundle:
description: Path where the trusted CA bundle is available
type: string
development_mode:
description: If the deployment should be done in development mode
type: boolean
ldap_cacert_secret:
description: Secret where can be found the LDAP trusted Certificate Authority Bundle
type: string
tower_projects_persistence:
description: Whether or not the /var/lib/projects directory will be persistent
default: false
type: boolean
tower_projects_use_existing_claim:
description: Using existing PersistentVolumeClaim
type: string
enum:
- _Yes_
- _No_
tower_projects_existing_claim:
description: PersistentVolumeClaim to mount /var/lib/projects directory
type: string
tower_projects_storage_class:
description: Storage class for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_storage_size:
description: Size for the /var/lib/projects PersistentVolumeClaim
default: 8Gi
type: string
tower_projects_storage_access_mode:
description: AccessMode for the /var/lib/projects PersistentVolumeClaim
default: ReadWriteMany
type: string
extra_settings:
description: Extra settings to specify for the API
items:
properties:
setting:
type: string
value:
type: string
type: object
type: array
type: object
status:
properties:
towerURL:
description: URL to access the deployed instance
type: string
towerAdminUser:
description: Admin user of the deployed instance
type: string
towerAdminPasswordSecret:
description: Admin password of the deployed instance
type: string
towerMigratedFromSecret:
description: The secret used for migrating an old Tower.
type: string
towerVersion:
description: Version of the deployed instance
type: string
towerImage:
description: URL of the image used for the deployed instance
type: string
conditions:
description: The resulting conditions when a Service Telemetry is instantiated
items:
properties:
status:
type: string
type:
type: string
reason:
type: string
lastTransitionTime:
type: string
type: object
type: array
type: object
type: object
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -11,19 +387,24 @@ rules:
- route.openshift.io
resources:
- routes
- routes/custom-host
verbs:
- '*'
- apiGroups:
- ""
- "rbac.authorization.k8s.io"
resources:
- pods
- services
- services/finalizers
- serviceaccounts
- endpoints
- persistentvolumeclaims
- events
- configmaps
- secrets
- roles
- rolebindings
verbs:
- '*'
- apiGroups:
@@ -52,6 +433,13 @@ rules:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments/scale
- statefulsets/scale
verbs:
- patch
- apiGroups:
- ""
resources:
@@ -111,7 +499,7 @@ spec:
serviceAccountName: awx-operator
containers:
- name: awx-operator
image: "quay.io/ansible/awx-operator:0.6.0"
image: "quay.io/ansible/awx-operator:0.9.0"
imagePullPolicy: "Always"
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
@@ -132,59 +520,8 @@ spec:
httpGet:
path: /healthz
port: 6789
initialDelaySeconds: 5
periodSeconds: 3
initialDelaySeconds: 15
periodSeconds: 20
volumes:
- name: runner
emptyDir: {}
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: awxs.awx.ansible.com
spec:
group: awx.ansible.com
names:
kind: AWX
listKind: AWXList
plural: awxs
singular: awx
scope: Namespaced
subresources:
status: {}
version: v1beta1
versions:
- name: v1beta1
served: true
storage: true
validation:
openAPIV3Schema:
description: Schema validation for the AWX CRD
type: object
properties:
spec:
type: object
properties:
external_database:
type: boolean
description: |
If true you must supply a secret containing the location and credentials for
connecting to the external database by a user who has permission to create
and apply a schema.
The secret should have the name: <custom resource name>-postgres-configuration and
should look like:
apiVersion: v1
kind: Secret
metadata:
name: <crname>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque

View File

@@ -1,33 +0,0 @@
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: example-awx
namespace: example-awx
spec:
tower_ingress_type: none
tower_task_privileged: false
tower_hostname: example-awx.test
tower_broadcast_websocket_secret: changeme
tower_admin_user: test
tower_admin_email: test@example.com
tower_admin_password: changeme
tower_image: ansible/awx:15.0.0
tower_task_mem_request: 1Gi
tower_task_cpu_request: 500m
tower_web_mem_request: 2Gi
tower_web_cpu_request: 1000m
tower_create_preload_data: true
tower_memcached_image: memcached:alpine
tower_redis_image: redis:latest
tower_postgres_storage_request: 8Gi
tower_postgres_storage_class: ''

View File

@@ -1,5 +1,5 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: awxs.awx.ansible.com
@@ -11,40 +11,365 @@ spec:
plural: awxs
singular: awx
scope: Namespaced
subresources:
status: {}
version: v1beta1
versions:
- name: v1beta1
served: true
storage: true
validation:
openAPIV3Schema:
description: Schema validation for the AWX CRD
type: object
properties:
spec:
type: object
subresources:
status: {}
schema:
openAPIV3Schema:
description: Schema validation for the AWX CRD
properties:
external_database:
type: boolean
description: |
If true you must supply a secret containing the location and credentials for
connecting to the external database by a user who has permission to create
and apply a schema.
The secret should have the name: <custom resource name>-postgres-configuration and
should look like:
apiVersion: v1
kind: Secret
metadata:
name: <crname>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque
spec:
properties:
deployment_type:
description: Name of the deployment type
type: string
default: awx
kind:
description: Kind of the deployment type
type: string
default: AWX
api_version:
description: apiVersion of the deployment type
type: string
default: awx.ansible.com/v1beta1
tower_task_privileged:
description: If a privileged security context should be enabled
type: boolean
default: false
tower_admin_user:
description: Username to use for the admin account
type: string
default: admin
tower_hostname:
description: The hostname of the instance
type: string
tower_admin_email:
description: The admin user email
type: string
tower_admin_password_secret:
description: Secret where the admin password can be found
type: string
tower_postgres_configuration_secret:
description: Secret where the database configuration can be found
type: string
tower_old_postgres_configuration_secret:
description: Secret where the old database configuration can be found for data migration
type: string
tower_secret_key_secret:
description: Secret where the secret key can be found
type: string
tower_broadcast_websocket_secret:
description: Secret where the broadcast websocket secret can be found
type: string
tower_extra_volumes:
description: Specify extra volumes to add to the application pod
type: string
tower_ingress_type:
description: The ingress type to use to reach the deployed instance
type: string
enum:
- none
- Ingress
- ingress
- Route
- route
- LoadBalancer
- loadbalancer
- NodePort
- nodeport
tower_ingress_annotations:
description: Annotations to add to the ingress
type: string
tower_ingress_tls_secret:
description: Secret where the ingress TLS secret can be found
type: string
tower_loadbalancer_annotations:
description: Annotations to add to the loadbalancer
type: string
tower_loadbalancer_protocol:
description: Protocol to use for the loadbalancer
type: string
default: http
enum:
- http
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
type: string
tower_route_tls_termination_mechanism:
description: The secure TLS termination mechanism to use
type: string
default: Edge
enum:
- Edge
- edge
- Passthrough
- passthrough
tower_route_tls_secret:
description: Secret where the TLS related credentials are stored
type: string
tower_node_selector:
description: nodeSelector for the AWX pods
type: string
tower_tolerations:
description: node tolerations for the AWX pods
type: string
tower_image:
description: Registry path to the application container to use
type: string
tower_image_version:
description: Application container image version to use
type: string
tower_ee_images:
description: Registry path to the Execution Environment container to use
type: array
items:
type: object
properties:
name:
type: string
image:
type: string
tower_image_pull_policy:
description: The image pull policy
type: string
default: IfNotPresent
enum:
- Always
- always
- Never
- never
- IfNotPresent
- ifnotpresent
tower_image_pull_secret:
description: The image pull secret
type: string
tower_task_resource_requirements:
description: Resource requirements for the task container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_web_resource_requirements:
description: Resource requirements for the web container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_replicas:
description: Number of instance replicas
type: integer
default: 1
format: int32
tower_garbage_collect_secrets:
description: Whether or not to remove secrets upon instance removal
default: false
type: boolean
tower_create_preload_data:
description: Whether or not to preload data upon Tower instance creation
default: true
type: boolean
tower_task_args:
type: array
items:
type: string
tower_task_command:
type: array
items:
type: string
tower_web_args:
type: array
items:
type: string
tower_web_command:
type: array
items:
type: string
tower_task_extra_env:
type: string
tower_web_extra_env:
type: string
tower_ee_extra_volume_mounts:
description: Specify volume mounts to be added to Execution container
type: string
tower_task_extra_volume_mounts:
description: Specify volume mounts to be added to Task container
type: string
tower_web_extra_volume_mounts:
description: Specify volume mounts to be added to the Web container
type: string
tower_redis_image:
description: Registry path to the redis container to use
type: string
tower_redis_image_version:
description: Redis container image version to use
type: string
tower_postgres_image:
description: Registry path to the PostgreSQL container to use
type: string
tower_postgres_image_version:
description: PostgreSQL container image version to use
type: string
tower_postgres_selector:
description: nodeSelector for the Postgres pods
type: string
tower_postgres_tolerations:
description: node tolerations for the Postgres pods
type: string
tower_postgres_storage_requirements:
description: Storage requirements for the PostgreSQL container
properties:
requests:
properties:
storage:
type: string
type: object
limits:
properties:
storage:
type: string
type: object
type: object
tower_postgres_resource_requirements:
description: Resource requirements for the PostgreSQL container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
type: object
type: object
tower_postgres_storage_class:
description: Storage class to use for the PostgreSQL PVC
type: string
tower_postgres_data_path:
description: Path where the PostgreSQL data are located
type: string
ca_trust_bundle:
description: Path where the trusted CA bundle is available
type: string
development_mode:
description: If the deployment should be done in development mode
type: boolean
ldap_cacert_secret:
description: Secret where can be found the LDAP trusted Certificate Authority Bundle
type: string
tower_projects_persistence:
description: Whether or not the /var/lib/projects directory will be persistent
default: false
type: boolean
tower_projects_use_existing_claim:
description: Using existing PersistentVolumeClaim
type: string
enum:
- _Yes_
- _No_
tower_projects_existing_claim:
description: PersistentVolumeClaim to mount /var/lib/projects directory
type: string
tower_projects_storage_class:
description: Storage class for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_storage_size:
description: Size for the /var/lib/projects PersistentVolumeClaim
default: 8Gi
type: string
tower_projects_storage_access_mode:
description: AccessMode for the /var/lib/projects PersistentVolumeClaim
default: ReadWriteMany
type: string
extra_settings:
description: Extra settings to specify for the API
items:
properties:
setting:
type: string
value:
type: string
type: object
type: array
type: object
status:
properties:
towerURL:
description: URL to access the deployed instance
type: string
towerAdminUser:
description: Admin user of the deployed instance
type: string
towerAdminPasswordSecret:
description: Admin password of the deployed instance
type: string
towerMigratedFromSecret:
description: The secret used for migrating an old Tower.
type: string
towerVersion:
description: Version of the deployed instance
type: string
towerImage:
description: URL of the image used for the deployed instance
type: string
conditions:
description: The resulting conditions when a Service Telemetry is instantiated
items:
properties:
status:
type: string
type:
type: string
reason:
type: string
lastTransitionTime:
type: string
type: object
type: array
type: object
type: object

View File

@@ -5,31 +5,13 @@ metadata:
name: example-awx
namespace: example-awx
spec:
deployment_type: awx
tower_ingress_type: ingress
tower_task_privileged: false
tower_hostname: example-awx.test
tower_broadcast_websocket_secret: changeme
tower_admin_user: test
tower_admin_email: test@example.com
tower_admin_password: changeme
tower_image: ansible/awx:15.0.0
tower_task_mem_request: 128M
tower_task_cpu_request: 500m
tower_web_mem_request: 128M
tower_web_cpu_request: 500m
tower_create_preload_data: true
tower_memcached_image: memcached:alpine
tower_redis_image: redis:latest
tower_postgres_pass: awxpass
tower_postgres_image: postgres:12
tower_postgres_storage_request: 8Gi
tower_postgres_storage_class: ''
tower_web_resource_requirements:
requests:
cpu: 500m
memory: 128M
tower_task_resource_requirements:
requests:
cpu: 500m
memory: 128M

View File

@@ -0,0 +1,5 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./awx-operator.yaml

View File

@@ -1,4 +1,3 @@
---
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
@@ -13,52 +12,20 @@ metadata:
"namespace": "example-awx"
},
"spec": {
"tower_admin_email": "test@example.com",
"tower_admin_password": "changeme",
"tower_admin_user": "test",
"tower_broadcast_websocket_secret": "changeme",
"tower_create_preload_data": true,
"tower_hostname": "example-awx.test",
"tower_ingress_type": "none",
"tower_memcached_image": "memcached:alpine",
"tower_postgres_storage_class": "",
"tower_postgres_storage_request": "8Gi",
"tower_redis_image": "redis:latest",
"tower_task_cpu_request": "500m",
"tower_image": "ansible/awx:15.0.0",
"tower_task_mem_request": "1Gi",
"tower_task_privileged": false,
"tower_web_cpu_request": "1000m"
"tower_web_mem_request": "2Gi"
}
},
{
"apiVersion": "awx.ansible.com/v1beta1",
"kind": "AWX",
"metadata": {
"name": "example-awx",
"namespace": "example-awx"
},
"spec": {
"tower_admin_email": "test@example.com",
"tower_admin_password": "changeme",
"tower_admin_user": "test",
"tower_broadcast_websocket_secret": "changeme",
"tower_create_preload_data": true,
"tower_hostname": "example-awx.test",
"deployment_type": "awx",
"tower_ingress_type": "ingress",
"tower_memcached_image": "memcached:alpine",
"tower_postgres_image": "postgres:12",
"tower_postgres_pass": "awxpass",
"tower_postgres_storage_class": "",
"tower_postgres_storage_request": "8Gi",
"tower_redis_image": "redis:latest",
"tower_task_cpu_request": "500m",
"tower_image": "ansible/awx:15.0.0",
"tower_task_mem_request": "128M",
"tower_task_privileged": false,
"tower_web_cpu_request": "500m",
"tower_web_mem_request": "128M"
"tower_task_resource_requirements": {
"requests": {
"cpu": "500m",
"memory": "128M"
}
},
"tower_web_resource_requirements": {
"requests": {
"cpu": "500m",
"memory": "128M"
}
}
}
}
]
@@ -71,149 +38,534 @@ spec:
apiservicedefinitions: {}
customresourcedefinitions:
owned:
- kind: AWX
name: awxs.awx.ansible.com
version: v1beta1
- description: A AWX Instance
displayName: AWX
kind: AWX
name: awxs.awx.ansible.com
specDescriptors:
- displayName: Hostname
path: tower_hostname
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Admin account username
path: tower_admin_user
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Admin email address
path: tower_admin_email
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Admin password secret
path: tower_admin_password_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Database configuration secret
path: tower_postgres_configuration_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Old Database configuration secret
path: tower_old_postgres_configuration_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Secret key secret
path: tower_secret_key_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Broadcast Websocket Secret
path: tower_broadcast_websocket_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Ingress Type
path: tower_ingress_type
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:select:none
- urn:alm:descriptor:com.tectonic.ui:select:Ingress
- urn:alm:descriptor:com.tectonic.ui:select:Route
- urn:alm:descriptor:com.tectonic.ui:select:LoadBalancer
- urn:alm:descriptor:com.tectonic.ui:select:NodePort
- displayName: Tower Ingress Annotations
path: tower_ingress_annotations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:Ingress
- displayName: Tower Ingress TLS Secret
path: tower_ingress_tls_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:Ingress
- displayName: Tower LoadBalancer Annotations
path: tower_loadbalancer_annotations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:LoadBalancer
- displayName: Tower LoadBalancer Protocol
path: tower_loadbalancer_protocol
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:select:http
- urn:alm:descriptor:com.tectonic.ui:select:https
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:LoadBalancer
- displayName: Tower LoadBalancer Port
path: tower_loadbalancer_port
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:number
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:LoadBalancer
- displayName: Route DNS host
path: tower_route_host
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:Route
- displayName: Route TLS termination mechanism
path: tower_route_tls_termination_mechanism
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:select:Edge
- urn:alm:descriptor:com.tectonic.ui:select:Passthrough
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:Route
- displayName: Route TLS credential secret
path: tower_route_tls_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_ingress_type:Route
- displayName: Image Pull Policy
path: tower_image_pull_policy
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:imagePullPolicy
- displayName: Image Pull Secret
path: tower_image_pull_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:imagePullSecret
- displayName: Web container resource requirements
path: tower_web_resource_requirements
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- displayName: Task container resource requirements
path: tower_task_resource_requirements
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- displayName: PostgreSQL container resource requirements (when using a managed instance)
path: tower_postgres_resource_requirements
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- displayName: PostgreSQL container storage requirements (when using a managed instance)
path: tower_postgres_storage_requirements
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:resourceRequirements
- displayName: Replicas
path: tower_replicas
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:number
- displayName: Remove used secrets on instance removal ?
path: tower_garbage_collect_secrets
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- displayName: Preload instance with data upon creation ?
path: tower_create_preload_data
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- displayName: Deploy the instance in development mode ?
path: development_mode
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Should Tower Task container deployed with privileged level ?
path: tower_task_privileged
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Deployment Type
path: deployment_type
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Deployment Kind
path: kind
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Deployment apiVersion
path: api_version
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Image
path: tower_image
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Image Version
path: tower_image_version
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Redis Image
path: tower_redis_image
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Redis Image Version
path: tower_redis_image_version
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: PostgreSQL Image
path: tower_postgres_image
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: PostgreSQL Image Version
path: tower_postgres_image_version
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Postgres Selector
path: tower_postgres_selector
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Postgres Tolerations
path: tower_postgres_tolerations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Postgres Storage Class
path: tower_postgres_storage_class
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Postgres Datapath
path: tower_postgres_data_path
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Certificate Authorirty Trust Bundle
path: ca_trust_bundle
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: LDAP Certificate Authority Trust Bundle
path: ldap_cacert_secret
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes:Secret
- displayName: Tower Task Args
path: tower_task_args
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Enable persistence for /var/lib/projects directory?
path: tower_projects_persistence
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- displayName: Use existing Persistent Claim?
path: tower_projects_use_existing_claim
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:select:_Yes_
- urn:alm:descriptor:com.tectonic.ui:select:_No_
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_projects_persistence:true
- displayName: Tower Projects Existing Persistent Claim
path: tower_projects_existing_claim
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_projects_use_existing_claim:_Yes_
- urn:alm:descriptor:io.kubernetes:PersistentVolumeClaim
- description: Tower Projects Storage Class Name. If not present, the default
storage class will be used.
displayName: Tower Projects Storage Class Name
path: tower_projects_storage_class
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_projects_use_existing_claim:_No_
- urn:alm:descriptor:com.tectonic.ui:text
- description: Tower Projects Storage Size
displayName: Tower Projects Storage Size
path: tower_projects_storage_size
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_projects_use_existing_claim:_No_
- urn:alm:descriptor:com.tectonic.ui:text
- description: Tower Projects Storage Access Mode
displayName: Tower Projects Storage Access Mode
path: tower_projects_storage_access_mode
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:tower_projects_use_existing_claim:_No_
- urn:alm:descriptor:com.tectonic.ui:text
- displayName: Tower Task Command
path: tower_task_command
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Task Extra Env
description: Environment variables to be added to Task container
path: tower_task_extra_env
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName:
path: tower_ee_extra_volume_mounts
description: Specify volume mounts to be added to Execution container
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower EE Images
description: Registry path to the Execution Environment container to use
path: tower_ee_images
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Task Extra Volume Mounts
description: Specify volume mounts to be added to Task container
path: tower_task_extra_volume_mounts
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Web Args
path: tower_web_args
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Web Command
path: tower_web_command
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Web Extra Env
description: Environment variables to be added to Web container
path: tower_web_extra_env
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Web Extra Volume Mounts
description: Specify volume mounts to be added to Web container
path: tower_web_extra_volume_mounts
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Extra Volumes
description: Specify extra volumes to add to the application pod
path: tower_extra_volumes
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Node Selector
path: tower_node_selector
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: Tower Tolerations
path: tower_tolerations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
- displayName: API Extra Settings
path: extra_settings
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:hidden
statusDescriptors:
- description: Route to access the instance deployed
displayName: URL
path: towerURL
x-descriptors:
- urn:alm:descriptor:org.w3:link
- description: Admin user for the instance deployed
displayName: Admin User
path: towerAdminUser
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- description: Admin password for the instance deployed
displayName: Admin Password
path: towerAdminPasswordSecret
x-descriptors:
- urn:alm:descriptor:io.kubernetes:Secret
- description: Version of the instance deployed
displayName: Version
path: towerVersion
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- description: Image of the instance deployed
displayName: Image
path: towerImage
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
version: v1beta1
description: AWX operator
displayName: AWX
icon:
- base64data: ""
mediatype: ""
- base64data: ""
mediatype: ""
install:
spec:
clusterPermissions:
- rules:
- apiGroups:
- route.openshift.io
resources:
- routes
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods
- services
- services/finalizers
- endpoints
- persistentvolumeclaims
- events
- configmaps
- secrets
verbs:
- '*'
- apiGroups:
- apps
- extensions
resources:
- deployments
- daemonsets
- replicasets
- statefulsets
- ingresses
verbs:
- '*'
- apiGroups:
- monitoring.coreos.com
resources:
- servicemonitors
verbs:
- get
- create
- apiGroups:
- apps
resourceNames:
- awx-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- ""
resources:
- pods/exec
verbs:
- create
- get
- apiGroups:
- apps
resources:
- replicasets
verbs:
- get
- apiGroups:
- awx.ansible.com
resources:
- '*'
verbs:
- '*'
serviceAccountName: awx-operator
- rules:
- apiGroups:
- route.openshift.io
resources:
- routes
- routes/custom-host
verbs:
- '*'
- apiGroups:
- ""
- rbac.authorization.k8s.io
resources:
- pods
- services
- services/finalizers
- serviceaccounts
- endpoints
- persistentvolumeclaims
- events
- configmaps
- secrets
- roles
- rolebindings
verbs:
- '*'
- apiGroups:
- apps
- extensions
resources:
- deployments
- daemonsets
- replicasets
- statefulsets
- ingresses
verbs:
- '*'
- apiGroups:
- monitoring.coreos.com
resources:
- servicemonitors
verbs:
- get
- create
- apiGroups:
- apps
resourceNames:
- awx-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments/scale
- statefulsets/scale
verbs:
- patch
- apiGroups:
- ""
resources:
- pods/exec
verbs:
- create
- get
- apiGroups:
- apps
resources:
- replicasets
verbs:
- get
- apiGroups:
- awx.ansible.com
resources:
- '*'
verbs:
- '*'
serviceAccountName: awx-operator
deployments:
- name: awx-operator
spec:
replicas: 1
selector:
matchLabels:
- name: awx-operator
spec:
replicas: 1
selector:
matchLabels:
name: awx-operator
strategy: {}
template:
metadata:
labels:
name: awx-operator
strategy: {}
template:
metadata:
labels:
name: awx-operator
spec:
containers:
- command:
- /usr/local/bin/ao-logs
- /tmp/ansible-operator/runner
- stdout
image: ansible/awx-operator:0.5.0
imagePullPolicy: Always
name: ansible
resources: {}
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
name: runner
readOnly: true
- env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.annotations['olm.targetNamespaces']
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPERATOR_NAME
value: awx-operator
image: ansible/awx-operator:0.5.0
imagePullPolicy: Always
name: operator
resources: {}
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
name: runner
serviceAccountName: awx-operator
volumes:
- emptyDir: {}
name: runner
spec:
containers:
- env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.annotations['olm.targetNamespaces']
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPERATOR_NAME
value: awx-operator
- name: ANSIBLE_GATHERING
value: explicit
image: quay.io/ansible/awx-operator:0.8.0
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /healthz
port: 6789
initialDelaySeconds: 15
periodSeconds: 20
name: awx-operator
resources: {}
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
name: runner
serviceAccountName: awx-operator
volumes:
- emptyDir: {}
name: runner
strategy: deployment
installModes:
- supported: true
type: OwnNamespace
- supported: true
type: SingleNamespace
- supported: false
type: MultiNamespace
- supported: true
type: AllNamespaces
- supported: true
type: OwnNamespace
- supported: true
type: SingleNamespace
- supported: false
type: MultiNamespace
- supported: true
type: AllNamespaces
keywords:
- awx
- awx
links:
- name: Awx Operator
url: https://github.com/ansible/awx-operator
- name: Awx Operator
url: https://github.com/ansible/awx-operator
maintainers:
- email: yguenane@redhat.com
name: Yanis Guenane
- email: yguenane@redhat.com
name: Yanis Guenane
maturity: alpha
provider:
name: AWX Community

View File

@@ -1,5 +1,4 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
@@ -12,43 +11,375 @@ spec:
plural: awxs
singular: awx
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: Schema validation for the AWX CRD
properties:
spec:
properties:
external_database:
description: |
If true you must supply a secret containing the location and credentials for
connecting to the external database by a user who has permission to create
and apply a schema.
The secret should have the name: <custom resource name>-postgres-configuration and
should look like:
apiVersion: v1
kind: Secret
metadata:
name: <crname>-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque
type: boolean
type: object
type: object
version: v1beta1
versions:
- name: v1beta1
served: true
storage: true
- name: v1beta1
schema:
openAPIV3Schema:
description: Schema validation for the AWX CRD
properties:
spec:
properties:
ca_trust_bundle:
description: Path where the trusted CA bundle is available
type: string
deployment_type:
description: Name of the deployment type
type: string
default: awx
kind:
description: Kind of the deployment type
type: string
default: AWX
api_version:
description: apiVersion of the deployment type
type: string
default: awx.ansible.com/v1beta1
development_mode:
description: If the deployment should be done in development mode
type: boolean
ldap_cacert_secret:
description: Secret where can be found the LDAP trusted Certificate
Authority Bundle
type: string
tower_admin_email:
description: The admin user email
type: string
tower_admin_password_secret:
description: Secret where the admin password can be found
type: string
tower_admin_user:
default: admin
description: Username to use for the admin account
type: string
tower_broadcast_websocket_secret:
description: Secret where the broadcast websocket secret can be found
type: string
tower_create_preload_data:
default: true
description: Whether or not to preload data upon Tower instance creation
type: boolean
tower_ee_images:
description: Registry path to the Execution Environment container
to use
items:
properties:
image:
type: string
name:
type: string
type: object
type: array
tower_extra_volumes:
description: Specify extra volumes to add to the application pod
type: string
tower_garbage_collect_secrets:
default: false
description: Whether or not to remove secrets upon instance removal
type: boolean
tower_hostname:
description: The hostname of the instance
type: string
tower_image:
description: Registry path to the application container to use
type: string
tower_image_version:
description: Application container image version to use
type: string
tower_image_pull_policy:
default: IfNotPresent
description: The image pull policy
enum:
- Always
- always
- Never
- never
- IfNotPresent
- ifnotpresent
type: string
tower_image_pull_secret:
description: The image pull secret
type: string
tower_ingress_annotations:
description: Annotations to add to the ingress
type: string
tower_ingress_tls_secret:
description: Secret where the ingress TLS secret can be found
type: string
tower_ingress_type:
description: The ingress type to use to reach the deployed instance
enum:
- none
- Ingress
- ingress
- Route
- route
- LoadBalancer
- loadbalancer
- NodePort
- nodeport
type: string
tower_loadbalancer_annotations:
description: Annotations to add to the loadbalancer
type: string
tower_loadbalancer_port:
default: 80
description: Port to use for the loadbalancer
type: integer
tower_loadbalancer_protocol:
default: http
description: Protocol to use for the loadbalancer
enum:
- http
- https
type: string
tower_node_selector:
description: nodeSelector for the AWX pods
type: string
tower_old_postgres_configuration_secret:
description: Secret where the old database configuration can be found
for data migration
type: string
tower_postgres_configuration_secret:
description: Secret where the database configuration can be found
type: string
tower_postgres_data_path:
description: Path where the PostgreSQL data are located
type: string
tower_postgres_image:
description: Registry path to the PostgreSQL container to use
type: string
tower_postgres_image_version:
description: PostgreSQL container image version to use
type: string
tower_postgres_selector:
description: nodeSelector for the Postgres pods
type: string
tower_postgres_tolerations:
description: node tolerations for the Postgres pods
type: string
tower_postgres_storage_requirements:
description: Storage requirements for the PostgreSQL container
properties:
requests:
properties:
storage:
type: string
type: object
limits:
properties:
storage:
type: string
type: object
type: object
tower_postgres_resource_requirements:
description: Resource requirements for the PostgreSQL container
properties:
requests:
properties:
cpu:
type: string
memory:
type: string
type: object
limits:
properties:
cpu:
type: string
memory:
type: string
type: object
type: object
tower_postgres_storage_class:
description: Storage class to use for the PostgreSQL PVC
type: string
tower_projects_existing_claim:
description: PersistentVolumeClaim to mount /var/lib/projects directory
type: string
tower_projects_persistence:
default: false
description: Whether or not the /var/lib/projects directory will be
persistent
type: boolean
tower_projects_storage_access_mode:
default: ReadWriteMany
description: AccessMode for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_storage_class:
description: Storage class for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_storage_size:
default: 8Gi
description: Size for the /var/lib/projects PersistentVolumeClaim
type: string
tower_projects_use_existing_claim:
description: Using existing PersistentVolumeClaim
enum:
- _Yes_
- _No_
type: string
tower_redis_image:
description: Registry path to the redis container to use
type: string
tower_redis_image_version:
description: Redis container image version to use
type: string
tower_replicas:
default: 1
description: Number of instance replicas
format: int32
type: integer
tower_route_host:
description: The DNS to use to points to the instance
type: string
tower_route_tls_secret:
description: Secret where the TLS related credentials are stored
type: string
tower_route_tls_termination_mechanism:
default: Edge
description: The secure TLS termination mechanism to use
enum:
- Edge
- edge
- Passthrough
- passthrough
type: string
tower_secret_key_secret:
description: Secret where the secret key can be found
type: string
tower_task_args:
items:
type: string
type: array
tower_task_command:
items:
type: string
type: array
tower_task_extra_env:
description: Environment variables to be added to Task container
type: string
tower_ee_extra_volume_mounts:
description: Specify volume mounts to be added to Execution container
type: string
tower_task_extra_volume_mounts:
description: Specify volume mounts to be added to Task container
type: string
tower_task_privileged:
default: false
description: If a privileged security context should be enabled
type: boolean
tower_task_resource_requirements:
description: Resource requirements for the task container
properties:
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
tower_tolerations:
description: node tolerations for the AWX pods
type: string
tower_web_args:
items:
type: string
type: array
tower_web_command:
items:
type: string
type: array
tower_web_extra_env:
description: Environment variables to be added to Web container
type: string
tower_web_extra_volume_mounts:
description: Specify volume mounts to be added to web container
type: string
tower_web_resource_requirements:
description: Resource requirements for the web container
properties:
limits:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
requests:
properties:
cpu:
type: string
memory:
type: string
storage:
type: string
type: object
type: object
extra_settings:
description: Extra settings to specify for the API
items:
properties:
setting:
type: string
value:
type: string
type: object
type: array
type: object
status:
properties:
conditions:
description: The resulting conditions when a Service Telemetry is
instantiated
items:
properties:
lastTransitionTime:
type: string
reason:
type: string
status:
type: string
type:
type: string
type: object
type: array
towerAdminPasswordSecret:
description: Admin password of the deployed instance
type: string
towerAdminUser:
description: Admin user of the deployed instance
type: string
towerImage:
description: URL of the image used for the deployed instance
type: string
towerMigratedFromSecret:
description: The secret used for migrating an old Tower.
type: string
towerURL:
description: URL to access the deployed instance
type: string
towerVersion:
description: Version of the deployed instance
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""

View File

@@ -1,4 +1,3 @@
---
annotations:
operators.operatorframework.io.bundle.channel.default.v1: alpha
operators.operatorframework.io.bundle.channels.v1: alpha

64
docs/migration.md Normal file
View File

@@ -0,0 +1,64 @@
# Migrating data from an old AWX instance
To migrate data from an older AWX installation, you must provide some information via Secrets.
## Creating Secrets for Migration
### Secret Key
You can find your old secret key in the inventory file you used to deploy AWX in releases prior to version 18.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: <resourcename>-secret-key
namespace: <target namespace>
stringData:
secret_key: <old-secret-key>
type: Opaque
```
**Note**: `<resourcename>` must match the `name` of the AWX object you are creating. In our example below, it is `awx`.
### Old Database Credentials
The secret should be formatted as follows:
```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: <resourcename>-old-postgres-configuration
namespace: <target namespace>
stringData:
host: <external ip or url resolvable by the cluster>
port: <external port, this usually defaults to 5432>
database: <desired database name>
username: <username to connect as>
password: <password to connect with>
type: Opaque
```
> For `host`, a URL resolvable by the cluster could look something like `postgresql.<namespace>.svc.cluster.local`, where `<namespace>` is filled in with the namespace of the AWX deployment you are migrating data from.
If your AWX deployment is already using an external database server or its database is otherwise not managed
by the AWX deployment, you can instead create the same secret as above but omit the `-old-` from the `name`.
In the next section pass it in through `tower_postgres_configuration_secret` instead, omitting the `_old_`
from the key and ensuring the value matches the name of the secret. This will make AWX pick up on the existing
database and apply any pending migrations. It is strongly recommended to backup your database beforehand.
## Deploy AWX
When you apply your AWX object, you must specify the name to the database secret you created above:
```yaml
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
tower_old_postgres_configuration_secret: <resourcename>-old-postgres-configuration
...
```

View File

@@ -2,4 +2,4 @@
- hosts: localhost
gather_facts: no
roles:
- awx
- installer

View File

@@ -7,12 +7,31 @@
ansible_python_interpreter: '{{ ansible_playbook_python }}'
tasks:
- name: Get AWX Kind data
k8s_info:
api_version: awx.ansible.com/v1beta1
kind: AWX
namespace: example-awx
label_selectors:
- "app.kubernetes.io/name=example-awx"
- "app.kubernetes.io/part-of=example-awx"
- "app.kubernetes.io/managed-by=awx-operator"
- "app.kubernetes.io/component=awx"
register: awx_kind
- name: Verify there is one AWX kind
assert:
that: '{{ (awx_kind.resources | length) == 1 }}'
- name: Get AWX Pod data
k8s_info:
kind: Pod
namespace: example-awx
label_selectors:
- app=awx
- "app.kubernetes.io/name=example-awx"
- "app.kubernetes.io/part-of=example-awx"
- "app.kubernetes.io/managed-by=awx-operator"
- "app.kubernetes.io/component=awx"
register: tower_pods
- name: Verify there is one AWX pod

View File

@@ -5,6 +5,6 @@
vars:
ansible_python_interpreter: '{{ ansible_playbook_python }}'
roles:
- awx
- installer
- import_playbook: '{{ playbook_dir }}/asserts.yml'

View File

@@ -0,0 +1,2 @@
[defaults]
stdout_callback = yaml

View File

@@ -97,8 +97,8 @@
kind=custom_resource.kind,
api_version=custom_resource.apiVersion,
namespace=custom_resource.metadata.namespace,
resource_name=custom_resource.metadata.name
)}}'
resource_name=custom_resource.metadata.name)
}}'
- name: debug awx deployment
ignore_errors: yes
@@ -110,13 +110,13 @@
kind="Deployment",
api_version="apps/v1",
namespace=custom_resource.metadata.namespace,
label_selector="app=awx"
)}}'
label_selector="app.kubernetes.io/name=example-awx")
}}'
- name: get operator logs
ignore_errors: yes
failed_when: false
command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }} -c operator
command: kubectl logs deployment/{{ definition.metadata.name }} -n {{ operator_namespace }}
environment:
KUBECONFIG: '{{ lookup("env", "KUBECONFIG") }}'
vars:

View File

@@ -11,7 +11,7 @@ platforms:
- name: kind-test-local
groups:
- k8s
image: bsycorp/kind:latest-1.15
image: bsycorp/kind:v1.17.9
privileged: True
override_command: no
exposed_ports:

View File

@@ -105,8 +105,8 @@
kind=custom_resource.kind,
api_version=custom_resource.apiVersion,
namespace=custom_resource.metadata.namespace,
resource_name=custom_resource.metadata.name
)}}'
resource_name=custom_resource.metadata.name)
}}'
- name: debug awx deployment
ignore_errors: yes
@@ -118,8 +118,8 @@
kind="Deployment",
api_version="apps/v1",
namespace=custom_resource.metadata.namespace,
label_selector="app=awx"
)}}'
label_selector="app.kubernetes.io/name=example-awx")
}}'
- name: get operator logs
ignore_errors: yes

View File

@@ -1,82 +0,0 @@
---
tower_task_privileged: false
tower_ingress_type: none
# Add annotations to the ingress. Specify as literal block. E.g.:
# tower_ingress_annotations: |
# kubernetes.io/ingress.class: nginx
# nginx.ingress.kubernetes.io/proxy-connect-timeout: 60s
tower_ingress_annotations: ''
# TLS secret for the ingress. The secret either has to exist before hand with
# the corresponding cert and key or just be an indicator for where an automated
# process like cert-manager (enabled via annotations) will store the TLS
# certificate and key.
tower_ingress_tls_secret: ''
tower_hostname: example-awx.test
tower_admin_user: test
tower_admin_email: test@example.com
tower_admin_password: changeme
tower_broadcast_websocket_secret: changeme
# Add extra volumes to the AWX pod. Specify as literal block. E.g.:
# tower_extra_volumes: |
# - name: my-volume
# emptyDir: {}
tower_extra_volumes: ''
# Use these image versions for Ansible AWX.
tower_image: ansible/awx:15.0.0
tower_image_pull_policy: IfNotPresent
tower_create_preload_data: true
tower_replicas: "1"
tower_task_args:
- /usr/bin/launch_awx_task.sh
tower_task_command: []
tower_web_args: []
tower_web_command: []
tower_task_mem_request: 1Gi
tower_task_cpu_request: 500m
tower_web_mem_request: 2Gi
tower_web_cpu_request: 1000m
# Add extra environment variables to the AWX task/web containers. Specify as
# literal block. E.g.:
# tower_task_extra_env: |
# - name: FOO
# value: bar
# - name: BAZ
# value: bing
tower_task_extra_env: ''
tower_web_extra_env: ''
# Mount extra volumes on the AWX task/web containers. Specify as literal block.
# E.g.:
# tower_task_extra_volume_mounts: ''
# - name: my-volume
# mountPath: /some/path
tower_task_extra_volume_mounts: ''
tower_web_extra_volume_mounts: ''
tower_redis_image: redis:latest
tower_postgres_pass: awxpass
tower_postgres_image: postgres:12
tower_postgres_storage_request: 8Gi
tower_postgres_storage_class: ''
tower_postgres_data_path: '/var/lib/postgresql/data/pgdata'
tower_postgres_port: 5432
ca_trust_bundle: "/etc/pki/tls/certs/ca-bundle.crt"
development_mode: false

View File

@@ -1,111 +0,0 @@
---
- name: Check for existing secret key
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-secret-key'
register: secret_key_resources
- name: Check for existing postgres configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: postgres_config_resources
- name: Create Database configuration if it doesn't already exist
k8s:
apply: yes
definition: "{{ lookup('template', 'tower_postgres_secret.yaml.j2') }}"
register: k8s_postgres_config_result
when: postgres_config_resources['resources'] | length < 1 and not external_database | default(False) | bool
- name: Create Database if External Database not selected
k8s:
apply: yes
definition: "{{ lookup('template', 'tower_postgres.yaml.j2') }}"
register: k8s_postgres_result
when: not external_database | default(False) | bool
- name: Read Database Configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: postgres_configuration
- name: Store Database Configuration
set_fact:
awx_postgres_user: "{{ postgres_configuration['resources'][0]['data']['username'] | b64decode }}"
awx_postgres_pass: "{{ postgres_configuration['resources'][0]['data']['password'] | b64decode }}"
awx_postgres_database: "{{ postgres_configuration['resources'][0]['data']['database'] | b64decode }}"
awx_postgres_port: "{{ postgres_configuration['resources'][0]['data']['port'] | b64decode }}"
awx_postgres_host: "{{ postgres_configuration['resources'][0]['data']['host'] | b64decode }}"
- name: Deploy Tower Secret Key if needed
k8s:
apply: yes
definition: "{{ lookup('template', 'tower_secret.yaml.j2') }}"
register: k8s_tower_secret_result
when: secret_key_resources['resources'] | length < 1
- name: Ensure configured AWX resources exist in the cluster.
k8s:
apply: yes
definition: "{{ lookup('template', item) | from_yaml_all | list }}"
register: k8s_defs_result
with_items:
- tower_config.yaml.j2
- name: Apply Tower Deployment Configuration
k8s:
apply: yes
definition: "{{ lookup('template', 'tower.yaml.j2') }}"
register: tower_deployment_result
- name: Get the AWX pod information.
k8s_info:
kind: Pod
namespace: '{{ meta.namespace }}'
label_selectors:
- app=awx
register: tower_pods
until: "tower_pods['resources'][0]['status']['phase'] == 'Running'"
delay: 5
retries: 60
- name: Set the awx pod name as a variable.
set_fact:
tower_pod_name: "{{ tower_pods['resources'][0]['metadata']['name'] }}"
- name: Verify tower_pod_name is populated.
assert:
that: tower_pod_name != ''
fail_msg: "Could not find the tower pod's name."
- name: Check if database is populated (auth_user table exists).
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ tower_pod_name }}"
container: "{{ meta.name }}-task"
command: >-
bash -c "echo 'from django.db import connection;
tbl = \"auth_user\" in connection.introspection.table_names();
exit(0 if tbl else 1)'
| awx-manage shell"
ignore_errors: true
changed_when: false
register: database_check
when: k8s_defs_result is not changed
- name: Migrate the database if the K8s resources were updated. # noqa 305
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ tower_pod_name }}"
container: "{{ meta.name }}-task"
command: >-
bash -c "awx-manage migrate --noinput"
register: migrate_result
when: (k8s_defs_result is changed) or (database_check is defined and database_check.return_code != 0)
- include_tasks: initialize.yml

View File

@@ -1,5 +0,0 @@
DATABASE_USER={{ awx_postgres_user }}
DATABASE_NAME={{ awx_postgres_database }}
DATABASE_HOST={{ awx_postgres_host }}
DATABASE_PORT={{ awx_postgres_port }}
DATABASE_PASSWORD={{ awx_postgres_pass }}

View File

@@ -1,280 +0,0 @@
# AWX Secret Configurations
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-secrets'
namespace: '{{ meta.namespace }}'
data:
credentials_py: "{{ lookup('template', 'credentials.py.j2') | b64encode }}"
environment_sh: "{{ lookup('template', 'environment.sh.j2') | b64encode }}"
# AWX Deployment.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
labels:
app: awx
spec:
replicas: {{ tower_replicas }}
selector:
matchLabels:
app: awx
template:
metadata:
labels:
app: awx
spec:
containers:
- image: '{{ tower_redis_image }}'
name: redis
args: ["redis-server", "/etc/redis.conf"]
volumeMounts:
- name: {{ meta.name }}-redis-config
mountPath: "/etc/redis.conf"
subPath: redis.conf
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- image: '{{ tower_image }}'
name: '{{ meta.name }}-web'
{% if tower_web_command %}
command: {{ tower_web_command }}
{% endif %}
{% if tower_web_args %}
args: {{ tower_web_args }}
{% endif %}
imagePullPolicy: '{{ tower_image_pull_policy }}'
ports:
- containerPort: 8052
volumeMounts:
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/"
readOnly: true
- name: {{ meta.name }}-secret-key
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
- name: {{ meta.name }}-nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- name: supervisor-socket
mountPath: "/var/run/supervisor"
- name: rsyslog-socket
mountPath: "/var/run/awx-rsyslog"
- name: rsyslog-dir
mountPath: "/var/lib/awx/rsyslog"
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
{% if tower_web_extra_volume_mounts -%}
{{ tower_web_extra_volume_mounts | indent(width=12, indentfirst=True) }}
{% endif %}
{% if (development_mode | bool) or (tower_task_extra_env | bool) %}
env:
{% endif %}
{% if development_mode | bool %}
- name: AWX_KUBE_DEVEL
value: "1"
{% endif %}
{% if tower_task_extra_env %}
{{ tower_web_extra_env | indent(width=12, indentfirst=True) }}
{% endif %}
resources:
requests:
memory: '{{ tower_web_mem_request }}'
cpu: '{{ tower_web_cpu_request }}'
- image: '{{ tower_image }}'
name: '{{ meta.name }}-task'
imagePullPolicy: '{{ tower_image_pull_policy }}'
{% if tower_task_privileged == true %}
securityContext:
privileged: true
{% endif %}
{% if tower_task_command %}
command: {{ tower_task_command }}
{% endif %}
{% if tower_task_args %}
args: {{ tower_task_args }}
{% endif %}
volumeMounts:
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/"
readOnly: true
- name: {{ meta.name }}-secret-key
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- name: supervisor-socket
mountPath: "/var/run/supervisor"
- name: rsyslog-socket
mountPath: "/var/run/awx-rsyslog"
- name: rsyslog-dir
mountPath: "/var/lib/awx/rsyslog"
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
{% if tower_task_extra_volume_mounts -%}
{{ tower_task_extra_volume_mounts | indent(width=12, indentfirst=True) }}
{% endif %}
env:
- name: SUPERVISOR_WEB_CONFIG_PATH
value: "/supervisor.conf"
- name: AWX_SKIP_MIGRATIONS
value: "1"
- name: MY_POD_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{% if development_mode | bool %}
- name: AWX_KUBE_DEVEL
value: "1"
{% endif %}
{% if tower_task_extra_env -%}
{{ tower_task_extra_env | indent(width=12, indentfirst=True) }}
{% endif %}
resources:
requests:
memory: '{{ tower_task_mem_request }}'
cpu: '{{ tower_task_cpu_request }}'
volumes:
- name: "{{ meta.name }}-application-credentials"
secret:
secretName: "{{ meta.name }}-secrets"
items:
- key: credentials_py
path: 'credentials.py'
- key: environment_sh
path: 'environment.sh'
- name: {{ meta.name }}-secret-key
secret:
secretName: '{{ meta.name }}-secret-key'
items:
- key: secret_key
path: SECRET_KEY
- name: {{ meta.name }}-settings
configMap:
name: '{{ meta.name }}-awx-configmap'
items:
- key: settings
path: settings.py
- name: {{ meta.name }}-nginx-conf
configMap:
name: '{{ meta.name }}-awx-configmap'
items:
- key: nginx_conf
path: nginx.conf
- name: {{ meta.name }}-redis-config
configMap:
name: {{ meta.name }}-awx-configmap
items:
- key: redis_conf
path: redis.conf
- name: {{ meta.name }}-redis-socket
emptyDir: {}
- name: supervisor-socket
emptyDir: {}
- name: rsyslog-socket
emptyDir: {}
- name: rsyslog-dir
emptyDir: {}
{% if development_mode | bool %}
- name: awx-devel
hostPath:
path: /awx_devel
{% endif %}
{% if tower_extra_volumes -%}
{{ tower_extra_volumes | indent(width=8, indentfirst=True) }}
{% endif %}
# AWX Service.
---
apiVersion: v1
kind: Service
metadata:
name: '{{ meta.name }}-service'
namespace: '{{ meta.namespace }}'
labels:
app: awx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8052
name: http
selector:
app: awx
{% if tower_ingress_type != "none" %}
type: NodePort
{% endif %}
# AWX Ingress.
{% if 'ingress' == tower_ingress_type|lower %}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: '{{ meta.name }}-ingress'
namespace: '{{ meta.namespace }}'
{% if tower_ingress_annotations %}
annotations:
{{ tower_ingress_annotations | indent(width=4) }}
{% endif %}
spec:
rules:
- host: '{{ tower_hostname }}'
http:
paths:
- path: /
backend:
serviceName: '{{ meta.name }}-service'
servicePort: 80
{% if tower_ingress_tls_secret %}
tls:
- hosts:
- {{ tower_hostname }}
secretName: {{ tower_ingress_tls_secret }}
{% endif %}
{% endif %}
{% if 'route' == tower_ingress_type|lower %}
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
spec:
port:
targetPort: http
tls:
insecureEdgeTerminationPolicy: Redirect
termination: edge
to:
kind: Service
name: {{ meta.name }}-service
weight: 100
wildcardPolicy: None
{% endif %}

View File

@@ -1,79 +0,0 @@
# Postgres StatefulSet.
---
apiVersion: v1
kind: StatefulSet
metadata:
name: '{{ meta.name }}-postgres'
namespace: '{{ meta.namespace }}'
labels:
app: awx-postgres
spec:
selector:
matchLabels:
app: awx-postgres
serviceName: '{{ meta.name }}'
replicas: 1
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: awx-postgres
spec:
containers:
- image: '{{ tower_postgres_image }}'
name: postgres
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: database
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: password
- name: PGDATA
value: '{{ tower_postgres_data_path }}'
ports:
- containerPort: 5432
name: postgres
volumeMounts:
- name: postgres
mountPath: '{{ tower_postgres_data_path | dirname }}'
subPath: '{{ tower_postgres_data_path | dirname | basename }}'
volumeClaimTemplates:
- metadata:
name: postgres
spec:
accessModes:
- ReadWriteOnce
{% if tower_postgres_storage_class != '' %}
storageClassName: '{{ tower_postgres_storage_class }}'
{% endif %}
resources:
requests:
storage: '{{ tower_postgres_storage_request }}'
# Postgres Service.
---
apiVersion: v1
kind: Service
metadata:
name: '{{ meta.name }}-postgres'
namespace: '{{ meta.namespace }}'
labels:
app: awx-postgres
spec:
ports:
- port: 5432
clusterIP: None
selector:
app: awx-postgres

View File

@@ -1,13 +0,0 @@
# Postgres Secret.
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-postgres-configuration'
namespace: '{{ meta.namespace }}'
stringData:
password: '{{ lookup('password', 'p' + meta.name + 'pg length=32 chars=ascii_letters,digits') }}'
username: 'awx'
database: 'awx'
port: '5432'
host: {{ meta.name }}-postgres

View File

@@ -1,8 +0,0 @@
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-secret-key'
namespace: '{{ meta.namespace }}'
stringData:
secret_key: '{{ lookup('password', 'ts' + meta.name + 'pg length=32 chars=ascii_letters,digits') }}'

View File

@@ -1,36 +0,0 @@
---
- name: Check for existing secret key
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-secret-key'
register: secret_key_resources
- name: Check for existing postgres configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: postgres_config_resources
- name: Remove ownerReferences from PG configuration if it exists
k8s:
definition:
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-postgres-configuration'
namespace: '{{ meta.namespace }}'
ownerReferences: null
when: postgres_config_resources['resources'] | length > 0
- name: Remove ownerReferences from Tower Secret if it exists
k8s:
definition:
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-secret-key'
namespace: '{{ meta.namespace }}'
ownerReferences: null
when: secret_key_resources['resources'] | length > 0

View File

@@ -0,0 +1,21 @@
---
# Whether secrets should be garbage collected
# on teardown
#
tower_garbage_collect_secrets: false
# Secret to lookup that provide the admin password
#
tower_admin_password_secret: ''
# Secret to lookup that provide the secret key
#
tower_secret_key_secret: ''
# Secret to lookup that provide the PostgreSQL configuration
#
tower_postgres_configuration_secret: ''
# Secret to lookup that provide the broadcast websocket key
#
tower_broadcast_websocket_secret: ''

View File

@@ -0,0 +1,27 @@
---
- block:
- name: Define secrets name
set_fact:
_admin_password: '{{ tower_admin_password_secret | length | ternary(tower_admin_password_secret, meta.name + "-admin-password") }}'
_secret_key: '{{ tower_secret_key_secret | length | ternary(tower_secret_key_secret, meta.name + "-secret-key") }}'
# yamllint disable-line rule:line-length
_broadcast_websocket_secret: '{{ tower_broadcast_websocket_secret | length | ternary(tower_broadcast_websocket_secret, meta.name + "-broadcast-websocket") }}' # noqa 204
# yamllint disable-line rule:line-length
_postgres_configuration: '{{ tower_postgres_configuration_secret | length | ternary(tower_postgres_configuration_secret, meta.name + "-postgres-configuration") }}' # noqa 204
- name: Remove ownerReferences reference
k8s:
definition:
apiVersion: v1
kind: Secret
metadata:
name: '{{ item }}'
namespace: '{{ meta.namespace }}'
ownerReferences: null
loop:
- '{{ _admin_password }}'
- '{{ _secret_key }}'
- '{{ _postgres_configuration }}'
- '{{ _broadcast_websocket_secret }}'
when: not tower_garbage_collect_secrets | bool

View File

@@ -0,0 +1,185 @@
---
deployment_type: awx
kind: '{{ deployment_type | upper }}'
api_version: '{{ deployment_type }}.ansible.com/v1beta1'
database_name: "{{ deployment_type }}"
database_username: "{{ deployment_type }}"
tower_task_privileged: false
tower_ingress_type: none
# Add annotations to the ingress. Specify as literal block. E.g.:
# tower_ingress_annotations: |
# kubernetes.io/ingress.class: nginx
# nginx.ingress.kubernetes.io/proxy-connect-timeout: 60s
tower_ingress_annotations: ''
# TLS secret for the ingress. The secret either has to exist before hand with
# the corresponding cert and key or just be an indicator for where an automated
# process like cert-manager (enabled via annotations) will store the TLS
# certificate and key.
tower_ingress_tls_secret: ''
tower_loadbalancer_protocol: 'http'
tower_loadbalancer_port: '80'
# The TLS termination mechanism to use to access
# the services. Supported mechanism are: edge, passthrough
#
tower_route_tls_termination_mechanism: edge
# Secret to lookup that provide the TLS specific
# credentials to deploy
#
tower_route_tls_secret: ''
# Host to create the root with.
# If not specific will default to <instance-name>-<namespace>-<routerCanonicalHostname>
#
tower_route_host: ''
tower_hostname: '{{ deployment_type }}.example.com'
# Add a nodeSelector for the AWX pods. It must match a node's labels for the pod
# to be scheduled on that node. Specify as literal block. E.g.:
# tower_node_selector: |
# disktype: ssd
# kubernetes.io/arch: amd64
# kubernetes.io/os: linux
tower_node_selector: ''
# Add node tolerations for the AWX pods. Specify as literal block. E.g.:
# tower_tolerations: |
# - key: "dedicated"
# operator: "Equal"
# value: "AWX"
# effect: "NoSchedule"
tower_tolerations: ''
tower_admin_user: admin
tower_admin_email: test@example.com
# Secret to lookup that provide the admin password
#
tower_admin_password_secret: ''
# Secret to lookup that provide the broadcast websocket key
#
tower_broadcast_websocket_secret: ''
# Secret to lookup that provide the secret key
#
tower_secret_key_secret: ''
# Secret to lookup that provides old database credentials (for migration)
tower_old_postgres_configuration_secret: ''
# Add extra volumes to the AWX pod. Specify as literal block. E.g.:
# tower_extra_volumes: |
# - name: my-volume
# emptyDir: {}
tower_extra_volumes: ''
# Use these image versions for Ansible AWX.
tower_image: quay.io/ansible/awx
tower_image_version: 19.1.0
tower_redis_image: docker.io/redis
tower_redis_image_version: latest
tower_postgres_image: postgres
tower_postgres_image_version: 12
tower_image_pull_policy: IfNotPresent
tower_image_pull_secret: ''
tower_ee_images:
- name: AWX EE 0.2.0
image: quay.io/ansible/awx-ee:0.2.0
tower_create_preload_data: true
tower_replicas: "1"
tower_task_args:
- /usr/bin/launch_awx_task.sh
tower_task_command: []
tower_web_args: []
tower_web_command: []
tower_task_resource_requirements:
requests:
cpu: 500m
memory: 1Gi
tower_web_resource_requirements:
requests:
cpu: 1000m
memory: 2Gi
# Add extra environment variables to the AWX task/web containers. Specify as
# literal block. E.g.:
# tower_task_extra_env: |
# - name: FOO
# value: bar
# - name: BAZ
# value: bing
tower_task_extra_env: ''
tower_web_extra_env: ''
# Mount extra volumes on the AWX task/web containers. Specify as literal block.
# E.g.:
# tower_task_extra_volume_mounts: ''
# - name: my-volume
# mountPath: /some/path
tower_task_extra_volume_mounts: ''
tower_web_extra_volume_mounts: ''
tower_ee_extra_volume_mounts: ''
# Add a nodeSelector for the Postgres pods.
# It must match a node's labels for the pod to be scheduled on that node.
# Specify as literal block. E.g.:
# tower_postgres_selector: |
# disktype: ssd
# kubernetes.io/arch: amd64
# kubernetes.io/os: linux
tower_postgres_selector: ''
# Add node tolerations for the Postgres pods.
# Specify as literal block. E.g.:
# tower_postgres_tolerations: |
# - key: "dedicated"
# operator: "Equal"
# value: "AWX"
# effect: "NoSchedule"
tower_postgres_tolerations: ''
tower_postgres_storage_requirements:
requests:
storage: 8Gi
tower_postgres_resource_requirements: {}
tower_postgres_storage_class: ''
tower_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
tower_projects_persistence: false
#
# Define an existing PersistentVolumeClaim to use
tower_projects_existing_claim: ''
#
# Define the storage_class, size and access_mode
# when not using an existing claim
tower_projects_storage_class: ''
tower_projects_storage_size: 8Gi
tower_projects_storage_access_mode: ReadWriteMany
# Secret to lookup that provide the PostgreSQL configuration
#
tower_postgres_configuration_secret: ''
ca_trust_bundle: "/etc/pki/tls/certs/ca-bundle.crt"
# Secret to lookup that provides the LDAP CACert trusted bundle
#
ldap_cacert_secret: ''
development_mode: false

View File

@@ -29,3 +29,4 @@ dependencies: []
collections:
- community.kubernetes
- operator_sdk.util

View File

@@ -0,0 +1,42 @@
---
- name: Check for specified admin password configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_admin_password_secret }}'
register: _custom_admin_password
when: tower_admin_password_secret | length
- name: Check for default admin password configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-admin-password'
register: _default_admin_password
- name: Set admin password secret
set_fact:
_admin_password_secret: '{{ _custom_admin_password["resources"] | default([]) | length | ternary(_custom_admin_password, _default_admin_password) }}'
- block:
- name: Create admin password secret
k8s:
apply: true
definition: "{{ lookup('template', 'tower_admin_password_secret.yaml.j2') }}"
- name: Read admin password secret
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-admin-password'
register: _generated_admin_password
when: not _admin_password_secret['resources'] | default([]) | length
- name: Set admin password secret
set_fact:
admin_password_secret: '{{ _generated_admin_password["resources"] | default([]) | length | ternary(_generated_admin_password, _admin_password_secret) }}'
- name: Store admin password
set_fact:
tower_admin_password: "{{ admin_password_secret['resources'][0]['data']['password'] | b64decode }}"

View File

@@ -0,0 +1,44 @@
---
- name: Check for specified broadcast websocket secret configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_broadcast_websocket_secret }}'
register: _custom_broadcast_websocket
when: tower_broadcast_websocket_secret | length
- name: Check for default broadcast websocket secret configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-broadcast-websocket'
register: _default_broadcast_websocket
- name: Set broadcast websocket secret
set_fact:
# yamllint disable-line rule:line-length
_broadcast_websocket_secret: '{{ _custom_broadcast_websocket["resources"] | default([]) | length | ternary(_custom_broadcast_websocket, _default_broadcast_websocket) }}' # noqa 204
- block:
- name: Create broadcast websocket secret
k8s:
apply: true
definition: "{{ lookup('template', 'tower_broadcast_websocket_secret.yaml.j2') }}"
- name: Read broadcast websocket secret
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-broadcast-websocket'
register: _generated_broadcast_websocket
when: not _broadcast_websocket_secret['resources'] | default([]) | length
- name: Set broadcast websocket secret
set_fact:
# yamllint disable-line rule:line-length
broadcast_websocket_secret: '{{ _generated_broadcast_websocket["resources"] | default([]) | length | ternary(_generated_broadcast_websocket, _broadcast_websocket_secret) }}' # noqa 204
- name: Store broadcast websocket secret name
set_fact:
broadcast_websocket_secret_value: "{{ broadcast_websocket_secret['resources'][0]['data']['secret'] | b64decode }}"

View File

@@ -0,0 +1,126 @@
---
- name: Check for specified PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_postgres_configuration_secret }}'
register: _custom_pg_config_resources
when: tower_postgres_configuration_secret | length
- name: Check for default PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: _default_pg_config_resources
- name: Check for specified old PostgreSQL configuration secret
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_old_postgres_configuration_secret }}'
register: _custom_old_pg_config_resources
when: tower_old_postgres_configuration_secret | length
- name: Check for default old PostgreSQL configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-old-postgres-configuration'
register: _default_old_pg_config_resources
- name: Set old PostgreSQL configuration
set_fact:
# yamllint disable-line rule:line-length
old_pg_config: '{{ _custom_old_pg_config_resources["resources"] | default([]) | length | ternary(_custom_old_pg_config_resources, _default_old_pg_config_resources) }}' # noqa 204
- name: Set proper database name when migrating from old deployment
set_fact:
database_name: "{{ old_pg_config['resources'][0]['data']['database'] | b64decode }}"
database_username: "{{ old_pg_config['resources'][0]['data']['username'] | b64decode }}"
when:
- old_pg_config['resources'] is defined
- old_pg_config['resources'] | length
- name: Set PostgreSQL configuration
set_fact:
_pg_config: '{{ _custom_pg_config_resources["resources"] | default([]) | length | ternary(_custom_pg_config_resources, _default_pg_config_resources) }}'
- block:
- name: Create Database configuration
k8s:
apply: true
definition: "{{ lookup('template', 'tower_postgres_secret.yaml.j2') }}"
- name: Read Database Configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: _generated_pg_config_resources
when: not _pg_config['resources'] | default([]) | length
- name: Set PostgreSQL Configuration
set_fact:
pg_config: '{{ _generated_pg_config_resources["resources"] | default([]) | length | ternary(_generated_pg_config_resources, _pg_config) }}'
- block:
- name: Create Database if no database is specified
k8s:
apply: true
definition: "{{ lookup('template', 'tower_postgres.yaml.j2') }}"
register: create_statefulset_result
rescue:
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
- name: Scale down PostgreSQL statefulset for migration
community.kubernetes.k8s_scale:
api_version: apps/v1
kind: StatefulSet
name: "{{ meta.name }}-postgres"
namespace: "{{ meta.namespace }}"
replicas: 0
wait: yes
- name: Remove PostgreSQL statefulset for upgrade
k8s:
state: absent
api_version: apps/v1
kind: StatefulSet
name: "{{ meta.name }}-postgres"
namespace: "{{ meta.namespace }}"
wait: yes
when: create_statefulset_result.error == 422
- name: Recreate PostgreSQL statefulset with updated values
k8s:
apply: true
definition: "{{ lookup('template', 'tower_postgres.yaml.j2') }}"
when: pg_config['resources'][0]['data']['type'] | default('') | b64decode == 'managed'
- name: Store Database Configuration
set_fact:
awx_postgres_user: "{{ pg_config['resources'][0]['data']['username'] | b64decode }}"
awx_postgres_pass: "{{ pg_config['resources'][0]['data']['password'] | b64decode }}"
awx_postgres_database: "{{ pg_config['resources'][0]['data']['database'] | b64decode }}"
awx_postgres_port: "{{ pg_config['resources'][0]['data']['port'] | b64decode }}"
awx_postgres_host: "{{ pg_config['resources'][0]['data']['host'] | b64decode }}"
awx_postgres_sslmode: "{{ pg_config['resources'][0]['data']['sslmode'] | default('prefer'|b64encode) | b64decode }}"
- name: Look up details for this deployment
k8s_info:
api_version: 'v1beta1' # TODO: How to parameterize this?
kind: "AWX" # TODO: How to parameterize this?
name: "{{ meta.name }}"
namespace: "{{ 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']['towerMigratedFromSecret'] is not defined

View File

@@ -23,7 +23,6 @@
User.objects.create_superuser('{{ tower_admin_user }}', '{{ tower_admin_email }}', '{{ tower_admin_password }}')\"
| awx-manage shell"
when: users_result.return_code > 0
no_log: true
- name: Create preload data if necessary. # noqa 305
community.kubernetes.k8s_exec:

View File

@@ -0,0 +1,12 @@
---
- name: Retrieve LDAP CA Certificate Secret
community.kubernetes.k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ ldap_cacert_secret }}'
register: ldap_cacert
- name: Load LDAP CA Certificate Secret content
set_fact:
ldap_cacert_ca_crt: '{{ ldap_cacert["resources"][0]["data"]["ldap-ca.crt"] | b64decode }}'
when: '"ldap-ca.crt" in ldap_cacert["resources"][0]["data"]'

View File

@@ -0,0 +1,17 @@
---
- name: Retrieve Route TLS Secret
community.kubernetes.k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_route_tls_secret }}'
register: route_tls
- name: Load Route TLS Secret content
set_fact:
tower_route_tls_key: '{{ route_tls["resources"][0]["data"]["tls.key"] | b64decode }}'
tower_route_tls_crt: '{{ route_tls["resources"][0]["data"]["tls.crt"] | b64decode }}'
- name: Load Route TLS Secret content
set_fact:
tower_route_ca_crt: '{{ route_tls["resources"][0]["data"]["ca.crt"] | b64decode }}'
when: '"ca.crt" in route_tls["resources"][0]["data"]'

View File

@@ -0,0 +1,71 @@
---
- name: Patching labels to AWX kind
k8s:
state: present
definition:
apiVersion: '{{ api_version }}'
kind: '{{ kind }}'
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
- name: Include secret key configuration tasks
include_tasks: secret_key_configuration.yml
- name: Load LDAP CAcert certificate
include_tasks: load_ldap_cacert_secret.yml
when:
- ldap_cacert_secret != ''
- name: Include admin password configuration tasks
include_tasks: admin_password_configuration.yml
- name: Include broadcast websocket configuration tasks
include_tasks: broadcast_websocket_configuration.yml
- name: Include database configuration tasks
include_tasks: database_configuration.yml
- name: Load Route TLS certificate
include_tasks: load_route_tls_secret.yml
when:
- tower_ingress_type | lower == 'route'
- tower_route_tls_secret != ''
- name: Include resources configuration tasks
include_tasks: resources_configuration.yml
- name: Check for pending migrations
k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ tower_pod_name }}"
container: "{{ meta.name }}-task"
command: >-
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
changed_when: false
register: database_check
- name: Migrate the database if the K8s resources were updated. # noqa 305
k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ tower_pod_name }}"
container: "{{ meta.name }}-task"
command: >-
bash -c "awx-manage migrate --noinput"
register: migrate_result
when:
- database_check is defined
- (database_check.stdout|trim) != '0'
- name: Initialize Django
include_tasks: initialize_django.yml
- name: Update status variables
include_tasks: update_status.yml

View File

@@ -0,0 +1,61 @@
---
- name: Store Database Configuration
set_fact:
tower_old_postgres_user: "{{ old_pg_config['resources'][0]['data']['username'] | b64decode }}"
tower_old_postgres_pass: "{{ old_pg_config['resources'][0]['data']['password'] | b64decode }}"
tower_old_postgres_database: "{{ old_pg_config['resources'][0]['data']['database'] | b64decode }}"
tower_old_postgres_port: "{{ old_pg_config['resources'][0]['data']['port'] | b64decode }}"
tower_old_postgres_host: "{{ old_pg_config['resources'][0]['data']['host'] | b64decode }}"
- name: Get the postgres pod information
k8s_info:
kind: Pod
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-0' # using name to keep compatibility
field_selectors:
- status.phase=Running
register: postgres_pod
until: postgres_pod['resources'] | length
delay: 5
retries: 60
- name: Set the resource pod name as a variable.
set_fact:
postgres_pod_name: "{{ postgres_pod['resources'][0]['metadata']['name'] }}"
- name: Scale down Deployment for migration
include_tasks: scale_down_deployment.yml
- name: Set pg_dump command
set_fact:
pgdump: >-
pg_dump --clean --create
-h {{ tower_old_postgres_host }}
-U {{ tower_old_postgres_user }}
-d {{ tower_old_postgres_database }}
-p {{ tower_old_postgres_port }}
- name: Set pg_restore command
set_fact:
psql_restore: >-
psql -U {{ database_username }}
-d template1
-p {{ awx_postgres_port }}
- name: Stream backup from pg_dump to the new postgresql container
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ postgres_pod_name }}"
command: |
bash -c """
set -e -o pipefail
PGPASSWORD={{ tower_old_postgres_pass }} {{ pgdump }} | PGPASSWORD={{ awx_postgres_pass }} {{ psql_restore }}
echo 'Successful'
"""
register: data_migration
failed_when: "'Successful' not in data_migration.stdout"
- name: Set flag signifying that this instance has been migrated
set_fact:
tower_migrated_from_secret: "{{ tower_old_postgres_configuration_secret }}"

View File

@@ -0,0 +1,80 @@
---
- name: Get the current resource pod information.
k8s_info:
api_version: v1
kind: Pod
namespace: '{{ meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ meta.name }}"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
- "app.kubernetes.io/component={{ deployment_type }}"
field_selectors:
- status.phase=Running
register: tower_pods
- name: Set the resource pod name as a variable.
set_fact:
tower_pod_name: "{{ tower_pods['resources'][0]['metadata']['name'] | default('') }}"
- name: Apply Resources
k8s:
apply: yes
definition: "{{ lookup('template', item + '.yaml.j2') }}"
wait: yes
register: tower_resources_result
loop:
- 'tower_config'
- 'tower_app_credentials'
- 'tower_service_account'
- 'tower_persistent'
- 'tower_service'
- 'tower_ingress'
- name: Apply deployment resources
k8s:
apply: yes
definition: "{{ lookup('template', 'tower_deployment.yaml.j2') }}"
wait: yes
register: tower_deployment_result
- block:
- name: Delete pod to reload a resource configuration
k8s:
api_version: v1
state: absent
kind: Pod
namespace: '{{ meta.namespace }}'
name: '{{ tower_pod_name }}'
wait: yes
when:
- tower_resources_result.changed
- tower_pod_name | length
- name: Get the new resource pod information after updating resource.
k8s_info:
kind: Pod
namespace: '{{ meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ meta.name }}"
- "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'][0]['metadata']['name'] != tower_pod_name
delay: 5
retries: 60
- name: Update new resource pod name as a variable.
set_fact:
tower_pod_name: '{{ _new_pod["resources"][0]["metadata"]["name"] }}'
when:
- tower_resources_result.changed or tower_deployment_result.changed
- name: Verify the resource pod name is populated.
assert:
that: tower_pod_name != ''
fail_msg: "Could not find the tower pod's name."

View File

@@ -0,0 +1,19 @@
---
- name: Check for presence of Deployment
k8s_info:
api_version: v1
kind: Deployment
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
register: tower_deployment
- name: Scale down Deployment for migration
community.kubernetes.k8s_scale:
api_version: v1
kind: Deployment
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
replicas: 0
wait: yes
when: tower_deployment['resources'] | length

View File

@@ -0,0 +1,42 @@
---
- name: Check for specified secret key configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_secret_key_secret }}'
register: _custom_secret_key
when: tower_secret_key_secret | length
- name: Check for default secret key configuration
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-secret-key'
register: _default_secret_key
- name: Set secret key secret
set_fact:
_secret_key_secret: '{{ _custom_secret_key["resources"] | default([]) | length | ternary(_custom_secret_key, _default_secret_key) }}'
- block:
- name: Create secret key secret
k8s:
apply: true
definition: "{{ lookup('template', 'tower_secret_key.yaml.j2') }}"
- name: Read secret key secret
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-secret-key'
register: _generated_secret_key
when: not _secret_key_secret['resources'] | default([]) | length
- name: Set secret key secret
set_fact:
secret_key_secret: '{{ _generated_secret_key["resources"] | default([]) | length | ternary(_generated_secret_key, _secret_key_secret) }}'
- name: Store secret key secret name
set_fact:
secret_key_secret_name: "{{ secret_key_secret['resources'][0]['metadata']['name'] }}"

View File

@@ -0,0 +1,75 @@
---
- name: Update admin password status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerAdminPasswordSecret: "{{ admin_password_secret['resources'][0]['metadata']['name'] }}"
- name: Update admin user status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerAdminUser: "{{ tower_admin_user }}"
- name: Retrieve instance version
community.kubernetes.k8s_exec:
namespace: "{{ meta.namespace }}"
pod: "{{ tower_pod_name }}"
container: "{{ meta.name }}-task"
command: >-
bash -c "awx-manage --version"
register: instance_version
changed_when: false
- name: Update version status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerVersion: "{{ instance_version.stdout | trim }}"
- name: Update image status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerImage: "{{ tower_image }}"
- block:
- name: Retrieve route URL
community.kubernetes.k8s_info:
kind: Route
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}'
register: route_url
- name: Update URL status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerURL: "https://{{ route_url['resources'][0]['status']['ingress'][0]['host'] }}"
when: tower_ingress_type | lower == 'route'
- name: Update towerMigratedFromSecret status
operator_sdk.util.k8s_status:
api_version: '{{ api_version }}'
kind: "{{ kind }}"
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
status:
towerMigratedFromSecret: "{{ tower_migrated_from_secret }}"
when: tower_migrated_from_secret is defined

View File

@@ -7,10 +7,10 @@ DATABASES = {
'PASSWORD': "{{ awx_postgres_pass }}",
'HOST': '{{ awx_postgres_host }}',
'PORT': "{{ awx_postgres_port }}",
'OPTIONS': { 'sslmode': '{{ pg_sslmode|default("prefer") }}',
'OPTIONS': { 'sslmode': '{{ awx_postgres_sslmode }}',
'sslrootcert': '{{ ca_trust_bundle }}',
},
}
}
BROADCAST_WEBSOCKET_SECRET = "{{ tower_broadcast_websocket_secret | b64encode }}"
BROADCAST_WEBSOCKET_SECRET = "{{ broadcast_websocket_secret_value }}"

View File

@@ -0,0 +1,5 @@
DEFAULT_EXECUTION_ENVIRONMENTS = [
{% for item in tower_ee_images %}
{'name': '{{ item.name }}' , 'image': '{{ item.image }}'},
{% endfor %}
]

View File

@@ -0,0 +1,6 @@
AUTH_LDAP_GLOBAL_OPTIONS = {
{% if ldap_cacert_ca_crt %}
ldap.OPT_X_TLS_REQUIRE_CERT: True,
ldap.OPT_X_TLS_CACERTFILE: "/etc/openldap/certs/ldap-ca.crt"
{% endif %}
}

View File

@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-admin-password'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
stringData:
password: '{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}'

View File

@@ -0,0 +1,16 @@
# AWX Secret Configurations
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-app-credentials'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
data:
credentials.py: "{{ lookup('template', 'credentials.py.j2') | b64encode }}"
ldap.py: "{{ lookup('template', 'ldap.py.j2') | b64encode }}"
execution_environments.py: "{{ lookup('template', 'execution_environments.py.j2') | b64encode }}"

View File

@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-broadcast-websocket'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
stringData:
secret: '{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}'

View File

@@ -3,17 +3,15 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: '{{ meta.name }}-awx-configmap'
name: '{{ meta.name }}-{{ deployment_type }}-configmap'
namespace: '{{ meta.namespace }}'
labels:
app: awx
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
data:
environment: |
DATABASE_USER=awx
DATABASE_NAME=awx
DATABASE_HOST='{{ meta.name }}-postgres.{{ meta.namespace }}.svc.cluster.local'
DATABASE_PORT='5432'
DATABASE_PASSWORD={{ tower_postgres_pass | quote }}
AWX_SKIP_MIGRATIONS=true
settings: |
@@ -28,7 +26,9 @@ data:
STATIC_ROOT = '/var/lib/awx/public/static'
PROJECTS_ROOT = '/var/lib/awx/projects'
JOBOUTPUT_ROOT = '/var/lib/awx/job_status'
IS_K8S = True
SECRET_KEY = get_secret()
ALLOWED_HOSTS = ['*']
@@ -64,6 +64,7 @@ data:
'()': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'simple',
'filters': ['guid'],
}
LOGGING['loggers']['django.request']['handlers'] = ['console']
@@ -76,33 +77,21 @@ data:
LOGGING['loggers']['social']['handlers'] = ['console']
LOGGING['loggers']['system_tracking_migrations']['handlers'] = ['console']
LOGGING['loggers']['rbac_migrations']['handlers'] = ['console']
LOGGING['loggers']['awx.isolated.manager.playbooks']['handlers'] = ['console']
LOGGING['handlers']['callback_receiver'] = {'class': 'logging.NullHandler'}
LOGGING['handlers']['task_system'] = {'class': 'logging.NullHandler'}
LOGGING['handlers']['tower_warnings'] = {'class': 'logging.NullHandler'}
LOGGING['handlers']['rbac_migrations'] = {'class': 'logging.NullHandler'}
LOGGING['handlers']['system_tracking_migrations'] = {'class': 'logging.NullHandler'}
LOGGING['handlers']['management_playbooks'] = {'class': 'logging.NullHandler'}
DATABASES = {
'default': {
'ATOMIC_REQUESTS': True,
'ENGINE': 'awx.main.db.profiled_pg',
'NAME': 'awx',
'USER': 'awx',
'PASSWORD': '{{ tower_postgres_pass | quote }}',
'HOST': '{{ meta.name }}-postgres.{{ meta.namespace }}.svc.cluster.local',
'PORT': '5432',
}
}
if os.getenv("DATABASE_SSLMODE", False):
DATABASES['default']['OPTIONS'] = {'sslmode': os.getenv("DATABASE_SSLMODE")}
USE_X_FORWARDED_PORT = True
BROADCAST_WEBSOCKET_PORT = 8052
BROADCAST_WEBSOCKET_PROTOCOL = 'http'
{% for item in extra_settings | default([]) %}
{{ item.setting }} = {{ item.value }}
{% endfor %}
nginx_conf: |
worker_processes 1;
pid /tmp/nginx.pid;
@@ -139,9 +128,27 @@ data:
server 127.0.0.1:8051;
}
{% if tower_route_tls_termination_mechanism | lower == 'passthrough' %}
server {
listen 8052 default_server;
server_name _;
# Redirect all HTTP links to the matching HTTPS page
return 301 https://$host$request_uri;
}
{% endif %}
server {
{% if tower_route_tls_termination_mechanism | lower == 'passthrough' %}
listen 8053 ssl;
ssl_certificate /etc/nginx/pki/web.crt;
ssl_certificate_key /etc/nginx/pki/web.key;
{% else %}
listen 8052 default_server;
{% endif %}
# If you have a domain name, this is where to add it
server_name _;
keepalive_timeout 65;
@@ -210,3 +217,33 @@ data:
unixsocketperm 777
port 0
bind 127.0.0.1
receptor_conf: |
---
- log-level: debug
- control-service:
service: control
filename: /var/run/receptor/receptor.sock
permissions: 0660
- local-only:
- work-command:
worktype: local
command: ansible-runner
params: worker
allowruntimeparams: true
- work-kubernetes:
worktype: kubernetes-runtime-auth
authmethod: runtime
allowruntimeauth: true
allowruntimepod: true
allowruntimeparams: true
- work-kubernetes:
worktype: kubernetes-incluster-auth
authmethod: incluster
allowruntimeauth: true
allowruntimepod: true
allowruntimeparams: true

View File

@@ -0,0 +1,327 @@
# AWX Deployment.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/version: '{{ tower_image_version }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
spec:
replicas: {{ tower_replicas }}
selector:
matchLabels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
template:
metadata:
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/version: '{{ tower_image_version }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
spec:
serviceAccountName: '{{ meta.name }}'
{% if tower_image_pull_secret %}
imagePullSecrets:
- name: {{ tower_image_pull_secret }}
{% endif %}
containers:
- image: '{{ tower_redis_image }}:{{ tower_redis_image_version }}'
imagePullPolicy: '{{ tower_image_pull_policy }}'
name: redis
args: ["redis-server", "/etc/redis.conf"]
volumeMounts:
- name: {{ meta.name }}-redis-config
mountPath: "/etc/redis.conf"
subPath: redis.conf
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- name: "{{ meta.name }}-redis-data"
mountPath: "/data"
- image: '{{ tower_image }}:{{ tower_image_version }}'
name: '{{ meta.name }}-web'
{% if tower_web_command %}
command: {{ tower_web_command }}
{% endif %}
{% if tower_web_args %}
args: {{ tower_web_args }}
{% endif %}
imagePullPolicy: '{{ tower_image_pull_policy }}'
ports:
- containerPort: 8052
{% if tower_ingress_type | lower == 'route' and tower_route_tls_termination_mechanism | lower == 'passthrough' %}
- containerPort: 8053
{% endif %}
volumeMounts:
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/execution_environments.py"
subPath: execution_environments.py
readOnly: true
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/ldap.py"
subPath: ldap.py
readOnly: true
{% if tower_ingress_type | lower == 'route' and tower_route_tls_termination_mechanism | lower == 'passthrough' %}
- name: "{{ meta.name }}-nginx-certs"
mountPath: "/etc/nginx/pki"
readOnly: true
{% endif %}
{% if ldap_cacert_ca_crt %}
- name: "{{ meta.name }}-ldap-cacert"
mountPath: /etc/openldap/certs/ldap-ca.crt
subPath: ldap-ca.crt
readOnly: true
{% endif %}
- name: "{{ secret_key_secret_name }}"
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
- name: {{ meta.name }}-nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- name: supervisor-socket
mountPath: "/var/run/supervisor"
- name: rsyslog-socket
mountPath: "/var/run/awx-rsyslog"
- name: rsyslog-dir
mountPath: "/var/lib/awx/rsyslog"
- name: "{{ meta.name }}-projects"
mountPath: "/var/lib/awx/projects"
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
{% if tower_web_extra_volume_mounts -%}
{{ tower_web_extra_volume_mounts | indent(width=12, indentfirst=True) }}
{% endif %}
env:
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{% if development_mode | bool %}
- name: AWX_KUBE_DEVEL
value: "1"
{% endif %}
{% if tower_web_extra_env -%}
{{ tower_web_extra_env | indent(width=12, indentfirst=True) }}
{% endif %}
resources: {{ tower_web_resource_requirements }}
- image: '{{ tower_image }}:{{ tower_image_version }}'
name: '{{ meta.name }}-task'
imagePullPolicy: '{{ tower_image_pull_policy }}'
{% if tower_task_privileged == true %}
securityContext:
privileged: true
{% endif %}
{% if tower_task_command %}
command: {{ tower_task_command }}
{% endif %}
{% if tower_task_args %}
args: {{ tower_task_args }}
{% endif %}
volumeMounts:
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/execution_environments.py"
subPath: execution_environments.py
readOnly: true
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/credentials.py"
subPath: credentials.py
readOnly: true
- name: "{{ meta.name }}-application-credentials"
mountPath: "/etc/tower/conf.d/ldap.py"
subPath: ldap.py
readOnly: true
- name: "{{ secret_key_secret_name }}"
mountPath: /etc/tower/SECRET_KEY
subPath: SECRET_KEY
readOnly: true
- name: {{ meta.name }}-settings
mountPath: /etc/tower/settings.py
subPath: settings.py
readOnly: true
- name: {{ meta.name }}-redis-socket
mountPath: "/var/run/redis"
- name: supervisor-socket
mountPath: "/var/run/supervisor"
- name: rsyslog-socket
mountPath: "/var/run/awx-rsyslog"
- name: rsyslog-dir
mountPath: "/var/lib/awx/rsyslog"
- name: receptor-socket
mountPath: "/var/run/receptor"
- name: "{{ meta.name }}-projects"
mountPath: "/var/lib/awx/projects"
{% if development_mode | bool %}
- name: awx-devel
mountPath: "/awx_devel"
{% endif %}
{% if tower_task_extra_volume_mounts -%}
{{ tower_task_extra_volume_mounts | indent(width=12, indentfirst=True) }}
{% endif %}
env:
- name: SUPERVISOR_WEB_CONFIG_PATH
value: "/etc/supervisord.conf"
- name: AWX_SKIP_MIGRATIONS
value: "1"
- name: MY_POD_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{% if development_mode | bool %}
- name: AWX_KUBE_DEVEL
value: "1"
{% endif %}
{% if tower_task_extra_env -%}
{{ tower_task_extra_env | indent(width=12, indentfirst=True) }}
{% endif %}
resources: {{ tower_task_resource_requirements }}
- image: '{{ tower_ee_images[0].image }}'
name: '{{ meta.name }}-ee'
imagePullPolicy: '{{ tower_image_pull_policy }}'
args: ['receptor', '--config', '/etc/receptor.conf']
volumeMounts:
- name: "{{ meta.name }}-receptor-config"
mountPath: "/etc/receptor.conf"
subPath: receptor.conf
readOnly: true
- name: receptor-socket
mountPath: "/var/run/receptor"
- name: "{{ meta.name }}-projects"
mountPath: "/var/lib/awx/projects"
{% if tower_ee_extra_volume_mounts -%}
{{ tower_ee_extra_volume_mounts | indent(width=12, indentfirst=True) }}
{% endif %}
{% if development_mode | bool %}
env:
- name: SDB_NOTIFY_HOST
valueFrom:
fieldRef:
fieldPath: status.podIP
{% endif %}
{% if tower_node_selector %}
nodeSelector:
{{ tower_node_selector | indent(width=8) }}
{% endif %}
{% if tower_tolerations %}
tolerations:
{{ tower_tolerations | indent(width=8) }}
{% endif %}
volumes:
{% if tower_ingress_type | lower == 'route' and tower_route_tls_termination_mechanism | lower == 'passthrough' %}
- name: "{{ meta.name }}-nginx-certs"
secret:
secretName: "{{ tower_route_tls_secret }}"
items:
- key: tls.key
path: 'web.key'
- key: tls.crt
path: 'web.crt'
{% endif %}
{% if ldap_cacert_ca_crt %}
- name: "{{ meta.name }}-ldap-cacert"
secret:
secretName: "{{ ldap_cacert_secret }}"
items:
- key: ldap-ca.crt
path: 'ldap-ca.crt'
{% endif %}
- name: "{{ meta.name }}-application-credentials"
secret:
secretName: "{{ 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: {{ meta.name }}-settings
configMap:
name: '{{ meta.name }}-{{ deployment_type }}-configmap'
items:
- key: settings
path: settings.py
- name: {{ meta.name }}-nginx-conf
configMap:
name: '{{ meta.name }}-{{ deployment_type }}-configmap'
items:
- key: nginx_conf
path: nginx.conf
- name: {{ meta.name }}-redis-config
configMap:
name: {{ meta.name }}-{{ deployment_type }}-configmap
items:
- key: redis_conf
path: redis.conf
- name: {{ meta.name }}-redis-socket
emptyDir: {}
- name: {{ meta.name }}-redis-data
emptyDir: {}
- name: supervisor-socket
emptyDir: {}
- name: rsyslog-socket
emptyDir: {}
- name: receptor-socket
emptyDir: {}
- name: rsyslog-dir
emptyDir: {}
- name: {{ meta.name }}-receptor-config
configMap:
name: '{{ meta.name }}-{{ deployment_type }}-configmap'
items:
- key: receptor_conf
path: receptor.conf
- name: "{{ meta.name }}-projects"
{% if tower_projects_persistence|bool %}
persistentVolumeClaim:
{% if tower_projects_existing_claim %}
claimName: {{ tower_projects_existing_claim }}
{% else %}
claimName: '{{ meta.name }}-projects-claim'
{% endif %}
{% else %}
emptyDir: {}
{% endif %}
{% if development_mode | bool %}
- name: awx-devel
hostPath:
path: /awx_devel
{% endif %}
{% if tower_extra_volumes -%}
{{ tower_extra_volumes | indent(width=8, indentfirst=True) }}
{% endif %}

View File

@@ -0,0 +1,70 @@
{% if 'ingress' == tower_ingress_type|lower %}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: '{{ meta.name }}-ingress'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
{% if tower_ingress_annotations %}
annotations:
{{ tower_ingress_annotations | indent(width=4) }}
{% endif %}
spec:
rules:
- host: '{{ tower_hostname }}'
http:
paths:
- path: /
backend:
serviceName: '{{ meta.name }}-service'
servicePort: 80
{% if tower_ingress_tls_secret %}
tls:
- hosts:
- {{ tower_hostname }}
secretName: {{ tower_ingress_tls_secret }}
{% endif %}
{% endif %}
{% if 'route' == tower_ingress_type|lower %}
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
spec:
{% if tower_route_host != '' %}
host: {{ tower_route_host }}
{% endif %}
port:
targetPort: '{{ (tower_route_tls_termination_mechanism | lower == "passthrough") | ternary("https", "http") }}'
tls:
insecureEdgeTerminationPolicy: Redirect
termination: {{ tower_route_tls_termination_mechanism | lower }}
{% if tower_route_tls_termination_mechanism | lower == 'edge' and tower_route_tls_secret != '' %}
key: |-
{{ tower_route_tls_key | indent(width=6, indentfirst=True) }}
certificate: |-
{{ tower_route_tls_crt | indent(width=6, indentfirst=True) }}
{% if tower_route_ca_crt is defined %}
caCertificate: |-
{{ tower_route_ca_crt | indent(width=6, indentfirst=True) }}
{% endif %}
{% endif %}
to:
kind: Service
name: {{ meta.name }}-service
weight: 100
wildcardPolicy: None
{% endif %}

View File

@@ -0,0 +1,21 @@
{% if tower_projects_persistence|bool and tower_projects_existing_claim == '' %}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: '{{ meta.name }}-projects-claim'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
spec:
accessModes:
- {{ tower_projects_storage_access_mode }}
resources:
requests:
storage: {{ tower_projects_storage_size }}
{% if tower_projects_storage_class != '' %}
storageClassName: {{ tower_projects_storage_class }}
{% endif %}
{% endif %}

View File

@@ -0,0 +1,120 @@
# Postgres StatefulSet.
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: '{{ meta.name }}-postgres'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}-postgres'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: database
spec:
selector:
matchLabels:
app.kubernetes.io/name: '{{ meta.name }}-postgres'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: database
serviceName: '{{ meta.name }}'
replicas: 1
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/name: '{{ meta.name }}-postgres'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: database
spec:
containers:
- image: '{{ tower_postgres_image }}:{{ tower_postgres_image_version }}'
name: postgres
env:
# For tower_postgres_image based on rhel8/postgresql-12
- name: POSTGRESQL_DATABASE
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: database
- name: POSTGRESQL_USER
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: username
- name: POSTGRESQL_PASSWORD
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: password
# For tower_postgres_image based on postgres
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: database
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: '{{ meta.name }}-postgres-configuration'
key: password
- name: PGDATA
value: '{{ tower_postgres_data_path }}'
- name: POSTGRES_INITDB_ARGS
value: '{{ postgres_initdb_args }}'
- name: POSTGRES_HOST_AUTH_METHOD
value: '{{ postgres_host_auth_method }}'
ports:
- containerPort: 5432
name: postgres
volumeMounts:
- name: postgres
mountPath: '{{ tower_postgres_data_path | dirname }}'
subPath: '{{ tower_postgres_data_path | dirname | basename }}'
resources: {{ tower_postgres_resource_requirements }}
{% if tower_postgres_selector %}
nodeSelector:
{{ tower_postgres_selector | indent(width=8) }}
{% endif %}
{% if tower_postgres_tolerations %}
tolerations:
{{ tower_postgres_tolerations | indent(width=8) }}
{% endif %}
volumeClaimTemplates:
- metadata:
name: postgres
spec:
accessModes:
- ReadWriteOnce
{% if tower_postgres_storage_class != '' %}
storageClassName: '{{ tower_postgres_storage_class }}'
{% endif %}
resources: {{ tower_postgres_storage_requirements }}
# Postgres Service.
---
apiVersion: v1
kind: Service
metadata:
name: '{{ meta.name }}-postgres'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}-postgres'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: database
spec:
ports:
- port: 5432
clusterIP: None
selector:
app.kubernetes.io/name: '{{ meta.name }}-postgres'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: database

View File

@@ -0,0 +1,19 @@
# Postgres Secret.
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-postgres-configuration'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
stringData:
password: '{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}'
username: '{{ database_username }}'
database: '{{ database_name }}'
port: '5432'
host: {{ meta.name }}-postgres
type: 'managed'

View File

@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
name: '{{ meta.name }}-secret-key'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
stringData:
secret_key: '{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}'

View File

@@ -0,0 +1,51 @@
---
apiVersion: v1
kind: Service
metadata:
name: '{{ meta.name }}-service'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
{% if tower_ingress_type | lower == 'loadbalancer' and tower_loadbalancer_annotations %}
annotations:
{{ tower_loadbalancer_annotations | indent(width=4) }}
{% endif %}
spec:
ports:
{% if tower_ingress_type | lower != 'loadbalancer' and tower_loadbalancer_protocol | lower != 'https' %}
- port: 80
protocol: TCP
targetPort: 8052
name: http
{% endif %}
{% if tower_ingress_type | lower == 'route' and tower_route_tls_termination_mechanism | lower == 'passthrough' %}
- port: 443
protocol: TCP
targetPort: 8053
name: https
{% endif %}
{% if tower_ingress_type | lower == 'loadbalancer' and tower_loadbalancer_protocol | lower == 'https' %}
- port: {{ tower_loadbalancer_port }}
protocol: TCP
targetPort: 8052
name: https
{% elif tower_ingress_type | lower == 'loadbalancer' and tower_loadbalancer_protocol | lower != 'https' %}
- port: {{ tower_loadbalancer_port }}
protocol: TCP
targetPort: 8052
name: http
{% endif %}
selector:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
{% if tower_ingress_type | lower == "loadbalancer" %}
type: LoadBalancer
{% elif tower_ingress_type != "none" %}
type: NodePort
{% else %}
type: ClusterIP
{% endif %}

View File

@@ -0,0 +1,41 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
labels:
app.kubernetes.io/name: '{{ meta.name }}'
app.kubernetes.io/part-of: '{{ meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: [""]
resources: ["pods/attach"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: '{{ meta.name }}'
namespace: '{{ meta.namespace }}'
subjects:
- kind: ServiceAccount
name: '{{ meta.name }}'
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: '{{ meta.name }}'

View File

@@ -0,0 +1,5 @@
---
postgres_initdb_args: '--auth-host=scram-sha-256'
postgres_host_auth_method: 'scram-sha-256'
ldap_cacert_ca_crt: ''
tower_projects_existing_claim: ''

117
scripts/build.sh Executable file
View File

@@ -0,0 +1,117 @@
#!/bin/bash
## This script will be build 3 images awx-{operator,bundle,catalog}
## and push to the $REGISTRY specified.
##
## The goal is provide an quick way to build a test image.
##
## Example:
##
## git clone https://github.com/ansible/awx-operator.git
## cd awx-operator
## REGISTRY=registry.example.com/ansible TAG=mytag scripts/build.sh
##
## As a result, the $REGISTRY will be populated with 2 images
## registry.example.com/ansible/awx-operator:mytag
## registry.example.com/ansible/awx-operator-bundle:mytag
## registry.example.com/ansible/awx-operator-catalog:mytag
OPERATOR_IMAGE=${OPERATOR_IMAGE:-awx-operator}
BUNDLE_IMAGE=${BUNDLE_IMAGE:-awx-operator-bundle}
CATALOG_IMAGE=${CATALOG_IMAGE:-awx-operator-catalog}
verify_podman_binary() {
if hash podman 2>/dev/null; then
POD_MANAGER="podman"
else
POD_MANAGER="docker"
fi
}
verify_operator_sdk_binary() {
if hash operator-sdk 2>/dev/null; then
OPERATOR_SDK="$(which operator-sdk)"
else
echo "operator-sdk binary not found."
echo "Please visit https://sdk.operatorframework.io/docs/building-operators/ansible/installation"
exit 1
fi
}
verify_opm_binary() {
if hash opm 2>/dev/null; then
OPM_BINARY="$(which opm)"
else
echo "opm binary not found."
echo "Please visit https://github.com/operator-framework/operator-registry/releases"
exit 1
fi
}
prepare_local_deploy() {
echo "operator_image: $REGISTRY/$OPERATOR_IMAGE" > ansible/group_vars/all
echo "operator_version: $TAG" >> ansible/group_vars/all
echo "pull_policy: Always" >> ansible/group_vars/all
ansible-playbook ansible/chain-operator-files.yml
}
REGISTRY=${REGISTRY:-''}
if [[ -z "$REGISTRY" ]]; then
echo "Set your \$REGISTRY variable to your registry server."
echo "export REGISTRY=quay.io/ansible"
exit 1
fi
TAG=${TAG:-''}
if [[ -z "$TAG" ]]; then
echo "Set your \$TAG variable to your registry server."
echo "export TAG=mytag"
exit 1
fi
build_operator_image() {
echo "Building and pushing $OPERATOR_IMAGE image"
$POD_MANAGER build . -f build/Dockerfile -t $REGISTRY/$OPERATOR_IMAGE:$TAG
$POD_MANAGER push $REGISTRY/$OPERATOR_IMAGE:$TAG
}
build_bundle_image() {
echo "Building and pushing $BUNDLE_IMAGE image"
$POD_MANAGER build . -f bundle.Dockerfile -t $REGISTRY/$BUNDLE_IMAGE:$TAG
$POD_MANAGER push $REGISTRY/$BUNDLE_IMAGE:$TAG
}
build_catalog_image() {
echo "Building and pushing $CATALOG_IMAGE image"
$OPM_BINARY index add --bundles $REGISTRY/$BUNDLE_IMAGE:$TAG --tag $REGISTRY/$CATALOG_IMAGE:$TAG
$POD_MANAGER push $REGISTRY/$CATALOG_IMAGE:$TAG
}
generate_catalogsource_yaml() {
echo "Creating CatalogSource YAML"
cat > catalogsource.yaml << EOF
---
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: awx-operator
namespace: operators
spec:
displayName: 'Ansible AWX Operator'
image: "$REGISTRY/$CATALOG_IMAGE:$TAG"
publisher: 'Ansible AWX Operator'
sourceType: grpc
EOF
echo "Now run: 'kubectl apply -f catalogsource.yaml' to update the operator"
echo "Happy testing!"
}
verify_podman_binary
verify_operator_sdk_binary
verify_opm_binary
prepare_local_deploy
build_operator_image
build_bundle_image
build_catalog_image
generate_catalogsource_yaml

View File

@@ -5,4 +5,4 @@
playbook: /opt/ansible/main.yml
finalizer:
name: finalizer.awx.ansible.com
role: awx_remove
role: finalizer