From b177c7b55895696879bb754d7f9147d34b092f1c Mon Sep 17 00:00:00 2001 From: Nikhil Jain Date: Fri, 12 Feb 2021 08:19:32 +0530 Subject: [PATCH 01/26] add support diff mode in tower_settings module --- .../plugins/modules/tower_settings.py | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/awx_collection/plugins/modules/tower_settings.py b/awx_collection/plugins/modules/tower_settings.py index c2e8ed1ae5..7fcd3618dc 100644 --- a/awx_collection/plugins/modules/tower_settings.py +++ b/awx_collection/plugins/modules/tower_settings.py @@ -133,7 +133,7 @@ def main(): existing_settings = module.get_endpoint('settings/all')['json'] # Begin a json response - json_response = {'changed': False, 'old_values': {}} + json_output = {'changed': False, 'old_values': {}, 'new_values': {} } # Check any of the settings to see if anything needs to be updated needs_update = False @@ -141,18 +141,29 @@ def main(): if a_setting not in existing_settings or existing_settings[a_setting] != new_settings[a_setting]: # At least one thing is different so we need to patch needs_update = True - json_response['old_values'][a_setting] = existing_settings[a_setting] + json_output['old_values'][a_setting] = existing_settings[a_setting] + json_output['new_values'][a_setting] = new_settings[a_setting] + + if module._diff: + json_output['diff'] = { + 'before': json_output['old_values'], + 'after': json_output['new_values'] + } # If nothing needs an update we can simply exit with the response (as not changed) if not needs_update: - module.exit_json(**json_response) + module.exit_json(**json_output) + + if module.check_mode and module._diff: + json_output['changed'] = True + module.exit_json(**json_output) # Make the call to update the settings response = module.patch_endpoint('settings/all', **{'data': new_settings}) if response['status_code'] == 200: # Set the changed response to True - json_response['changed'] = True + json_output['changed'] = True # To deal with the old style values we need to return 'value' in the response new_values = {} @@ -161,11 +172,11 @@ def main(): # If we were using a name we will just add a value of a string, otherwise we will return an array in values if name is not None: - json_response['value'] = new_values[name] + json_output['value'] = new_values[name] else: - json_response['values'] = new_values + json_output['values'] = new_values - module.exit_json(**json_response) + module.exit_json(**json_output) elif 'json' in response and '__all__' in response['json']: module.fail_json(msg=response['json']['__all__']) else: From 33b10288827e94e6c584337c9efc46c3aae708cb Mon Sep 17 00:00:00 2001 From: nixocio Date: Mon, 1 Feb 2021 08:55:31 -0500 Subject: [PATCH 02/26] Add relaunch against failed hosts Add relaunch against failed hosts See: https://github.com/ansible/awx/issues/8670 --- .../src/components/JobList/JobListItem.jsx | 38 +++++--- .../components/JobList/JobListItem.test.jsx | 84 ++++++++++++++++ .../components/LaunchButton/LaunchButton.jsx | 4 +- .../LaunchButton/LaunchButton.test.jsx | 2 +- .../LaunchButton/ReLaunchDropDown.jsx | 96 +++++++++++++++++++ .../LaunchButton/ReLaunchDropDown.test.jsx | 55 +++++++++++ .../src/components/LaunchButton/index.js | 3 +- .../TemplateList/TemplateListItem.jsx | 2 +- .../src/screens/Job/JobDetail/JobDetail.jsx | 16 +++- .../Job/JobOutput/shared/OutputToolbar.jsx | 43 ++++++--- .../ProjectJobTemplatesListItem.jsx | 2 +- .../JobTemplateDetail/JobTemplateDetail.jsx | 2 +- .../WorkflowJobTemplateDetail.jsx | 2 +- .../VisualizerToolbar.jsx | 2 +- 14 files changed, 313 insertions(+), 38 deletions(-) create mode 100644 awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.jsx create mode 100644 awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.test.jsx diff --git a/awx/ui_next/src/components/JobList/JobListItem.jsx b/awx/ui_next/src/components/JobList/JobListItem.jsx index a1cb09ad8a..27047015de 100644 --- a/awx/ui_next/src/components/JobList/JobListItem.jsx +++ b/awx/ui_next/src/components/JobList/JobListItem.jsx @@ -7,7 +7,7 @@ import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table'; import { RocketIcon } from '@patternfly/react-icons'; import styled from 'styled-components'; import { ActionsTd, ActionItem } from '../PaginatedTable'; -import LaunchButton from '../LaunchButton'; +import { LaunchButton, ReLaunchDropDown } from '../LaunchButton'; import StatusLabel from '../StatusLabel'; import { DetailList, Detail, LaunchedByDetail } from '../DetailList'; import ChipGroup from '../ChipGroup'; @@ -83,19 +83,31 @@ function JobListItem({ job.type !== 'system_job' && job.summary_fields?.user_capabilities?.start } - tooltip={i18n._(t`Relaunch Job`)} + tooltip={ + job.status === 'failed' && job.type === 'job' + ? i18n._(t`Relaunch using host parameters`) + : i18n._(t`Relaunch Job`) + } > - - {({ handleRelaunch }) => ( - - )} - + {job.status === 'failed' && job.type === 'job' ? ( + + {({ handleRelaunch }) => ( + + )} + + ) : ( + + {({ handleRelaunch }) => ( + + )} + + )} diff --git a/awx/ui_next/src/components/JobList/JobListItem.test.jsx b/awx/ui_next/src/components/JobList/JobListItem.test.jsx index 6b9a9c3ae4..2e35f181a0 100644 --- a/awx/ui_next/src/components/JobList/JobListItem.test.jsx +++ b/awx/ui_next/src/components/JobList/JobListItem.test.jsx @@ -53,6 +53,10 @@ describe('', () => { expect(wrapper.find('LaunchButton').length).toBe(1); }); + test('launch button shown to users with launch capabilities', () => { + expect(wrapper.find('LaunchButton').length).toBe(1); + }); + test('launch button hidden from users without launch capabilities', () => { wrapper = mountWithContexts( @@ -92,3 +96,83 @@ describe('', () => { expect(wrapper.find('Td[dataLabel="Type"]').length).toBe(1); }); }); + +describe('', () => { + let wrapper; + + beforeEach(() => { + const history = createMemoryHistory({ + initialEntries: ['/jobs'], + }); + wrapper = mountWithContexts( +
+ + {}} + /> + +
, + { context: { router: { history } } } + ); + }); + + afterEach(() => { + wrapper.unmount(); + }); + + test('launch button shown to users with launch capabilities', () => { + expect(wrapper.find('LaunchButton').length).toBe(1); + }); + + test('dropdown should be displayed in case of failed job', () => { + expect(wrapper.find('LaunchButton').length).toBe(1); + const dropdown = wrapper.find('Dropdown'); + expect(dropdown).toHaveLength(1); + expect(dropdown.find('DropdownItem')).toHaveLength(0); + dropdown.find('button').simulate('click'); + wrapper.update(); + expect(wrapper.find('DropdownItem')).toHaveLength(3); + }); + + test('dropdown should not be rendered for job type different of playbook run', () => { + wrapper = mountWithContexts( + + + {}} + isSelected + /> + +
+ ); + expect(wrapper.find('LaunchButton').length).toBe(1); + expect(wrapper.find('Dropdown')).toHaveLength(0); + }); + + test('launch button hidden from users without launch capabilities', () => { + wrapper = mountWithContexts( + + + {}} + isSelected={false} + /> + +
+ ); + expect(wrapper.find('LaunchButton').length).toBe(0); + }); +}); diff --git a/awx/ui_next/src/components/LaunchButton/LaunchButton.jsx b/awx/ui_next/src/components/LaunchButton/LaunchButton.jsx index a8322d86c5..17f7a4d0c1 100644 --- a/awx/ui_next/src/components/LaunchButton/LaunchButton.jsx +++ b/awx/ui_next/src/components/LaunchButton/LaunchButton.jsx @@ -87,7 +87,7 @@ function LaunchButton({ resource, i18n, children, history }) { } }; - const handleRelaunch = async () => { + const handleRelaunch = async params => { let readRelaunch; let relaunch; @@ -125,7 +125,7 @@ function LaunchButton({ resource, i18n, children, history }) { } else if (resource.type === 'ad_hoc_command') { relaunch = AdHocCommandsAPI.relaunch(resource.id); } else if (resource.type === 'job') { - relaunch = JobsAPI.relaunch(resource.id); + relaunch = JobsAPI.relaunch(resource.id, params || {}); } const { data: job } = await relaunch; history.push(`/jobs/${job.id}/output`); diff --git a/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx b/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx index 4d4ce3ac2e..09af167081 100644 --- a/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx +++ b/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx @@ -147,7 +147,7 @@ describe('LaunchButton', () => { await act(() => button.prop('onClick')()); expect(JobsAPI.readRelaunch).toHaveBeenCalledWith(1); await sleep(0); - expect(JobsAPI.relaunch).toHaveBeenCalledWith(1); + expect(JobsAPI.relaunch).toHaveBeenCalledWith(1, {}); expect(history.location.pathname).toEqual('/jobs/9000/output'); }); diff --git a/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.jsx b/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.jsx new file mode 100644 index 0000000000..dbd70d13ab --- /dev/null +++ b/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.jsx @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; +import { withI18n } from '@lingui/react'; +import { t } from '@lingui/macro'; +import { + Dropdown, + DropdownToggle, + DropdownItem, + DropdownPosition, + DropdownSeparator, + DropdownDirection, +} from '@patternfly/react-core'; +import { RocketIcon } from '@patternfly/react-icons'; + +function ReLaunchDropDown({ isPrimary = false, handleRelaunch, i18n }) { + const [isOpen, setIsOPen] = useState(false); + + const onToggle = () => { + setIsOPen(prev => !prev); + }; + + const dropdownItems = [ + + {i18n._(t`Relaunch on`)} + , + , + { + handleRelaunch({ hosts: 'all' }); + }} + > + {i18n._(t`All`)} + , + + { + handleRelaunch({ hosts: 'failed' }); + }} + > + {i18n._(t`Failed hosts`)} + , + ]; + + if (isPrimary) { + return ( + + {i18n._(t`Relaunch`)} + + } + /> + ); + } + + return ( + + + + } + /> + ); +} + +export default withI18n()(ReLaunchDropDown); diff --git a/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.test.jsx b/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.test.jsx new file mode 100644 index 0000000000..dcd7d1e5ad --- /dev/null +++ b/awx/ui_next/src/components/LaunchButton/ReLaunchDropDown.test.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; +import ReLaunchDropDown from './ReLaunchDropDown'; + +describe('ReLaunchDropDown', () => { + const handleRelaunch = jest.fn(); + + test('expected content is rendered on initialization', () => { + const wrapper = mountWithContexts( + + ); + + expect(wrapper.find('Dropdown')).toHaveLength(1); + }); + + test('dropdown have expected items and callbacks', () => { + const wrapper = mountWithContexts( + + ); + expect(wrapper.find('DropdownItem')).toHaveLength(0); + wrapper.find('button').simulate('click'); + wrapper.update(); + expect(wrapper.find('DropdownItem')).toHaveLength(3); + + wrapper + .find('DropdownItem[aria-label="Relaunch failed hosts"]') + .simulate('click'); + expect(handleRelaunch).toHaveBeenCalledWith({ hosts: 'failed' }); + + wrapper + .find('DropdownItem[aria-label="Relaunch all hosts"]') + .simulate('click'); + expect(handleRelaunch).toHaveBeenCalledWith({ hosts: 'all' }); + }); + + test('dropdown isPrimary have expected items and callbacks', () => { + const wrapper = mountWithContexts( + + ); + expect(wrapper.find('DropdownItem')).toHaveLength(0); + wrapper.find('button').simulate('click'); + wrapper.update(); + expect(wrapper.find('DropdownItem')).toHaveLength(3); + + wrapper + .find('DropdownItem[aria-label="Relaunch failed hosts"]') + .simulate('click'); + expect(handleRelaunch).toHaveBeenCalledWith({ hosts: 'failed' }); + + wrapper + .find('DropdownItem[aria-label="Relaunch all hosts"]') + .simulate('click'); + expect(handleRelaunch).toHaveBeenCalledWith({ hosts: 'all' }); + }); +}); diff --git a/awx/ui_next/src/components/LaunchButton/index.js b/awx/ui_next/src/components/LaunchButton/index.js index ed31194c06..6cc13ea141 100644 --- a/awx/ui_next/src/components/LaunchButton/index.js +++ b/awx/ui_next/src/components/LaunchButton/index.js @@ -1 +1,2 @@ -export { default } from './LaunchButton'; +export { default as LaunchButton } from './LaunchButton'; +export { default as ReLaunchDropDown } from './ReLaunchDropDown'; diff --git a/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx b/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx index dc53622737..1b7d9bfb24 100644 --- a/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx +++ b/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx @@ -18,7 +18,7 @@ import CredentialChip from '../CredentialChip'; import { timeOfDay, formatDateString } from '../../util/dates'; import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '../../api'; -import LaunchButton from '../LaunchButton'; +import { LaunchButton } from '../LaunchButton'; import Sparkline from '../Sparkline'; import { toTitleCase } from '../../util/strings'; import CopyButton from '../CopyButton'; diff --git a/awx/ui_next/src/screens/Job/JobDetail/JobDetail.jsx b/awx/ui_next/src/screens/Job/JobDetail/JobDetail.jsx index d41632008b..b50b25ea23 100644 --- a/awx/ui_next/src/screens/Job/JobDetail/JobDetail.jsx +++ b/awx/ui_next/src/screens/Job/JobDetail/JobDetail.jsx @@ -19,7 +19,10 @@ import CredentialChip from '../../../components/CredentialChip'; import { VariablesInput as _VariablesInput } from '../../../components/CodeMirrorInput'; import DeleteButton from '../../../components/DeleteButton'; import ErrorDetail from '../../../components/ErrorDetail'; -import LaunchButton from '../../../components/LaunchButton'; +import { + LaunchButton, + ReLaunchDropDown, +} from '../../../components/LaunchButton'; import StatusIcon from '../../../components/StatusIcon'; import { toTitleCase } from '../../../util/strings'; import { formatDateString } from '../../../util/dates'; @@ -346,7 +349,14 @@ function JobDetail({ job, i18n }) { )} {job.type !== 'system_job' && - job.summary_fields.user_capabilities.start && ( + job.summary_fields.user_capabilities.start && + (job.status === 'failed' && job.type === 'job' ? ( + + {({ handleRelaunch }) => ( + + )} + + ) : ( {({ handleRelaunch }) => ( )} - )} + ))} {job.summary_fields.user_capabilities.delete && ( { {job.type !== 'system_job' && job.summary_fields.user_capabilities?.start && ( - - - {({ handleRelaunch }) => ( - - )} - + + {job.status === 'failed' && job.type === 'job' ? ( + + {({ handleRelaunch }) => ( + + )} + + ) : ( + + {({ handleRelaunch }) => ( + + )} + + )} )} diff --git a/awx/ui_next/src/screens/Project/ProjectJobTemplatesList/ProjectJobTemplatesListItem.jsx b/awx/ui_next/src/screens/Project/ProjectJobTemplatesList/ProjectJobTemplatesListItem.jsx index df2fe6630f..2468ca8352 100644 --- a/awx/ui_next/src/screens/Project/ProjectJobTemplatesList/ProjectJobTemplatesListItem.jsx +++ b/awx/ui_next/src/screens/Project/ProjectJobTemplatesList/ProjectJobTemplatesListItem.jsx @@ -20,7 +20,7 @@ import { import styled from 'styled-components'; import DataListCell from '../../../components/DataListCell'; -import LaunchButton from '../../../components/LaunchButton'; +import { LaunchButton } from '../../../components/LaunchButton'; import Sparkline from '../../../components/Sparkline'; import { toTitleCase } from '../../../util/strings'; diff --git a/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx b/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx index db3e45bc91..3feed6bb7d 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateDetail/JobTemplateDetail.jsx @@ -26,7 +26,7 @@ import { } from '../../../components/DetailList'; import DeleteButton from '../../../components/DeleteButton'; import ErrorDetail from '../../../components/ErrorDetail'; -import LaunchButton from '../../../components/LaunchButton'; +import { LaunchButton } from '../../../components/LaunchButton'; import { VariablesDetail } from '../../../components/CodeMirrorInput'; import { JobTemplatesAPI } from '../../../api'; import useRequest, { useDismissableError } from '../../../util/useRequest'; diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.jsx index 2a5242b9a0..0ce65ca092 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.jsx @@ -24,7 +24,7 @@ import { UserDateDetail, } from '../../../components/DetailList'; import ErrorDetail from '../../../components/ErrorDetail'; -import LaunchButton from '../../../components/LaunchButton'; +import { LaunchButton } from '../../../components/LaunchButton'; import Sparkline from '../../../components/Sparkline'; import { toTitleCase } from '../../../util/strings'; import useRequest, { useDismissableError } from '../../../util/useRequest'; diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx index 1170858f83..f68453185a 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.jsx @@ -18,7 +18,7 @@ import { WrenchIcon, } from '@patternfly/react-icons'; import styled from 'styled-components'; -import LaunchButton from '../../../components/LaunchButton'; +import { LaunchButton } from '../../../components/LaunchButton'; import { WorkflowDispatchContext, WorkflowStateContext, From e93518a030c1af1af156b4aa39e259347faf01f5 Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Fri, 12 Feb 2021 16:44:19 -0500 Subject: [PATCH 03/26] Fix Openstack credential region implementation. The injector wasn't using the same variable name as the model. --- awx/main/models/credential/injectors.py | 4 ++-- .../data/inventory/plugins/openstack/files/file_reference | 1 + awx/main/tests/unit/test_tasks.py | 4 ++-- .../src/screens/Credential/shared/data.credentialTypes.json | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/awx/main/models/credential/injectors.py b/awx/main/models/credential/injectors.py index ef30b91945..90615f2d66 100644 --- a/awx/main/models/credential/injectors.py +++ b/awx/main/models/credential/injectors.py @@ -92,8 +92,8 @@ def _openstack_data(cred): }, } - if cred.has_input('project_region_name'): - openstack_data['clouds']['devstack']['region_name'] = cred.get_input('project_region_name', default='') + if cred.has_input('region'): + openstack_data['clouds']['devstack']['region_name'] = cred.get_input('region', default='') return openstack_data diff --git a/awx/main/tests/data/inventory/plugins/openstack/files/file_reference b/awx/main/tests/data/inventory/plugins/openstack/files/file_reference index c578942ca1..4e1d1c6a02 100644 --- a/awx/main/tests/data/inventory/plugins/openstack/files/file_reference +++ b/awx/main/tests/data/inventory/plugins/openstack/files/file_reference @@ -8,4 +8,5 @@ clouds: project_name: fooo username: fooo private: true + region_name: fooo verify: false diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index 166ea95f19..ceb2c7186f 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -249,7 +249,7 @@ def test_openstack_client_config_generation_with_project_domain_name(mocker, sou @pytest.mark.parametrize("source,expected", [ (None, True), (False, False), (True, True) ]) -def test_openstack_client_config_generation_with_project_region_name(mocker, source, expected, private_data_dir): +def test_openstack_client_config_generation_with_region(mocker, source, expected, private_data_dir): update = tasks.RunInventoryUpdate() credential_type = CredentialType.defaults['openstack']() inputs = { @@ -259,7 +259,7 @@ def test_openstack_client_config_generation_with_project_region_name(mocker, sou 'project': 'demo-project', 'domain': 'my-demo-domain', 'project_domain_name': 'project-domain', - 'project_region_name': 'region-name', + 'region': 'region-name', } if source is not None: inputs['verify_ssl'] = source diff --git a/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json b/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json index 6281f15024..d3e048dbd7 100644 --- a/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json +++ b/awx/ui_next/src/screens/Credential/shared/data.credentialTypes.json @@ -276,7 +276,7 @@ "help_text": "OpenStack domains define administrative boundaries. It is only needed for Keystone v3 authentication URLs. Refer to Ansible Tower documentation for common scenarios." }, { - "id": "project_region_name", + "id": "region", "label": "Region Name", "type": "string" }, From 055222bb82ef526a9b88e2d4e2ba12ed14120367 Mon Sep 17 00:00:00 2001 From: John Losito Date: Sat, 13 Feb 2021 11:05:00 -0500 Subject: [PATCH 04/26] Allow dependabot to check python dependencies --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..738e1e132b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +--- +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/requirements" + schedule: + interval: "weekly" From 5548f7e91d74401f2f56df2c2105fedc334b30c1 Mon Sep 17 00:00:00 2001 From: sean-m-sullivan Date: Sun, 14 Feb 2021 17:17:04 -0600 Subject: [PATCH 05/26] fix default value bug --- .../plugins/modules/tower_ad_hoc_command.py | 2 +- .../modules/tower_credential_input_source.py | 4 ++-- .../plugins/modules/tower_job_template.py | 18 +++++++++--------- .../plugins/modules/tower_project.py | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/awx_collection/plugins/modules/tower_ad_hoc_command.py b/awx_collection/plugins/modules/tower_ad_hoc_command.py index d952f954cf..00f16d9f13 100644 --- a/awx_collection/plugins/modules/tower_ad_hoc_command.py +++ b/awx_collection/plugins/modules/tower_ad_hoc_command.py @@ -118,7 +118,7 @@ def main(): limit=dict(), credential=dict(required=True), module_name=dict(required=True), - module_args=dict(default=""), + module_args=dict(), forks=dict(type='int'), verbosity=dict(type='int', choices=['0', '1', '2', '3', '4', '5']), extra_vars=dict(type='dict'), diff --git a/awx_collection/plugins/modules/tower_credential_input_source.py b/awx_collection/plugins/modules/tower_credential_input_source.py index cdc55cb1f0..e53c632777 100644 --- a/awx_collection/plugins/modules/tower_credential_input_source.py +++ b/awx_collection/plugins/modules/tower_credential_input_source.py @@ -76,10 +76,10 @@ from ..module_utils.tower_api import TowerAPIModule def main(): # Any additional arguments that are not fields of the item can be added here argument_spec = dict( - description=dict(default=''), + description=dict(), input_field_name=dict(required=True), target_credential=dict(required=True), - source_credential=dict(default=''), + source_credential=dict(), metadata=dict(type="dict"), state=dict(choices=['present', 'absent'], default='present'), ) diff --git a/awx_collection/plugins/modules/tower_job_template.py b/awx_collection/plugins/modules/tower_job_template.py index c99eb73118..787c145a20 100644 --- a/awx_collection/plugins/modules/tower_job_template.py +++ b/awx_collection/plugins/modules/tower_job_template.py @@ -340,24 +340,24 @@ def main(): argument_spec = dict( name=dict(required=True), new_name=dict(), - description=dict(default=''), + description=dict(), organization=dict(), job_type=dict(choices=['run', 'check']), inventory=dict(), project=dict(), playbook=dict(), - credential=dict(default=''), - vault_credential=dict(default=''), + credential=dict(), + vault_credential=dict(), custom_virtualenv=dict(), credentials=dict(type='list', elements='str'), forks=dict(type='int'), - limit=dict(default=''), + limit=dict(), verbosity=dict(type='int', choices=[0, 1, 2, 3, 4], default=0), extra_vars=dict(type='dict'), - job_tags=dict(default=''), + job_tags=dict(), force_handlers=dict(type='bool', default=False, aliases=['force_handlers_enabled']), - skip_tags=dict(default=''), - start_at_task=dict(default=''), + skip_tags=dict(), + start_at_task=dict(), timeout=dict(type='int', default=0), use_fact_cache=dict(type='bool', aliases=['fact_caching_enabled']), host_config_key=dict(), @@ -399,11 +399,11 @@ def main(): credential = module.params.get('credential') vault_credential = module.params.get('vault_credential') credentials = module.params.get('credentials') - if vault_credential != '': + if vault_credential: if credentials is None: credentials = [] credentials.append(vault_credential) - if credential != '': + if credential: if credentials is None: credentials = [] credentials.append(credential) diff --git a/awx_collection/plugins/modules/tower_project.py b/awx_collection/plugins/modules/tower_project.py index 015badc02b..76cef63f10 100644 --- a/awx_collection/plugins/modules/tower_project.py +++ b/awx_collection/plugins/modules/tower_project.py @@ -229,8 +229,8 @@ def main(): scm_type=dict(choices=['manual', 'git', 'svn', 'insights'], default='manual'), scm_url=dict(), local_path=dict(), - scm_branch=dict(default=''), - scm_refspec=dict(default=''), + scm_branch=dict(), + scm_refspec=dict(), credential=dict(aliases=['scm_credential']), scm_clean=dict(type='bool', default=False), scm_delete_on_update=dict(type='bool', default=False), From 3ad2bb1bb9a4b9f0fdddf39cb6416f8373a245b5 Mon Sep 17 00:00:00 2001 From: Nikhil Jain Date: Mon, 15 Feb 2021 09:31:16 +0530 Subject: [PATCH 06/26] remove whitespaces --- awx_collection/plugins/modules/tower_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awx_collection/plugins/modules/tower_settings.py b/awx_collection/plugins/modules/tower_settings.py index 7fcd3618dc..b0f39126c3 100644 --- a/awx_collection/plugins/modules/tower_settings.py +++ b/awx_collection/plugins/modules/tower_settings.py @@ -133,7 +133,7 @@ def main(): existing_settings = module.get_endpoint('settings/all')['json'] # Begin a json response - json_output = {'changed': False, 'old_values': {}, 'new_values': {} } + json_output = {'changed': False, 'old_values': {}, 'new_values': {}} # Check any of the settings to see if anything needs to be updated needs_update = False @@ -153,7 +153,7 @@ def main(): # If nothing needs an update we can simply exit with the response (as not changed) if not needs_update: module.exit_json(**json_output) - + if module.check_mode and module._diff: json_output['changed'] = True module.exit_json(**json_output) From a691caf34660cd8d3f1ce4f6f57d97427f4b8082 Mon Sep 17 00:00:00 2001 From: mabashian Date: Tue, 9 Feb 2021 11:22:25 -0500 Subject: [PATCH 07/26] Disable inventory copy button when inventory has sources. Refactor copy button props since tooltip is now handled by the ActionItem component. --- .../src/components/CopyButton/CopyButton.jsx | 31 +++++----- .../components/CopyButton/CopyButton.test.jsx | 58 +++++++++++-------- .../components/PaginatedTable/ActionItem.jsx | 2 +- .../PaginatedTable/ActionItem.test.jsx | 2 +- .../TemplateList/TemplateListItem.jsx | 10 ++-- .../CredentialList/CredentialListItem.jsx | 10 ++-- .../InventoryList/InventoryListItem.jsx | 21 +++---- .../NotificationTemplateListItem.jsx | 19 +++--- .../Project/ProjectList/ProjectListItem.jsx | 10 ++-- 9 files changed, 83 insertions(+), 80 deletions(-) diff --git a/awx/ui_next/src/components/CopyButton/CopyButton.jsx b/awx/ui_next/src/components/CopyButton/CopyButton.jsx index 30927f22c5..2856c69c0c 100644 --- a/awx/ui_next/src/components/CopyButton/CopyButton.jsx +++ b/awx/ui_next/src/components/CopyButton/CopyButton.jsx @@ -3,7 +3,7 @@ import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import PropTypes from 'prop-types'; -import { Button, Tooltip } from '@patternfly/react-core'; +import { Button } from '@patternfly/react-core'; import { CopyIcon } from '@patternfly/react-icons'; import useRequest, { useDismissableError } from '../../util/useRequest'; import AlertModal from '../AlertModal'; @@ -15,7 +15,7 @@ function CopyButton({ isDisabled, onCopyStart, onCopyFinish, - helperText, + errorMessage, i18n, }) { const { isLoading, error: copyError, request: copyItemToAPI } = useRequest( @@ -33,17 +33,15 @@ function CopyButton({ return ( <> - - - + - {helperText.errorMessage} + {errorMessage} @@ -62,10 +60,7 @@ CopyButton.propTypes = { copyItem: PropTypes.func.isRequired, onCopyStart: PropTypes.func.isRequired, onCopyFinish: PropTypes.func.isRequired, - helperText: PropTypes.shape({ - tooltip: PropTypes.string.isRequired, - errorMessage: PropTypes.string.isRequired, - }).isRequired, + errorMessage: PropTypes.string.isRequired, isDisabled: PropTypes.bool, }; diff --git a/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx b/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx index f81c0eab1d..296f4aebf1 100644 --- a/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx +++ b/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx @@ -1,36 +1,44 @@ import React from 'react'; +import { act } from 'react-dom/test-utils'; import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; import CopyButton from './CopyButton'; jest.mock('../../api'); +let wrapper; + describe('', () => { - test('shold mount properly', () => { - const wrapper = mountWithContexts( - {}} - onCopyFinish={() => {}} - copyItem={() => {}} - helperText={{ - tooltip: `Copy Template`, - errorMessage: `Failed to copy template.`, - }} - /> - ); + afterEach(() => { + wrapper.unmount(); + }); + test('should mount properly', async () => { + await act(async () => { + wrapper = mountWithContexts( + {}} + onCopyFinish={() => {}} + copyItem={() => {}} + errorMessage={`Failed to copy template.`} + /> + ); + }); expect(wrapper.find('CopyButton').length).toBe(1); }); - test('should render proper tooltip', () => { - const wrapper = mountWithContexts( - {}} - onCopyFinish={() => {}} - copyItem={() => {}} - helperText={{ - tooltip: `Copy Template`, - errorMessage: `Failed to copy template.`, - }} - /> - ); - expect(wrapper.find('Tooltip').prop('content')).toBe('Copy Template'); + test('should call the correct function on button click', async () => { + const copyItem = jest.fn(); + await act(async () => { + wrapper = mountWithContexts( + {}} + onCopyFinish={() => {}} + copyItem={copyItem} + errorMessage={`Failed to copy template.`} + /> + ); + }); + await act(async () => { + wrapper.find('button').simulate('click'); + }); + expect(copyItem).toHaveBeenCalledTimes(1); }); }); diff --git a/awx/ui_next/src/components/PaginatedTable/ActionItem.jsx b/awx/ui_next/src/components/PaginatedTable/ActionItem.jsx index a6c5e2b239..f9c423fee3 100644 --- a/awx/ui_next/src/components/PaginatedTable/ActionItem.jsx +++ b/awx/ui_next/src/components/PaginatedTable/ActionItem.jsx @@ -14,7 +14,7 @@ export default function ActionItem({ column, tooltip, visible, children }) { `} > - {children} +
{children}
); diff --git a/awx/ui_next/src/components/PaginatedTable/ActionItem.test.jsx b/awx/ui_next/src/components/PaginatedTable/ActionItem.test.jsx index 202e556e83..d38653802f 100644 --- a/awx/ui_next/src/components/PaginatedTable/ActionItem.test.jsx +++ b/awx/ui_next/src/components/PaginatedTable/ActionItem.test.jsx @@ -12,7 +12,7 @@ describe('', () => { const tooltip = wrapper.find('Tooltip'); expect(tooltip.prop('content')).toEqual('a tooltip'); - expect(tooltip.prop('children')).toEqual('foo'); + expect(tooltip.prop('children')).toEqual(
foo
); }); test('should render null if not visible', async () => { diff --git a/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx b/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx index dc53622737..5638b8d123 100644 --- a/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx +++ b/awx/ui_next/src/components/TemplateList/TemplateListItem.jsx @@ -177,13 +177,13 @@ function TemplateListItem({
- + - + diff --git a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx index 099fd78767..2b2f660efd 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryList/InventoryListItem.jsx @@ -28,7 +28,7 @@ function InventoryListItem({ isSelected: bool.isRequired, onSelect: func.isRequired, }; - const [isDisabled, setIsDisabled] = useState(false); + const [isCopying, setIsCopying] = useState(false); const copyInventory = useCallback(async () => { await InventoriesAPI.copy(inventory.id, { @@ -38,11 +38,11 @@ function InventoryListItem({ }, [inventory.id, inventory.name, fetchInventories]); const handleCopyStart = useCallback(() => { - setIsDisabled(true); + setIsCopying(true); }, []); const handleCopyFinish = useCallback(() => { - setIsDisabled(false); + setIsCopying(false); }, []); const labelId = `check-action-${inventory.id}`; @@ -115,7 +115,7 @@ function InventoryListItem({ tooltip={i18n._(t`Edit Inventory`)} > - + From f6bddfd336b9b895aa413ef4788f652a5e6c4219 Mon Sep 17 00:00:00 2001 From: mabashian Date: Mon, 15 Feb 2021 11:33:38 -0500 Subject: [PATCH 08/26] Fix linting error in CopyButton test --- awx/ui_next/src/components/CopyButton/CopyButton.test.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx b/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx index 296f4aebf1..894431bc2d 100644 --- a/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx +++ b/awx/ui_next/src/components/CopyButton/CopyButton.test.jsx @@ -18,7 +18,7 @@ describe('', () => { onCopyStart={() => {}} onCopyFinish={() => {}} copyItem={() => {}} - errorMessage={`Failed to copy template.`} + errorMessage="Failed to copy template." /> ); }); @@ -32,7 +32,7 @@ describe('', () => { onCopyStart={() => {}} onCopyFinish={() => {}} copyItem={copyItem} - errorMessage={`Failed to copy template.`} + errorMessage="Failed to copy template." /> ); }); From 62d91365a7800a124cc2e56f659ae20a23f424c4 Mon Sep 17 00:00:00 2001 From: sean-m-sullivan Date: Mon, 15 Feb 2021 12:23:18 -0600 Subject: [PATCH 09/26] add test for ad hoc no module arg --- .../targets/tower_ad_hoc_command/tasks/main.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/awx_collection/tests/integration/targets/tower_ad_hoc_command/tasks/main.yml b/awx_collection/tests/integration/targets/tower_ad_hoc_command/tasks/main.yml index 1c45ea6b1e..8dafa2338d 100644 --- a/awx_collection/tests/integration/targets/tower_ad_hoc_command/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_ad_hoc_command/tasks/main.yml @@ -48,6 +48,19 @@ - "result is changed" - "result.status == 'successful'" +- name: Launch an Ad Hoc Command without module argument + tower_ad_hoc_command: + inventory: "Demo Inventory" + credential: "{{ ssh_cred_name }}" + module_name: "ping" + wait: true + register: result + +- assert: + that: + - "result is changed" + - "result.status == 'successful'" + - name: Check module fails with correct msg tower_ad_hoc_command: inventory: "{{ inv_name }}" From 3c8f5f666f021572b8f3078c881b273520b35df0 Mon Sep 17 00:00:00 2001 From: nixocio Date: Mon, 15 Feb 2021 17:41:32 -0500 Subject: [PATCH 10/26] Fix typo Fix typo on error message --- awx/ui_next/src/components/Lookup/shared/LookupErrorMessage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui_next/src/components/Lookup/shared/LookupErrorMessage.jsx b/awx/ui_next/src/components/Lookup/shared/LookupErrorMessage.jsx index 3197417449..ad1bc32fc8 100644 --- a/awx/ui_next/src/components/Lookup/shared/LookupErrorMessage.jsx +++ b/awx/ui_next/src/components/Lookup/shared/LookupErrorMessage.jsx @@ -9,7 +9,7 @@ function LookupErrorMessage({ error, i18n }) { return (
- {error.message || i18n._(t`An error occured`)} + {error.message || i18n._(t`An error occurred`)}
); } From 5e91ae7b03f4692376dc8276ea7601c0829bdb2e Mon Sep 17 00:00:00 2001 From: John Losito Date: Tue, 16 Feb 2021 09:07:31 -0500 Subject: [PATCH 11/26] Change dependabot schedule to monthly --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 738e1e132b..beda045779 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,4 +4,4 @@ updates: - package-ecosystem: "pip" directory: "/requirements" schedule: - interval: "weekly" + interval: "monthly" From fbe5832d5a6a795dbfa0e37f55d71e1b4b8a0f3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:43:53 +0000 Subject: [PATCH 12/26] Bump atomicwrites from 1.1.5 to 1.4.0 in /requirements Bumps [atomicwrites](https://github.com/untitaker/python-atomicwrites) from 1.1.5 to 1.4.0. - [Release notes](https://github.com/untitaker/python-atomicwrites/releases) - [Commits](https://github.com/untitaker/python-atomicwrites/compare/1.1.5...1.4.0) Signed-off-by: dependabot[bot] --- requirements/requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index 3dbcc2f97c..fe51fff164 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -21,4 +21,4 @@ backports.tempfile # support in unit tests for py32+ tempfile.TemporaryDirector mockldap sdb gprof2dot -atomicwrites==1.1.5 +atomicwrites==1.4.0 From 02c8f4cc597e91da3af19c1abaf651ef46e4c9c7 Mon Sep 17 00:00:00 2001 From: nixocio Date: Tue, 9 Feb 2021 13:18:56 -0500 Subject: [PATCH 13/26] Update Patternfly to allow access to slider component Update Patternfly to allow access to slider component See: https://github.com/ansible/awx/issues/7777 --- awx/ui_next/package-lock.json | 40 ++++++++++++++----- awx/ui_next/package.json | 4 +- .../MultiButtonToggle/MultiButtonToggle.jsx | 6 ++- .../DeleteRoleConfirmationModal.test.jsx.snap | 1 + .../ResourceAccessListItem.test.jsx.snap | 1 + 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/awx/ui_next/package-lock.json b/awx/ui_next/package-lock.json index 70e18e4165..d4ed859ea9 100644 --- a/awx/ui_next/package-lock.json +++ b/awx/ui_next/package-lock.json @@ -2121,22 +2121,39 @@ "dev": true }, "@patternfly/patternfly": { - "version": "4.70.2", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.70.2.tgz", - "integrity": "sha512-XKCHnOjx1JThY3s98AJhsApSsGHPvEdlY7r+b18OecqUnmThVGw3nslzYYrwfCGlJ/xQtV5so29SduH2/uhHzA==" + "version": "4.80.3", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.80.3.tgz", + "integrity": "sha512-YLUk4L6iCBXql92YP6zHg0FdlnEkd5/3V+uz/A3UoBuuDdEoyDpx4M/Tf56R7IXmYiRaHE1mToJHPDYypIlnmw==" }, "@patternfly/react-core": { - "version": "4.84.3", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.84.3.tgz", - "integrity": "sha512-VeCv/r09ay6yIER7Eb8Dp5ZhbDu6SCW9smwgUTNp80kt83wIfKvGvQOKg+/7cev/GC6VzfgPHhiS04Jm/N5loA==", + "version": "4.90.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.90.2.tgz", + "integrity": "sha512-Ld4HCXYrVZR+ycWKvygmOEDyyMpb/pfZFklJiT/9ktSSSU9SfKwH2XmXotgjwBy1lYUoRYJ58xTpV19duouEoA==", "requires": { - "@patternfly/react-icons": "^4.7.22", - "@patternfly/react-styles": "^4.7.22", - "@patternfly/react-tokens": "^4.9.22", + "@patternfly/react-icons": "^4.8.4", + "@patternfly/react-styles": "^4.7.29", + "@patternfly/react-tokens": "^4.9.26", "focus-trap": "6.2.2", "react-dropzone": "9.0.0", "tippy.js": "5.1.2", "tslib": "1.13.0" + }, + "dependencies": { + "@patternfly/react-icons": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.8.4.tgz", + "integrity": "sha512-nGrZ6F57drim7t5FlFz7YusHVs8xngiayB20oSsJeewppOZ3vJDVhHaiJjsIRMB9PcVOY99QT2wnyiY1eYPVyA==" + }, + "@patternfly/react-styles": { + "version": "4.7.29", + "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.7.29.tgz", + "integrity": "sha512-eAO9xh2+IQHIBCihmwNuDVCeAWhGXIhbUNJEwZzvevYuH4Pnl0X8YaWoYmM2ZfL8ZdagRTLvjGW+hoZGkUyCBQ==" + }, + "@patternfly/react-tokens": { + "version": "4.9.26", + "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.9.26.tgz", + "integrity": "sha512-SSbY6BaUb7ycXhvdBNk2yzOlteRUHnchHSYPBFvhUk+SqpsjQ7j13/ZTok6pcHXrcj3FaL9f82/ep4eTXPzmWg==" + } } }, "@patternfly/react-icons": { @@ -2163,6 +2180,11 @@ "tslib": "1.13.0" }, "dependencies": { + "@patternfly/patternfly": { + "version": "4.70.2", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.70.2.tgz", + "integrity": "sha512-XKCHnOjx1JThY3s98AJhsApSsGHPvEdlY7r+b18OecqUnmThVGw3nslzYYrwfCGlJ/xQtV5so29SduH2/uhHzA==" + }, "@patternfly/react-core": { "version": "4.84.4", "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.84.4.tgz", diff --git a/awx/ui_next/package.json b/awx/ui_next/package.json index 7eb3759e74..2e791418db 100644 --- a/awx/ui_next/package.json +++ b/awx/ui_next/package.json @@ -7,8 +7,8 @@ }, "dependencies": { "@lingui/react": "^2.9.1", - "@patternfly/patternfly": "4.70.2", - "@patternfly/react-core": "4.84.3", + "@patternfly/patternfly": "^4.80.3", + "@patternfly/react-core": "^4.90.2", "@patternfly/react-icons": "4.7.22", "@patternfly/react-table": "^4.19.15", "ansi-to-html": "^0.6.11", diff --git a/awx/ui_next/src/components/MultiButtonToggle/MultiButtonToggle.jsx b/awx/ui_next/src/components/MultiButtonToggle/MultiButtonToggle.jsx index b76c4c6a61..efc1cb3d92 100644 --- a/awx/ui_next/src/components/MultiButtonToggle/MultiButtonToggle.jsx +++ b/awx/ui_next/src/components/MultiButtonToggle/MultiButtonToggle.jsx @@ -5,8 +5,10 @@ import { Button } from '@patternfly/react-core'; import ButtonGroup from './ButtonGroup'; const SmallButton = styled(Button)` - padding: 3px 8px; - font-size: var(--pf-global--FontSize--xs); + && { + padding: 3px 8px; + font-size: var(--pf-global--FontSize--xs); + } `; function MultiButtonToggle({ buttons, value, onChange }) { diff --git a/awx/ui_next/src/components/ResourceAccessList/__snapshots__/DeleteRoleConfirmationModal.test.jsx.snap b/awx/ui_next/src/components/ResourceAccessList/__snapshots__/DeleteRoleConfirmationModal.test.jsx.snap index caeea4e351..820035723e 100644 --- a/awx/ui_next/src/components/ResourceAccessList/__snapshots__/DeleteRoleConfirmationModal.test.jsx.snap +++ b/awx/ui_next/src/components/ResourceAccessList/__snapshots__/DeleteRoleConfirmationModal.test.jsx.snap @@ -290,6 +290,7 @@ exports[` should render initially 1`] = ` } } paused={false} + preventScrollOnDeactivate={false} >
initially renders succesfully 1`] = ` isClosable={false} numChips={5} onClick={[Function]} + onOverflowChipClick={[Function]} tooltipPosition="top" > Date: Tue, 16 Feb 2021 18:50:24 -0500 Subject: [PATCH 14/26] Fix bug where credential inputs were not filled on edit --- .../src/screens/Credential/CredentialEdit/CredentialEdit.jsx | 2 +- awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx index 9ffc29f39b..ded0a30120 100644 --- a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx +++ b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx @@ -116,7 +116,7 @@ function CredentialEdit({ credential, me }) { }, ] = await Promise.all([ CredentialTypesAPI.read({ page_size: 200 }), - CredentialsAPI.readInputSources(credId, { page_size: 200 }), + CredentialsAPI.readInputSources(credId), ]); const credTypes = data.results; if (data.next && data.next.includes('page=2')) { diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx index b46ddf8573..a1e717bf24 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx @@ -197,7 +197,7 @@ function CredentialForm({ description: credential.description || '', organization: credential?.summary_fields?.organization || null, credential_type: credential?.credential_type || '', - inputs: {}, + inputs: credential?.inputs || {}, passwordPrompts: {}, }; From 051efa4a193a1bd72f20aa0904e262a5845f51e2 Mon Sep 17 00:00:00 2001 From: mabashian Date: Wed, 17 Feb 2021 09:56:48 -0500 Subject: [PATCH 15/26] Adds unit test coverage for input rendering on credential edit --- .../CredentialEdit/CredentialEdit.test.jsx | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.test.jsx b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.test.jsx index 17ab9d3ed4..75cdeb2589 100644 --- a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.test.jsx +++ b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.test.jsx @@ -197,6 +197,58 @@ CredentialTypesAPI.read.mockResolvedValue({ }, injectors: {}, }, + { + id: 9, + type: 'credential_type', + url: '/api/v2/credential_types/9/', + related: { + credentials: '/api/v2/credential_types/9/credentials/', + activity_stream: '/api/v2/credential_types/9/activity_stream/', + }, + summary_fields: { + user_capabilities: { + edit: true, + delete: true, + }, + }, + created: '2021-02-12T19:13:22.352791Z', + modified: '2021-02-12T19:14:15.578773Z', + name: 'Google Compute Engine', + description: '', + kind: 'cloud', + namespace: 'gce', + managed_by_tower: true, + inputs: { + fields: [ + { + id: 'username', + label: 'Service Account Email Address', + type: 'string', + help_text: + 'The email address assigned to the Google Compute Engine service account.', + }, + { + id: 'project', + label: 'Project', + type: 'string', + help_text: + 'The Project ID is the GCE assigned identification. It is often constructed as three words or two words followed by a three-digit number. Examples: project-id-000 and another-project-id', + }, + { + id: 'ssh_key_data', + label: 'RSA Private Key', + type: 'string', + format: 'ssh_private_key', + secret: true, + multiline: true, + help_text: + 'Paste the contents of the PEM file associated with the service account email.', + }, + ], + required: ['username', 'ssh_key_data'], + }, + injectors: {}, + }, ], }, }); @@ -354,6 +406,38 @@ describe('', () => { expect(CredentialInputSourcesAPI.destroy).toHaveBeenCalledWith(34); expect(history.location.pathname).toBe('/credentials/3/details'); }); + test('inputs are properly rendered', async () => { + history = createMemoryHistory({ initialEntries: ['/credentials'] }); + await act(async () => { + wrapper = mountWithContexts( + , + { + context: { router: { history } }, + } + ); + }); + wrapper.update(); + expect(wrapper.find('input#credential-username').prop('value')).toBe( + 'foo@ansible.com' + ); + expect(wrapper.find('input#credential-project').prop('value')).toBe( + 'foo' + ); + expect( + wrapper.find('textarea#credential-ssh_key_data').prop('value') + ).toBe('$encrypted$'); + }); }); describe('Initial GET request fails', () => { test('shows error when initial GET request fails', async () => { From 29520f1ca69d41315c84dea80f5816484a4bd6b0 Mon Sep 17 00:00:00 2001 From: fedora Date: Wed, 17 Feb 2021 10:14:06 -0500 Subject: [PATCH 16/26] fix for issue 4696(tower) , Upstream commit for tower PR 4840 --- awx/sso/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/awx/sso/views.py b/awx/sso/views.py index ddbc2cbd59..1f2dcad0b9 100644 --- a/awx/sso/views.py +++ b/awx/sso/views.py @@ -58,12 +58,12 @@ class MetadataView(View): def get(self, request, *args, **kwargs): from social_django.utils import load_backend, load_strategy complete_url = reverse('social:complete', args=('saml', )) - saml_backend = load_backend( - load_strategy(request), - 'saml', - redirect_uri=complete_url, - ) try: + saml_backend = load_backend( + load_strategy(request), + 'saml', + redirect_uri=complete_url, + ) metadata, errors = saml_backend.generate_metadata_xml() except Exception as e: logger.exception('unable to generate SAML metadata') From 2a9a47118141e33ed2af4eab8fecc1881843bd15 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 24 Nov 2020 13:33:34 -0500 Subject: [PATCH 17/26] adds sorting by role on org access lists --- .../ResourceAccessList/ResourceAccessList.jsx | 42 +++++++++++------ .../ResourceAccessList.test.jsx | 46 ++++++++++++++++++- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx index 0f5f7c1c64..3a9b7dedb9 100644 --- a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx +++ b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx @@ -78,7 +78,33 @@ function ResourceAccessList({ i18n, apiModel, resource }) { fetchItems: fetchAccessRecords, } ); + const toolbarSearchColumns = [ + { + name: i18n._(t`Username`), + key: 'username__icontains', + isDefault: true, + }, + { + name: i18n._(t`First Name`), + key: 'first_name__icontains', + }, + { + name: i18n._(t`Last Name`), + key: 'last_name__icontains', + }, + ]; + if (location.pathname.includes('/organizations')) { + const roles = Object.values( + resource.summary_fields.object_roles + ).map(opt => [opt.id.toString(), opt.name]); + + toolbarSearchColumns.push({ + name: i18n._(t`Roles`), + key: `or__roles__in`, + options: roles, + }); + } return ( <> ', () => { id: 1, name: 'Default', summary_fields: { - object_roles: {}, + object_roles: { + admin_role: { + description: 'Can manage all aspects of the organization', + name: 'Admin', + id: 2, + user_only: true, + }, + execute_role: { + description: 'May run any executable resources in the organization', + name: 'Execute', + id: 3, + }, + project_admin_role: { + description: 'Can manage all projects of the organization', + name: 'Project Admin', + id: 4, + }, + }, user_capabilities: { edit: true, }, @@ -87,12 +105,16 @@ describe('', () => { }); TeamsAPI.disassociateRole.mockResolvedValue({}); UsersAPI.disassociateRole.mockResolvedValue({}); + const history = createMemoryHistory({ + initialEntries: ['/organizations/1/access'], + }); await act(async () => { wrapper = mountWithContexts( + />, + { context: { router: { history } } } ); }); wrapper.update(); @@ -168,4 +190,24 @@ describe('', () => { expect(OrganizationsAPI.readAccessList).toHaveBeenCalledTimes(2); done(); }); + test('should call api to get org details', async () => { + await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); + + expect( + wrapper.find('PaginatedDataList').prop('toolbarSearchColumns') + ).toStrictEqual([ + { isDefault: true, key: 'username__icontains', name: 'Username' }, + { key: 'first_name__icontains', name: 'First Name' }, + { key: 'last_name__icontains', name: 'Last Name' }, + { + key: 'or__roles__in', + name: 'Roles', + options: [ + ['2', 'Admin'], + ['3', 'Execute'], + ['4', 'Project Admin'], + ], + }, + ]); + }); }); From 3cc3cf1f8005c963cf6c56666abdaee435120b5a Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Tue, 16 Feb 2021 12:33:54 -0500 Subject: [PATCH 18/26] add a per-request GUID and log as it travels through background services see: https://github.com/ansible/awx/issues/9329 --- awx/main/dispatch/periodic.py | 2 ++ awx/main/dispatch/pool.py | 3 +++ awx/main/dispatch/publish.py | 4 ++++ awx/main/dispatch/worker/callback.py | 5 +++++ awx/main/dispatch/worker/task.py | 4 ++++ awx/main/tasks.py | 6 ++++++ awx/main/tests/unit/test_tasks.py | 2 +- awx/main/utils/filters.py | 15 ++++++++++++++ awx/main/utils/formatters.py | 3 +++ awx/settings/defaults.py | 29 ++++++++++++++++++---------- docs/licenses/django-guid.txt | 27 ++++++++++++++++++++++++++ requirements/requirements.in | 1 + requirements/requirements.txt | 5 +++-- 13 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 docs/licenses/django-guid.txt diff --git a/awx/main/dispatch/periodic.py b/awx/main/dispatch/periodic.py index c76366a8d4..b3a1b769c0 100644 --- a/awx/main/dispatch/periodic.py +++ b/awx/main/dispatch/periodic.py @@ -6,6 +6,7 @@ from multiprocessing import Process from django.conf import settings from django.db import connections from schedule import Scheduler +from django_guid.middleware import GuidMiddleware from awx.main.dispatch.worker import TaskWorker @@ -35,6 +36,7 @@ class Scheduler(Scheduler): # If the database connection has a hiccup, re-establish a new # connection conn.close_if_unusable_or_obsolete() + GuidMiddleware.set_guid(GuidMiddleware._generate_guid()) self.run_pending() except Exception: logger.exception( diff --git a/awx/main/dispatch/pool.py b/awx/main/dispatch/pool.py index dc97402788..5dbe034547 100644 --- a/awx/main/dispatch/pool.py +++ b/awx/main/dispatch/pool.py @@ -16,6 +16,7 @@ from queue import Full as QueueFull, Empty as QueueEmpty from django.conf import settings from django.db import connection as django_connection, connections from django.core.cache import cache as django_cache +from django_guid.middleware import GuidMiddleware from jinja2 import Template import psutil @@ -445,6 +446,8 @@ class AutoscalePool(WorkerPool): return super(AutoscalePool, self).up() def write(self, preferred_queue, body): + if 'guid' in body: + GuidMiddleware.set_guid(body['guid']) try: # when the cluster heartbeat occurs, clean up internally if isinstance(body, dict) and 'cluster_node_heartbeat' in body['task']: diff --git a/awx/main/dispatch/publish.py b/awx/main/dispatch/publish.py index f7fd7cf4fb..4d75654b5d 100644 --- a/awx/main/dispatch/publish.py +++ b/awx/main/dispatch/publish.py @@ -5,6 +5,7 @@ import json from uuid import uuid4 from django.conf import settings +from django_guid.middleware import GuidMiddleware from . import pg_bus_conn @@ -83,6 +84,9 @@ class task: 'kwargs': kwargs, 'task': cls.name } + guid = GuidMiddleware.get_guid() + if guid: + obj['guid'] = guid obj.update(**kw) if callable(queue): queue = queue() diff --git a/awx/main/dispatch/worker/callback.py b/awx/main/dispatch/worker/callback.py index e61a516094..342280868c 100644 --- a/awx/main/dispatch/worker/callback.py +++ b/awx/main/dispatch/worker/callback.py @@ -9,6 +9,7 @@ from django.conf import settings from django.utils.timezone import now as tz_now from django.db import DatabaseError, OperationalError, connection as django_connection from django.db.utils import InterfaceError, InternalError +from django_guid.middleware import GuidMiddleware import psutil @@ -152,6 +153,8 @@ class CallbackBrokerWorker(BaseWorker): if body.get('event') == 'EOF': try: + if 'guid' in body: + GuidMiddleware.set_guid(body['guid']) final_counter = body.get('final_counter', 0) logger.info('Event processing is finished for Job {}, sending notifications'.format(job_identifier)) # EOF events are sent when stdout for the running task is @@ -176,6 +179,8 @@ class CallbackBrokerWorker(BaseWorker): handle_success_and_failure_notifications.apply_async([uj.id]) except Exception: logger.exception('Worker failed to emit notifications: Job {}'.format(job_identifier)) + finally: + GuidMiddleware.set_guid('') return event = cls.create_from_data(**body) diff --git a/awx/main/dispatch/worker/task.py b/awx/main/dispatch/worker/task.py index 7e7437d445..80a414770b 100644 --- a/awx/main/dispatch/worker/task.py +++ b/awx/main/dispatch/worker/task.py @@ -6,6 +6,8 @@ import traceback from kubernetes.config import kube_config +from django_guid.middleware import GuidMiddleware + from awx.main.tasks import dispatch_startup, inform_cluster_of_shutdown from .base import BaseWorker @@ -52,6 +54,8 @@ class TaskWorker(BaseWorker): uuid = body.get('uuid', '') args = body.get('args', []) kwargs = body.get('kwargs', {}) + if 'guid' in body: + GuidMiddleware.set_guid(body.pop('guid')) _call = TaskWorker.resolve_callable(task) if inspect.isclass(_call): # the callable is a class, e.g., RunJob; instantiate and diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 32529c3d21..b6ab905837 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -34,6 +34,7 @@ from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _, gettext_noop from django.core.cache import cache from django.core.exceptions import ObjectDoesNotExist +from django_guid.middleware import GuidMiddleware # Kubernetes from kubernetes.client.rest import ApiException @@ -839,6 +840,7 @@ class BaseTask(object): self.cleanup_paths = [] self.parent_workflow_job_id = None self.host_map = {} + self.guid = GuidMiddleware.get_guid() def update_model(self, pk, _attempt=0, **updates): """Reload the model instance from the database and update the @@ -1274,6 +1276,9 @@ class BaseTask(object): except json.JSONDecodeError: pass + if 'event_data' in event_data: + event_data['event_data']['guid'] = self.guid + event_data.setdefault(self.event_data_key, self.instance.id) self.dispatcher.dispatch(event_data) self.event_ct += 1 @@ -1310,6 +1315,7 @@ class BaseTask(object): event_data = { 'event': 'EOF', 'final_counter': self.event_ct, + 'guid': self.guid, } event_data.setdefault(self.event_data_key, self.instance.id) self.dispatcher.dispatch(event_data) diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index ceb2c7186f..053745cc64 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -527,7 +527,7 @@ class TestGenericRun(): task.instance = Job(pk=1, id=1) task.event_ct = 17 task.finished_callback(None) - task.dispatcher.dispatch.assert_called_with({'event': 'EOF', 'final_counter': 17, 'job_id': 1}) + task.dispatcher.dispatch.assert_called_with({'event': 'EOF', 'final_counter': 17, 'job_id': 1, 'guid': None}) def test_save_job_metadata(self, job, update_model_wrapper): class MockMe(): diff --git a/awx/main/utils/filters.py b/awx/main/utils/filters.py index 5a01599e86..279a6a30e4 100644 --- a/awx/main/utils/filters.py +++ b/awx/main/utils/filters.py @@ -15,6 +15,10 @@ from django.apps import apps from django.db import models from django.conf import settings +from django_guid.log_filters import CorrelationId +from django_guid.middleware import GuidMiddleware + +from awx import MODE from awx.main.constants import LOGGER_BLOCKLIST from awx.main.utils.common import get_search_fields @@ -364,3 +368,14 @@ class SmartFilter(object): return res[0].result raise RuntimeError("Parsing the filter_string %s went terribly wrong" % filter_string) + + + +class DefaultCorrelationId(CorrelationId): + + def filter(self, record): + guid = GuidMiddleware.get_guid() or '-' + if MODE == 'development': + guid = guid[:8] + record.guid = guid + return True diff --git a/awx/main/utils/formatters.py b/awx/main/utils/formatters.py index 6f804f9f1b..8ebd1fb0c4 100644 --- a/awx/main/utils/formatters.py +++ b/awx/main/utils/formatters.py @@ -154,6 +154,9 @@ class LogstashFormatter(LogstashFormatterBase): if kind == 'job_events' and raw_data.get('python_objects', {}).get('job_event'): job_event = raw_data['python_objects']['job_event'] + guid = job_event.event_data.pop('guid', None) + if guid: + data_for_log['guid'] = guid for field_object in job_event._meta.fields: if not field_object.__class__ or not field_object.__class__.__name__: diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 0167325730..af1590862c 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -285,6 +285,7 @@ INSTALLED_APPS = [ 'polymorphic', 'taggit', 'social_django', + 'django_guid', 'corsheaders', 'awx.conf', 'awx.main', @@ -828,11 +829,14 @@ LOGGING = { }, 'dynamic_level_filter': { '()': 'awx.main.utils.filters.DynamicLevelFilter' - } + }, + 'guid': { + '()': 'awx.main.utils.filters.DefaultCorrelationId' + }, }, 'formatters': { 'simple': { - 'format': '%(asctime)s %(levelname)-8s %(name)s %(message)s', + 'format': '%(asctime)s %(levelname)-8s [%(guid)s] %(name)s %(message)s', }, 'json': { '()': 'awx.main.utils.formatters.LogstashFormatter' @@ -842,7 +846,7 @@ LOGGING = { 'format': '%(relativeSeconds)9.3f %(levelname)-8s %(message)s' }, 'dispatcher': { - 'format': '%(asctime)s %(levelname)-8s %(name)s PID:%(process)d %(message)s', + 'format': '%(asctime)s %(levelname)-8s [%(guid)s] %(name)s PID:%(process)d %(message)s', }, 'job_lifecycle': { '()': 'awx.main.utils.formatters.JobLifeCycleFormatter', @@ -852,7 +856,7 @@ LOGGING = { 'console': { '()': 'logging.StreamHandler', 'level': 'DEBUG', - 'filters': ['require_debug_true_or_test'], + 'filters': ['require_debug_true_or_test', 'guid'], 'formatter': 'simple', }, 'null': { @@ -872,33 +876,33 @@ LOGGING = { 'class': 'awx.main.utils.handlers.RSysLogHandler', 'formatter': 'json', 'address': '/var/run/awx-rsyslog/rsyslog.sock', - 'filters': ['external_log_enabled', 'dynamic_level_filter'], + 'filters': ['external_log_enabled', 'dynamic_level_filter', 'guid'], }, 'tower_warnings': { # don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL 'class': 'logging.handlers.WatchedFileHandler', - 'filters': ['require_debug_false', 'dynamic_level_filter'], + 'filters': ['require_debug_false', 'dynamic_level_filter', 'guid'], 'filename': os.path.join(LOG_ROOT, 'tower.log'), 'formatter':'simple', }, 'callback_receiver': { # don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL 'class': 'logging.handlers.WatchedFileHandler', - 'filters': ['require_debug_false', 'dynamic_level_filter'], + 'filters': ['require_debug_false', 'dynamic_level_filter', 'guid'], 'filename': os.path.join(LOG_ROOT, 'callback_receiver.log'), 'formatter':'simple', }, 'dispatcher': { # don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL 'class': 'logging.handlers.WatchedFileHandler', - 'filters': ['require_debug_false', 'dynamic_level_filter'], + 'filters': ['require_debug_false', 'dynamic_level_filter', 'guid'], 'filename': os.path.join(LOG_ROOT, 'dispatcher.log'), 'formatter':'dispatcher', }, 'wsbroadcast': { # don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL 'class': 'logging.handlers.WatchedFileHandler', - 'filters': ['require_debug_false', 'dynamic_level_filter'], + 'filters': ['require_debug_false', 'dynamic_level_filter', 'guid'], 'filename': os.path.join(LOG_ROOT, 'wsbroadcast.log'), 'formatter':'simple', }, @@ -914,7 +918,7 @@ LOGGING = { 'task_system': { # don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL 'class': 'logging.handlers.WatchedFileHandler', - 'filters': ['require_debug_false', 'dynamic_level_filter'], + 'filters': ['require_debug_false', 'dynamic_level_filter', 'guid'], 'filename': os.path.join(LOG_ROOT, 'task_system.log'), 'formatter':'simple', }, @@ -1094,6 +1098,7 @@ AWX_CALLBACK_PROFILE = False AWX_CLEANUP_PATHS = True MIDDLEWARE = [ + 'django_guid.middleware.GuidMiddleware', 'awx.main.middleware.TimingMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'awx.main.middleware.MigrationRanCheckMiddleware', @@ -1134,3 +1139,7 @@ BROADCAST_WEBSOCKET_NEW_INSTANCE_POLL_RATE_SECONDS = 10 # How often websocket process will generate stats BROADCAST_WEBSOCKET_STATS_POLL_RATE_SECONDS = 5 + +DJANGO_GUID = { + 'GUID_HEADER_NAME': 'X-API-Request-Id', +} diff --git a/docs/licenses/django-guid.txt b/docs/licenses/django-guid.txt new file mode 100644 index 0000000000..de842ea1c7 --- /dev/null +++ b/docs/licenses/django-guid.txt @@ -0,0 +1,27 @@ +Copyright (c) 2019 Jonas Krüger Svensson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the authors nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/requirements/requirements.in b/requirements/requirements.in index 263b95dfbe..93b5b4f72e 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -13,6 +13,7 @@ django-auth-ldap django-cors-headers django-crum django-extensions>=2.2.9 # https://github.com/ansible/awx/pull/6441 +django-guid==2.2.0 # pinned to match Django 2.2 django-jsonfield==1.2.0 # see UPGRADE BLOCKERs django-oauth-toolkit==1.1.3 # see UPGRADE BLOCKERs django-polymorphic diff --git a/requirements/requirements.txt b/requirements/requirements.txt index fd1591dc29..5829401c78 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -19,7 +19,7 @@ channels-redis==3.1.0 # via -r /awx_devel/requirements/requirements.in channels==2.4.0 # via -r /awx_devel/requirements/requirements.in, channels-redis chardet==3.0.4 # via aiohttp, requests constantly==15.1.0 # via twisted -cryptography==2.9.2 # via adal, autobahn, azure-keyvault, pyopenssl, service-identity, social-auth-core +cryptography==2.9.2 # via -r /awx_devel/requirements/requirements.in, adal, autobahn, azure-keyvault, pyopenssl, service-identity, social-auth-core daphne==2.4.1 # via -r /awx_devel/requirements/requirements.in, channels defusedxml==0.6.0 # via python3-openid, python3-saml, social-auth-core dictdiffer==0.8.1 # via openshift @@ -27,6 +27,7 @@ django-auth-ldap==2.1.0 # via -r /awx_devel/requirements/requirements.in django-cors-headers==3.2.1 # via -r /awx_devel/requirements/requirements.in django-crum==0.7.5 # via -r /awx_devel/requirements/requirements.in django-extensions==2.2.9 # via -r /awx_devel/requirements/requirements.in +django-guid==2.2.0 # via -r /awx_devel/requirements/requirements.in django-jsonfield==1.2.0 # via -r /awx_devel/requirements/requirements.in django-oauth-toolkit==1.1.3 # via -r /awx_devel/requirements/requirements.in django-pglocks==1.0.4 # via -r /awx_devel/requirements/requirements.in @@ -37,7 +38,7 @@ django-redis==4.5.0 # via -r /awx_devel/requirements/requirements.in django-solo==1.1.3 # via -r /awx_devel/requirements/requirements.in django-split-settings==1.0.0 # via -r /awx_devel/requirements/requirements.in django-taggit==1.2.0 # via -r /awx_devel/requirements/requirements.in -django==2.2.16 # via -r /awx_devel/requirements/requirements.in, channels, django-auth-ldap, django-cors-headers, django-crum, django-jsonfield, django-oauth-toolkit, django-polymorphic, django-taggit, djangorestframework +django==2.2.16 # via -r /awx_devel/requirements/requirements.in, channels, django-auth-ldap, django-cors-headers, django-crum, django-guid, django-jsonfield, django-oauth-toolkit, django-polymorphic, django-taggit, djangorestframework djangorestframework-yaml==1.0.3 # via -r /awx_devel/requirements/requirements.in djangorestframework==3.12.1 # via -r /awx_devel/requirements/requirements.in docutils==0.16 # via python-daemon From 64b49feeeefef3cd8f8274e86b3f3cae99368d22 Mon Sep 17 00:00:00 2001 From: beeankha Date: Wed, 17 Feb 2021 14:42:50 -0500 Subject: [PATCH 19/26] Remove functional test files that are no longer in use --- awx/main/tests/functional/ansible.json | 283 --- awx/main/tests/functional/packages.json | 2922 ----------------------- awx/main/tests/functional/services.json | 697 ------ 3 files changed, 3902 deletions(-) delete mode 100644 awx/main/tests/functional/ansible.json delete mode 100644 awx/main/tests/functional/packages.json delete mode 100644 awx/main/tests/functional/services.json diff --git a/awx/main/tests/functional/ansible.json b/awx/main/tests/functional/ansible.json deleted file mode 100644 index e877df2ad1..0000000000 --- a/awx/main/tests/functional/ansible.json +++ /dev/null @@ -1,283 +0,0 @@ -{ - "ansible_all_ipv4_addresses": [ - "172.17.0.7" - ], - "ansible_all_ipv6_addresses": [ - "fe80::42:acff:fe11:7" - ], - "ansible_architecture": "x86_64", - "ansible_bios_date": "12/01/2006", - "ansible_bios_version": "VirtualBox", - "ansible_cmdline": { - "BOOT_IMAGE": "/boot/vmlinuz64", - "base": true, - "console": "tty0", - "initrd": "/boot/initrd.img", - "loglevel": "3", - "noembed": true, - "nomodeset": true, - "norestore": true, - "user": "docker", - "waitusb": "10:LABEL=boot2docker-data" - }, - "ansible_date_time": { - "date": "2016-02-02", - "day": "02", - "epoch": "1454424257", - "hour": "14", - "iso8601": "2016-02-02T14:44:17Z", - "iso8601_basic": "20160202T144417348424", - "iso8601_basic_short": "20160202T144417", - "iso8601_micro": "2016-02-02T14:44:17.348496Z", - "minute": "44", - "month": "02", - "second": "17", - "time": "14:44:17", - "tz": "UTC", - "tz_offset": "+0000", - "weekday": "Tuesday", - "weekday_number": "2", - "weeknumber": "05", - "year": "2016" - }, - "ansible_default_ipv4": { - "address": "172.17.0.7", - "alias": "eth0", - "broadcast": "global", - "gateway": "172.17.0.1", - "interface": "eth0", - "macaddress": "02:42:ac:11:00:07", - "mtu": 1500, - "netmask": "255.255.0.0", - "network": "172.17.0.0", - "type": "ether" - }, - "ansible_default_ipv6": {}, - "ansible_devices": { - "sda": { - "holders": [], - "host": "", - "model": "VBOX HARDDISK", - "partitions": { - "sda1": { - "sectors": "510015555", - "sectorsize": 512, - "size": "243.19 GB", - "start": "1975995" - }, - "sda2": { - "sectors": "1975932", - "sectorsize": 512, - "size": "964.81 MB", - "start": "63" - } - }, - "removable": "0", - "rotational": "0", - "scheduler_mode": "deadline", - "sectors": "512000000", - "sectorsize": "512", - "size": "244.14 GB", - "support_discard": "0", - "vendor": "ATA" - }, - "sr0": { - "holders": [], - "host": "", - "model": "CD-ROM", - "partitions": {}, - "removable": "1", - "rotational": "1", - "scheduler_mode": "deadline", - "sectors": "61440", - "sectorsize": "2048", - "size": "120.00 MB", - "support_discard": "0", - "vendor": "VBOX" - } - }, - "ansible_distribution": "Ubuntu", - "ansible_distribution_major_version": "14", - "ansible_distribution_release": "trusty", - "ansible_distribution_version": "14.04", - "ansible_dns": { - "nameservers": [ - "8.8.8.8" - ] - }, - "ansible_domain": "", - "ansible_env": { - "HOME": "/root", - "HOSTNAME": "ede894599989", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US.UTF-8", - "LC_MESSAGES": "en_US.UTF-8", - "LESSCLOSE": "/usr/bin/lesspipe %s %s", - "LESSOPEN": "| /usr/bin/lesspipe %s", - "LS_COLORS": "", - "OLDPWD": "/ansible", - "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "PWD": "/ansible/examples", - "SHLVL": "1", - "_": "/usr/local/bin/ansible", - "container": "docker" - }, - "ansible_eth0": { - "active": true, - "device": "eth0", - "ipv4": { - "address": "172.17.0.7", - "broadcast": "global", - "netmask": "255.255.0.0", - "network": "172.17.0.0" - }, - "ipv6": [ - { - "address": "fe80::42:acff:fe11:7", - "prefix": "64", - "scope": "link" - } - ], - "macaddress": "02:42:ac:11:00:07", - "mtu": 1500, - "promisc": false, - "type": "ether" - }, - "ansible_fips": false, - "ansible_form_factor": "Other", - "ansible_fqdn": "ede894599989", - "ansible_hostname": "ede894599989", - "ansible_interfaces": [ - "lo", - "eth0" - ], - "ansible_kernel": "4.1.12-boot2docker", - "ansible_lo": { - "active": true, - "device": "lo", - "ipv4": { - "address": "127.0.0.1", - "broadcast": "host", - "netmask": "255.0.0.0", - "network": "127.0.0.0" - }, - "ipv6": [ - { - "address": "::1", - "prefix": "128", - "scope": "host" - } - ], - "mtu": 65536, - "promisc": false, - "type": "loopback" - }, - "ansible_lsb": { - "codename": "trusty", - "description": "Ubuntu 14.04.3 LTS", - "id": "Ubuntu", - "major_release": "14", - "release": "14.04" - }, - "ansible_machine": "x86_64", - "ansible_memfree_mb": 3746, - "ansible_memory_mb": { - "nocache": { - "free": 8896, - "used": 3638 - }, - "real": { - "free": 3746, - "total": 12534, - "used": 8788 - }, - "swap": { - "cached": 0, - "free": 4048, - "total": 4048, - "used": 0 - } - }, - "ansible_memtotal_mb": 12534, - "ansible_mounts": [ - { - "device": "/dev/sda1", - "fstype": "ext4", - "mount": "/etc/resolv.conf", - "options": "rw,relatime,data=ordered", - "size_available": 201281392640, - "size_total": 256895700992, - "uuid": "NA" - }, - { - "device": "/dev/sda1", - "fstype": "ext4", - "mount": "/etc/hostname", - "options": "rw,relatime,data=ordered", - "size_available": 201281392640, - "size_total": 256895700992, - "uuid": "NA" - }, - { - "device": "/dev/sda1", - "fstype": "ext4", - "mount": "/etc/hosts", - "options": "rw,relatime,data=ordered", - "size_available": 201281392640, - "size_total": 256895700992, - "uuid": "NA" - } - ], - "ansible_nodename": "ede894599989", - "ansible_os_family": "Debian", - "ansible_pkg_mgr": "apt", - "ansible_processor": [ - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", - "GenuineIntel", - "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz" - ], - "ansible_processor_cores": 8, - "ansible_processor_count": 1, - "ansible_processor_threads_per_core": 1, - "ansible_processor_vcpus": 8, - "ansible_product_name": "VirtualBox", - "ansible_product_serial": "0", - "ansible_product_uuid": "25C5EA5A-1DF1-48D9-A2C6-81227DA153C0", - "ansible_product_version": "1.2", - "ansible_python_version": "2.7.6", - "ansible_selinux": false, - "ansible_service_mgr": "upstart", - "ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBALF0xsM8UMXgSKiWNw4t19wxbxLnxQX742t/dIM0O8YLx+/lIP+Q69Dv5uoVt0zKV39eFziRlCh96qj2KYkGEJ6XfVZFnhpculL2Pv2CPpSwKuQ1vTbDO/xxUrvY+bHpfNJf9Rh69bFEE2pTsjomFPCgp8M0qGaFtwg6czSaeBONAAAAFQCGEfVtj97JiexTVRqgQITYlFp/eQAAAIEAg+S9qWn+AIb3amwVoLL/usQYOPCmZY9RVPzpkjJ6OG+HI4B7cXeauPtNTJwT0f9vGEqzf4mPpmS+aCShj6iwdmJ+cOwR5+SJlNalab3CMBoXKVLbT1J2XWFlK0szKKnoReP96IDbkAkGQ3fkm4jz0z6Wy0u6wOQVNcd4G5cwLZ4AAACAFvBm+H1LwNrwWBjWio+ayhglZ4Y25mLMEn2+dqBz0gLK5szEbft1HMPOWIVHvl6vi3v34pAJHKpxXpkLlNliTn8iw9BzCOrgP4V8sp2/85mxEuCdI1w/QERj9cHu5iS2pZ0cUwDE3pfuuGBB3IEliaJyaapowdrM8lN12jQl11E=", - "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHiYp4e9RfXpxDcEWpK4EuXPHW9++xcFI9hiB0TYAZgxEF9RIgwfucpPawFk7HIFoNc7EXQMlryilLSbg155KWM=", - "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAILclD2JaC654azEsAfcHRIOA2Ig9/Qk6MX80i/VCEdSH", - "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDeSUGxZaZsgBsezld0mj3HcbAwx6aykGnejceBjcs6lVwSGMHevofzSXIQDPYBhZoyWNl0PYAHv6AsQ8+3khd2SitUMJAuHSz1ZjgHCCGQP9ijXTKHn+lWCKA8rhLG/dwYwiouoOPZfn1G+erbKO6XiVbELrrf2RadnMGuMinESIOKVj3IunXsaGRMsDOQferOnUf7MvH7xpQnoySyQ1+p4rGruaohWG+Y2cDo7+B2FylPVbrpRDDJkfbt4J96WHx0KOdD0qzOicQP8JqDflqQPJJCWcgrvjQOSe4gXdPB6GZDtBl2qgQRwt1IgizPMm+b7Bwbd2VDe1TeWV2gT/7H", - "ansible_swapfree_mb": 4048, - "ansible_swaptotal_mb": 4048, - "ansible_system": "Linux", - "ansible_system_vendor": "innotek GmbH", - "ansible_uptime_seconds": 178398, - "ansible_user_dir": "/root", - "ansible_user_gecos": "root", - "ansible_user_gid": 0, - "ansible_user_id": "root", - "ansible_user_shell": "/bin/bash", - "ansible_user_uid": 0, - "ansible_userspace_architecture": "x86_64", - "ansible_userspace_bits": "64", - "ansible_virtualization_role": "guest", - "ansible_virtualization_type": "docker", - "module_setup": true -} diff --git a/awx/main/tests/functional/packages.json b/awx/main/tests/functional/packages.json deleted file mode 100644 index 7bc735d06f..0000000000 --- a/awx/main/tests/functional/packages.json +++ /dev/null @@ -1,2922 +0,0 @@ -[ - { - "name": "kbd", - "source": "rpm", - "epoch": null, - "version": "1.15.5", - "release": "10.el7", - "arch": "x86_64" - }, - { - "name": "centos-release", - "source": "rpm", - "epoch": null, - "version": "7", - "release": "0.1406.el7.centos.2.3", - "arch": "x86_64" - }, - { - "name": "postfix", - "source": "rpm", - "epoch": 2, - "version": "2.10.1", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "filesystem", - "source": "rpm", - "epoch": null, - "version": "3.2", - "release": "18.el7", - "arch": "x86_64" - }, - { - "name": "tuned", - "source": "rpm", - "epoch": null, - "version": "2.3.0", - "release": "11.el7", - "arch": "noarch" - }, - { - "name": "ncurses-base", - "source": "rpm", - "epoch": null, - "version": "5.9", - "release": "13.20130511.el7", - "arch": "noarch" - }, - { - "name": "aic94xx-firmware", - "source": "rpm", - "epoch": null, - "version": "30", - "release": "6.el7", - "arch": "noarch" - }, - { - "name": "kbd-misc", - "source": "rpm", - "epoch": null, - "version": "1.15.5", - "release": "10.el7", - "arch": "noarch" - }, - { - "name": "irqbalance", - "source": "rpm", - "epoch": 2, - "version": "1.0.6", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "tzdata", - "source": "rpm", - "epoch": null, - "version": "2014b", - "release": "1.el7", - "arch": "noarch" - }, - { - "name": "openssh-clients", - "source": "rpm", - "epoch": null, - "version": "6.4p1", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "glibc-common", - "source": "rpm", - "epoch": null, - "version": "2.17", - "release": "55.el7", - "arch": "x86_64" - }, - { - "name": "authconfig", - "source": "rpm", - "epoch": null, - "version": "6.2.8", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "xz-libs", - "source": "rpm", - "epoch": null, - "version": "5.1.2", - "release": "8alpha.el7", - "arch": "x86_64" - }, - { - "name": "btrfs-progs", - "source": "rpm", - "epoch": null, - "version": "3.12", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "ncurses-libs", - "source": "rpm", - "epoch": null, - "version": "5.9", - "release": "13.20130511.el7", - "arch": "x86_64" - }, - { - "name": "sudo", - "source": "rpm", - "epoch": null, - "version": "1.8.6p7", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "libsepol", - "source": "rpm", - "epoch": null, - "version": "2.1.9", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "iprutils", - "source": "rpm", - "epoch": null, - "version": "2.3.16", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libselinux", - "source": "rpm", - "epoch": null, - "version": "2.2.2", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "iwl6000g2b-firmware", - "source": "rpm", - "epoch": null, - "version": "17.168.5.2", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "info", - "source": "rpm", - "epoch": null, - "version": "5.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iwl7260-firmware", - "source": "rpm", - "epoch": null, - "version": "22.0.7.0", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "dbus-libs", - "source": "rpm", - "epoch": 1, - "version": "1.6.12", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "libertas-sd8787-firmware", - "source": "rpm", - "epoch": null, - "version": "20140213", - "release": "0.3.git4164c23.el7", - "arch": "noarch" - }, - { - "name": "sed", - "source": "rpm", - "epoch": null, - "version": "4.2.2", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "iwl6050-firmware", - "source": "rpm", - "epoch": null, - "version": "41.28.5.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "chkconfig", - "source": "rpm", - "epoch": null, - "version": "1.3.61", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iwl1000-firmware", - "source": "rpm", - "epoch": 1, - "version": "39.31.5.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "nspr", - "source": "rpm", - "epoch": null, - "version": "4.10.2", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iwl6000-firmware", - "source": "rpm", - "epoch": null, - "version": "9.221.4.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "nss-util", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "iwl2000-firmware", - "source": "rpm", - "epoch": null, - "version": "18.168.6.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "grep", - "source": "rpm", - "epoch": null, - "version": "2.16", - "release": "1.el7", - "arch": "x86_64" - }, - { - "name": "iwl5150-firmware", - "source": "rpm", - "epoch": null, - "version": "8.24.2.2", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "gawk", - "source": "rpm", - "epoch": null, - "version": "4.0.2", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iwl4965-firmware", - "source": "rpm", - "epoch": null, - "version": "228.61.2.24", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "expat", - "source": "rpm", - "epoch": null, - "version": "2.1.0", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "iwl3160-firmware", - "source": "rpm", - "epoch": null, - "version": "22.0.7.0", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libattr", - "source": "rpm", - "epoch": null, - "version": "2.4.46", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "iwl3945-firmware", - "source": "rpm", - "epoch": null, - "version": "15.32.2.9", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libcap", - "source": "rpm", - "epoch": null, - "version": "2.22", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "libsemanage-python", - "source": "rpm", - "epoch": null, - "version": "2.1.10", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "libxml2", - "source": "rpm", - "epoch": null, - "version": "2.9.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "perl-HTTP-Tiny", - "source": "rpm", - "epoch": null, - "version": "0.033", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "libgcrypt", - "source": "rpm", - "epoch": null, - "version": "1.5.3", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "perl-Pod-Perldoc", - "source": "rpm", - "epoch": null, - "version": "3.20", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "lua", - "source": "rpm", - "epoch": null, - "version": "5.1.4", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "perl-Encode", - "source": "rpm", - "epoch": null, - "version": "2.51", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "pkgconfig", - "source": "rpm", - "epoch": 1, - "version": "0.27.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "perl-Pod-Usage", - "source": "rpm", - "epoch": null, - "version": "1.63", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "shared-mime-info", - "source": "rpm", - "epoch": null, - "version": "1.1", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "perl-Exporter", - "source": "rpm", - "epoch": null, - "version": "5.68", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "libcap-ng", - "source": "rpm", - "epoch": null, - "version": "0.7.3", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "perl-Time-Local", - "source": "rpm", - "epoch": null, - "version": "1.2300", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "libidn", - "source": "rpm", - "epoch": null, - "version": "1.28", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "perl-Carp", - "source": "rpm", - "epoch": null, - "version": "1.26", - "release": "244.el7", - "arch": "noarch" - }, - { - "name": "gmp", - "source": "rpm", - "epoch": 1, - "version": "5.1.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "perl-PathTools", - "source": "rpm", - "epoch": null, - "version": "3.40", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "p11-kit", - "source": "rpm", - "epoch": null, - "version": "0.18.7", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "perl-macros", - "source": "rpm", - "epoch": 4, - "version": "5.16.3", - "release": "285.el7", - "arch": "x86_64" - }, - { - "name": "libdaemon", - "source": "rpm", - "epoch": null, - "version": "0.14", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "perl-File-Temp", - "source": "rpm", - "epoch": null, - "version": "0.23.01", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "libcroco", - "source": "rpm", - "epoch": null, - "version": "0.6.8", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "perl-threads-shared", - "source": "rpm", - "epoch": null, - "version": "1.43", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "libnl3-cli", - "source": "rpm", - "epoch": null, - "version": "3.2.21", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "perl-Filter", - "source": "rpm", - "epoch": null, - "version": "1.49", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "cyrus-sasl-lib", - "source": "rpm", - "epoch": null, - "version": "2.1.26", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "perl-Getopt-Long", - "source": "rpm", - "epoch": null, - "version": "2.40", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "groff-base", - "source": "rpm", - "epoch": null, - "version": "1.22.2", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "gpg-pubkey", - "source": "rpm", - "epoch": null, - "version": "04bbaa7b", - "release": "4c881cbf", - "arch": null - }, - { - "name": "libunistring", - "source": "rpm", - "epoch": null, - "version": "0.9.3", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "libicu", - "source": "rpm", - "epoch": null, - "version": "50.1.2", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "diffutils", - "source": "rpm", - "epoch": null, - "version": "3.3", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libdnet", - "source": "rpm", - "epoch": null, - "version": "1.12", - "release": "13.1.el7", - "arch": "x86_64" - }, - { - "name": "xz", - "source": "rpm", - "epoch": null, - "version": "5.1.2", - "release": "8alpha.el7", - "arch": "x86_64" - }, - { - "name": "open-vm-tools", - "source": "rpm", - "epoch": null, - "version": "9.4.0", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "sysvinit-tools", - "source": "rpm", - "epoch": null, - "version": "2.88", - "release": "14.dsf.el7", - "arch": "x86_64" - }, - { - "name": "open-vm-tools-deploypkg", - "source": "rpm", - "epoch": 0, - "version": "9.4.10", - "release": "3", - "arch": "x86_64" - }, - { - "name": "newt", - "source": "rpm", - "epoch": null, - "version": "0.52.15", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "python-kitchen", - "source": "rpm", - "epoch": null, - "version": "1.1.1", - "release": "5.el7", - "arch": "noarch" - }, - { - "name": "ethtool", - "source": "rpm", - "epoch": 2, - "version": "3.8", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "yum-utils", - "source": "rpm", - "epoch": null, - "version": "1.1.31", - "release": "29.el7", - "arch": "noarch" - }, - { - "name": "hostname", - "source": "rpm", - "epoch": null, - "version": "3.13", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "emacs-filesystem", - "source": "rpm", - "epoch": 1, - "version": "24.3", - "release": "11.el7", - "arch": "noarch" - }, - { - "name": "gdbm", - "source": "rpm", - "epoch": null, - "version": "1.10", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "emacs-common", - "source": "rpm", - "epoch": 1, - "version": "24.3", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "less", - "source": "rpm", - "epoch": null, - "version": "458", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "epel-release", - "source": "rpm", - "epoch": null, - "version": "7", - "release": "5", - "arch": "noarch" - }, - { - "name": "p11-kit-trust", - "source": "rpm", - "epoch": null, - "version": "0.18.7", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "pkcs11-helper", - "source": "rpm", - "epoch": null, - "version": "1.11", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "nettle", - "source": "rpm", - "epoch": null, - "version": "2.7.1", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "easy-rsa", - "source": "rpm", - "epoch": null, - "version": "2.2.2", - "release": "1.el7", - "arch": "noarch" - }, - { - "name": "gobject-introspection", - "source": "rpm", - "epoch": null, - "version": "1.36.0", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libevent", - "source": "rpm", - "epoch": null, - "version": "2.0.21", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "gsettings-desktop-schemas", - "source": "rpm", - "epoch": null, - "version": "3.8.2", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "dhcp-libs", - "source": "rpm", - "epoch": 12, - "version": "4.2.5", - "release": "36.el7.centos", - "arch": "x86_64" - }, - { - "name": "acl", - "source": "rpm", - "epoch": null, - "version": "2.2.51", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "dhcp", - "source": "rpm", - "epoch": 12, - "version": "4.2.5", - "release": "36.el7.centos", - "arch": "x86_64" - }, - { - "name": "elfutils-libs", - "source": "rpm", - "epoch": null, - "version": "0.158", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "bind-license", - "source": "rpm", - "epoch": 32, - "version": "9.9.4", - "release": "18.el7_1.1", - "arch": "noarch" - }, - { - "name": "mozjs17", - "source": "rpm", - "epoch": null, - "version": "17.0.0", - "release": "10.el7", - "arch": "x86_64" - }, - { - "name": "bind", - "source": "rpm", - "epoch": 32, - "version": "9.9.4", - "release": "18.el7_1.1", - "arch": "x86_64" - }, - { - "name": "pinentry", - "source": "rpm", - "epoch": null, - "version": "0.8.1", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "bind-libs-lite", - "source": "rpm", - "epoch": 32, - "version": "9.9.4", - "release": "18.el7_1.1", - "arch": "x86_64" - }, - { - "name": "libselinux-utils", - "source": "rpm", - "epoch": null, - "version": "2.2.2", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "audit-libs", - "source": "rpm", - "epoch": null, - "version": "2.4.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "libedit", - "source": "rpm", - "epoch": null, - "version": "3.0", - "release": "12.20121213cvs.el7", - "arch": "x86_64" - }, - { - "name": "audit-libs-python", - "source": "rpm", - "epoch": null, - "version": "2.4.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "libmodman", - "source": "rpm", - "epoch": null, - "version": "2.0.1", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "checkpolicy", - "source": "rpm", - "epoch": null, - "version": "2.1.12", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "glib-networking", - "source": "rpm", - "epoch": null, - "version": "2.36.2", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "setools-libs", - "source": "rpm", - "epoch": null, - "version": "3.3.7", - "release": "46.el7", - "arch": "x86_64" - }, - { - "name": "snappy", - "source": "rpm", - "epoch": null, - "version": "1.1.0", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "audit", - "source": "rpm", - "epoch": null, - "version": "2.4.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "numactl-libs", - "source": "rpm", - "epoch": null, - "version": "2.0.9", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "autogen-libopts", - "source": "rpm", - "epoch": null, - "version": "5.18", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "libverto", - "source": "rpm", - "epoch": null, - "version": "0.2.5", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "ntp", - "source": "rpm", - "epoch": null, - "version": "4.2.6p5", - "release": "19.el7.centos.3", - "arch": "x86_64" - }, - { - "name": "libsemanage", - "source": "rpm", - "epoch": null, - "version": "2.1.10", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "krb5-libs", - "source": "rpm", - "epoch": null, - "version": "1.11.3", - "release": "49.el7", - "arch": "x86_64" - }, - { - "name": "openldap", - "source": "rpm", - "epoch": null, - "version": "2.4.39", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "cracklib", - "source": "rpm", - "epoch": null, - "version": "2.9.0", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "libmount", - "source": "rpm", - "epoch": null, - "version": "2.23.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "systemd-libs", - "source": "rpm", - "epoch": null, - "version": "208", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "libpwquality", - "source": "rpm", - "epoch": null, - "version": "1.2.3", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "pam", - "source": "rpm", - "epoch": null, - "version": "1.1.8", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "shadow-utils", - "source": "rpm", - "epoch": 2, - "version": "4.1.5.1", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "util-linux", - "source": "rpm", - "epoch": null, - "version": "2.23.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "python-libs", - "source": "rpm", - "epoch": null, - "version": "2.7.5", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "python-decorator", - "source": "rpm", - "epoch": null, - "version": "3.4.0", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "gettext", - "source": "rpm", - "epoch": null, - "version": "0.18.2.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "centos-logos", - "source": "rpm", - "epoch": null, - "version": "70.0.6", - "release": "1.el7.centos", - "arch": "noarch" - }, - { - "name": "libselinux-python", - "source": "rpm", - "epoch": null, - "version": "2.2.2", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "python-slip-dbus", - "source": "rpm", - "epoch": null, - "version": "0.4.0", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "pyliblzma", - "source": "rpm", - "epoch": null, - "version": "0.5.3", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "yum-metadata-parser", - "source": "rpm", - "epoch": null, - "version": "1.1.4", - "release": "10.el7", - "arch": "x86_64" - }, - { - "name": "pyxattr", - "source": "rpm", - "epoch": null, - "version": "0.5.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "python-backports-ssl_match_hostname", - "source": "rpm", - "epoch": null, - "version": "3.4.0.2", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "python-pyudev", - "source": "rpm", - "epoch": null, - "version": "0.15", - "release": "6.el7", - "arch": "noarch" - }, - { - "name": "binutils", - "source": "rpm", - "epoch": null, - "version": "2.23.52.0.1", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "logrotate", - "source": "rpm", - "epoch": null, - "version": "3.8.6", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "alsa-lib", - "source": "rpm", - "epoch": null, - "version": "1.0.27.2", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "mariadb-libs", - "source": "rpm", - "epoch": 1, - "version": "5.5.35", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "libcurl", - "source": "rpm", - "epoch": null, - "version": "7.29.0", - "release": "19.el7", - "arch": "x86_64" - }, - { - "name": "python-urlgrabber", - "source": "rpm", - "epoch": null, - "version": "3.10", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "rpm-libs", - "source": "rpm", - "epoch": null, - "version": "4.11.1", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "fipscheck", - "source": "rpm", - "epoch": null, - "version": "1.4.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "json-c", - "source": "rpm", - "epoch": null, - "version": "0.11", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "virt-what", - "source": "rpm", - "epoch": null, - "version": "1.13", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "libnetfilter_conntrack", - "source": "rpm", - "epoch": null, - "version": "1.0.4", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "iproute", - "source": "rpm", - "epoch": null, - "version": "3.10.0", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "qrencode-libs", - "source": "rpm", - "epoch": null, - "version": "3.4.1", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "device-mapper-libs", - "source": "rpm", - "epoch": 7, - "version": "1.02.84", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "systemd", - "source": "rpm", - "epoch": null, - "version": "208", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "systemd-sysv", - "source": "rpm", - "epoch": null, - "version": "208", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "iputils", - "source": "rpm", - "epoch": null, - "version": "20121221", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "device-mapper-event-libs", - "source": "rpm", - "epoch": 7, - "version": "1.02.84", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "NetworkManager-glib", - "source": "rpm", - "epoch": 1, - "version": "0.9.9.1", - "release": "13.git20140326.4dba720.el7", - "arch": "x86_64" - }, - { - "name": "polkit-pkla-compat", - "source": "rpm", - "epoch": null, - "version": "0.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "cronie-anacron", - "source": "rpm", - "epoch": null, - "version": "1.4.11", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "crontabs", - "source": "rpm", - "epoch": null, - "version": "1.11", - "release": "6.20121102git.el7", - "arch": "noarch" - }, - { - "name": "device-mapper-event", - "source": "rpm", - "epoch": 7, - "version": "1.02.84", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "avahi-libs", - "source": "rpm", - "epoch": null, - "version": "0.6.31", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "avahi-autoipd", - "source": "rpm", - "epoch": null, - "version": "0.6.31", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "dnsmasq", - "source": "rpm", - "epoch": null, - "version": "2.66", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "ebtables", - "source": "rpm", - "epoch": null, - "version": "2.0.10", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "libpciaccess", - "source": "rpm", - "epoch": null, - "version": "0.13.1", - "release": "4.1.el7", - "arch": "x86_64" - }, - { - "name": "fxload", - "source": "rpm", - "epoch": null, - "version": "2002_04_11", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "alsa-tools-firmware", - "source": "rpm", - "epoch": null, - "version": "1.0.27", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libpipeline", - "source": "rpm", - "epoch": null, - "version": "1.2.3", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "gnupg2", - "source": "rpm", - "epoch": null, - "version": "2.0.22", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "rpm-python", - "source": "rpm", - "epoch": null, - "version": "4.11.1", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "pygpgme", - "source": "rpm", - "epoch": null, - "version": "0.3", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "hardlink", - "source": "rpm", - "epoch": 1, - "version": "1.0", - "release": "19.el7", - "arch": "x86_64" - }, - { - "name": "dracut-network", - "source": "rpm", - "epoch": null, - "version": "033", - "release": "161.el7", - "arch": "x86_64" - }, - { - "name": "plymouth", - "source": "rpm", - "epoch": null, - "version": "0.8.9", - "release": "0.10.20140113.el7.centos", - "arch": "x86_64" - }, - { - "name": "teamd", - "source": "rpm", - "epoch": null, - "version": "1.9", - "release": "15.el7", - "arch": "x86_64" - }, - { - "name": "libestr", - "source": "rpm", - "epoch": null, - "version": "0.1.9", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "NetworkManager-tui", - "source": "rpm", - "epoch": 1, - "version": "0.9.9.1", - "release": "13.git20140326.4dba720.el7", - "arch": "x86_64" - }, - { - "name": "kernel", - "source": "rpm", - "epoch": null, - "version": "3.10.0", - "release": "123.el7", - "arch": "x86_64" - }, - { - "name": "dracut-config-rescue", - "source": "rpm", - "epoch": null, - "version": "033", - "release": "161.el7", - "arch": "x86_64" - }, - { - "name": "man-db", - "source": "rpm", - "epoch": null, - "version": "2.6.3", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "lvm2", - "source": "rpm", - "epoch": 7, - "version": "2.02.105", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "libgcc", - "source": "rpm", - "epoch": null, - "version": "4.8.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "setup", - "source": "rpm", - "epoch": null, - "version": "2.8.71", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "microcode_ctl", - "source": "rpm", - "epoch": 2, - "version": "2.1", - "release": "7.1.el7", - "arch": "x86_64" - }, - { - "name": "basesystem", - "source": "rpm", - "epoch": null, - "version": "10.0", - "release": "7.el7.centos", - "arch": "noarch" - }, - { - "name": "biosdevname", - "source": "rpm", - "epoch": null, - "version": "0.5.0", - "release": "10.el7", - "arch": "x86_64" - }, - { - "name": "linux-firmware", - "source": "rpm", - "epoch": null, - "version": "20140213", - "release": "0.3.git4164c23.el7", - "arch": "noarch" - }, - { - "name": "openssh-server", - "source": "rpm", - "epoch": null, - "version": "6.4p1", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "parted", - "source": "rpm", - "epoch": null, - "version": "3.1", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "nss-softokn-freebl", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "selinux-policy-targeted", - "source": "rpm", - "epoch": null, - "version": "3.12.1", - "release": "153.el7", - "arch": "noarch" - }, - { - "name": "glibc", - "source": "rpm", - "epoch": null, - "version": "2.17", - "release": "55.el7", - "arch": "x86_64" - }, - { - "name": "xfsprogs", - "source": "rpm", - "epoch": null, - "version": "3.2.0", - "release": "0.10.alpha2.el7", - "arch": "x86_64" - }, - { - "name": "libstdc++", - "source": "rpm", - "epoch": null, - "version": "4.8.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "e2fsprogs", - "source": "rpm", - "epoch": null, - "version": "1.42.9", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "bash", - "source": "rpm", - "epoch": null, - "version": "4.2.45", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "passwd", - "source": "rpm", - "epoch": null, - "version": "0.79", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "pcre", - "source": "rpm", - "epoch": null, - "version": "8.32", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "tar", - "source": "rpm", - "epoch": 2, - "version": "1.26", - "release": "29.el7", - "arch": "x86_64" - }, - { - "name": "zlib", - "source": "rpm", - "epoch": null, - "version": "1.2.7", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "rootfiles", - "source": "rpm", - "epoch": null, - "version": "8.1", - "release": "11.el7", - "arch": "noarch" - }, - { - "name": "iwl6000g2a-firmware", - "source": "rpm", - "epoch": null, - "version": "17.168.5.3", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libuuid", - "source": "rpm", - "epoch": null, - "version": "2.23.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "iwl2030-firmware", - "source": "rpm", - "epoch": null, - "version": "18.168.6.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "popt", - "source": "rpm", - "epoch": null, - "version": "1.13", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "iwl100-firmware", - "source": "rpm", - "epoch": null, - "version": "39.31.5.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libcom_err", - "source": "rpm", - "epoch": null, - "version": "1.42.9", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iwl135-firmware", - "source": "rpm", - "epoch": null, - "version": "18.168.6.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libdb", - "source": "rpm", - "epoch": null, - "version": "5.3.21", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "iwl105-firmware", - "source": "rpm", - "epoch": null, - "version": "18.168.6.1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "bzip2-libs", - "source": "rpm", - "epoch": null, - "version": "1.0.6", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "libertas-sd8686-firmware", - "source": "rpm", - "epoch": null, - "version": "20140213", - "release": "0.3.git4164c23.el7", - "arch": "noarch" - }, - { - "name": "readline", - "source": "rpm", - "epoch": null, - "version": "6.2", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "ivtv-firmware", - "source": "rpm", - "epoch": 2, - "version": "20080701", - "release": "26.el7", - "arch": "noarch" - }, - { - "name": "elfutils-libelf", - "source": "rpm", - "epoch": null, - "version": "0.158", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "libertas-usb8388-firmware", - "source": "rpm", - "epoch": 2, - "version": "20140213", - "release": "0.3.git4164c23.el7", - "arch": "noarch" - }, - { - "name": "libgpg-error", - "source": "rpm", - "epoch": null, - "version": "1.12", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "iwl5000-firmware", - "source": "rpm", - "epoch": null, - "version": "8.83.5.1_1", - "release": "34.el7", - "arch": "noarch" - }, - { - "name": "libacl", - "source": "rpm", - "epoch": null, - "version": "2.2.51", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "gpg-pubkey", - "source": "rpm", - "epoch": null, - "version": "f4a80eb5", - "release": "53a7ff4b", - "arch": null - }, - { - "name": "cpio", - "source": "rpm", - "epoch": null, - "version": "2.11", - "release": "22.el7", - "arch": "x86_64" - }, - { - "name": "perl-parent", - "source": "rpm", - "epoch": 1, - "version": "0.225", - "release": "244.el7", - "arch": "noarch" - }, - { - "name": "libnl3", - "source": "rpm", - "epoch": null, - "version": "3.2.21", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "perl-podlators", - "source": "rpm", - "epoch": null, - "version": "2.5.1", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "sqlite", - "source": "rpm", - "epoch": null, - "version": "3.7.17", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "perl-Pod-Escapes", - "source": "rpm", - "epoch": 1, - "version": "1.04", - "release": "285.el7", - "arch": "noarch" - }, - { - "name": "libffi", - "source": "rpm", - "epoch": null, - "version": "3.0.13", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "perl-Text-ParseWords", - "source": "rpm", - "epoch": null, - "version": "3.29", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "glib2", - "source": "rpm", - "epoch": null, - "version": "2.36.3", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "perl-Storable", - "source": "rpm", - "epoch": null, - "version": "2.45", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "dbus-glib", - "source": "rpm", - "epoch": null, - "version": "0.100", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "perl-constant", - "source": "rpm", - "epoch": null, - "version": "1.27", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "findutils", - "source": "rpm", - "epoch": 1, - "version": "4.5.11", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "perl-Socket", - "source": "rpm", - "epoch": null, - "version": "2.010", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "file-libs", - "source": "rpm", - "epoch": null, - "version": "5.11", - "release": "21.el7", - "arch": "x86_64" - }, - { - "name": "perl-Time-HiRes", - "source": "rpm", - "epoch": 4, - "version": "1.9725", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "libtasn1", - "source": "rpm", - "epoch": null, - "version": "3.3", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "perl-Scalar-List-Utils", - "source": "rpm", - "epoch": null, - "version": "1.27", - "release": "248.el7", - "arch": "x86_64" - }, - { - "name": "tcp_wrappers-libs", - "source": "rpm", - "epoch": null, - "version": "7.6", - "release": "77.el7", - "arch": "x86_64" - }, - { - "name": "perl-Pod-Simple", - "source": "rpm", - "epoch": 1, - "version": "3.28", - "release": "4.el7", - "arch": "noarch" - }, - { - "name": "file", - "source": "rpm", - "epoch": null, - "version": "5.11", - "release": "21.el7", - "arch": "x86_64" - }, - { - "name": "perl-File-Path", - "source": "rpm", - "epoch": null, - "version": "2.09", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "nss-softokn", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "perl-threads", - "source": "rpm", - "epoch": null, - "version": "1.87", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libassuan", - "source": "rpm", - "epoch": null, - "version": "2.1.0", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "perl-libs", - "source": "rpm", - "epoch": 4, - "version": "5.16.3", - "release": "285.el7", - "arch": "x86_64" - }, - { - "name": "e2fsprogs-libs", - "source": "rpm", - "epoch": null, - "version": "1.42.9", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "perl", - "source": "rpm", - "epoch": 4, - "version": "5.16.3", - "release": "285.el7", - "arch": "x86_64" - }, - { - "name": "which", - "source": "rpm", - "epoch": null, - "version": "2.20", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "gpg-pubkey", - "source": "rpm", - "epoch": null, - "version": "66fd4949", - "release": "4803fe57", - "arch": null - }, - { - "name": "libgomp", - "source": "rpm", - "epoch": null, - "version": "4.8.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "procps-ng", - "source": "rpm", - "epoch": null, - "version": "3.3.10", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "kmod-libs", - "source": "rpm", - "epoch": null, - "version": "14", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "net-tools", - "source": "rpm", - "epoch": null, - "version": "2.0", - "release": "0.17.20131004git.el7", - "arch": "x86_64" - }, - { - "name": "libnfnetlink", - "source": "rpm", - "epoch": null, - "version": "1.0.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "libmspack", - "source": "rpm", - "epoch": 0, - "version": "0.0.20040308alpha", - "release": "2", - "arch": "x86_64" - }, - { - "name": "slang", - "source": "rpm", - "epoch": null, - "version": "2.2.4", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "python-chardet", - "source": "rpm", - "epoch": null, - "version": "2.0.1", - "release": "7.el7", - "arch": "noarch" - }, - { - "name": "lzo", - "source": "rpm", - "epoch": null, - "version": "2.06", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "yum", - "source": "rpm", - "epoch": null, - "version": "3.4.3", - "release": "125.el7.centos", - "arch": "noarch" - }, - { - "name": "pciutils-libs", - "source": "rpm", - "epoch": null, - "version": "3.2.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "gpm-libs", - "source": "rpm", - "epoch": null, - "version": "1.20.7", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "keyutils-libs", - "source": "rpm", - "epoch": null, - "version": "1.5.8", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "liblockfile", - "source": "rpm", - "epoch": null, - "version": "1.08", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "gettext-libs", - "source": "rpm", - "epoch": null, - "version": "0.18.2.1", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "emacs-nox", - "source": "rpm", - "epoch": 1, - "version": "24.3", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "libteam", - "source": "rpm", - "epoch": null, - "version": "1.9", - "release": "15.el7", - "arch": "x86_64" - }, - { - "name": "gpg-pubkey", - "source": "rpm", - "epoch": null, - "version": "352c64e5", - "release": "52ae6884", - "arch": null - }, - { - "name": "ca-certificates", - "source": "rpm", - "epoch": null, - "version": "2013.1.95", - "release": "71.el7", - "arch": "noarch" - }, - { - "name": "openvpn", - "source": "rpm", - "epoch": null, - "version": "2.3.7", - "release": "1.el7", - "arch": "x86_64" - }, - { - "name": "gnutls", - "source": "rpm", - "epoch": null, - "version": "3.1.18", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "strace", - "source": "rpm", - "epoch": null, - "version": "4.8", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "ModemManager-glib", - "source": "rpm", - "epoch": null, - "version": "1.1.0", - "release": "6.git20130913.el7", - "arch": "x86_64" - }, - { - "name": "tmux", - "source": "rpm", - "epoch": null, - "version": "1.8", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "vim-minimal", - "source": "rpm", - "epoch": 2, - "version": "7.4.160", - "release": "1.el7", - "arch": "x86_64" - }, - { - "name": "dhcp-common", - "source": "rpm", - "epoch": 12, - "version": "4.2.5", - "release": "36.el7.centos", - "arch": "x86_64" - }, - { - "name": "device-mapper-persistent-data", - "source": "rpm", - "epoch": null, - "version": "0.3.2", - "release": "1.el7", - "arch": "x86_64" - }, - { - "name": "dhclient", - "source": "rpm", - "epoch": 12, - "version": "4.2.5", - "release": "36.el7.centos", - "arch": "x86_64" - }, - { - "name": "libdb-utils", - "source": "rpm", - "epoch": null, - "version": "5.3.21", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "bind-libs", - "source": "rpm", - "epoch": 32, - "version": "9.9.4", - "release": "18.el7_1.1", - "arch": "x86_64" - }, - { - "name": "libss", - "source": "rpm", - "epoch": null, - "version": "1.42.9", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "bind-utils", - "source": "rpm", - "epoch": 32, - "version": "9.9.4", - "release": "18.el7_1.1", - "arch": "x86_64" - }, - { - "name": "make", - "source": "rpm", - "epoch": 1, - "version": "3.82", - "release": "21.el7", - "arch": "x86_64" - }, - { - "name": "nmap-ncat", - "source": "rpm", - "epoch": 2, - "version": "6.40", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "freetype", - "source": "rpm", - "epoch": null, - "version": "2.4.11", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "policycoreutils", - "source": "rpm", - "epoch": null, - "version": "2.2.5", - "release": "15.el7", - "arch": "x86_64" - }, - { - "name": "ncurses", - "source": "rpm", - "epoch": null, - "version": "5.9", - "release": "13.20130511.el7", - "arch": "x86_64" - }, - { - "name": "python-IPy", - "source": "rpm", - "epoch": null, - "version": "0.75", - "release": "6.el7", - "arch": "noarch" - }, - { - "name": "libproxy", - "source": "rpm", - "epoch": null, - "version": "0.4.11", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "libcgroup", - "source": "rpm", - "epoch": null, - "version": "0.41", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "libsoup", - "source": "rpm", - "epoch": null, - "version": "2.42.2", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "policycoreutils-python", - "source": "rpm", - "epoch": null, - "version": "2.2.5", - "release": "15.el7", - "arch": "x86_64" - }, - { - "name": "libndp", - "source": "rpm", - "epoch": null, - "version": "1.2", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "iftop", - "source": "rpm", - "epoch": null, - "version": "1.0", - "release": "0.7.pre4.el7", - "arch": "x86_64" - }, - { - "name": "libsysfs", - "source": "rpm", - "epoch": null, - "version": "2.1.0", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "ntpdate", - "source": "rpm", - "epoch": null, - "version": "4.2.6p5", - "release": "19.el7.centos.3", - "arch": "x86_64" - }, - { - "name": "ustr", - "source": "rpm", - "epoch": null, - "version": "1.0.4", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "nss-tools", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "openssl-libs", - "source": "rpm", - "epoch": 1, - "version": "1.0.1e", - "release": "34.el7", - "arch": "x86_64" - }, - { - "name": "gzip", - "source": "rpm", - "epoch": null, - "version": "1.5", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "cracklib-dicts", - "source": "rpm", - "epoch": null, - "version": "2.9.0", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "nss", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "libuser", - "source": "rpm", - "epoch": null, - "version": "0.60", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "coreutils", - "source": "rpm", - "epoch": null, - "version": "8.22", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "libblkid", - "source": "rpm", - "epoch": null, - "version": "2.23.2", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "libutempter", - "source": "rpm", - "epoch": null, - "version": "1.1.6", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "nss-sysinit", - "source": "rpm", - "epoch": null, - "version": "3.15.4", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "python", - "source": "rpm", - "epoch": null, - "version": "2.7.5", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "dbus-python", - "source": "rpm", - "epoch": null, - "version": "1.1.1", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "pygobject3-base", - "source": "rpm", - "epoch": null, - "version": "3.8.2", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "python-slip", - "source": "rpm", - "epoch": null, - "version": "0.4.0", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "python-iniparse", - "source": "rpm", - "epoch": null, - "version": "0.4", - "release": "9.el7", - "arch": "noarch" - }, - { - "name": "newt-python", - "source": "rpm", - "epoch": null, - "version": "0.52.15", - "release": "4.el7", - "arch": "x86_64" - }, - { - "name": "python-configobj", - "source": "rpm", - "epoch": null, - "version": "4.7.2", - "release": "7.el7", - "arch": "noarch" - }, - { - "name": "python-backports", - "source": "rpm", - "epoch": null, - "version": "1.0", - "release": "6.el7", - "arch": "noarch" - }, - { - "name": "python-setuptools", - "source": "rpm", - "epoch": null, - "version": "0.9.8", - "release": "3.el7", - "arch": "noarch" - }, - { - "name": "grubby", - "source": "rpm", - "epoch": null, - "version": "8.28", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "kmod", - "source": "rpm", - "epoch": null, - "version": "14", - "release": "9.el7", - "arch": "x86_64" - }, - { - "name": "openssl", - "source": "rpm", - "epoch": 1, - "version": "1.0.1e", - "release": "34.el7", - "arch": "x86_64" - }, - { - "name": "plymouth-core-libs", - "source": "rpm", - "epoch": null, - "version": "0.8.9", - "release": "0.10.20140113.el7.centos", - "arch": "x86_64" - }, - { - "name": "libssh2", - "source": "rpm", - "epoch": null, - "version": "1.4.3", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "python-pycurl", - "source": "rpm", - "epoch": null, - "version": "7.19.0", - "release": "17.el7", - "arch": "x86_64" - }, - { - "name": "curl", - "source": "rpm", - "epoch": null, - "version": "7.29.0", - "release": "19.el7", - "arch": "x86_64" - }, - { - "name": "rpm", - "source": "rpm", - "epoch": null, - "version": "4.11.1", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "selinux-policy", - "source": "rpm", - "epoch": null, - "version": "3.12.1", - "release": "153.el7", - "arch": "noarch" - }, - { - "name": "fipscheck-lib", - "source": "rpm", - "epoch": null, - "version": "1.4.1", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "openssh", - "source": "rpm", - "epoch": null, - "version": "6.4p1", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "dmidecode", - "source": "rpm", - "epoch": 1, - "version": "2.12", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "libmnl", - "source": "rpm", - "epoch": null, - "version": "1.0.3", - "release": "7.el7", - "arch": "x86_64" - }, - { - "name": "iptables", - "source": "rpm", - "epoch": null, - "version": "1.4.21", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "libpcap", - "source": "rpm", - "epoch": 14, - "version": "1.5.3", - "release": "3.el7", - "arch": "x86_64" - }, - { - "name": "device-mapper", - "source": "rpm", - "epoch": 7, - "version": "1.02.84", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "cryptsetup-libs", - "source": "rpm", - "epoch": null, - "version": "1.6.3", - "release": "2.el7", - "arch": "x86_64" - }, - { - "name": "dbus", - "source": "rpm", - "epoch": 1, - "version": "1.6.12", - "release": "8.el7", - "arch": "x86_64" - }, - { - "name": "libgudev1", - "source": "rpm", - "epoch": null, - "version": "208", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "initscripts", - "source": "rpm", - "epoch": null, - "version": "9.49.17", - "release": "1.el7", - "arch": "x86_64" - }, - { - "name": "polkit", - "source": "rpm", - "epoch": null, - "version": "0.112", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "os-prober", - "source": "rpm", - "epoch": null, - "version": "1.58", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "cronie", - "source": "rpm", - "epoch": null, - "version": "1.4.11", - "release": "11.el7", - "arch": "x86_64" - }, - { - "name": "grub2-tools", - "source": "rpm", - "epoch": 1, - "version": "2.02", - "release": "0.2.10.el7.centos.1", - "arch": "x86_64" - }, - { - "name": "lvm2-libs", - "source": "rpm", - "epoch": 7, - "version": "2.02.105", - "release": "14.el7", - "arch": "x86_64" - }, - { - "name": "avahi", - "source": "rpm", - "epoch": null, - "version": "0.6.31", - "release": "13.el7", - "arch": "x86_64" - }, - { - "name": "wpa_supplicant", - "source": "rpm", - "epoch": 1, - "version": "2.0", - "release": "12.el7", - "arch": "x86_64" - }, - { - "name": "ppp", - "source": "rpm", - "epoch": null, - "version": "2.4.5", - "release": "33.el7", - "arch": "x86_64" - }, - { - "name": "hwdata", - "source": "rpm", - "epoch": null, - "version": "0.252", - "release": "7.3.el7", - "arch": "noarch" - }, - { - "name": "libdrm", - "source": "rpm", - "epoch": null, - "version": "2.4.50", - "release": "1.1.el7", - "arch": "x86_64" - }, - { - "name": "alsa-firmware", - "source": "rpm", - "epoch": null, - "version": "1.0.27", - "release": "2.el7", - "arch": "noarch" - }, - { - "name": "kpartx", - "source": "rpm", - "epoch": null, - "version": "0.4.9", - "release": "66.el7", - "arch": "x86_64" - }, - { - "name": "pth", - "source": "rpm", - "epoch": null, - "version": "2.0.7", - "release": "22.el7", - "arch": "x86_64" - }, - { - "name": "rpm-build-libs", - "source": "rpm", - "epoch": null, - "version": "4.11.1", - "release": "16.el7", - "arch": "x86_64" - }, - { - "name": "gpgme", - "source": "rpm", - "epoch": null, - "version": "1.3.2", - "release": "5.el7", - "arch": "x86_64" - }, - { - "name": "yum-plugin-fastestmirror", - "source": "rpm", - "epoch": null, - "version": "1.1.31", - "release": "24.el7", - "arch": "noarch" - }, - { - "name": "kernel-tools-libs", - "source": "rpm", - "epoch": null, - "version": "3.10.0", - "release": "123.el7", - "arch": "x86_64" - }, - { - "name": "dracut", - "source": "rpm", - "epoch": null, - "version": "033", - "release": "161.el7", - "arch": "x86_64" - }, - { - "name": "plymouth-scripts", - "source": "rpm", - "epoch": null, - "version": "0.8.9", - "release": "0.10.20140113.el7.centos", - "arch": "x86_64" - }, - { - "name": "jansson", - "source": "rpm", - "epoch": null, - "version": "2.4", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "NetworkManager", - "source": "rpm", - "epoch": 1, - "version": "0.9.9.1", - "release": "13.git20140326.4dba720.el7", - "arch": "x86_64" - }, - { - "name": "rsyslog", - "source": "rpm", - "epoch": null, - "version": "7.4.7", - "release": "6.el7", - "arch": "x86_64" - }, - { - "name": "kexec-tools", - "source": "rpm", - "epoch": null, - "version": "2.0.4", - "release": "32.el7.centos", - "arch": "x86_64" - }, - { - "name": "grub2", - "source": "rpm", - "epoch": 1, - "version": "2.02", - "release": "0.2.10.el7.centos.1", - "arch": "x86_64" - }, - { - "name": "kernel-tools", - "source": "rpm", - "epoch": null, - "version": "3.10.0", - "release": "123.el7", - "arch": "x86_64" - }, - { - "name": "firewalld", - "source": "rpm", - "epoch": null, - "version": "0.3.9", - "release": "7.el7", - "arch": "noarch" - } -] diff --git a/awx/main/tests/functional/services.json b/awx/main/tests/functional/services.json deleted file mode 100644 index a86bf4a875..0000000000 --- a/awx/main/tests/functional/services.json +++ /dev/null @@ -1,697 +0,0 @@ -[ - { - "source": "sysv", - "state": "running", - "name": "iprdump" - }, - { - "source": "sysv", - "state": "running", - "name": "iprinit" - }, - { - "source": "sysv", - "state": "running", - "name": "iprupdate" - }, - { - "source": "sysv", - "state": "stopped", - "name": "netconsole" - }, - { - "source": "sysv", - "state": "running", - "name": "network" - }, - { - "source": "systemd", - "state": "stopped", - "name": "arp-ethers.service" - }, - { - "source": "systemd", - "state": "running", - "name": "auditd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "autovt@.service" - }, - { - "source": "systemd", - "state": "running", - "name": "avahi-daemon.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "blk-availability.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "brandbot.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "console-getty.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "console-shell.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "cpupower.service" - }, - { - "source": "systemd", - "state": "running", - "name": "crond.service" - }, - { - "source": "systemd", - "state": "running", - "name": "dbus-org.fedoraproject.FirewallD1.service" - }, - { - "source": "systemd", - "state": "running", - "name": "dbus-org.freedesktop.Avahi.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus-org.freedesktop.hostname1.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus-org.freedesktop.locale1.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus-org.freedesktop.login1.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus-org.freedesktop.machine1.service" - }, - { - "source": "systemd", - "state": "running", - "name": "dbus-org.freedesktop.NetworkManager.service" - }, - { - "source": "systemd", - "state": "running", - "name": "dbus-org.freedesktop.nm-dispatcher.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus-org.freedesktop.timedate1.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dbus.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "debug-shell.service" - }, - { - "source": "systemd", - "state": "running", - "name": "dhcpd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dhcpd6.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dhcrelay.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dm-event.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dnsmasq.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-cmdline.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-initqueue.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-mount.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-pre-mount.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-pre-pivot.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-pre-trigger.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-pre-udev.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "dracut-shutdown.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "ebtables.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "emergency.service" - }, - { - "source": "systemd", - "state": "running", - "name": "firewalld.service" - }, - { - "source": "systemd", - "state": "running", - "name": "getty@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "halt-local.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "initrd-cleanup.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "initrd-parse-etc.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "initrd-switch-root.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "initrd-udevadm-cleanup-db.service" - }, - { - "source": "systemd", - "state": "running", - "name": "irqbalance.service" - }, - { - "source": "systemd", - "state": "running", - "name": "kdump.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "kmod-static-nodes.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "lvm2-lvmetad.service" - }, - { - "source": "systemd", - "state": "running", - "name": "lvm2-monitor.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "lvm2-pvscan@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "messagebus.service" - }, - { - "source": "systemd", - "state": "running", - "name": "microcode.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "named-setup-rndc.service" - }, - { - "source": "systemd", - "state": "running", - "name": "named.service" - }, - { - "source": "systemd", - "state": "running", - "name": "NetworkManager-dispatcher.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "NetworkManager-wait-online.service" - }, - { - "source": "systemd", - "state": "running", - "name": "NetworkManager.service" - }, - { - "source": "systemd", - "state": "running", - "name": "ntpd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "ntpdate.service" - }, - { - "source": "systemd", - "state": "running", - "name": "openvpn@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-halt.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-kexec.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-poweroff.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-quit-wait.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-quit.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-read-write.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-reboot.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-start.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "plymouth-switch-root.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "polkit.service" - }, - { - "source": "systemd", - "state": "running", - "name": "postfix.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "quotaon.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rc-local.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rdisc.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rescue.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-autorelabel-mark.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-autorelabel.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-configure.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-dmesg.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-domainname.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-import-state.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-loadmodules.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "rhel-readonly.service" - }, - { - "source": "systemd", - "state": "running", - "name": "rsyslog.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "serial-getty@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "sshd-keygen.service" - }, - { - "source": "systemd", - "state": "running", - "name": "sshd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "sshd@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-ask-password-console.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-ask-password-plymouth.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-ask-password-wall.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-backlight@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-binfmt.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-fsck-root.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-fsck@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-halt.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-hibernate.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-hostnamed.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-hybrid-sleep.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-initctl.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-journal-flush.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-journald.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-kexec.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-localed.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-logind.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-machined.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-modules-load.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-nspawn@.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-poweroff.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-quotacheck.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-random-seed.service" - }, - { - "source": "systemd", - "state": "running", - "name": "systemd-readahead-collect.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-readahead-done.service" - }, - { - "source": "systemd", - "state": "running", - "name": "systemd-readahead-drop.service" - }, - { - "source": "systemd", - "state": "running", - "name": "systemd-readahead-replay.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-reboot.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-remount-fs.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-shutdownd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-suspend.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-sysctl.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-timedated.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-tmpfiles-clean.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-tmpfiles-setup-dev.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-tmpfiles-setup.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-udev-settle.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-udev-trigger.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-udevd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-update-utmp-runlevel.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-update-utmp.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-user-sessions.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "systemd-vconsole-setup.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "teamd@.service" - }, - { - "source": "systemd", - "state": "running", - "name": "tuned.service" - }, - { - "source": "systemd", - "state": "running", - "name": "vmtoolsd.service" - }, - { - "source": "systemd", - "state": "stopped", - "name": "wpa_supplicant.service" - } -] From 1f59d6182b078aa5e44ae74dab99813e4313b55f Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Wed, 17 Feb 2021 14:43:22 -0500 Subject: [PATCH 20/26] Adds filtering for system level roles --- .../ResourceAccessList/ResourceAccessList.jsx | 57 ++++++++++++++++--- .../ResourceAccessList.test.jsx | 12 +++- .../ResourceAccessListItem.jsx | 2 + .../ResourceAccessListItem.test.jsx.snap | 25 ++++---- 4 files changed, 75 insertions(+), 21 deletions(-) diff --git a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx index 3a9b7dedb9..1cc04c5fa3 100644 --- a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx +++ b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { TeamsAPI, UsersAPI } from '../../api'; +import { RolesAPI, TeamsAPI, UsersAPI } from '../../api'; import AddResourceRole from '../AddRole/AddResourceRole'; import AlertModal from '../AlertModal'; import DataListToolbar from '../DataListToolbar'; @@ -26,7 +26,13 @@ function ResourceAccessList({ i18n, apiModel, resource }) { const location = useLocation(); const { - result: { accessRecords, itemCount, relatedSearchableKeys, searchableKeys }, + result: { + accessRecords, + itemCount, + relatedSearchableKeys, + searchableKeys, + organizationRoles, + }, error: contentError, isLoading, request: fetchAccessRecords, @@ -37,6 +43,41 @@ function ResourceAccessList({ i18n, apiModel, resource }) { apiModel.readAccessList(resource.id, params), apiModel.readAccessOptions(resource.id), ]); + + // Eventually this could be expanded to other access lists. + // We will need to combine the role ids of all the different level + // of resource level roles. + + let orgRoles; + if (location.pathname.includes('/organizations')) { + const { + data: { results: roles }, + } = await RolesAPI.read({ content_type__isnull: true }); + const sysAdmin = roles.filter( + role => role.name === 'System Administrator' + ); + const sysAud = roles.filter(role => { + let auditor; + if (role.name === 'System Auditor') { + auditor = role.id; + } + return auditor; + }); + + orgRoles = Object.values(resource.summary_fields.object_roles).map( + opt => { + let item; + if (opt.name === 'Admin') { + item = [`${opt.id}, ${sysAdmin[0].id}`, opt.name]; + } else if (sysAud[0].id && opt.name === 'Auditor') { + item = [`${sysAud[0].id}, ${opt.id}`, opt.name]; + } else { + item = [`${opt.id}`, opt.name]; + } + return item; + } + ); + } return { accessRecords: response.data.results, itemCount: response.data.count, @@ -46,8 +87,9 @@ function ResourceAccessList({ i18n, apiModel, resource }) { searchableKeys: Object.keys( actionsResponse.data.actions?.GET || {} ).filter(key => actionsResponse.data.actions?.GET[key].filterable), + organizationRoles: orgRoles, }; - }, [apiModel, location, resource.id]), + }, [apiModel, location, resource]), { accessRecords: [], itemCount: 0, @@ -94,17 +136,14 @@ function ResourceAccessList({ i18n, apiModel, resource }) { }, ]; - if (location.pathname.includes('/organizations')) { - const roles = Object.values( - resource.summary_fields.object_roles - ).map(opt => [opt.id.toString(), opt.name]); - + if (organizationRoles?.length > 0) { toolbarSearchColumns.push({ name: i18n._(t`Roles`), key: `or__roles__in`, - options: roles, + options: organizationRoles, }); } + return ( <> ', () => { }); TeamsAPI.disassociateRole.mockResolvedValue({}); UsersAPI.disassociateRole.mockResolvedValue({}); + RolesAPI.read.mockResolvedValue({ + data: { + results: [ + { id: 1, name: 'System Administrator' }, + { id: 14, name: 'System Auditor' }, + ], + }, + }); const history = createMemoryHistory({ initialEntries: ['/organizations/1/access'], }); @@ -203,7 +211,7 @@ describe('', () => { key: 'or__roles__in', name: 'Roles', options: [ - ['2', 'Admin'], + ['2, 1', 'Admin'], ['3', 'Execute'], ['4', 'Project Admin'], ], diff --git a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessListItem.jsx b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessListItem.jsx index d641e67e01..669c5223ab 100644 --- a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessListItem.jsx +++ b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessListItem.jsx @@ -56,6 +56,8 @@ function ResourceAccessListItem({ accessRecord, onRoleDelete, i18n }) { onRoleDelete(role, accessRecord); }} isReadOnly={!role.user_capabilities.unattach} + ouiaId={`${role.name}-${role.id}`} + closeBtnAriaLabel={i18n._(t`Remove ${role.name} chip`)} > {role.name} diff --git a/awx/ui_next/src/components/ResourceAccessList/__snapshots__/ResourceAccessListItem.test.jsx.snap b/awx/ui_next/src/components/ResourceAccessList/__snapshots__/ResourceAccessListItem.test.jsx.snap index 7271c0a62b..7d1c5a4da8 100644 --- a/awx/ui_next/src/components/ResourceAccessList/__snapshots__/ResourceAccessListItem.test.jsx.snap +++ b/awx/ui_next/src/components/ResourceAccessList/__snapshots__/ResourceAccessListItem.test.jsx.snap @@ -98,11 +98,12 @@ exports[` initially renders succesfully 1`] = ` > Member @@ -164,11 +165,12 @@ exports[` initially renders succesfully 1`] = ` > Member @@ -253,11 +255,12 @@ exports[` initially renders succesfully 1`] = ` > Member @@ -688,11 +691,12 @@ exports[` initially renders succesfully 1`] = ` > Member @@ -865,12 +869,13 @@ exports[` initially renders succesfully 1`] = ` > initially renders succesfully 1`] = ` >
@@ -889,19 +894,19 @@ exports[` initially renders succesfully 1`] = ` Member - + {% trans 'REST API' %}