feat: show action logs of a zun container

Show action logs of a zun container

Change-Id: Icd660776a220941b05511c4f2eef3547b7f952dc
This commit is contained in:
xusongfu 2022-08-03 15:44:14 +08:00
parent 4ccb380ff4
commit 88d877cde2
7 changed files with 249 additions and 77 deletions

View File

@ -71,6 +71,11 @@ export class ZunClient extends Base {
{
key: 'stats',
},
{
name: 'actions',
key: 'container_actions',
responseKey: 'containerAction',
},
],
},
{

View File

@ -0,0 +1,52 @@
// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from 'react';
import { getLocalTimeStr } from 'utils/time';
import IPopover from './Popover';
export default function PopActionEvent({ id, requestId, store, actionEvent }) {
const columns = [
{
title: t('Operation Name'),
dataIndex: 'event',
key: 'event',
render: (value) => actionEvent[value] || value,
},
{
title: t('Start Time'),
dataIndex: 'start_time',
key: 'start_time',
render: (value) => getLocalTimeStr(value),
},
{
title: t('End Time'),
dataIndex: 'finish_time',
key: 'finish_time',
render: (value) => (value ? getLocalTimeStr(value) : '-'),
},
{
title: t('Execution Result'),
dataIndex: 'result',
key: 'result',
render: (value) => (value === 'Success' ? t('Success') : '-'),
},
];
const getData = async () => {
const detail = (await store.fetchDetail({ id, requestId })) || {};
const { events = [] } = detail;
return events.slice().reverse();
};
return <IPopover columns={columns} getData={getData} />;
}

View File

@ -0,0 +1,36 @@
// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Base from 'containers/List';
import { inject, observer } from 'mobx-react';
import { ActionsLogStore } from 'src/stores/zun/action-log';
import { actionColumn } from 'resources/zun/actions';
export class ActionLogs extends Base {
init() {
this.store = new ActionsLogStore();
}
get name() {
return t('Action Logs');
}
get policy() {
return 'container:actions';
}
getColumns = () => actionColumn(this);
}
export default inject('rootStore')(observer(ActionLogs));

View File

@ -16,6 +16,7 @@ import globalContainersStore from 'src/stores/zun/containers';
import { containerStatus } from 'resources/zun/container';
import actionConfigs from '../actions';
import BaseDetail from './BaseDetail';
import ActionLogs from './ActionLogs';
export class ContainerDetail extends Base {
init() {
@ -62,6 +63,11 @@ export class ContainerDetail extends Base {
key: 'general_info',
component: BaseDetail,
},
{
title: t('Action Logs'),
key: 'action_logs',
component: ActionLogs,
},
];
}
}

View File

@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import React, { useEffect, useState } from 'react';
import React from 'react';
import ImageType from 'components/ImageType';
import { getLocalTimeStr } from 'utils/time';
import { Table, Popover, Tag, Tooltip } from 'antd';
import globalActionLogStore from 'stores/nova/action-log';
import { Tag, Tooltip } from 'antd';
import { ActionLogStore } from 'stores/nova/action-log';
import { ironicOriginEndpoint } from 'client/client/constants';
import { projectTagsColors } from 'src/utils/constants';
import PopActionEvent from 'src/components/Popover/PopActionEvent';
import lockSvg from 'asset/image/lock.svg';
import unlockSvg from 'asset/image/unlock.svg';
import { isEmpty } from 'lodash';
@ -506,64 +505,6 @@ export const actionEvent = {
compute_reboot_instance: t('Compute Reboot Instance'),
};
function PopUpContent({ id, requestId }) {
const [event, setEvent] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
let timeout = null;
(async function () {
setLoading(true);
const cb = await globalActionLogStore.fetchDetail({ id, requestId });
const { events = [] } = cb;
timeout = setTimeout(() => {
setLoading(false);
setEvent(events.slice().reverse());
}, 200);
})();
return () => {
clearTimeout(timeout);
};
}, []);
const columns = [
{
title: t('Operation Name'),
dataIndex: 'event',
key: 'event',
render: (value) => actionEvent[value],
},
{
title: t('Start Time'),
dataIndex: 'start_time',
key: 'start_time',
render: (value) => getLocalTimeStr(value),
},
{
title: t('End Time'),
dataIndex: 'finish_time',
key: 'finish_time',
render: (value) => (value ? getLocalTimeStr(value) : '-'),
},
{
title: t('Execution Result'),
dataIndex: 'result',
key: 'result',
render: (value) => (value === 'Success' ? t('Success') : '-'),
},
];
const table = (
<Table
columns={columns}
dataSource={event}
pagination={false}
loading={loading}
size="small"
rowKey="event"
/>
);
return table;
}
export const actionColumn = (self) => {
return [
{
@ -586,20 +527,17 @@ export const actionColumn = (self) => {
title: t('Request ID'),
dataIndex: 'request_id',
isHideable: true,
render: (value, record) => {
const content = (
<PopUpContent id={record.instance_uuid} requestId={value} />
);
return (
<>
{value && (
<Popover content={content} destroyTooltipOnHide trigger="click">
<span className="link-class">{value}</span>
</Popover>
)}
</>
);
},
render: (value, record) => (
<>
<span>{value}</span>
<PopActionEvent
id={record.instance_uuid}
requestId={value}
store={new ActionLogStore()}
actionEvent={actionEvent}
/>
</>
),
},
{
title: t('User ID'),

View File

@ -0,0 +1,90 @@
// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from 'react';
import { ActionsLogStore } from 'src/stores/zun/action-log';
import PopActionEvent from 'src/components/Popover/PopActionEvent';
export const actionEvent = {
compute__do_container_start: t('Start Container'),
compute__do_container_create: t('Create Container'),
compute__do_container_stop: t('Stop Container'),
compute__do_container_reboot: t('Reboot Container'),
compute__do_container_restart: t('Restart Container'),
compute__do_container_pause: t('Pause Container'),
compute__do_container_unpause: t('Unpause Container'),
compute__do_container_resize: t('Resize Container'),
compute__do_container_rebuild: t('Rebuild Container'),
compute__do_container_kill: t('Kill Container'),
compute__do_container_delete: t('Delete Container'),
};
export const actionMap = {
create: t('Create'),
stop: t('Stop'),
reboot: t('Reboot'),
start: t('Start'),
restart: t('Restart'),
pause: t('Pause'),
unpause: t('Unpause'),
resize: t('Resize'),
rebuild: t('Rebuild'),
kill: t('Kill'),
delete: t('Delete'),
};
export const actionColumn = (self) => {
return [
{
title: t('Operation Name'),
dataIndex: 'action',
render: (value) => actionMap[value] || value,
},
{
title: t('Project ID/Name'),
dataIndex: 'project_name',
isHideable: true,
hidden: !self.isAdminPage,
},
{
title: t('Operation Time'),
dataIndex: 'start_time',
valueRender: 'toLocalTimeMoment',
},
{
title: t('Request ID'),
dataIndex: 'request_id',
isHideable: true,
render: (value, record) => (
<>
<span>{value}</span>
<PopActionEvent
id={record.container_uuid}
requestId={value}
store={new ActionsLogStore()}
actionEvent={actionEvent}
/>
</>
),
},
{
title: t('User ID'),
dataIndex: 'user_id',
isHideable: true,
hidden: !self.isAdminPage,
render: (value) =>
self.getLinkRender('userDetail', value, { id: value }, null),
},
];
};

View File

@ -0,0 +1,45 @@
// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Base from 'stores/base';
import client from 'client';
export class ActionsLogStore extends Base {
get client() {
return client.zun.containers.actions;
}
get isSubResource() {
return true;
}
get paramsFunc() {
return () => {};
}
get mapper() {
return (data) => ({
...data,
id: data.request_id,
});
}
detailFetchByClient(resourceParams) {
const { id, requestId } = resourceParams;
return this.client.show(id, requestId);
}
}
const globalActionsLogStore = new ActionsLogStore();
export default globalActionsLogStore;