mirror of
https://github.com/ansible/awx-operator.git
synced 2026-05-08 14:22:49 +00:00
Rename base roles
This commit is contained in:
34
roles/installer/README.md
Normal file
34
roles/installer/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
AWX
|
||||
=======
|
||||
|
||||
This role builds and maintains an Ansible Tower instance inside of Kubernetes.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
TODO.
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
See `defaults/main.yml` for all the role variables that you can override.
|
||||
|
||||
TODO: add variable description table.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
N/A
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
roles:
|
||||
- awx
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT / BSD
|
||||
80
roles/installer/defaults/main.yml
Normal file
80
roles/installer/defaults/main.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
deployment_type: awx
|
||||
|
||||
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: '{{ deployment_type }}.example.com'
|
||||
|
||||
tower_admin_user: admin
|
||||
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_image: postgres:12
|
||||
tower_postgres_storage_request: 8Gi
|
||||
tower_postgres_storage_class: ''
|
||||
tower_postgres_data_path: '/var/lib/postgresql/data/pgdata'
|
||||
|
||||
ca_trust_bundle: "/etc/pki/tls/certs/ca-bundle.crt"
|
||||
|
||||
development_mode: false
|
||||
31
roles/installer/meta/main.yml
Normal file
31
roles/installer/meta/main.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Ansible
|
||||
description: AWX role for AWX Operator for Kubernetes.
|
||||
company: Red Hat, Inc.
|
||||
|
||||
license: MIT
|
||||
|
||||
min_ansible_version: 2.8
|
||||
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
- name: Debian
|
||||
versions:
|
||||
- all
|
||||
|
||||
galaxy_tags:
|
||||
- tower
|
||||
- awx
|
||||
- ansible
|
||||
- automation
|
||||
- ci
|
||||
- cd
|
||||
- deployment
|
||||
|
||||
dependencies: []
|
||||
|
||||
collections:
|
||||
- community.kubernetes
|
||||
37
roles/installer/tasks/initialize.yml
Normal file
37
roles/installer/tasks/initialize.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
- name: Check if there are any super users defined.
|
||||
community.kubernetes.k8s_exec:
|
||||
namespace: "{{ meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "echo 'from django.contrib.auth.models import User;
|
||||
nsu = User.objects.filter(is_superuser=True).count();
|
||||
exit(0 if nsu > 0 else 1)'
|
||||
| awx-manage shell"
|
||||
ignore_errors: true
|
||||
register: users_result
|
||||
changed_when: users_result.return_code > 0
|
||||
|
||||
- name: Create super user via Django if it doesn't exist.
|
||||
community.kubernetes.k8s_exec:
|
||||
namespace: "{{ meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "echo \"from django.contrib.auth.models import User;
|
||||
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:
|
||||
namespace: "{{ meta.namespace }}"
|
||||
pod: "{{ tower_pod_name }}"
|
||||
container: "{{ meta.name }}-task"
|
||||
command: >-
|
||||
bash -c "awx-manage create_preload_data"
|
||||
register: cdo
|
||||
changed_when: "'added' in cdo.stdout"
|
||||
when: tower_create_preload_data | bool
|
||||
111
roles/installer/tasks/main.yml
Normal file
111
roles/installer/tasks/main.yml
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
- 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 instance 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 Resource Deployment Configuration
|
||||
k8s:
|
||||
apply: yes
|
||||
definition: "{{ lookup('template', 'tower.yaml.j2') }}"
|
||||
register: tower_deployment_result
|
||||
|
||||
- name: Get the resource pod information.
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
namespace: '{{ meta.namespace }}'
|
||||
label_selectors:
|
||||
- "app={{ deployment_type }}"
|
||||
register: tower_pods
|
||||
until: "tower_pods['resources'][0]['status']['phase'] == 'Running'"
|
||||
delay: 5
|
||||
retries: 60
|
||||
|
||||
- name: Set the resource pod name as a variable.
|
||||
set_fact:
|
||||
tower_pod_name: "{{ tower_pods['resources'][0]['metadata']['name'] }}"
|
||||
|
||||
- name: Verify the resource 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
|
||||
16
roles/installer/templates/credentials.py.j2
Normal file
16
roles/installer/templates/credentials.py.j2
Normal file
@@ -0,0 +1,16 @@
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ATOMIC_REQUESTS': True,
|
||||
'ENGINE': 'awx.main.db.profiled_pg',
|
||||
'NAME': "{{ awx_postgres_database }}",
|
||||
'USER': "{{ awx_postgres_user }}",
|
||||
'PASSWORD': "{{ awx_postgres_pass }}",
|
||||
'HOST': '{{ awx_postgres_host }}',
|
||||
'PORT': "{{ awx_postgres_port }}",
|
||||
'OPTIONS': { 'sslmode': '{{ pg_sslmode|default("prefer") }}',
|
||||
'sslrootcert': '{{ ca_trust_bundle }}',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
BROADCAST_WEBSOCKET_SECRET = "{{ tower_broadcast_websocket_secret | b64encode }}"
|
||||
5
roles/installer/templates/environment.sh.j2
Normal file
5
roles/installer/templates/environment.sh.j2
Normal file
@@ -0,0 +1,5 @@
|
||||
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 }}
|
||||
280
roles/installer/templates/tower.yaml.j2
Normal file
280
roles/installer/templates/tower.yaml.j2
Normal file
@@ -0,0 +1,280 @@
|
||||
# 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: '{{ deployment_type }}'
|
||||
spec:
|
||||
replicas: {{ tower_replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ deployment_type }}'
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ deployment_type }}'
|
||||
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 }}-{{ 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: 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: '{{ deployment_type }}'
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 8052
|
||||
name: http
|
||||
selector:
|
||||
app: '{{ deployment_type }}'
|
||||
{% 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 %}
|
||||
212
roles/installer/templates/tower_config.yaml.j2
Normal file
212
roles/installer/templates/tower_config.yaml.j2
Normal file
@@ -0,0 +1,212 @@
|
||||
# AWX Web ConfigMap.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: '{{ meta.name }}-{{ deployment_type }}-configmap'
|
||||
namespace: '{{ meta.namespace }}'
|
||||
labels:
|
||||
app: '{{ 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={{ awx_postgres_pass | quote }}
|
||||
AWX_SKIP_MIGRATIONS=true
|
||||
|
||||
settings: |
|
||||
import os
|
||||
import socket
|
||||
|
||||
def get_secret():
|
||||
if os.path.exists("/etc/tower/SECRET_KEY"):
|
||||
return open('/etc/tower/SECRET_KEY', 'rb').read().strip()
|
||||
|
||||
ADMINS = ()
|
||||
STATIC_ROOT = '/var/lib/awx/public/static'
|
||||
PROJECTS_ROOT = '/var/lib/awx/projects'
|
||||
JOBOUTPUT_ROOT = '/var/lib/awx/job_status'
|
||||
|
||||
SECRET_KEY = get_secret()
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
INTERNAL_API_URL = 'http://127.0.0.1:8052'
|
||||
|
||||
# Sets Ansible Collection path
|
||||
AWX_ANSIBLE_COLLECTIONS_PATHS = '/var/lib/awx/vendor/awx_ansible_collections'
|
||||
|
||||
# Container environments don't like chroots
|
||||
AWX_PROOT_ENABLED = False
|
||||
|
||||
# Automatically deprovision pods that go offline
|
||||
AWX_AUTO_DEPROVISION_INSTANCES = True
|
||||
|
||||
CLUSTER_HOST_ID = socket.gethostname()
|
||||
SYSTEM_UUID = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
CSRF_COOKIE_SECURE = False
|
||||
SESSION_COOKIE_SECURE = False
|
||||
|
||||
SERVER_EMAIL = 'root@localhost'
|
||||
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
|
||||
EMAIL_SUBJECT_PREFIX = '[AWX] '
|
||||
|
||||
EMAIL_HOST = 'localhost'
|
||||
EMAIL_PORT = 25
|
||||
EMAIL_HOST_USER = ''
|
||||
EMAIL_HOST_PASSWORD = ''
|
||||
EMAIL_USE_TLS = False
|
||||
|
||||
LOGGING['handlers']['console'] = {
|
||||
'()': 'logging.StreamHandler',
|
||||
'level': 'DEBUG',
|
||||
'formatter': 'simple',
|
||||
}
|
||||
|
||||
LOGGING['loggers']['django.request']['handlers'] = ['console']
|
||||
LOGGING['loggers']['rest_framework.request']['handlers'] = ['console']
|
||||
LOGGING['loggers']['awx']['handlers'] = ['console', 'external_logger']
|
||||
LOGGING['loggers']['awx.main.commands.run_callback_receiver']['handlers'] = ['console']
|
||||
LOGGING['loggers']['awx.main.tasks']['handlers'] = ['console', 'external_logger']
|
||||
LOGGING['loggers']['awx.main.scheduler']['handlers'] = ['console', 'external_logger']
|
||||
LOGGING['loggers']['django_auth_ldap']['handlers'] = ['console']
|
||||
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': '{{ awx_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'
|
||||
|
||||
nginx_conf: |
|
||||
worker_processes 1;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
server_tokens off;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /dev/stdout main;
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
#gzip on;
|
||||
|
||||
upstream uwsgi {
|
||||
server 127.0.0.1:8050;
|
||||
}
|
||||
|
||||
upstream daphne {
|
||||
server 127.0.0.1:8051;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8052 default_server;
|
||||
|
||||
# If you have a domain name, this is where to add it
|
||||
server_name _;
|
||||
keepalive_timeout 65;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' ws: wss:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' *.pendo.io; img-src 'self' *.pendo.io data:; report-uri /csp-violation/";
|
||||
add_header X-Content-Security-Policy "default-src 'self'; connect-src 'self' ws: wss:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' *.pendo.io; img-src 'self' *.pendo.io data:; report-uri /csp-violation/";
|
||||
|
||||
# Protect against click-jacking https://www.owasp.org/index.php/Testing_for_Clickjacking_(OTG-CLIENT-009)
|
||||
add_header X-Frame-Options "DENY";
|
||||
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
access_log off;
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /var/lib/awx/public/static/;
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
alias /var/lib/awx/public/static/favicon.ico;
|
||||
}
|
||||
|
||||
location /websocket {
|
||||
# Pass request to the upstream alias
|
||||
proxy_pass http://daphne;
|
||||
# Require http version 1.1 to allow for upgrade requests
|
||||
proxy_http_version 1.1;
|
||||
# We want proxy_buffering off for proxying to websockets.
|
||||
proxy_buffering off;
|
||||
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# enable this if you use HTTPS:
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
# pass the Host: header from the client for the sake of redirects
|
||||
proxy_set_header Host $http_host;
|
||||
# We've set the Host header, so we don't need Nginx to muddle
|
||||
# about with redirects
|
||||
proxy_redirect off;
|
||||
# Depending on the request value, set the Upgrade and
|
||||
# connection headers
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
}
|
||||
|
||||
location / {
|
||||
# Add trailing / if missing
|
||||
rewrite ^(.*)$http_host(.*[^/])$ $1$http_host$2/ permanent;
|
||||
uwsgi_read_timeout 120s;
|
||||
uwsgi_pass uwsgi;
|
||||
include /etc/nginx/uwsgi_params;
|
||||
{%- if extra_nginx_include is defined %}
|
||||
include {{ extra_nginx_include }};
|
||||
{%- endif %}
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
uwsgi_param HTTP_X_FORWARDED_PORT 443;
|
||||
}
|
||||
}
|
||||
}
|
||||
redis_conf: |
|
||||
unixsocket /var/run/redis/redis.sock
|
||||
unixsocketperm 777
|
||||
port 0
|
||||
bind 127.0.0.1
|
||||
78
roles/installer/templates/tower_postgres.yaml.j2
Normal file
78
roles/installer/templates/tower_postgres.yaml.j2
Normal file
@@ -0,0 +1,78 @@
|
||||
# Postgres StatefulSet.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: '{{ meta.name }}-postgres'
|
||||
namespace: '{{ meta.namespace }}'
|
||||
labels:
|
||||
app: '{{ deployment_type }}-postgres'
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: '{{ deployment_type }}-postgres'
|
||||
serviceName: '{{ meta.name }}'
|
||||
replicas: 1
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: '{{ deployment_type }}-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: '{{ deployment_type }}-postgres'
|
||||
spec:
|
||||
ports:
|
||||
- port: 5432
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: '{{ deployment_type }}-postgres'
|
||||
13
roles/installer/templates/tower_postgres_secret.yaml.j2
Normal file
13
roles/installer/templates/tower_postgres_secret.yaml.j2
Normal file
@@ -0,0 +1,13 @@
|
||||
# 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: '{{ deployment_type }}'
|
||||
database: '{{ deployment_type }}'
|
||||
port: '5432'
|
||||
host: {{ meta.name }}-postgres
|
||||
8
roles/installer/templates/tower_secret.yaml.j2
Normal file
8
roles/installer/templates/tower_secret.yaml.j2
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
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') }}'
|
||||
Reference in New Issue
Block a user