diff --git a/app/models.py b/app/models.py index e7d9156f93eaa6ecba854943db973318fa5ef06f..8ad58ba67d2ff19a739da5c53d900f4b5eef0b7e 100644 --- a/app/models.py +++ b/app/models.py @@ -294,6 +294,7 @@ class User(db.Model, UserMixin): task = Task( id=job.id, name=name, + awx_resource=kwargs.get("resource", None), command=job.get_call_string(), status=JobStatus(job.status), user=self, @@ -1581,6 +1582,7 @@ class Task(db.Model): name = db.Column(db.Text, nullable=False, index=True) command = db.Column(db.Text) status = db.Column(db.Enum(JobStatus, name="job_status")) + awx_resource = db.Column(db.Text) awx_job_id = db.Column(db.Integer) exception = db.Column(db.Text) user_id = db.Column( @@ -1594,8 +1596,15 @@ class Task(db.Model): def awx_job_url(self): if self.awx_job_id is None: return None + if self.awx_resource == "job": + route = "jobs/playbook" + elif self.awx_resource == "workflow_job": + route = "workflows" + else: + current_app.logger.warning(f"Unknown AWX resource: {self.awx_resource}") + return None return urllib.parse.urljoin( - current_app.config["AWX_URL"], f"/#/jobs/{self.awx_job_id}" + current_app.config["AWX_URL"], f"/#/{route}/{self.awx_job_id}" ) def __str__(self): @@ -1608,6 +1617,7 @@ class Task(db.Model): "created_at": utils.format_field(self.created_at), "ended_at": utils.format_field(self.ended_at), "status": self.status.name, + "awx_resource": self.awx_resource, "awx_job_id": self.awx_job_id, "awx_job_url": self.awx_job_url, "command": self.command, diff --git a/app/tasks.py b/app/tasks.py index 6543c5a1a24913a8755d0352af282a141d654d65..96808d9d227169718c4ee6bd0f5668ecacab26fc 100644 --- a/app/tasks.py +++ b/app/tasks.py @@ -107,6 +107,7 @@ def trigger_vm_creation( ) task = current_user.launch_task( task_name, + resource="job", func="launch_job_template", job_template=job_template, extra_vars=extra_vars, @@ -115,6 +116,7 @@ def trigger_vm_creation( if post_job_template and not skip_post_install_job: current_user.launch_task( "trigger_post_install_job", + resource="job", func="launch_job_template", job_template=post_job_template, limit=f"{host.fqdn}", @@ -144,6 +146,7 @@ def trigger_ztp_configuration(host): ) task = current_user.launch_task( "trigger_ztp_configuration", + resource="job", func="launch_job_template", job_template=job_template, extra_vars=extra_vars, diff --git a/app/templates/task/view_task.html b/app/templates/task/view_task.html index 4a5afbb92ac21b5a2d685bb74ea6a2c657bdd942..bfd1a8f7c4c69f58135a46536296316defdc04e6 100644 --- a/app/templates/task/view_task.html +++ b/app/templates/task/view_task.html @@ -22,6 +22,8 @@ <dd class="col-sm-9">{{ task.ended_at }}</dd> <dt class="col-sm-3">Status</dt> <dd class="col-sm-9">{{ task.status.name }}</dd> + <dt class="col-sm-3">AWX resource</dt> + <dd class="col-sm-9">{{ task.awx_resource }}</dd> <dt class="col-sm-3">AWX job</dt> {% if task.awx_job_id %} <dd class="col-sm-9"><a href="{{ task.awx_job_url }}">{{ task.awx_job_id }}</a></dd> diff --git a/migrations/versions/166572b78449_add_awx_resource_field_to_task_table.py b/migrations/versions/166572b78449_add_awx_resource_field_to_task_table.py new file mode 100644 index 0000000000000000000000000000000000000000..b0e02bc2746c5eaa7ca9ba3c765018cd9b46da3c --- /dev/null +++ b/migrations/versions/166572b78449_add_awx_resource_field_to_task_table.py @@ -0,0 +1,33 @@ +"""Add awx_resource field to Task table + +Revision ID: 166572b78449 +Revises: ac04850e5f68 +Create Date: 2019-03-18 08:08:07.399875 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "166572b78449" +down_revision = "ac04850e5f68" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column("task", sa.Column("awx_resource", sa.Text(), nullable=True)) + # Fill the task awx_resource based on the value from the name column + task = sa.sql.table("task", sa.sql.column("name"), sa.sql.column("awx_resource")) + # generate_items_excel_file is not an AWX task but a local one (no awx_resource) + # others are assumed to be "job" + op.execute( + task.update() + .where(task.c.name != "generate_items_excel_file") + .values(awx_resource="job") + ) + + +def downgrade(): + op.drop_column("task", "awx_resource") diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py index 3c57475a19ec34d2911b1472eec0958902f800f1..a653fc2a844526944a454829c5426089955a82d5 100644 --- a/tests/functional/conftest.py +++ b/tests/functional/conftest.py @@ -58,6 +58,7 @@ def app(request): "lab.example.org": ["CSEntry Lab"], "foo.example.org": ["CSEntry User", "CSEntry Consultant"], }, + "AWX_URL": "https://awx.example.org", } app = create_app(config=config) ctx = app.app_context() diff --git a/tests/functional/test_models.py b/tests/functional/test_models.py index b57ed01279cbfbe5fb06dedfe6d185f7fe6658f8..ecfd31791fb2d11a8cf17dbe53c033a9e6176616 100644 --- a/tests/functional/test_models.py +++ b/tests/functional/test_models.py @@ -533,3 +533,14 @@ def test_cname_unique_by_domain(db, interface_factory, network_factory, cname_fa with pytest.raises(ValidationError) as excinfo: cname_factory(name="mycname", interface=interface3) assert f"Duplicate cname on the {network1.domain} domain" in str(excinfo.value) + + +def test_task_awx_job_url(db, task_factory): + task1 = task_factory(awx_resource="job", awx_job_id=42) + assert task1.awx_job_url == "https://awx.example.org/#/jobs/playbook/42" + task2 = task_factory(awx_resource="workflow_job", awx_job_id=43) + assert task2.awx_job_url == "https://awx.example.org/#/workflows/43" + task3 = task_factory(awx_resource="foo", awx_job_id=44) + assert task3.awx_job_url is None + task4 = task_factory(awx_job_id=45) + assert task4.awx_job_url is None