mirror of
https://github.com/ansible/awx.git
synced 2026-03-04 02:01:01 -03:30
Add EE to the settings page
Allow a system admin to set the global default execution environment. See: https://github.com/ansible/awx/issues/9088 This PR is also addressing the issue: https://github.com/ansible/awx/issues/9669
This commit is contained in:
@@ -186,7 +186,7 @@ register(
|
|||||||
default=None,
|
default=None,
|
||||||
queryset=ExecutionEnvironment.objects.all(),
|
queryset=ExecutionEnvironment.objects.all(),
|
||||||
label=_('Global default execution environment'),
|
label=_('Global default execution environment'),
|
||||||
help_text=_('.'),
|
help_text=_('The Execution Environment to be used when one has not been configured for a job template.'),
|
||||||
category=_('System'),
|
category=_('System'),
|
||||||
category_slug='system',
|
category_slug='system',
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ function ExecutionEnvironmentLookup({
|
|||||||
globallyAvailable,
|
globallyAvailable,
|
||||||
i18n,
|
i18n,
|
||||||
isDefaultEnvironment,
|
isDefaultEnvironment,
|
||||||
|
isGlobalDefaultEnvironment,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
onBlur,
|
onBlur,
|
||||||
onChange,
|
onChange,
|
||||||
@@ -154,17 +155,26 @@ function ExecutionEnvironmentLookup({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderLabel = (
|
||||||
|
globalDefaultEnvironment,
|
||||||
|
defaultExecutionEnvironment
|
||||||
|
) => {
|
||||||
|
if (globalDefaultEnvironment) {
|
||||||
|
return i18n._(t`Global Default Execution Environment`);
|
||||||
|
}
|
||||||
|
if (defaultExecutionEnvironment) {
|
||||||
|
return i18n._(t`Default Execution Environment`);
|
||||||
|
}
|
||||||
|
return i18n._(t`Execution Environment`);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
fieldId="execution-environment-lookup"
|
fieldId="execution-environment-lookup"
|
||||||
label={
|
label={renderLabel(isGlobalDefaultEnvironment, isDefaultEnvironment)}
|
||||||
isDefaultEnvironment
|
|
||||||
? i18n._(t`Default Execution Environment`)
|
|
||||||
: i18n._(t`Execution Environment`)
|
|
||||||
}
|
|
||||||
labelIcon={popoverContent && <Popover content={popoverContent} />}
|
labelIcon={popoverContent && <Popover content={popoverContent} />}
|
||||||
>
|
>
|
||||||
{isDisabled ? (
|
{tooltip ? (
|
||||||
<Tooltip content={tooltip}>{renderLookup()}</Tooltip>
|
<Tooltip content={tooltip}>{renderLookup()}</Tooltip>
|
||||||
) : (
|
) : (
|
||||||
renderLookup()
|
renderLookup()
|
||||||
@@ -180,6 +190,7 @@ ExecutionEnvironmentLookup.propTypes = {
|
|||||||
popoverContent: string,
|
popoverContent: string,
|
||||||
onChange: func.isRequired,
|
onChange: func.isRequired,
|
||||||
isDefaultEnvironment: bool,
|
isDefaultEnvironment: bool,
|
||||||
|
isGlobalDefaultEnvironment: bool,
|
||||||
projectId: oneOfType([number, string]),
|
projectId: oneOfType([number, string]),
|
||||||
organizationId: oneOfType([number, string]),
|
organizationId: oneOfType([number, string]),
|
||||||
};
|
};
|
||||||
@@ -187,6 +198,7 @@ ExecutionEnvironmentLookup.propTypes = {
|
|||||||
ExecutionEnvironmentLookup.defaultProps = {
|
ExecutionEnvironmentLookup.defaultProps = {
|
||||||
popoverContent: '',
|
popoverContent: '',
|
||||||
isDefaultEnvironment: false,
|
isDefaultEnvironment: false,
|
||||||
|
isGlobalDefaultEnvironment: false,
|
||||||
value: null,
|
value: null,
|
||||||
projectId: null,
|
projectId: null,
|
||||||
organizationId: null,
|
organizationId: null,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import ContentError from '../../../../components/ContentError';
|
|||||||
import ContentLoading from '../../../../components/ContentLoading';
|
import ContentLoading from '../../../../components/ContentLoading';
|
||||||
import { DetailList } from '../../../../components/DetailList';
|
import { DetailList } from '../../../../components/DetailList';
|
||||||
import RoutedTabs from '../../../../components/RoutedTabs';
|
import RoutedTabs from '../../../../components/RoutedTabs';
|
||||||
import { SettingsAPI } from '../../../../api';
|
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
|
||||||
import useRequest from '../../../../util/useRequest';
|
import useRequest from '../../../../util/useRequest';
|
||||||
import { useConfig } from '../../../../contexts/Config';
|
import { useConfig } from '../../../../contexts/Config';
|
||||||
import { useSettings } from '../../../../contexts/Settings';
|
import { useSettings } from '../../../../contexts/Settings';
|
||||||
@@ -23,7 +23,15 @@ function MiscSystemDetail({ i18n }) {
|
|||||||
const { isLoading, error, request, result: system } = useRequest(
|
const { isLoading, error, request, result: system } = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const { data } = await SettingsAPI.readCategory('all');
|
const { data } = await SettingsAPI.readCategory('all');
|
||||||
|
let DEFAULT_EXECUTION_ENVIRONMENT = '';
|
||||||
|
if (data.DEFAULT_EXECUTION_ENVIRONMENT) {
|
||||||
|
const {
|
||||||
|
data: { name },
|
||||||
|
} = await ExecutionEnvironmentsAPI.readDetail(
|
||||||
|
data.DEFAULT_EXECUTION_ENVIRONMENT
|
||||||
|
);
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT = name;
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
OAUTH2_PROVIDER: {
|
OAUTH2_PROVIDER: {
|
||||||
ACCESS_TOKEN_EXPIRE_SECONDS,
|
ACCESS_TOKEN_EXPIRE_SECONDS,
|
||||||
@@ -49,19 +57,17 @@ function MiscSystemDetail({ i18n }) {
|
|||||||
'SESSION_COOKIE_AGE',
|
'SESSION_COOKIE_AGE',
|
||||||
'TOWER_URL_BASE'
|
'TOWER_URL_BASE'
|
||||||
);
|
);
|
||||||
|
|
||||||
const systemData = {
|
const systemData = {
|
||||||
...pluckedSystemData,
|
...pluckedSystemData,
|
||||||
ACCESS_TOKEN_EXPIRE_SECONDS,
|
ACCESS_TOKEN_EXPIRE_SECONDS,
|
||||||
REFRESH_TOKEN_EXPIRE_SECONDS,
|
REFRESH_TOKEN_EXPIRE_SECONDS,
|
||||||
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
OAUTH2_PROVIDER: OAUTH2_PROVIDER_OPTIONS,
|
OAUTH2_PROVIDER: OAUTH2_PROVIDER_OPTIONS,
|
||||||
...options
|
...options
|
||||||
} = allOptions;
|
} = allOptions;
|
||||||
|
|
||||||
const systemOptions = {
|
const systemOptions = {
|
||||||
...options,
|
...options,
|
||||||
ACCESS_TOKEN_EXPIRE_SECONDS: {
|
ACCESS_TOKEN_EXPIRE_SECONDS: {
|
||||||
@@ -80,7 +86,6 @@ function MiscSystemDetail({ i18n }) {
|
|||||||
label: i18n._(t`Authorization Code Expiration`),
|
label: i18n._(t`Authorization Code Expiration`),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const mergedData = {};
|
const mergedData = {};
|
||||||
Object.keys(systemData).forEach(key => {
|
Object.keys(systemData).forEach(key => {
|
||||||
mergedData[key] = systemOptions[key];
|
mergedData[key] = systemOptions[key];
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
waitForElement,
|
waitForElement,
|
||||||
} from '../../../../../testUtils/enzymeHelpers';
|
} from '../../../../../testUtils/enzymeHelpers';
|
||||||
import { SettingsProvider } from '../../../../contexts/Settings';
|
import { SettingsProvider } from '../../../../contexts/Settings';
|
||||||
import { SettingsAPI } from '../../../../api';
|
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
|
||||||
import {
|
import {
|
||||||
assertDetail,
|
assertDetail,
|
||||||
assertVariableDetail,
|
assertVariableDetail,
|
||||||
@@ -14,13 +14,14 @@ import mockAllOptions from '../../shared/data.allSettingOptions.json';
|
|||||||
import MiscSystemDetail from './MiscSystemDetail';
|
import MiscSystemDetail from './MiscSystemDetail';
|
||||||
|
|
||||||
jest.mock('../../../../api/models/Settings');
|
jest.mock('../../../../api/models/Settings');
|
||||||
|
jest.mock('../../../../api/models/ExecutionEnvironments');
|
||||||
|
|
||||||
SettingsAPI.readCategory.mockResolvedValue({
|
SettingsAPI.readCategory.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: false,
|
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: false,
|
||||||
AUTH_BASIC_ENABLED: true,
|
AUTH_BASIC_ENABLED: true,
|
||||||
AUTOMATION_ANALYTICS_GATHER_INTERVAL: 14400,
|
AUTOMATION_ANALYTICS_GATHER_INTERVAL: 14400,
|
||||||
AUTOMATION_ANALYTICS_URL: 'https://example.com',
|
AUTOMATION_ANALYTICS_URL: 'https://example.com',
|
||||||
CUSTOM_VENV_PATHS: [],
|
|
||||||
INSIGHTS_TRACKING_STATE: false,
|
INSIGHTS_TRACKING_STATE: false,
|
||||||
LOGIN_REDIRECT_OVERRIDE: 'https://redirect.com',
|
LOGIN_REDIRECT_OVERRIDE: 'https://redirect.com',
|
||||||
MANAGE_ORGANIZATION_AUTH: true,
|
MANAGE_ORGANIZATION_AUTH: true,
|
||||||
@@ -36,6 +37,16 @@ SettingsAPI.readCategory.mockResolvedValue({
|
|||||||
SESSIONS_PER_USER: -1,
|
SESSIONS_PER_USER: -1,
|
||||||
SESSION_COOKIE_AGE: 30000000000,
|
SESSION_COOKIE_AGE: 30000000000,
|
||||||
TOWER_URL_BASE: 'https://towerhost',
|
TOWER_URL_BASE: 'https://towerhost',
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ExecutionEnvironmentsAPI.readDetail.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Foo',
|
||||||
|
image: 'quay.io/ansible/awx-ee',
|
||||||
|
pull: 'missing',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -110,6 +121,33 @@ describe('<MiscSystemDetail />', () => {
|
|||||||
assertDetail(wrapper, 'Red Hat customer username', 'mock name');
|
assertDetail(wrapper, 'Red Hat customer username', 'mock name');
|
||||||
assertDetail(wrapper, 'Refresh Token Expiration', '3 seconds');
|
assertDetail(wrapper, 'Refresh Token Expiration', '3 seconds');
|
||||||
assertVariableDetail(wrapper, 'Remote Host Headers', '[]');
|
assertVariableDetail(wrapper, 'Remote Host Headers', '[]');
|
||||||
|
assertDetail(wrapper, 'Global default execution environment', 'Foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render execution environment as not configured', async () => {
|
||||||
|
ExecutionEnvironmentsAPI.readDetail.mockResolvedValue({
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
let newWrapper;
|
||||||
|
await act(async () => {
|
||||||
|
newWrapper = mountWithContexts(
|
||||||
|
<SettingsProvider
|
||||||
|
value={{
|
||||||
|
...mockAllOptions.actions,
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT: null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MiscSystemDetail />
|
||||||
|
</SettingsProvider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await waitForElement(newWrapper, 'ContentLoading', el => el.length === 0);
|
||||||
|
|
||||||
|
assertDetail(
|
||||||
|
newWrapper,
|
||||||
|
'Global default execution environment',
|
||||||
|
'Not configured'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hide edit button from non-superusers', async () => {
|
test('should hide edit button from non-superusers', async () => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import ContentError from '../../../../components/ContentError';
|
|||||||
import ContentLoading from '../../../../components/ContentLoading';
|
import ContentLoading from '../../../../components/ContentLoading';
|
||||||
import { FormSubmitError } from '../../../../components/FormField';
|
import { FormSubmitError } from '../../../../components/FormField';
|
||||||
import { FormColumnLayout } from '../../../../components/FormLayout';
|
import { FormColumnLayout } from '../../../../components/FormLayout';
|
||||||
|
import { ExecutionEnvironmentLookup } from '../../../../components/Lookup';
|
||||||
import { useSettings } from '../../../../contexts/Settings';
|
import { useSettings } from '../../../../contexts/Settings';
|
||||||
import {
|
import {
|
||||||
BooleanField,
|
BooleanField,
|
||||||
@@ -20,7 +21,7 @@ import {
|
|||||||
} from '../../shared';
|
} from '../../shared';
|
||||||
import useModal from '../../../../util/useModal';
|
import useModal from '../../../../util/useModal';
|
||||||
import useRequest from '../../../../util/useRequest';
|
import useRequest from '../../../../util/useRequest';
|
||||||
import { SettingsAPI } from '../../../../api';
|
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
|
||||||
import { pluck, formatJson } from '../../shared/settingUtils';
|
import { pluck, formatJson } from '../../shared/settingUtils';
|
||||||
|
|
||||||
function MiscSystemEdit({ i18n }) {
|
function MiscSystemEdit({ i18n }) {
|
||||||
@@ -44,7 +45,6 @@ function MiscSystemEdit({ i18n }) {
|
|||||||
'AUTH_BASIC_ENABLED',
|
'AUTH_BASIC_ENABLED',
|
||||||
'AUTOMATION_ANALYTICS_GATHER_INTERVAL',
|
'AUTOMATION_ANALYTICS_GATHER_INTERVAL',
|
||||||
'AUTOMATION_ANALYTICS_URL',
|
'AUTOMATION_ANALYTICS_URL',
|
||||||
'CUSTOM_VENV_PATHS',
|
|
||||||
'INSIGHTS_TRACKING_STATE',
|
'INSIGHTS_TRACKING_STATE',
|
||||||
'LOGIN_REDIRECT_OVERRIDE',
|
'LOGIN_REDIRECT_OVERRIDE',
|
||||||
'MANAGE_ORGANIZATION_AUTH',
|
'MANAGE_ORGANIZATION_AUTH',
|
||||||
@@ -55,7 +55,8 @@ function MiscSystemEdit({ i18n }) {
|
|||||||
'REMOTE_HOST_HEADERS',
|
'REMOTE_HOST_HEADERS',
|
||||||
'SESSIONS_PER_USER',
|
'SESSIONS_PER_USER',
|
||||||
'SESSION_COOKIE_AGE',
|
'SESSION_COOKIE_AGE',
|
||||||
'TOWER_URL_BASE'
|
'TOWER_URL_BASE',
|
||||||
|
'DEFAULT_EXECUTION_ENVIRONMENT'
|
||||||
);
|
);
|
||||||
|
|
||||||
const systemData = {
|
const systemData = {
|
||||||
@@ -128,6 +129,7 @@ function MiscSystemEdit({ i18n }) {
|
|||||||
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
||||||
...formData
|
...formData
|
||||||
} = form;
|
} = form;
|
||||||
|
|
||||||
await submitForm({
|
await submitForm({
|
||||||
...formData,
|
...formData,
|
||||||
REMOTE_HOST_HEADERS: formatJson(formData.REMOTE_HOST_HEADERS),
|
REMOTE_HOST_HEADERS: formatJson(formData.REMOTE_HOST_HEADERS),
|
||||||
@@ -136,6 +138,8 @@ function MiscSystemEdit({ i18n }) {
|
|||||||
REFRESH_TOKEN_EXPIRE_SECONDS,
|
REFRESH_TOKEN_EXPIRE_SECONDS,
|
||||||
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
AUTHORIZATION_CODE_EXPIRE_SECONDS,
|
||||||
},
|
},
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT:
|
||||||
|
formData.DEFAULT_EXECUTION_ENVIRONMENT?.id || null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,16 +182,73 @@ function MiscSystemEdit({ i18n }) {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
const executionEnvironmentId =
|
||||||
|
system?.DEFAULT_EXECUTION_ENVIRONMENT?.value || null;
|
||||||
|
|
||||||
|
const {
|
||||||
|
isLoading: isLoadingExecutionEnvironment,
|
||||||
|
error: errorExecutionEnvironment,
|
||||||
|
request: fetchExecutionEnvironment,
|
||||||
|
result: executionEnvironment,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
|
if (!executionEnvironmentId) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const { data } = await ExecutionEnvironmentsAPI.readDetail(
|
||||||
|
executionEnvironmentId
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
}, [executionEnvironmentId])
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchExecutionEnvironment();
|
||||||
|
}, [fetchExecutionEnvironment]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardBody>
|
<CardBody>
|
||||||
{isLoading && <ContentLoading />}
|
{(isLoading || isLoadingExecutionEnvironment) && <ContentLoading />}
|
||||||
{!isLoading && error && <ContentError error={error} />}
|
{!(isLoading || isLoadingExecutionEnvironment) && error && (
|
||||||
{!isLoading && system && (
|
<ContentError error={error || errorExecutionEnvironment} />
|
||||||
<Formik initialValues={initialValues(system)} onSubmit={handleSubmit}>
|
)}
|
||||||
|
{!(isLoading || isLoadingExecutionEnvironment) && system && (
|
||||||
|
<Formik
|
||||||
|
initialValues={{
|
||||||
|
...initialValues(system),
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT: executionEnvironment
|
||||||
|
? { id: executionEnvironment.id, name: executionEnvironment.name }
|
||||||
|
: null,
|
||||||
|
}}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
{formik => {
|
{formik => {
|
||||||
return (
|
return (
|
||||||
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||||
<FormColumnLayout>
|
<FormColumnLayout>
|
||||||
|
<ExecutionEnvironmentLookup
|
||||||
|
helperTextInvalid={
|
||||||
|
formik.errors.DEFAULT_EXECUTION_ENVIRONMENT
|
||||||
|
}
|
||||||
|
isValid={
|
||||||
|
!formik.touched.DEFAULT_EXECUTION_ENVIRONMENT ||
|
||||||
|
!formik.errors.DEFAULT_EXECUTION_ENVIRONMENT
|
||||||
|
}
|
||||||
|
onBlur={() =>
|
||||||
|
formik.setFieldTouched('DEFAULT_EXECUTION_ENVIRONMENT')
|
||||||
|
}
|
||||||
|
value={formik.values.DEFAULT_EXECUTION_ENVIRONMENT}
|
||||||
|
onChange={value =>
|
||||||
|
formik.setFieldValue(
|
||||||
|
'DEFAULT_EXECUTION_ENVIRONMENT',
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
popoverContent={i18n._(
|
||||||
|
t`The Execution Environment to be used when one has not been configured for a job template.`
|
||||||
|
)}
|
||||||
|
isGlobalDefaultEnvironment
|
||||||
|
/>
|
||||||
<InputField
|
<InputField
|
||||||
name="TOWER_URL_BASE"
|
name="TOWER_URL_BASE"
|
||||||
config={system.TOWER_URL_BASE}
|
config={system.TOWER_URL_BASE}
|
||||||
|
|||||||
@@ -8,14 +8,55 @@ import {
|
|||||||
import mockAllOptions from '../../shared/data.allSettingOptions.json';
|
import mockAllOptions from '../../shared/data.allSettingOptions.json';
|
||||||
import mockAllSettings from '../../shared/data.allSettings.json';
|
import mockAllSettings from '../../shared/data.allSettings.json';
|
||||||
import { SettingsProvider } from '../../../../contexts/Settings';
|
import { SettingsProvider } from '../../../../contexts/Settings';
|
||||||
import { SettingsAPI } from '../../../../api';
|
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
|
||||||
import MiscSystemEdit from './MiscSystemEdit';
|
import MiscSystemEdit from './MiscSystemEdit';
|
||||||
|
|
||||||
jest.mock('../../../../api/models/Settings');
|
jest.mock('../../../../api/models/Settings');
|
||||||
|
jest.mock('../../../../api/models/ExecutionEnvironments');
|
||||||
|
|
||||||
SettingsAPI.updateAll.mockResolvedValue({});
|
SettingsAPI.updateAll.mockResolvedValue({});
|
||||||
SettingsAPI.readCategory.mockResolvedValue({
|
SettingsAPI.readCategory.mockResolvedValue({
|
||||||
data: mockAllSettings,
|
data: mockAllSettings,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mockExecutionEnvironment = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Default EE',
|
||||||
|
description: '',
|
||||||
|
image: 'quay.io/ansible/awx-ee',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
ExecutionEnvironmentsAPI.read.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
results: mockExecutionEnvironment,
|
||||||
|
count: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const systemData = {
|
||||||
|
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: false,
|
||||||
|
AUTH_BASIC_ENABLED: true,
|
||||||
|
AUTOMATION_ANALYTICS_GATHER_INTERVAL: 14400,
|
||||||
|
AUTOMATION_ANALYTICS_URL: 'https://example.com',
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT: 1,
|
||||||
|
INSIGHTS_TRACKING_STATE: false,
|
||||||
|
LOGIN_REDIRECT_OVERRIDE: '',
|
||||||
|
MANAGE_ORGANIZATION_AUTH: true,
|
||||||
|
OAUTH2_PROVIDER: {
|
||||||
|
ACCESS_TOKEN_EXPIRE_SECONDS: 31536000000,
|
||||||
|
AUTHORIZATION_CODE_EXPIRE_SECONDS: 600,
|
||||||
|
REFRESH_TOKEN_EXPIRE_SECONDS: 2628000,
|
||||||
|
},
|
||||||
|
ORG_ADMINS_CAN_SEE_ALL_USERS: true,
|
||||||
|
REDHAT_PASSWORD: '',
|
||||||
|
REDHAT_USERNAME: '',
|
||||||
|
REMOTE_HOST_HEADERS: ['REMOTE_ADDR', 'REMOTE_HOST'],
|
||||||
|
SESSIONS_PER_USER: -1,
|
||||||
|
SESSION_COOKIE_AGE: 1800,
|
||||||
|
TOWER_URL_BASE: 'https://localhost:3000',
|
||||||
|
};
|
||||||
describe('<MiscSystemEdit />', () => {
|
describe('<MiscSystemEdit />', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let history;
|
let history;
|
||||||
@@ -42,10 +83,40 @@ describe('<MiscSystemEdit />', () => {
|
|||||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('initially renders without crashing', () => {
|
test('initially renders without crashing', async () => {
|
||||||
expect(wrapper.find('MiscSystemEdit').length).toBe(1);
|
expect(wrapper.find('MiscSystemEdit').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('save button should call updateAll', async () => {
|
||||||
|
expect(wrapper.find('MiscSystemEdit').length).toBe(1);
|
||||||
|
|
||||||
|
wrapper.find('ExecutionEnvironmentLookup').invoke('onChange')({
|
||||||
|
id: 1,
|
||||||
|
name: 'Foo',
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(SettingsAPI.updateAll).toHaveBeenCalledWith(systemData);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should remove execution environment', async () => {
|
||||||
|
expect(wrapper.find('MiscSystemEdit').length).toBe(1);
|
||||||
|
|
||||||
|
wrapper.find('ExecutionEnvironmentLookup').invoke('onChange')(null);
|
||||||
|
wrapper.update();
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(SettingsAPI.updateAll).toHaveBeenCalledWith({
|
||||||
|
...systemData,
|
||||||
|
DEFAULT_EXECUTION_ENVIRONMENT: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('should successfully send default values to api on form revert all', async () => {
|
test('should successfully send default values to api on form revert all', async () => {
|
||||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(0);
|
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(0);
|
||||||
expect(wrapper.find('RevertAllAlert')).toHaveLength(0);
|
expect(wrapper.find('RevertAllAlert')).toHaveLength(0);
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ export default withI18n()(
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'choice':
|
case 'choice':
|
||||||
|
case 'field':
|
||||||
|
case 'string':
|
||||||
detail = (
|
detail = (
|
||||||
<Detail
|
<Detail
|
||||||
alwaysVisible
|
alwaysVisible
|
||||||
@@ -110,18 +112,6 @@ export default withI18n()(
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'string':
|
|
||||||
detail = (
|
|
||||||
<Detail
|
|
||||||
alwaysVisible
|
|
||||||
dataCy={id}
|
|
||||||
helpText={helpText}
|
|
||||||
isNotConfigured={!value}
|
|
||||||
label={label}
|
|
||||||
value={!value ? i18n._(t`Not configured`) : value}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
detail = null;
|
detail = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2944,7 +2944,15 @@
|
|||||||
"child": {
|
"child": {
|
||||||
"type": "field"
|
"type": "field"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"DEFAULT_EXECUTION_ENVIRONMENT": {
|
||||||
|
"type": "field",
|
||||||
|
"label": "Global default execution environment",
|
||||||
|
"help_text": "The Execution Environment to be used when one has not been configured for a job template.",
|
||||||
|
"category": "System",
|
||||||
|
"category_slug": "system",
|
||||||
|
"defined_in_file": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"PUT": {
|
"PUT": {
|
||||||
"ACTIVITY_STREAM_ENABLED": {
|
"ACTIVITY_STREAM_ENABLED": {
|
||||||
@@ -7049,6 +7057,15 @@
|
|||||||
"read_only": false
|
"read_only": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DEFAULT_EXECUTION_ENVIRONMENT": {
|
||||||
|
"type": "field",
|
||||||
|
"required": false,
|
||||||
|
"label": "Global default execution environment",
|
||||||
|
"help_text": "The Execution Environment to be used when one has not been configured for a job template.",
|
||||||
|
"category": "System",
|
||||||
|
"category_slug": "system",
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
"SOCIAL_AUTH_SAML_TEAM_ATTR": {
|
"SOCIAL_AUTH_SAML_TEAM_ATTR": {
|
||||||
"type": "nested object",
|
"type": "nested object",
|
||||||
"required": false,
|
"required": false,
|
||||||
|
|||||||
@@ -303,5 +303,6 @@
|
|||||||
"applications":{"fields":["name"],"adj_list":[["organization","organizations"]]},
|
"applications":{"fields":["name"],"adj_list":[["organization","organizations"]]},
|
||||||
"users":{"fields":["username"],"adj_list":[]},
|
"users":{"fields":["username"],"adj_list":[]},
|
||||||
"instances":{"fields":["hostname"],"adj_list":[]}
|
"instances":{"fields":["hostname"],"adj_list":[]}
|
||||||
}
|
},
|
||||||
|
"DEFAULT_EXECUTION_ENVIRONMENT": 1
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user