Merge pull request #1 from ansible/devel

Merge changes
This commit is contained in:
billett83
2021-03-23 16:44:07 +00:00
committed by GitHub
23 changed files with 284 additions and 50 deletions

View File

@@ -1,3 +1,4 @@
---
skip_list:
- '306'
- '602'

View File

@@ -7,28 +7,31 @@ An [Ansible AWX](https://github.com/ansible/awx) operator for Kubernetes built w
# Table of Contents
<!--ts-->
* [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)
* [Managed PostgreSQL Service](#managed-postgresql-service)
* [Advanced Configuration](#advanced-configuration)
* [Deploying a specific version of AWX](#deploying-a-specific-version-of-awx)
* [Privilged Tasks](#privileged-tasks)
* [Containers Resource Requirements](#containers-resource-requirements)
* [Development](#development)
* [Testing](#testing)
* [Testing in Docker](#testing-in-docker)
* [Testing in Minikube](#testing-in-minikube)
* [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)
* [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)
* [Development](#development)
* [Testing](#testing)
* [Testing in Docker](#testing-in-docker)
* [Testing in Minikube](#testing-in-minikube)
* [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
@@ -196,6 +199,10 @@ stringData:
type: Opaque
```
#### 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.
@@ -231,12 +238,13 @@ spec:
#### Deploying a specific version of AWX
There are two variables that are customizable for awx the image management.
There are a few variables that are customizable for awx the image management.
| Name | Description | Default |
| ----------------------- | -------------------------- | ------------------ |
| tower_image | Path of the image to pull | ansible/awx:15.0.0 |
| tower_image_pull_policy | The pull policy to adopt | IfNotPresent |
| tower_image_pull_secret | The pull secret to use | '' |
Example of customization could be:
@@ -246,6 +254,7 @@ spec:
...
tower_image: myorg/my-custom-awx
tower_image_pull_policy: Always
tower_image_pull_secret: pull_secret_name
```
#### Privileged Tasks

View File

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

View File

@@ -9,7 +9,7 @@
- name: Deploy AWX
k8s:
state: "{{ state | default('present') }}"
namespace: default
namespace: "{{ namespace | default('default') }}"
apply: yes
wait: yes
definition:

View File

@@ -44,6 +44,9 @@ spec:
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
@@ -82,7 +85,7 @@ spec:
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: int32
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
@@ -246,6 +249,9 @@ spec:
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

View File

@@ -55,6 +55,12 @@ rules:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments/scale
verbs:
- patch
- apiGroups:
- ""
resources:

View File

@@ -57,6 +57,12 @@ rules:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments/scale
verbs:
- patch
- apiGroups:
- ""
resources:
@@ -116,7 +122,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.7.0"
imagePullPolicy: "Always"
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
@@ -189,6 +195,9 @@ spec:
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
@@ -227,7 +236,7 @@ spec:
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: number
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
@@ -391,6 +400,9 @@ spec:
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

View File

@@ -13,7 +13,7 @@ spec:
tower_admin_user: test
tower_admin_email: test@example.com
tower_image: quay.io/ansible/awx:execution-environments
tower_image: quay.io/ansible/awx:18.0.0
tower_create_preload_data: true

View File

@@ -44,6 +44,9 @@ spec:
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
@@ -82,7 +85,7 @@ spec:
- https
tower_loadbalancer_port:
description: Port to use for the loadbalancer
type: number
type: integer
default: 80
tower_route_host:
description: The DNS to use to points to the instance
@@ -246,6 +249,9 @@ spec:
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

View File

@@ -11,7 +11,7 @@ spec:
tower_admin_email: test@example.com
tower_image: quay.io/ansible/awx:execution-environments
tower_image: quay.io/ansible/awx:18.0.0
tower_web_resource_requirements:
requests:

View File

@@ -17,7 +17,7 @@ metadata:
"tower_broadcast_websocket_secret": "changeme",
"tower_create_preload_data": true,
"tower_hostname": "example-awx.test",
"tower_image": "quay.io/ansible/awx:execution-environments",
"tower_image": "quay.io/ansible/awx:18.0.0",
"tower_ingress_type": "none",
"tower_memcached_image": "memcached:alpine",
"tower_postgres_storage_class": "",
@@ -37,7 +37,7 @@ metadata:
"tower_admin_email": "test@example.com",
"tower_broadcast_websocket_secret": "changeme",
"tower_create_preload_data": true,
"tower_image": "quay.io/ansible/awx:execution-environments",
"tower_image": "quay.io/ansible/awx:18.0.0",
"tower_ingress_type": "ingress",
"tower_memcached_image": "memcached:alpine",
"tower_postgres_image": "postgres:12",
@@ -71,6 +71,7 @@ spec:
owned:
- description: A AWX Instance
kind: AWX
displayName: AWX
name: awxs.awx.ansible.com
specDescriptors:
- displayName: Hostname
@@ -98,6 +99,10 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:io.kubernetes: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:

View File

@@ -102,6 +102,9 @@ spec:
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_postgres_data_path:
description: Path where the PostgreSQL data are located
type: string

58
docs/migration.md Normal file
View File

@@ -0,0 +1,58 @@
# 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 Databse 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.
## 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

@@ -1,6 +1,9 @@
---
deployment_type: awx
database_name: "{{ deployment_type }}"
database_username: "{{ deployment_type }}"
tower_task_privileged: false
tower_ingress_type: none
@@ -50,6 +53,10 @@ tower_broadcast_websocket_secret: ''
#
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
@@ -58,8 +65,9 @@ tower_extra_volumes: ''
# Use these image versions for Ansible AWX.
tower_image: quay.io/ansible/awx:execution-environments
tower_image: quay.io/ansible/awx:18.0.0
tower_image_pull_policy: IfNotPresent
tower_image_pull_secret: ''
default_ee: quay.io/ansible/awx-ee
tower_create_preload_data: true

View File

@@ -14,6 +14,22 @@
name: '{{ meta.name }}-postgres-configuration'
register: _default_pg_config_resources
- name: Check for old PostgreSQL configuration secret
k8s_info:
kind: Secret
namespace: '{{ meta.namespace }}'
name: '{{ tower_old_postgres_configuration_secret }}'
register: old_pg_config
when: tower_old_postgres_configuration_secret | length
- 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) }}'
@@ -30,7 +46,6 @@
namespace: '{{ meta.namespace }}'
name: '{{ meta.name }}-postgres-configuration'
register: _generated_pg_config_resources
when: not _pg_config['resources'] | default([]) | length
- name: Set PostgreSQL Configuration
@@ -51,3 +66,18 @@
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 }}"
- 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

@@ -21,7 +21,6 @@
k8s:
apply: yes
definition: "{{ lookup('template', item) | from_yaml_all | list }}"
register: k8s_defs_result
with_items:
- tower_config.yaml.j2
@@ -57,30 +56,27 @@
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:
- name: Check for pending migrations
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
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
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:
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)
when:
- database_check is defined
- (database_check.stdout|trim) != '0'
- include_tasks: initialize.yml

View File

@@ -0,0 +1,74 @@
---
- 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 }}'
label_selectors:
- "app={{ deployment_type }}-postgres"
register: postgres_pod
until: "postgres_pod['resources'][0]['status']['phase'] == 'Running'"
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: 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
k8s_scale:
api_version: v1
kind: Deployment
name: "{{ meta.name }}"
namespace: "{{ meta.namespace }}"
replicas: 0
when: tower_deployment['resources'] | length
- 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 {{ awx_postgres_user }}
-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

@@ -68,3 +68,13 @@
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

@@ -18,6 +18,10 @@ spec:
app: '{{ deployment_type }}'
spec:
serviceAccountName: '{{ meta.name }}'
{% if tower_image_pull_secret %}
imagePullSecrets:
- name: {{ tower_image_pull_secret }}
{% endif %}
containers:
- image: '{{ tower_redis_image }}'
name: redis
@@ -90,7 +94,7 @@ spec:
- name: AWX_KUBE_DEVEL
value: "1"
{% endif %}
{% if tower_task_extra_env %}
{% if tower_web_extra_env -%}
{{ tower_web_extra_env | indent(width=12, indentfirst=True) }}
{% endif %}
resources: {{ tower_web_resource_requirements }}

View File

@@ -41,6 +41,10 @@ spec:
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

View File

@@ -7,8 +7,8 @@ metadata:
namespace: '{{ meta.namespace }}'
stringData:
password: '{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}'
username: '{{ deployment_type }}'
database: '{{ deployment_type }}'
username: '{{ database_username }}'
database: '{{ database_name }}'
port: '5432'
host: {{ meta.name }}-postgres
type: 'managed'

View File

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