mirror of
https://github.com/ZwareBear/awx.git
synced 2026-03-20 07:43:35 -05:00
Merge branch 'devel' into feature_web-task-split
This commit is contained in:
@@ -28,7 +28,7 @@ from rest_framework import generics
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework import views
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.renderers import StaticHTMLRenderer
|
||||
from rest_framework.negotiation import DefaultContentNegotiation
|
||||
|
||||
@@ -822,7 +822,7 @@ def trigger_delayed_deep_copy(*args, **kwargs):
|
||||
|
||||
class CopyAPIView(GenericAPIView):
|
||||
serializer_class = CopySerializer
|
||||
permission_classes = (AllowAny,)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
copy_return_serializer_class = None
|
||||
new_in_330 = True
|
||||
new_in_api_v2 = True
|
||||
|
||||
@@ -4288,7 +4288,7 @@ class WorkflowApprovalTemplateJobsList(SubListAPIView):
|
||||
parent_key = 'workflow_approval_template'
|
||||
|
||||
|
||||
class WorkflowApprovalList(ListCreateAPIView):
|
||||
class WorkflowApprovalList(ListAPIView):
|
||||
model = models.WorkflowApproval
|
||||
serializer_class = serializers.WorkflowApprovalListSerializer
|
||||
|
||||
|
||||
@@ -25,17 +25,21 @@
|
||||
connection: local
|
||||
name: Update source tree if necessary
|
||||
tasks:
|
||||
|
||||
- name: delete project directory before update
|
||||
command: "find -delete" # volume mounted, cannot delete folder itself
|
||||
- name: Delete project directory before update
|
||||
ansible.builtin.shell: set -o pipefail && find . -delete -print | head -2 # volume mounted, cannot delete folder itself
|
||||
register: reg
|
||||
changed_when: reg.stdout_lines | length > 1
|
||||
args:
|
||||
chdir: "{{ project_path }}"
|
||||
tags:
|
||||
- delete
|
||||
|
||||
- block:
|
||||
- name: update project using git
|
||||
git:
|
||||
- name: Update project using git
|
||||
tags:
|
||||
- update_git
|
||||
block:
|
||||
- name: Update project using git
|
||||
ansible.builtin.git:
|
||||
dest: "{{ project_path | quote }}"
|
||||
repo: "{{ scm_url }}"
|
||||
version: "{{ scm_branch | quote }}"
|
||||
@@ -46,15 +50,16 @@
|
||||
register: git_result
|
||||
|
||||
- name: Set the git repository version
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
scm_version: "{{ git_result['after'] }}"
|
||||
when: "'after' in git_result"
|
||||
tags:
|
||||
- update_git
|
||||
|
||||
- block:
|
||||
- name: update project using svn
|
||||
subversion:
|
||||
- name: Update project using svn
|
||||
tags:
|
||||
- update_svn
|
||||
block:
|
||||
- name: Update project using svn
|
||||
ansible.builtin.subversion:
|
||||
dest: "{{ project_path | quote }}"
|
||||
repo: "{{ scm_url | quote }}"
|
||||
revision: "{{ scm_branch | quote }}"
|
||||
@@ -68,21 +73,24 @@
|
||||
register: svn_result
|
||||
|
||||
- name: Set the svn repository version
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
scm_version: "{{ svn_result['after'] }}"
|
||||
when: "'after' in svn_result"
|
||||
|
||||
- name: parse subversion version string properly
|
||||
set_fact:
|
||||
- name: Parse subversion version string properly
|
||||
ansible.builtin.set_fact:
|
||||
scm_version: "{{ scm_version | regex_replace('^.*Revision: ([0-9]+).*$', '\\1') }}"
|
||||
tags:
|
||||
- update_svn
|
||||
|
||||
- block:
|
||||
|
||||
- name: Project update for Insights
|
||||
tags:
|
||||
- update_insights
|
||||
block:
|
||||
- name: Ensure the project directory is present
|
||||
file:
|
||||
ansible.builtin.file:
|
||||
dest: "{{ project_path | quote }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Fetch Insights Playbook(s)
|
||||
insights:
|
||||
@@ -95,25 +103,29 @@
|
||||
register: results
|
||||
|
||||
- name: Save Insights Version
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
scm_version: "{{ results.version }}"
|
||||
when: results is defined
|
||||
tags:
|
||||
- update_insights
|
||||
|
||||
- block:
|
||||
|
||||
- name: Update project using archive
|
||||
tags:
|
||||
- update_archive
|
||||
block:
|
||||
- name: Ensure the project archive directory is present
|
||||
file:
|
||||
ansible.builtin.file:
|
||||
dest: "{{ project_path | quote }}/.archive"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Get archive from url
|
||||
get_url:
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ scm_url | quote }}"
|
||||
dest: "{{ project_path | quote }}/.archive/"
|
||||
url_username: "{{ scm_username | default(omit) }}"
|
||||
url_password: "{{ scm_password | default(omit) }}"
|
||||
force_basic_auth: true
|
||||
mode: '0755'
|
||||
register: get_archive
|
||||
|
||||
- name: Unpack archive
|
||||
@@ -125,7 +137,7 @@
|
||||
register: unarchived
|
||||
|
||||
- name: Find previous archives
|
||||
find:
|
||||
ansible.builtin.find:
|
||||
paths: "{{ project_path | quote }}/.archive/"
|
||||
excludes:
|
||||
- "{{ get_archive.dest | basename }}"
|
||||
@@ -133,20 +145,18 @@
|
||||
register: previous_archive
|
||||
|
||||
- name: Remove previous archives
|
||||
file:
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ previous_archive.files }}"
|
||||
when: previous_archive.files | default([])
|
||||
|
||||
- name: Set scm_version to archive sha1 checksum
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
scm_version: "{{ get_archive.checksum_src }}"
|
||||
tags:
|
||||
- update_archive
|
||||
|
||||
- name: Repository Version
|
||||
debug:
|
||||
ansible.builtin.debug:
|
||||
msg: "Repository Version {{ scm_version }}"
|
||||
tags:
|
||||
- update_git
|
||||
@@ -188,23 +198,22 @@
|
||||
# otherwise, files cannot be moved accross volumes and will cause error
|
||||
ANSIBLE_LOCAL_TEMP: "{{ projects_root }}/.__awx_cache/{{ local_path }}/stage/tmp"
|
||||
tasks:
|
||||
|
||||
- name: Check content sync settings
|
||||
block:
|
||||
- debug:
|
||||
msg: >
|
||||
Collection and role syncing disabled. Check the AWX_ROLES_ENABLED and
|
||||
AWX_COLLECTIONS_ENABLED settings and Galaxy credentials on the project's organization.
|
||||
|
||||
- meta: end_play
|
||||
|
||||
when: not roles_enabled | bool and not collections_enabled | bool
|
||||
tags:
|
||||
- install_roles
|
||||
- install_collections
|
||||
block:
|
||||
- name: Warn about disabled content sync
|
||||
ansible.builtin.debug:
|
||||
msg: >
|
||||
Collection and role syncing disabled. Check the AWX_ROLES_ENABLED and
|
||||
AWX_COLLECTIONS_ENABLED settings and Galaxy credentials on the project's organization.
|
||||
- name: End play due to disabled content sync
|
||||
ansible.builtin.meta: end_play
|
||||
|
||||
- name: fetch galaxy roles from requirements.(yml/yaml)
|
||||
command: >
|
||||
- name: Fetch galaxy roles from requirements.(yml/yaml)
|
||||
ansible.builtin.command: >
|
||||
ansible-galaxy role install -r {{ item }}
|
||||
--roles-path {{ projects_root }}/.__awx_cache/{{ local_path }}/stage/requirements_roles
|
||||
{{ ' -' + 'v' * ansible_verbosity if ansible_verbosity else '' }}
|
||||
@@ -220,8 +229,8 @@
|
||||
tags:
|
||||
- install_roles
|
||||
|
||||
- name: fetch galaxy collections from collections/requirements.(yml/yaml)
|
||||
command: >
|
||||
- name: Fetch galaxy collections from collections/requirements.(yml/yaml)
|
||||
ansible.builtin.command: >
|
||||
ansible-galaxy collection install -r {{ item }}
|
||||
--collections-path {{ projects_root }}/.__awx_cache/{{ local_path }}/stage/requirements_collections
|
||||
{{ ' -' + 'v' * ansible_verbosity if ansible_verbosity else '' }}
|
||||
|
||||
@@ -57,7 +57,15 @@ extends_documentation_fragment: awx.awx.auth
|
||||
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Launch a workflow with a timeout of 10 seconds
|
||||
- name: Create a workflow approval node
|
||||
workflow_job_template_node:
|
||||
identifier: approval_test
|
||||
approval_node:
|
||||
name: approval_jt_name
|
||||
timeout: 900
|
||||
workflow: "Test Workflow"
|
||||
|
||||
- name: Launch the workflow with a timeout of 10 seconds
|
||||
workflow_launch:
|
||||
workflow_template: "Test Workflow"
|
||||
wait: False
|
||||
@@ -66,7 +74,7 @@ EXAMPLES = """
|
||||
- name: Wait for approval node to activate and approve
|
||||
workflow_approval:
|
||||
workflow_job_id: "{{ workflow.id }}"
|
||||
name: Approve Me
|
||||
name: approval_jt_name
|
||||
interval: 10
|
||||
timeout: 20
|
||||
action: deny
|
||||
|
||||
@@ -183,6 +183,20 @@ options:
|
||||
inventory:
|
||||
description:
|
||||
- Inventory applied as a prompt, if job template prompts for inventory
|
||||
type: dict
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Name Inventory to be applied to job as launch-time prompts.
|
||||
type: str
|
||||
organization:
|
||||
description:
|
||||
- Name of key for use in model for organizational reference
|
||||
type: dict
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- The organization of the credentials exists in.
|
||||
type: str
|
||||
scm_branch:
|
||||
description:
|
||||
@@ -544,6 +558,10 @@ EXAMPLES = '''
|
||||
type: job_template
|
||||
execution_environment:
|
||||
name: My EE
|
||||
inventory:
|
||||
name: Test inventory
|
||||
organization:
|
||||
name: Default
|
||||
related:
|
||||
credentials:
|
||||
- name: cyberark
|
||||
@@ -613,10 +631,6 @@ def create_workflow_nodes(module, response, workflow_nodes, workflow_id):
|
||||
if workflow_node['unified_job_template']['type'] != 'workflow_approval':
|
||||
module.fail_json(msg="Unable to Find unified_job_template: {0}".format(search_fields))
|
||||
|
||||
inventory = workflow_node.get('inventory')
|
||||
if inventory:
|
||||
workflow_node_fields['inventory'] = module.resolve_name_to_id('inventories', inventory)
|
||||
|
||||
# Lookup Values for other fields
|
||||
|
||||
for field_name in (
|
||||
@@ -645,6 +659,17 @@ def create_workflow_nodes(module, response, workflow_nodes, workflow_id):
|
||||
'execution_environments', name_or_id=workflow_node['execution_environment']['name']
|
||||
)['id']
|
||||
|
||||
# Two lookup methods are used based on a fix added in 21.11.0, and the awx export model
|
||||
if 'inventory' in workflow_node:
|
||||
if 'name' in workflow_node['inventory']:
|
||||
inv_lookup_data = {}
|
||||
if 'organization' in workflow_node['inventory']:
|
||||
inv_lookup_data['organization'] = module.resolve_name_to_id('organizations', workflow_node['inventory']['organization']['name'])
|
||||
workflow_node_fields['inventory'] = module.get_one(
|
||||
'inventories', name_or_id=workflow_node['inventory']['name'], data=inv_lookup_data)['id']
|
||||
else:
|
||||
workflow_node_fields['inventory'] = module.get_one('inventories', name_or_id=workflow_node['inventory'])['id']
|
||||
|
||||
# Set Search fields
|
||||
search_fields['workflow_job_template'] = workflow_node_fields['workflow_job_template'] = workflow_id
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import glob
|
||||
# Normally a read-only endpoint should not have a module (i.e. /api/v2/me) but sometimes we reuse a name
|
||||
# For example, we have a role module but /api/v2/roles is a read only endpoint.
|
||||
# This list indicates which read-only endpoints have associated modules with them.
|
||||
read_only_endpoints_with_modules = ['settings', 'role', 'project_update']
|
||||
read_only_endpoints_with_modules = ['settings', 'role', 'project_update', 'workflow_approval']
|
||||
|
||||
# If a module should not be created for an endpoint and the endpoint is not read-only add it here
|
||||
# THINK HARD ABOUT DOING THIS
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
- name: Generate a random string for names
|
||||
set_fact:
|
||||
test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
test_prefix: AWX-Collection-tests-workflow_approval
|
||||
|
||||
- name: Generate random names for test objects
|
||||
set_fact:
|
||||
org_name: "{{ test_prefix }}-org-{{ test_id }}"
|
||||
approval_node_name: "{{ test_prefix }}-node-{{ test_id }}"
|
||||
wfjt_name: "{{ test_prefix }}-wfjt-{{ test_id }}"
|
||||
|
||||
- block:
|
||||
- name: Create a new organization for test isolation
|
||||
organization:
|
||||
name: "{{ org_name }}"
|
||||
|
||||
- name: Create a workflow job template
|
||||
workflow_job_template:
|
||||
name: "{{ wfjt_name }}"
|
||||
organization: "{{ org_name }}"
|
||||
|
||||
- name: Create approval node
|
||||
workflow_job_template_node:
|
||||
identifier: approval_test
|
||||
approval_node:
|
||||
name: "{{ approval_node_name }}" # Referenced later on
|
||||
timeout: 900
|
||||
workflow: "{{ wfjt_name }}"
|
||||
|
||||
# Launch and approve the workflow
|
||||
- name: Launch the workflow
|
||||
workflow_launch:
|
||||
workflow_template: "{{ wfjt_name }}"
|
||||
wait: False
|
||||
register: workflow_job
|
||||
|
||||
- name: Wait for approval node to activate and approve
|
||||
workflow_approval:
|
||||
workflow_job_id: "{{ workflow_job.id }}"
|
||||
name: "{{ approval_node_name }}"
|
||||
interval: 10
|
||||
timeout: 20
|
||||
action: approve
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
- "result is not failed"
|
||||
|
||||
always:
|
||||
- name: Delete the workflow job template
|
||||
workflow_job_template:
|
||||
name: "{{ wfjt_name }}"
|
||||
state: absent
|
||||
ignore_errors: True
|
||||
@@ -493,6 +493,7 @@
|
||||
workflow_job_template:
|
||||
name: "copy_{{ wfjt_name }}"
|
||||
organization: Default
|
||||
ask_inventory_on_launch: true
|
||||
survey_spec:
|
||||
name: Basic Survey
|
||||
description: Basic Survey
|
||||
@@ -737,6 +738,10 @@
|
||||
timeout: 23
|
||||
execution_environment:
|
||||
name: "{{ ee1 }}"
|
||||
inventory:
|
||||
name: Test inventory
|
||||
organization:
|
||||
name: Default
|
||||
related:
|
||||
credentials:
|
||||
- name: "{{ scm_cred_name }}"
|
||||
|
||||
@@ -75,7 +75,8 @@ In the root of awx-operator:
|
||||
-e image_version=devel \
|
||||
-e image_pull_policy=Always \
|
||||
-e service_type=nodeport \
|
||||
-e namespace=awx
|
||||
-e namespace=awx \
|
||||
-e nodeport_port=30080
|
||||
```
|
||||
Check the operator with the following commands:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user