diff --git a/awx/ui/client/src/credentials/add/credentials-add.controller.js b/awx/ui/client/src/credentials/add/credentials-add.controller.js index bb95140311..bb5a708acf 100644 --- a/awx/ui/client/src/credentials/add/credentials-add.controller.js +++ b/awx/ui/client/src/credentials/add/credentials-add.controller.js @@ -61,7 +61,7 @@ export default ['$scope', '$rootScope', if ($rootScope.current_user && $rootScope.current_user.is_superuser) { $scope.canShareCredential = true; } else { - Rest.setUrl(`/api/v1/users/${$rootScope.current_user.id}/admin_of_organizations`); + Rest.setUrl(GetBasePath('users') + `${$rootScope.current_user.id}/admin_of_organizations`); Rest.get() .success(function(data) { $scope.canShareCredential = (data.count) ? true : false; diff --git a/awx/ui/client/src/credentials/credentials.form.js b/awx/ui/client/src/credentials/credentials.form.js index c8a125b9bf..f8c0440725 100644 --- a/awx/ui/client/src/credentials/credentials.form.js +++ b/awx/ui/client/src/credentials/credentials.form.js @@ -431,7 +431,7 @@ export default ['i18n', function(i18n) { dataTipWatch: 'permissionsTooltip', awToolTipTabEnabledInEditMode: true, dataPlacement: 'right', - basePath: 'api/v1/credentials/{{$stateParams.credential_id}}/access_list/', + basePath: 'api/v2/credentials/{{$stateParams.credential_id}}/access_list/', search: { order_by: 'username' }, diff --git a/awx/ui/client/src/credentials/edit/credentials-edit.controller.js b/awx/ui/client/src/credentials/edit/credentials-edit.controller.js index eb3c62ebe3..97e0fcc6f2 100644 --- a/awx/ui/client/src/credentials/edit/credentials-edit.controller.js +++ b/awx/ui/client/src/credentials/edit/credentials-edit.controller.js @@ -55,7 +55,7 @@ export default ['$scope', '$rootScope', '$location', if ($rootScope.current_user && $rootScope.current_user.is_superuser) { $scope.canShareCredential = true; } else { - Rest.setUrl(`/api/v1/users/${$rootScope.current_user.id}/admin_of_organizations`); + Rest.setUrl(GetBasePath('users') + `${$rootScope.current_user.id}/admin_of_organizations`); Rest.get() .success(function(data) { $scope.canShareCredential = (data.count) ? true : false; diff --git a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js b/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js index cfed3878f7..1a34984a79 100644 --- a/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js +++ b/awx/ui/client/src/home/dashboard/lists/job-templates/job-templates-list.directive.js @@ -30,14 +30,10 @@ export default // smartStatus?, launchUrl, editUrl, name scope.templates = _.map(list, function(template){ return { recent_jobs: template.summary_fields.recent_jobs, - launch_url: template.url, - edit_url: template.url.replace('api/v1', '#'), name: template.name, id: template.id, type: template.type }; }); - - scope.snapRows = (list.length < 4); } scope.isSuccessful = function (status) { diff --git a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js b/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js index be3d78c8bb..4d8be63ccd 100644 --- a/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js +++ b/awx/ui/client/src/home/dashboard/lists/jobs/jobs-list.directive.js @@ -29,14 +29,12 @@ export default // detailsUrl, status, name, time scope.jobs = _.map(list, function(job){ return { - detailsUrl: job.type && job.type === 'workflow_job' ? job.url.replace("api/v1/workflow_jobs", "#/workflows") : job.url.replace("api/v1", "#"), + detailsUrl: job.type && job.type === 'workflow_job' ? job.url.replace(/api\/v\d+\/workflow_jobs/, "#/workflows") : job.url.replace(/api\/v\d+/, "#"), status: job.status, name: job.name, id: job.id, time: $filter('longDate')(job.finished) }; }); - - scope.snapRows = (list.length < 4); } scope.isSuccessful = function (status) { diff --git a/awx/ui/client/src/home/home.controller.js b/awx/ui/client/src/home/home.controller.js index ef6794012e..bbdc615c69 100644 --- a/awx/ui/client/src/home/home.controller.js +++ b/awx/ui/client/src/home/home.controller.js @@ -23,7 +23,7 @@ export default ['$scope', '$rootScope','Wait', ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard host graph data: ' + status }); }); - Rest.setUrl("api/v1/unified_jobs?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); + Rest.setUrl(GetBasePath("unified_jobs") + "?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); Rest.get() .success(function (data) { $scope.dashboardJobsListData = data.results; @@ -99,7 +99,7 @@ export default ['$scope', '$rootScope','Wait', .error(function (data, status) { ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status }); }); - Rest.setUrl("api/v1/unified_jobs?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); + Rest.setUrl(GetBasePath("unified_jobs") + "?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); Rest.get() .success(function (data) { data = data.results; diff --git a/awx/ui/client/src/inventories/smart-inventory/smart-inventory.form.js b/awx/ui/client/src/inventories/smart-inventory/smart-inventory.form.js index de06dc4a6e..9e54ace85f 100644 --- a/awx/ui/client/src/inventories/smart-inventory/smart-inventory.form.js +++ b/awx/ui/client/src/inventories/smart-inventory/smart-inventory.form.js @@ -112,7 +112,7 @@ export default ['i18n', 'InventoryCompletedJobsList', function(i18n, InventoryCo name: 'permissions', awToolTip: i18n._('Please save before assigning permissions'), dataPlacement: 'top', - basePath: 'api/v1/inventories/{{$stateParams.smartinventory_id}}/access_list/', + basePath: 'api/v2/inventories/{{$stateParams.smartinventory_id}}/access_list/', type: 'collection', title: i18n._('Permissions'), iterator: 'permission', diff --git a/awx/ui/client/src/job-results/job-results.controller.js b/awx/ui/client/src/job-results/job-results.controller.js index 04d7fd5210..a74550393f 100644 --- a/awx/ui/client/src/job-results/job-results.controller.js +++ b/awx/ui/client/src/job-results/job-results.controller.js @@ -1,5 +1,5 @@ -export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'QuerySet', '$rootScope', 'moment', '$stateParams', 'i18n', 'fieldChoices', 'fieldLabels', 'workflowResultsService', 'statusSocket', -function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, QuerySet, $rootScope, moment, $stateParams, i18n, fieldChoices, fieldLabels, workflowResultsService, statusSocket) { +export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'QuerySet', '$rootScope', 'moment', '$stateParams', 'i18n', 'fieldChoices', 'fieldLabels', 'workflowResultsService', 'statusSocket', 'GetBasePath', +function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, QuerySet, $rootScope, moment, $stateParams, i18n, fieldChoices, fieldLabels, workflowResultsService, statusSocket, GetBasePath) { var toDestroy = []; var cancelRequests = false; var runTimeElapsedTimer = null; @@ -49,7 +49,7 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy var getTowerLink = function(key) { if(key === 'schedule') { if($scope.job.related.schedule) { - return '/#/templates/job_template/' + $scope.job.job_template + '/schedules' + $scope.job.related.schedule.split('api/v1/schedules')[1]; + return '/#/templates/job_template/' + $scope.job.job_template + '/schedules' + $scope.job.related.schedule.split(/api\/v\d+\/schedules/)[1]; } else { return null; @@ -66,7 +66,7 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy else { if ($scope.job.related[key]) { return '/#/' + $scope.job.related[key] - .split('api/v1/')[1]; + .split(/api\/v\d+\//)[1]; } else { return null; } @@ -132,7 +132,7 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy // return a promise from the options request with the permission type choices (including adhoc) as a param var fieldChoice = fieldChoices({ $scope: $scope, - url: 'api/v1/unified_jobs/', + url: GetBasePath('unified_jobs'), field: 'type' }); diff --git a/awx/ui/client/src/job-results/job-results.partial.html b/awx/ui/client/src/job-results/job-results.partial.html index 90700c8a68..8d497ca36c 100644 --- a/awx/ui/client/src/job-results/job-results.partial.html +++ b/awx/ui/client/src/job-results/job-results.partial.html @@ -505,7 +505,7 @@ + href="/api/v2/jobs/{{ job.id }}/stdout?format=txt_download"> - + diff --git a/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html b/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html index e5b0b17baf..9907c3df64 100644 --- a/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html +++ b/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html @@ -124,7 +124,7 @@ - + diff --git a/awx/ui/client/src/standard-out/scm-update/standard-out-scm-update.partial.html b/awx/ui/client/src/standard-out/scm-update/standard-out-scm-update.partial.html index 249cb0bf72..008516a2ad 100644 --- a/awx/ui/client/src/standard-out/scm-update/standard-out-scm-update.partial.html +++ b/awx/ui/client/src/standard-out/scm-update/standard-out-scm-update.partial.html @@ -98,7 +98,7 @@ - + diff --git a/awx/ui/client/src/teams/edit/teams-edit.controller.js b/awx/ui/client/src/teams/edit/teams-edit.controller.js index 6587311c7d..0091baf109 100644 --- a/awx/ui/client/src/teams/edit/teams-edit.controller.js +++ b/awx/ui/client/src/teams/edit/teams-edit.controller.js @@ -87,7 +87,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'TeamForm', 'Rest', $scope.convertApiUrl = function(str) { if (str) { - return str.replace("api/v1", "#"); + return str.replace(/api\/v\d+/, "#"); } else { return null; } diff --git a/awx/ui/client/src/teams/teams.form.js b/awx/ui/client/src/teams/teams.form.js index 2a3e97fcfa..78ba95f159 100644 --- a/awx/ui/client/src/teams/teams.form.js +++ b/awx/ui/client/src/teams/teams.form.js @@ -67,7 +67,7 @@ export default ['i18n', function(i18n) { name: 'users', dataPlacement: 'top', awToolTip: i18n._('Please save before adding users'), - basePath: 'api/v1/teams/{{$stateParams.team_id}}/access_list/', + basePath: 'api/v2/teams/{{$stateParams.team_id}}/access_list/', search: { order_by: 'username' }, @@ -104,7 +104,7 @@ export default ['i18n', function(i18n) { }, permissions: { name: 'permissions', - basePath: 'api/v1/teams/{{$stateParams.team_id}}/roles/', + basePath: 'api/v2/teams/{{$stateParams.team_id}}/roles/', search: { page_size: '10', // @todo ask about name field / serializer on this endpoint diff --git a/awx/ui/client/src/templates/completed-jobs.list.js b/awx/ui/client/src/templates/completed-jobs.list.js index 8ad664d3db..11e8c19b0a 100644 --- a/awx/ui/client/src/templates/completed-jobs.list.js +++ b/awx/ui/client/src/templates/completed-jobs.list.js @@ -11,7 +11,7 @@ export default ['i18n', function(i18n) { awToolTip: i18n._('Please save and run a job to view'), dataPlacement: 'top', name: 'completed_jobs', - basePath: 'api/v1/job_templates/{{$stateParams.job_template_id}}/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled', + basePath: 'api/v2/job_templates/{{$stateParams.job_template_id}}/jobs/?or__status=successful&or__status=failed&or__status=error&or__status=canceled', iterator: 'completed_job', editTitle: i18n._('COMPLETED JOBS'), index: false, diff --git a/awx/ui/client/src/templates/job-template.form.js b/awx/ui/client/src/templates/job-template.form.js index 5a3d5e0754..5c650038a3 100644 --- a/awx/ui/client/src/templates/job-template.form.js +++ b/awx/ui/client/src/templates/job-template.form.js @@ -426,7 +426,7 @@ function(NotificationsList, CompletedJobsList, i18n) { name: 'permissions', awToolTip: i18n._('Please save before assigning permissions'), dataPlacement: 'top', - basePath: 'api/v1/job_templates/{{$stateParams.job_template_id}}/access_list/', + basePath: 'api/v2/job_templates/{{$stateParams.job_template_id}}/access_list/', search: { order_by: 'username' }, diff --git a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js index 735dc4d421..f819b14b5f 100644 --- a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js +++ b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js @@ -137,7 +137,7 @@ callback: 'choicesReadyVerbosity' }); - Rest.setUrl('api/v1/labels'); + Rest.setUrl(GetBasePath('labels')); Rest.get() .success(function (data) { $scope.labelOptions = data.results diff --git a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js index eff695a1f1..56117cfb24 100644 --- a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js +++ b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js @@ -351,7 +351,7 @@ export default callback: 'choicesReady' }); - Rest.setUrl('api/v1/labels'); + Rest.setUrl(GetBasePath('labels')); Wait("start"); Rest.get() .success(function (data) { diff --git a/awx/ui/client/src/templates/workflows.form.js b/awx/ui/client/src/templates/workflows.form.js index 4906dfae75..a929e8b77e 100644 --- a/awx/ui/client/src/templates/workflows.form.js +++ b/awx/ui/client/src/templates/workflows.form.js @@ -108,7 +108,7 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n) { name: 'permissions', awToolTip: i18n._('Please save before assigning permissions'), dataPlacement: 'top', - basePath: 'api/v1/workflow_job_templates/{{$stateParams.workflow_job_template_id}}/access_list/', + basePath: 'api/v2/workflow_job_templates/{{$stateParams.workflow_job_template_id}}/access_list/', search: { order_by: 'username' }, diff --git a/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js b/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js index d3548540af..fb408745a2 100644 --- a/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js +++ b/awx/ui/client/src/templates/workflows/edit-workflow/workflow-edit.controller.js @@ -47,7 +47,7 @@ export default [ templateType: 'workflow_job_template' }); - Rest.setUrl('api/v1/labels'); + Rest.setUrl(GetBasePath('labels')); Wait("start"); Rest.get() .success(function (data) { diff --git a/awx/ui/client/src/users/edit/users-edit.controller.js b/awx/ui/client/src/users/edit/users-edit.controller.js index 864ba4ce71..9db7d1f83f 100644 --- a/awx/ui/client/src/users/edit/users-edit.controller.js +++ b/awx/ui/client/src/users/edit/users-edit.controller.js @@ -128,7 +128,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'UserForm', 'Rest', $scope.convertApiUrl = function(str) { if (str) { - return str.replace("api/v1", "#"); + return str.replace(/api\/v\d+/, "#"); } else { return null; } diff --git a/awx/ui/client/src/users/users.form.js b/awx/ui/client/src/users/users.form.js index c1a7946a6e..931d26e4a2 100644 --- a/awx/ui/client/src/users/users.form.js +++ b/awx/ui/client/src/users/users.form.js @@ -119,7 +119,7 @@ export default ['i18n', function(i18n) { organizations: { name: 'organizations', awToolTip: i18n._('Please save before assigning to organizations'), - basePath: 'api/v1/users/{{$stateParams.user_id}}/organizations', + basePath: 'api/v2/users/{{$stateParams.user_id}}/organizations', emptyListText: i18n._('Please add user to an Organization.'), search: { page_size: '10' @@ -147,7 +147,7 @@ export default ['i18n', function(i18n) { teams: { name: 'teams', awToolTip: i18n._('Please save before assigning to teams'), - basePath: 'api/v1/users/{{$stateParams.user_id}}/teams', + basePath: 'api/v2/users/{{$stateParams.user_id}}/teams', search: { page_size: '10' }, @@ -172,7 +172,7 @@ export default ['i18n', function(i18n) { }, permissions: { name: 'permissions', - basePath: 'api/v1/users/{{$stateParams.user_id}}/roles/', + basePath: 'api/v2/users/{{$stateParams.user_id}}/roles/', search: { page_size: '10', order_by: 'id' diff --git a/awx/ui/client/src/workflow-results/workflow-results.controller.js b/awx/ui/client/src/workflow-results/workflow-results.controller.js index 8a20e8c57d..38802ce315 100644 --- a/awx/ui/client/src/workflow-results/workflow-results.controller.js +++ b/awx/ui/client/src/workflow-results/workflow-results.controller.js @@ -10,7 +10,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions', var getTowerLink = function(key) { if(key === 'schedule') { if($scope.workflow.related.schedule) { - return '/#/templates/workflow_job_template/' + $scope.workflow.workflow_job_template + '/schedules' + $scope.workflow.related.schedule.split('api/v1/schedules')[1]; + return '/#/templates/workflow_job_template/' + $scope.workflow.workflow_job_template + '/schedules' + $scope.workflow.related.schedule.split(/api\/v\d+\/schedules/)[1]; } else { return null; @@ -19,7 +19,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions', else { if ($scope.workflow.related[key]) { return '/#/' + $scope.workflow.related[key] - .split('api/v1/')[1]; + .split(/api\/v\d+\//)[1]; } else { return null; } diff --git a/awx/ui/tests/spec/inventories/manage/inventory-manage.service-test.js b/awx/ui/tests/spec/inventories/manage/inventory-manage.service-test.js index 43ec43b341..c60508ef15 100644 --- a/awx/ui/tests/spec/inventories/manage/inventory-manage.service-test.js +++ b/awx/ui/tests/spec/inventories/manage/inventory-manage.service-test.js @@ -20,7 +20,7 @@ describe('Service: InventoryManageService', () => { spyOn(InventoryManageService, 'error'); }); it('InventoryManageService.getInventory should handle errors', () => { - Rest.expectGET('/api/v1/inventory:id/').respond(400, {}); + Rest.expectGET('/api/v2/inventory:id/').respond(400, {}); Rest.flush(); expect(InventoryManageService.error).toHaveBeenCalled(); }); diff --git a/awx/ui/tests/spec/job-results/job-results.controller-test.js b/awx/ui/tests/spec/job-results/job-results.controller-test.js index 239c296b59..0cacc68a9b 100644 --- a/awx/ui/tests/spec/job-results/job-results.controller-test.js +++ b/awx/ui/tests/spec/job-results/job-results.controller-test.js @@ -198,12 +198,12 @@ describe('Controller: jobResultsController', () => { describe('getTowerLinks()', () => { beforeEach(() => { jobData.related = { - "created_by": "api/v1/users/12", - "inventory": "api/v1/inventories/12", - "project": "api/v1/projects/12", - "credential": "api/v1/credentials/12", - "cloud_credential": "api/v1/credentials/13", - "network_credential": "api/v1/credentials/14", + "created_by": "api/v2/users/12", + "inventory": "api/v2/inventories/12", + "project": "api/v2/projects/12", + "credential": "api/v2/credentials/12", + "cloud_credential": "api/v2/credentials/13", + "network_credential": "api/v2/credentials/14", }; jobData.summary_fields.inventory = { diff --git a/awx/ui/tests/spec/smart-search/queryset.service-test.js b/awx/ui/tests/spec/smart-search/queryset.service-test.js index c558f82233..4ac549a9f0 100644 --- a/awx/ui/tests/spec/smart-search/queryset.service-test.js +++ b/awx/ui/tests/spec/smart-search/queryset.service-test.js @@ -60,8 +60,8 @@ describe('Service: QuerySet', () => { describe('fn search', () => { - let pattern = /\/api\/v1\/inventories\/(.+)\/groups\/*/, - endpoint = '/api/v1/inventories/1/groups/', + let pattern = /\/api\/v2\/inventories\/(.+)\/groups\/*/, + endpoint = '/api/v2/inventories/1/groups/', params = { or__name: 'borg', or__description__icontains: 'assimilate' @@ -72,7 +72,7 @@ describe('Service: QuerySet', () => { .expectGET(pattern) .respond(200, {}); QuerySet.search(endpoint, params).then((data) =>{ - expect(data.config.url).toEqual('/api/v1/inventories/1/groups/?or__name=borg&or__description__icontains=assimilate'); + expect(data.config.url).toEqual('/api/v2/inventories/1/groups/?or__name=borg&or__description__icontains=assimilate'); }); $httpBackend.flush(); }); diff --git a/awx/ui/tests/spec/workflow--results/data/workflow_job.js b/awx/ui/tests/spec/workflow--results/data/workflow_job.js index 997c488e7a..6893b63216 100644 --- a/awx/ui/tests/spec/workflow--results/data/workflow_job.js +++ b/awx/ui/tests/spec/workflow--results/data/workflow_job.js @@ -1,17 +1,17 @@ export default { "id": 109, "type": "workflow_job", - "url": "/api/v1/workflow_jobs/109/", + "url": "/api/v2/workflow_jobs/109/", "related": { - "created_by": "/api/v1/users/1/", - "unified_job_template": "/api/v1/workflow_job_templates/27/", - "workflow_job_template": "/api/v1/workflow_job_templates/27/", - "notifications": "/api/v1/workflow_jobs/109/notifications/", - "workflow_nodes": "/api/v1/workflow_jobs/109/workflow_nodes/", - "labels": "/api/v1/workflow_jobs/109/labels/", - "activity_stream": "/api/v1/workflow_jobs/109/activity_stream/", - "relaunch": "/api/v1/workflow_jobs/109/relaunch/", - "cancel": "/api/v1/workflow_jobs/109/cancel/" + "created_by": "/api/v2/users/1/", + "unified_job_template": "/api/v2/workflow_job_templates/27/", + "workflow_job_template": "/api/v2/workflow_job_templates/27/", + "notifications": "/api/v2/workflow_jobs/109/notifications/", + "workflow_nodes": "/api/v2/workflow_jobs/109/workflow_nodes/", + "labels": "/api/v2/workflow_jobs/109/labels/", + "activity_stream": "/api/v2/workflow_jobs/109/activity_stream/", + "relaunch": "/api/v2/workflow_jobs/109/relaunch/", + "cancel": "/api/v2/workflow_jobs/109/cancel/" }, "summary_fields": { "workflow_job_template": {