Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add EE to the settings page #9653

Merged
merged 1 commit into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion awx/main/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
default=None,
queryset=ExecutionEnvironment.objects.all(),
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_slug='system',
)
Expand Down
24 changes: 18 additions & 6 deletions awx/ui_next/src/components/Lookup/ExecutionEnvironmentLookup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function ExecutionEnvironmentLookup({
globallyAvailable,
i18n,
isDefaultEnvironment,
isGlobalDefaultEnvironment,
isDisabled,
onBlur,
onChange,
Expand Down Expand Up @@ -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 (
<FormGroup
fieldId="execution-environment-lookup"
label={
isDefaultEnvironment
? i18n._(t`Default Execution Environment`)
: i18n._(t`Execution Environment`)
}
label={renderLabel(isGlobalDefaultEnvironment, isDefaultEnvironment)}
labelIcon={popoverContent && <Popover content={popoverContent} />}
>
{isDisabled ? (
{tooltip ? (
<Tooltip content={tooltip}>{renderLookup()}</Tooltip>
) : (
renderLookup()
Expand All @@ -180,13 +190,15 @@ ExecutionEnvironmentLookup.propTypes = {
popoverContent: string,
onChange: func.isRequired,
isDefaultEnvironment: bool,
isGlobalDefaultEnvironment: bool,
projectId: oneOfType([number, string]),
organizationId: oneOfType([number, string]),
};

ExecutionEnvironmentLookup.defaultProps = {
popoverContent: '',
isDefaultEnvironment: false,
isGlobalDefaultEnvironment: false,
value: null,
projectId: null,
organizationId: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ContentError from '../../../../components/ContentError';
import ContentLoading from '../../../../components/ContentLoading';
import { DetailList } from '../../../../components/DetailList';
import RoutedTabs from '../../../../components/RoutedTabs';
import { SettingsAPI } from '../../../../api';
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
import useRequest from '../../../../util/useRequest';
import { useConfig } from '../../../../contexts/Config';
import { useSettings } from '../../../../contexts/Settings';
Expand All @@ -23,7 +23,15 @@ function MiscSystemDetail({ i18n }) {
const { isLoading, error, request, result: system } = useRequest(
useCallback(async () => {
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 {
OAUTH2_PROVIDER: {
ACCESS_TOKEN_EXPIRE_SECONDS,
Expand All @@ -49,19 +57,17 @@ function MiscSystemDetail({ i18n }) {
'SESSION_COOKIE_AGE',
'TOWER_URL_BASE'
);

const systemData = {
...pluckedSystemData,
ACCESS_TOKEN_EXPIRE_SECONDS,
REFRESH_TOKEN_EXPIRE_SECONDS,
AUTHORIZATION_CODE_EXPIRE_SECONDS,
DEFAULT_EXECUTION_ENVIRONMENT,
};

const {
OAUTH2_PROVIDER: OAUTH2_PROVIDER_OPTIONS,
...options
} = allOptions;

const systemOptions = {
...options,
ACCESS_TOKEN_EXPIRE_SECONDS: {
Expand All @@ -80,7 +86,6 @@ function MiscSystemDetail({ i18n }) {
label: i18n._(t`Authorization Code Expiration`),
},
};

const mergedData = {};
Object.keys(systemData).forEach(key => {
mergedData[key] = systemOptions[key];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
waitForElement,
} from '../../../../../testUtils/enzymeHelpers';
import { SettingsProvider } from '../../../../contexts/Settings';
import { SettingsAPI } from '../../../../api';
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
import {
assertDetail,
assertVariableDetail,
Expand All @@ -14,13 +14,14 @@ import mockAllOptions from '../../shared/data.allSettingOptions.json';
import MiscSystemDetail from './MiscSystemDetail';

jest.mock('../../../../api/models/Settings');
jest.mock('../../../../api/models/ExecutionEnvironments');

SettingsAPI.readCategory.mockResolvedValue({
data: {
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: false,
AUTH_BASIC_ENABLED: true,
AUTOMATION_ANALYTICS_GATHER_INTERVAL: 14400,
AUTOMATION_ANALYTICS_URL: 'https://example.com',
CUSTOM_VENV_PATHS: [],
INSIGHTS_TRACKING_STATE: false,
LOGIN_REDIRECT_OVERRIDE: 'https://redirect.com',
MANAGE_ORGANIZATION_AUTH: true,
Expand All @@ -36,6 +37,16 @@ SettingsAPI.readCategory.mockResolvedValue({
SESSIONS_PER_USER: -1,
SESSION_COOKIE_AGE: 30000000000,
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',
},
});

Expand Down Expand Up @@ -110,6 +121,33 @@ describe('<MiscSystemDetail />', () => {
assertDetail(wrapper, 'Red Hat customer username', 'mock name');
assertDetail(wrapper, 'Refresh Token Expiration', '3 seconds');
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 () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ContentError from '../../../../components/ContentError';
import ContentLoading from '../../../../components/ContentLoading';
import { FormSubmitError } from '../../../../components/FormField';
import { FormColumnLayout } from '../../../../components/FormLayout';
import { ExecutionEnvironmentLookup } from '../../../../components/Lookup';
import { useSettings } from '../../../../contexts/Settings';
import {
BooleanField,
Expand All @@ -20,7 +21,7 @@ import {
} from '../../shared';
import useModal from '../../../../util/useModal';
import useRequest from '../../../../util/useRequest';
import { SettingsAPI } from '../../../../api';
import { SettingsAPI, ExecutionEnvironmentsAPI } from '../../../../api';
import { pluck, formatJson } from '../../shared/settingUtils';

function MiscSystemEdit({ i18n }) {
Expand All @@ -44,7 +45,6 @@ function MiscSystemEdit({ i18n }) {
'AUTH_BASIC_ENABLED',
'AUTOMATION_ANALYTICS_GATHER_INTERVAL',
'AUTOMATION_ANALYTICS_URL',
'CUSTOM_VENV_PATHS',
'INSIGHTS_TRACKING_STATE',
'LOGIN_REDIRECT_OVERRIDE',
'MANAGE_ORGANIZATION_AUTH',
Expand All @@ -55,7 +55,8 @@ function MiscSystemEdit({ i18n }) {
'REMOTE_HOST_HEADERS',
'SESSIONS_PER_USER',
'SESSION_COOKIE_AGE',
'TOWER_URL_BASE'
'TOWER_URL_BASE',
'DEFAULT_EXECUTION_ENVIRONMENT'
);

const systemData = {
Expand Down Expand Up @@ -128,6 +129,7 @@ function MiscSystemEdit({ i18n }) {
AUTHORIZATION_CODE_EXPIRE_SECONDS,
...formData
} = form;

await submitForm({
...formData,
REMOTE_HOST_HEADERS: formatJson(formData.REMOTE_HOST_HEADERS),
Expand All @@ -136,6 +138,8 @@ function MiscSystemEdit({ i18n }) {
REFRESH_TOKEN_EXPIRE_SECONDS,
AUTHORIZATION_CODE_EXPIRE_SECONDS,
},
DEFAULT_EXECUTION_ENVIRONMENT:
formData.DEFAULT_EXECUTION_ENVIRONMENT?.id || null,
});
};

Expand Down Expand Up @@ -178,16 +182,73 @@ function MiscSystemEdit({ i18n }) {
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 (
<CardBody>
{isLoading && <ContentLoading />}
{!isLoading && error && <ContentError error={error} />}
{!isLoading && system && (
<Formik initialValues={initialValues(system)} onSubmit={handleSubmit}>
{(isLoading || isLoadingExecutionEnvironment) && <ContentLoading />}
{!(isLoading || isLoadingExecutionEnvironment) && error && (
<ContentError error={error || errorExecutionEnvironment} />
)}
{!(isLoading || isLoadingExecutionEnvironment) && system && (
<Formik
initialValues={{
...initialValues(system),
DEFAULT_EXECUTION_ENVIRONMENT: executionEnvironment
? { id: executionEnvironment.id, name: executionEnvironment.name }
: null,
}}
onSubmit={handleSubmit}
>
{formik => {
return (
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
<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
name="TOWER_URL_BASE"
config={system.TOWER_URL_BASE}
Expand Down
Loading