mirror of
https://github.com/ansible/awx.git
synced 2026-03-20 10:27:34 -02:30
Merge pull request #8078 from nixocio/ui_issue_8073
Add Container Group details
Reviewed-by: Kersom
https://github.com/nixocio
This commit is contained in:
@@ -114,7 +114,7 @@ function ContainerGroup({ i18n, setBreadcrumb }) {
|
|||||||
<ContainerGroupEdit instanceGroup={instanceGroup} />
|
<ContainerGroupEdit instanceGroup={instanceGroup} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/instance_groups/container_group/:id/details">
|
<Route path="/instance_groups/container_group/:id/details">
|
||||||
<ContainerGroupDetails />
|
<ContainerGroupDetails instanceGroup={instanceGroup} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/instance_groups/container_group/:id/jobs">
|
<Route path="/instance_groups/container_group/:id/jobs">
|
||||||
<JobList
|
<JobList
|
||||||
|
|||||||
@@ -1,14 +1,118 @@
|
|||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Card, PageSection } from '@patternfly/react-core';
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
|
import { Button, Label } from '@patternfly/react-core';
|
||||||
|
|
||||||
|
import { VariablesDetail } from '../../../components/CodeMirrorInput';
|
||||||
|
import AlertModal from '../../../components/AlertModal';
|
||||||
|
import { CardBody, CardActionsRow } from '../../../components/Card';
|
||||||
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
|
import {
|
||||||
|
Detail,
|
||||||
|
DetailList,
|
||||||
|
UserDateDetail,
|
||||||
|
} from '../../../components/DetailList';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
import { jsonToYaml, isJsonString } from '../../../util/yaml';
|
||||||
|
import { InstanceGroupsAPI } from '../../../api';
|
||||||
|
|
||||||
|
function ContainerGroupDetails({ instanceGroup, i18n }) {
|
||||||
|
const { id, name } = instanceGroup;
|
||||||
|
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const {
|
||||||
|
request: deleteInstanceGroup,
|
||||||
|
isLoading,
|
||||||
|
error: deleteError,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
|
await InstanceGroupsAPI.destroy(id);
|
||||||
|
history.push(`/instance_groups`);
|
||||||
|
}, [id, history])
|
||||||
|
);
|
||||||
|
|
||||||
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
|
|
||||||
function ContainerGroupDetails() {
|
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<CardBody>
|
||||||
<Card>
|
<DetailList>
|
||||||
<div>Container group details</div>
|
<Detail
|
||||||
</Card>
|
label={i18n._(t`Name`)}
|
||||||
</PageSection>
|
value={instanceGroup.name}
|
||||||
|
dataCy="container-group-detail-name"
|
||||||
|
/>
|
||||||
|
<Detail
|
||||||
|
label={i18n._(t`Type`)}
|
||||||
|
value={i18n._(t`Container group`)}
|
||||||
|
dataCy="container-group-type"
|
||||||
|
/>
|
||||||
|
<Detail
|
||||||
|
label={i18n._(t`Credential`)}
|
||||||
|
value={
|
||||||
|
<Label variant="outline" color="blue">
|
||||||
|
{instanceGroup.summary_fields.credential.name}
|
||||||
|
</Label>
|
||||||
|
}
|
||||||
|
dataCy="container-group-credential"
|
||||||
|
/>
|
||||||
|
<UserDateDetail
|
||||||
|
label={i18n._(t`Created`)}
|
||||||
|
date={instanceGroup.created}
|
||||||
|
user={instanceGroup.summary_fields.created_by}
|
||||||
|
/>
|
||||||
|
<UserDateDetail
|
||||||
|
label={i18n._(t`Last Modified`)}
|
||||||
|
date={instanceGroup.modified}
|
||||||
|
user={instanceGroup.summary_fields.modified_by}
|
||||||
|
/>
|
||||||
|
{instanceGroup.pod_spec_override && (
|
||||||
|
<VariablesDetail
|
||||||
|
label={i18n._(t`Pod spec override`)}
|
||||||
|
value={
|
||||||
|
isJsonString(instanceGroup.pod_spec_override)
|
||||||
|
? jsonToYaml(instanceGroup.pod_spec_override)
|
||||||
|
: instanceGroup.pod_spec_override
|
||||||
|
}
|
||||||
|
rows={6}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DetailList>
|
||||||
|
|
||||||
|
<CardActionsRow>
|
||||||
|
{instanceGroup.summary_fields.user_capabilities &&
|
||||||
|
instanceGroup.summary_fields.user_capabilities.edit && (
|
||||||
|
<Button
|
||||||
|
aria-label={i18n._(t`edit`)}
|
||||||
|
component={Link}
|
||||||
|
to={`/instance_groups/container_group/${id}/edit`}
|
||||||
|
>
|
||||||
|
{i18n._(t`Edit`)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{instanceGroup.summary_fields.user_capabilities &&
|
||||||
|
instanceGroup.summary_fields.user_capabilities.delete && (
|
||||||
|
<DeleteButton
|
||||||
|
name={name}
|
||||||
|
modalTitle={i18n._(t`Delete instance group`)}
|
||||||
|
onConfirm={deleteInstanceGroup}
|
||||||
|
isDisabled={isLoading}
|
||||||
|
>
|
||||||
|
{i18n._(t`Delete`)}
|
||||||
|
</DeleteButton>
|
||||||
|
)}
|
||||||
|
</CardActionsRow>
|
||||||
|
{error && (
|
||||||
|
<AlertModal
|
||||||
|
isOpen={error}
|
||||||
|
onClose={dismissError}
|
||||||
|
title={i18n._(t`Error`)}
|
||||||
|
variant="error"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</CardBody>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ContainerGroupDetails;
|
export default withI18n()(ContainerGroupDetails);
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { createMemoryHistory } from 'history';
|
||||||
|
|
||||||
|
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||||
|
import { InstanceGroupsAPI } from '../../../api';
|
||||||
|
|
||||||
|
import ContainerGroupDetails from './ContainerGroupDetails';
|
||||||
|
|
||||||
|
jest.mock('../../../api');
|
||||||
|
|
||||||
|
const instanceGroup = {
|
||||||
|
id: 42,
|
||||||
|
type: 'instance_group',
|
||||||
|
url: '/api/v2/instance_groups/128/',
|
||||||
|
related: {
|
||||||
|
named_url: '/api/v2/instance_groups/A1/',
|
||||||
|
jobs: '/api/v2/instance_groups/128/jobs/',
|
||||||
|
instances: '/api/v2/instance_groups/128/instances/',
|
||||||
|
credential: '/api/v2/credentials/71/',
|
||||||
|
},
|
||||||
|
name: 'Foo',
|
||||||
|
created: '2020-09-03T18:26:47.113934Z',
|
||||||
|
modified: '2020-09-03T19:34:23.244694Z',
|
||||||
|
capacity: 0,
|
||||||
|
committed_capacity: 0,
|
||||||
|
consumed_capacity: 0,
|
||||||
|
percent_capacity_remaining: 0.0,
|
||||||
|
jobs_running: 0,
|
||||||
|
jobs_total: 0,
|
||||||
|
instances: 0,
|
||||||
|
controller: null,
|
||||||
|
is_controller: false,
|
||||||
|
is_isolated: false,
|
||||||
|
is_containerized: true,
|
||||||
|
credential: 71,
|
||||||
|
policy_instance_percentage: 0,
|
||||||
|
policy_instance_minimum: 0,
|
||||||
|
policy_instance_list: [],
|
||||||
|
pod_spec_override:
|
||||||
|
'apiVersion: v1\nkind: Pod\nmetadata:\n namespace: default\nspec:\n containers:\n - image: ansible/ansible-runner\n tty: true\n stdin: true\n imagePullPolicy: Always\n args:\n - sleep\n - infinity\n - test',
|
||||||
|
summary_fields: {
|
||||||
|
credential: {
|
||||||
|
id: 71,
|
||||||
|
name: 'CG',
|
||||||
|
description: 'Container Group',
|
||||||
|
kind: 'kubernetes_bearer_token',
|
||||||
|
cloud: false,
|
||||||
|
kubernetes: true,
|
||||||
|
credential_type_id: 17,
|
||||||
|
},
|
||||||
|
user_capabilities: {
|
||||||
|
edit: true,
|
||||||
|
delete: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('<ContainerGroupDetails/>', () => {
|
||||||
|
let wrapper;
|
||||||
|
test('should render details properly', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<ContainerGroupDetails instanceGroup={instanceGroup} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
expect(wrapper.find('Detail[label="Name"]').prop('value')).toEqual(
|
||||||
|
instanceGroup.name
|
||||||
|
);
|
||||||
|
expect(wrapper.find('Detail[label="Type"]').prop('value')).toEqual(
|
||||||
|
'Container group'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Detail[label="Credential"]').prop('value').props.children
|
||||||
|
).toEqual(instanceGroup.summary_fields.credential.name);
|
||||||
|
expect(wrapper.find('VariablesDetail').prop('value')).toEqual(
|
||||||
|
instanceGroup.pod_spec_override
|
||||||
|
);
|
||||||
|
const dates = wrapper.find('UserDateDetail');
|
||||||
|
expect(dates).toHaveLength(2);
|
||||||
|
expect(dates.at(0).prop('date')).toEqual(instanceGroup.created);
|
||||||
|
expect(dates.at(1).prop('date')).toEqual(instanceGroup.modified);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('expected api call is made for delete', async () => {
|
||||||
|
const history = createMemoryHistory({
|
||||||
|
initialEntries: ['/credential_types/42/details'],
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<ContainerGroupDetails instanceGroup={instanceGroup} />,
|
||||||
|
{
|
||||||
|
context: { router: { history } },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('DeleteButton').invoke('onConfirm')();
|
||||||
|
});
|
||||||
|
expect(InstanceGroupsAPI.destroy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(history.location.pathname).toBe('/instance_groups');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render delete button', async () => {
|
||||||
|
instanceGroup.summary_fields.user_capabilities.delete = false;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<ContainerGroupDetails instanceGroup={instanceGroup} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
expect(wrapper.find('Button[aria-label="Delete"]').length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render edit button', async () => {
|
||||||
|
instanceGroup.summary_fields.user_capabilities.edit = false;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<ContainerGroupDetails instanceGroup={instanceGroup} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
expect(wrapper.find('Button[aria-label="Edit"]').length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user