Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing workflow_job_templates does not set node job_templates correctly #7793

Closed
zedr opened this issue Jul 31, 2020 · 7 comments
Closed

Comments

@zedr
Copy link

zedr commented Jul 31, 2020

ISSUE TYPE

When importing workflow_job_templates, the unified_job_template field in each associated workflow_job_template_node is incorrectly set to null.

SUMMARY

AWX CLI has recently introduced the ability to export and import many types of AWX objects, including Workflow Job Templates. These objects have related objects called Workflow Job Template Nodes, that can point to an existing Job Template.

Unfortunately, when importing a previously exported resource, any Workflow Job Template Node that points to a Job Template, using its natural key, will not be able to find that object, even it it is present. The result a mangled workflow.

I've run into this problem when exporting a Workflow Job Template from an AWX 9.2.0 to Tower 3.7.1

ENVIRONMENT
  • AWX version: Tower 3.7.1
  • AWX install method: openshift
  • Ansible version: 2.9.9
  • Operating System: OpenShift 3.11, RHEL
  • Web Browser: Google Chrome
STEPS TO REPRODUCE

Export a Workflow Job Tempates with nodes that point to existing Job Templates, e.g.

workflow_job_templates:
-   allow_simultaneous: true
    ask_inventory_on_launch: false
    ask_limit_on_launch: false
    ask_scm_branch_on_launch: true
    ask_variables_on_launch: true
    description: WF MyTest provisioning
    extra_vars: ''
    inventory: 25
    limit: null
    name: WF-infra_provisioning
    natural_key:
        name: WF-infra_provisioning
        organization:
            name: ITDP
            type: organization
        type: workflow_job_template
    organization:
        name: ITDP
        type: organization
    related:
        notification_templates_approvals: []
        notification_templates_error: []
        notification_templates_started: []
        notification_templates_success: []
        schedules: []
        survey_spec: {}
        workflow_nodes:
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: null
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-vmw_provisioning
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: null
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-varsmng-provisioning
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-os_configuration
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-network_configuration
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-security_configuration
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: null
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-vmw_common
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-fs_configuration
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-register_configuration
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: ''
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes: []
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-update_reboot
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: null
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Template-git-inventory-provisioning-os
                type: job_template
        -   all_parents_must_converge: false
            diff_mode: null
            extra_data: {}
            inventory: null
            job_tags: null
            limit: null
            natural_key:
                type: workflow_job_template_node
                workflow_job_template:
                    name: WF-infra_provisioning
                    organization:
                        name: ITDP
                        type: organization
                    type: workflow_job_template
            related:
                always_nodes: []
                credentials: []
                failure_nodes: []
                success_nodes:
                -   type: workflow_job_template_node
                    workflow_job_template:
                        name: WF-infra_provisioning
                        organization:
                            name: ITDP
                            type: organization
                        type: workflow_job_template
            scm_branch: null
            skip_tags: null
            unified_job_template:
                name: Proj-MyTest_VM
                organization:
                    name: ITDP
                    type: organization
                type: project
    scm_branch: null
    survey_enabled: false
    webhook_credential: null

Import with awx cli using the following command:
awx cli import < workflow.json

EXPECTED RESULTS

The workflow template nodes of the imported workflow should point to the correct Job Template, e.g.

{
            "id": 25,
            "type": "workflow_job_template_node",
            "url": "/api/v2/workflow_job_template_nodes/25/",
            "related": {
                "credentials": "/api/v2/workflow_job_template_nodes/25/credentials/",
                "create_approval_template": "/api/v2/workflow_job_template_nodes/25/create_approval_template/",
                "success_nodes": "/api/v2/workflow_job_template_nodes/25/success_nodes/",
                "failure_nodes": "/api/v2/workflow_job_template_nodes/25/failure_nodes/",
                "always_nodes": "/api/v2/workflow_job_template_nodes/25/always_nodes/",
                "unified_job_template": "/api/v2/job_templates/89/",
                "workflow_job_template": "/api/v2/workflow_job_templates/105/"
            },
            "summary_fields": {
                "workflow_job_template": {
                    "id": 105,
                    "name": "WF-infra_provisioning",
                    "description": "WF MyTest provisioning"
                },
                "unified_job_template": {
                    "id": 89,
                    "name": "Template-vmw_provisioning",
                    "description": "Template for vmw provisioning activities (NON USARE)",
                    "unified_job_type": "job"
                }
            },
            "created": "2019-07-15T15:17:08.774769Z",
            "modified": "2019-07-15T15:17:08.899445Z",
            "extra_data": {},
            "inventory": null,
            "scm_branch": null,
            "job_type": null,
            "job_tags": null,
            "skip_tags": null,
            "limit": null,
            "diff_mode": null,
            "verbosity": null,
            "workflow_job_template": 105,
            "unified_job_template": 89,
            "success_nodes": [
                52
            ],
            "failure_nodes": [],
            "always_nodes": [],
            "all_parents_must_converge": false
        }

See summary_fields.unified_job_template.

ACTUAL RESULTS

The workflow sequence of nodes appears mangled in the viewer. The equivalent API resource of the above example has the following incorrect payload:

 {
            "id": 131,
            "type": "workflow_job_template_node",
            "url": "/api/v2/workflow_job_template_nodes/1317/",
            "related": {
                "credentials": "/api/v2/workflow_job_template_nodes/1317/credentials/",
                "create_approval_template": "/api/v2/workflow_job_template_nodes/1317/create_approval_template/",
                "success_nodes": "/api/v2/workflow_job_template_nodes/1317/success_nodes/",
                "failure_nodes": "/api/v2/workflow_job_template_nodes/1317/failure_nodes/",
                "always_nodes": "/api/v2/workflow_job_template_nodes/1317/always_nodes/",
                "workflow_job_template": "/api/v2/workflow_job_templates/310/"
            },
            "summary_fields": {
                "workflow_job_template": {
                    "id": 310,
                    "name": "WF-infra_provisioning",
                    "description": "WF MyTestprovisioning"
                }
            },
            "created": "2020-07-31T21:01:51.332486Z",
            "modified": "2020-07-31T21:01:51.332505Z",
            "extra_data": {},
            "inventory": null,
            "scm_branch": null,
            "job_type": null,
            "job_tags": null,
            "skip_tags": null,
            "limit": null,
            "diff_mode": null,
            "verbosity": null,
            "workflow_job_template": 310,
            "unified_job_template": null,
            "success_nodes": [],
            "failure_nodes": [],
            "always_nodes": [],
            "all_parents_must_converge": false,
            "identifier": "845296f0-49b9-47ce-8b2d-dbeaf97a5549"
        },

Notice the missing summary_fields.unified_job_template.

ADDITIONAL INFORMATION

NGINX access log from when I kick off the import process (IPs replaced for privacy reasons):

10.0.10.11 - - [31/Jul/2020:21:00:58 +0000] "GET /api/ HTTP/1.1" 200 186 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:00:58 +0000] "GET /api/v2/ HTTP/1.1" 200 1688 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:00:58 +0000] "GET /api/ HTTP/1.1" 200 186 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:00:59 +0000] "POST /api/login/ HTTP/1.1" 302 0 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/login/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:00:59 +0000] "GET /api/ HTTP/1.1" 200 186 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/login/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:00 +0000] "GET /api/ HTTP/1.1" 200 186 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:00 +0000] "GET /api/v2/users/ HTTP/1.1" 200 939 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:00 +0000] "OPTIONS /api/v2/users/ HTTP/1.1" 200 9823 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:00 +0000] "GET /api/v2/organizations/ HTTP/1.1" 200 12563 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:02 +0000] "OPTIONS /api/v2/organizations/ HTTP/1.1" 200 9773 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:02 +0000] "GET /api/v2/credential_types/ HTTP/1.1" 200 23555 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:02 +0000] "OPTIONS /api/v2/credential_types/ HTTP/1.1" 200 10331 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:02 +0000] "GET /api/v2/notification_templates/ HTTP/1.1" 200 5543 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:03 +0000] "OPTIONS /api/v2/notification_templates/ HTTP/1.1" 200 35233 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:03 +0000] "GET /api/v2/teams/ HTTP/1.1" 200 2359 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:03 +0000] "OPTIONS /api/v2/teams/ HTTP/1.1" 200 7952 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:05 +0000] "GET /api/v2/inventories/ HTTP/1.1" 200 55395 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:05 +0000] "GET /api/v2/inventories/?page=2 HTTP/1.1" 200 11552 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:06 +0000] "OPTIONS /api/v2/inventories/ HTTP/1.1" 200 14052 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:11 +0000] "GET /api/v2/workflow_job_templates/ HTTP/1.1" 200 71531 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:16 +0000] "GET /api/v2/workflow_job_templates/?page=2 HTTP/1.1" 200 77497 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:17 +0000] "GET /api/v2/workflow_job_templates/?page=3 HTTP/1.1" 200 43528 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:18 +0000] "OPTIONS /api/v2/workflow_job_templates/ HTTP/1.1" 200 14767 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:19 +0000] "POST /api/v2/workflow_job_templates/ HTTP/1.1" 201 3040 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:19 +0000] "GET /api/v2/credentials/ HTTP/1.1" 200 19348 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:25 +0000] "OPTIONS /api/v2/credentials/ HTTP/1.1" 200 11530 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:30 +0000] "GET /api/v2/projects/ HTTP/1.1" 200 73555 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:31 +0000] "GET /api/v2/projects/?page=2 HTTP/1.1" 200 74827 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:32 +0000] "GET /api/v2/projects/?page=3 HTTP/1.1" 200 74457 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:33 +0000] "GET /api/v2/projects/?page=4 HTTP/1.1" 200 29722 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:37 +0000] "OPTIONS /api/v2/projects/ HTTP/1.1" 200 17765 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:38 +0000] "GET /api/v2/inventory_sources/ HTTP/1.1" 200 18523 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:38 +0000] "OPTIONS /api/v2/inventory_sources/ HTTP/1.1" 200 24960 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:39 +0000] "GET /api/v2/job_templates/ HTTP/1.1" 200 94433 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:40 +0000] "GET /api/v2/job_templates/?page=2 HTTP/1.1" 200 90206 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:41 +0000] "GET /api/v2/job_templates/?page=3 HTTP/1.1" 200 91137 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:42 +0000] "GET /api/v2/job_templates/?page=4 HTTP/1.1" 200 87297 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:42 +0000] "GET /api/v2/job_templates/?page=5 HTTP/1.1" 200 88139 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:46 +0000] "GET /api/v2/job_templates/?page=6 HTTP/1.1" 200 38863 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:48 +0000] "OPTIONS /api/v2/job_templates/ HTTP/1.1" 200 23317 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:50 +0000] "GET /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:51 +0000] "OPTIONS /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 200 14423 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:51 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:56 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:01:56 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:01 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:02 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:02 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:03 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:04 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:07 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:07 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1227 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:10 +0000] "POST /api/v2/workflow_job_templates/310/workflow_nodes/ HTTP/1.1" 201 1400 "https://ansible-tower-web-svc-tower-test.ose.private.my.local/api/v2/workflow_job_templates/310/workflow_nodes/" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:11 +0000] "GET /api/v2/workflow_job_template_nodes/1317/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1318/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1319/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1320/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1321/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1322/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1323/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:12 +0000] "GET /api/v2/workflow_job_template_nodes/1324/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:13 +0000] "GET /api/v2/workflow_job_template_nodes/1326/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
10.0.10.11 - - [31/Jul/2020:21:02:13 +0000] "GET /api/v2/workflow_job_template_nodes/1327/success_nodes/ HTTP/1.1" 200 52 "-" "python-requests/2.24.0" "10.0.10.10"
@zedr
Copy link
Author

zedr commented Aug 4, 2020

I think I found two bugs that are related to the problem.

The first is related to https://github.com/ansible/awx/blob/devel/awxkit/awxkit/api/pages/api.py#L273

    def _assign_related(self):
        for _page, name, related_set in self._related:
            endpoint = _page.related[name]
            if isinstance(related_set, dict):  # Relateds that are just json blobs, e.g. survey_spec
                endpoint.post(related_set)
                return

If the resource has two related object lists of different types (e.g. survey_spec and workflow_job_template_nodes) the function will exit early and the second object list will be ignored. That return should really be a continue. This explains why workflow_job_templates that had surveys did not have any nodes generated at all.

The second bug is more subtle. If the workflow nodes are generated, the are always missing their related job_template. The reason for this is that the exported natural key for that job_template is not complete. For example:

    workflow_nodes:
    - all_parents_must_converge: false

      (...)

      related:
        - type: workflow_job_template_node
          workflow_job_template:
            name: my-config
            organization:
              name: ACME
              type: organization
            type: workflow_job_template
      unified_job_template:
        name: Template-varsmng_pgsql_configuration
        type: job_template

The natural key for the unified_job_template is missing the organization. PageCache.pages_by_natural_key expects: [frozenset({('organization', frozenset({('type', 'organization'), ('name', 'ACME')})), ('type', 'job_template'), ('name', 'my-config')})]

@zedr
Copy link
Author

zedr commented Aug 4, 2020

A third bug seems to be related to success_nodes, failure_nodes, and always_nodes being unset.

@zedr
Copy link
Author

zedr commented Aug 4, 2020

The reason for the third bug seems to be due to the missing identifier when we export workflow_job_templates from certain (ancient) versions of awx, such as AWX 9.2.0.

I think I can fix it in the export process.

@zedr
Copy link
Author

zedr commented Aug 5, 2020

OK. I have a working solution for this. See: zedr@6b528cb The fix attempts to patch resources that have been exported from AWX instances prior to version 10.0.0, specifically, by creating identifier fields or adding organizations by their natural key. This is not final, and I'm looking for feedback on how best to engineer this solution.

@AlanCoding does this project want to support scenarios where documents that have been exported from older AWX releases need to be imported into more recent ones, and may not have a compatible schema? I am working on a project where we have this use case, and I think it would be valuable to have, or at least flag schema incompatibilities by erroring out during the import process.

@AlanCoding
Copy link
Member

Using import/export to migrate from <10.0.0 is going to be hard.

I don't have any problem with what you're doing in that diff, in terms of implicitly grabbing the JT organization, or making up a workflow node identifier in older versions.

The most likely issue may be dealing with the method of applying the patch, and I would like to ping @jbradberry to weigh in on that. Verifying and regression testing this is going to be a hard question, and I defer to him about overall cross-version strategy.

@jbradberry
Copy link
Contributor

@zedr instead of this new patches module, I think it would be preferable to override get_natural_key() for the relevant Page types, much like how Role is currently done.

@tiagodread
Copy link
Contributor

Verified if summary_fields.unified_job_template is populated correctly and it does.

{
              "id": 44,
              "type": "workflow_job_template_node",
              "url": "/api/v2/workflow_job_template_nodes/44/",
              "related": {
                   "credentials": "/api/v2/workflow_job_template_nodes/44/credentials/",
                   "create_approval_template": "/api/v2/workflow_job_template_nodes/44/create_approval_template/",
                   "success_nodes": "/api/v2/workflow_job_template_nodes/44/success_nodes/",
                   "failure_nodes": "/api/v2/workflow_job_template_nodes/44/failure_nodes/",
                   "always_nodes": "/api/v2/workflow_job_template_nodes/44/always_nodes/",
                   "unified_job_template": "/api/v2/job_templates/69/",
                   "workflow_job_template": "/api/v2/workflow_job_templates/66/"
              },
              "summary_fields": {
                   "workflow_job_template": {
                        "id": 66,
                        "name": "WFJT",
                        "description": ""
                   },
                   "unified_job_template": {
                        "id": 69,
                        "name": "Ping-20",
                        "description": "",
                        "unified_job_type": "job"
                   }
              },
              "created": "2020-09-21T21:07:29.275168Z",
              "modified": "2020-09-21T21:07:29.275183Z",
              "extra_data": {},
              "inventory": null,
              "scm_branch": null,
              "job_type": null,
              "job_tags": null,
              "skip_tags": null,
              "limit": null,
              "diff_mode": null,
              "verbosity": null,
              "workflow_job_template": 66,
              "unified_job_template": 69,
              "success_nodes": [
                   43
              ],
              "failure_nodes": [],
              "always_nodes": [],
              "all_parents_must_converge": false,
              "identifier": "9191bfb1-273f-4900-8f7b-627543893a44"
         }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants