1. fix tr language file in the gulp task 2. update i18n file for each languages 3. fix some i18n Change-Id: I31f6324d79bb57c0721d6d771a199daa26856811
385 lines
9.0 KiB
JavaScript
385 lines
9.0 KiB
JavaScript
// 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 { inject, observer } from 'mobx-react';
|
|
import { message as $message } from 'antd';
|
|
import { StepAction } from 'src/containers/Action';
|
|
import globalContainersStore from 'stores/zun/containers';
|
|
import globalProjectStore from 'stores/keystone/project';
|
|
import { isEmpty } from 'lodash';
|
|
import StepInfo from './StepInfo';
|
|
import StepSpec from './StepSpec';
|
|
import StepVolumes from './StepVolumes';
|
|
import StepNetworks from './StepNetworks';
|
|
import StepOthers from './StepOthers';
|
|
|
|
export class StepCreate extends StepAction {
|
|
init() {
|
|
this.store = globalContainersStore;
|
|
this.projectStore = globalProjectStore;
|
|
this.getQuota();
|
|
this.state.isLoading = true;
|
|
this.errorMsg = '';
|
|
}
|
|
|
|
static id = 'create-container';
|
|
|
|
static title = t('Create Container');
|
|
|
|
static path = '/container-service/containers/create';
|
|
|
|
static policy = 'container:create';
|
|
|
|
static aliasPolicy = 'zun:container:create';
|
|
|
|
static allowed() {
|
|
return Promise.resolve(true);
|
|
}
|
|
|
|
get name() {
|
|
return t('Create Container');
|
|
}
|
|
|
|
get listUrl() {
|
|
return this.getRoutePath('zunContainers');
|
|
}
|
|
|
|
get hasConfirmStep() {
|
|
return false;
|
|
}
|
|
|
|
get steps() {
|
|
return [
|
|
{
|
|
title: t('Info'),
|
|
component: StepInfo,
|
|
},
|
|
{
|
|
title: t('Spec'),
|
|
component: StepSpec,
|
|
},
|
|
{
|
|
title: t('Volumes'),
|
|
component: StepVolumes,
|
|
},
|
|
{
|
|
title: t('Network Config'),
|
|
component: StepNetworks,
|
|
},
|
|
{
|
|
title: t('Others'),
|
|
component: StepOthers,
|
|
},
|
|
];
|
|
}
|
|
|
|
get showQuota() {
|
|
return true;
|
|
}
|
|
|
|
get quotaInfo() {
|
|
if (this.state.isLoading) {
|
|
return [];
|
|
}
|
|
const {
|
|
containers = {},
|
|
cpu = {},
|
|
memory = {},
|
|
disk = {},
|
|
} = this.projectStore.zunQuota;
|
|
const { left = 0 } = containers || {};
|
|
const {
|
|
data: {
|
|
cpu: cpuCount = 0,
|
|
memory: memoryCount = 0,
|
|
disk: diskCount = 0,
|
|
} = {},
|
|
} = this.state;
|
|
const containersQuotaInfo = {
|
|
...containers,
|
|
add: left ? 1 : 0,
|
|
name: 'containers',
|
|
title: t('Containers'),
|
|
};
|
|
|
|
const { left: cpuLeft = 0 } = cpu;
|
|
const { left: memoryLeft = 0 } = memory;
|
|
const { left: diskLeft = 0 } = disk;
|
|
const canAdd =
|
|
left &&
|
|
(cpuLeft === -1 || cpuCount <= cpuLeft) &&
|
|
(memoryLeft === -1 || memoryCount <= memoryLeft) &&
|
|
(diskLeft === -1 || diskCount <= diskLeft);
|
|
|
|
const cpuQuotaInfo = {
|
|
...cpu,
|
|
add: canAdd ? cpuCount : 0,
|
|
name: 'cpu',
|
|
title: t('Containers CPU'),
|
|
type: 'line',
|
|
};
|
|
|
|
const memoryQuotaInfo = {
|
|
...memory,
|
|
add: canAdd ? memoryCount : 0,
|
|
name: 'memory',
|
|
title: t('Containers Memory (MiB)'),
|
|
type: 'line',
|
|
};
|
|
|
|
const diskQuotaInfo = {
|
|
...disk,
|
|
add: canAdd ? diskCount : 0,
|
|
name: 'disk',
|
|
title: t('Containers Disk (GiB)'),
|
|
type: 'line',
|
|
};
|
|
|
|
this.checkQuota(this.state.data, this.projectStore.zunQuota);
|
|
|
|
return [containersQuotaInfo, cpuQuotaInfo, memoryQuotaInfo, diskQuotaInfo];
|
|
}
|
|
|
|
async getQuota() {
|
|
await this.projectStore.fetchProjectZunQuota();
|
|
this.setState({
|
|
isLoading: false,
|
|
});
|
|
}
|
|
|
|
getQuotaMessage(input, left, name) {
|
|
if (left === -1) {
|
|
return '';
|
|
}
|
|
if (left === 0) {
|
|
return t('Quota: Insufficient { name } quota to create resources.', {
|
|
name,
|
|
});
|
|
}
|
|
if (input > left) {
|
|
return t(
|
|
'Insufficient {name} quota to create resources (left { quota }, input { input }).',
|
|
{ name, quota: left, input }
|
|
);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
checkQuota(data, quota) {
|
|
const { containers = {}, cpu = {}, memory = {}, disk = {} } = quota || {};
|
|
const {
|
|
cpu: cpuCount = 0,
|
|
memory: memoryCount = 0,
|
|
disk: diskCount = 0,
|
|
} = data || {};
|
|
|
|
const { left: containerLeft = 0 } = containers;
|
|
const containerMsg = this.getQuotaMessage(
|
|
1,
|
|
containerLeft,
|
|
t('Containers')
|
|
);
|
|
|
|
const { left: cpuLeft = 0 } = cpu;
|
|
const cpuMsg = this.getQuotaMessage(cpuCount, cpuLeft, t('CPU'));
|
|
|
|
const { left: memoryLeft = 0 } = memory;
|
|
const memoryMsg = this.getQuotaMessage(
|
|
memoryCount,
|
|
memoryLeft,
|
|
t('Memory')
|
|
);
|
|
|
|
const { left: diskLeft = 0 } = disk;
|
|
const diskMsg = this.getQuotaMessage(diskCount, diskLeft, t('Disk'));
|
|
|
|
if (!containerMsg && !cpuMsg && !memoryMsg && !diskMsg) {
|
|
this.errorMsg = '';
|
|
} else {
|
|
const msg = containerMsg || cpuMsg || memoryMsg || diskMsg;
|
|
if (this.errorMsg !== msg) {
|
|
$message.error(msg);
|
|
}
|
|
this.errorMsg = msg;
|
|
}
|
|
}
|
|
|
|
get disableNext() {
|
|
return !!this.errorMsg;
|
|
}
|
|
|
|
get disableSubmit() {
|
|
return !!this.errorMsg;
|
|
}
|
|
|
|
onSubmit = (values) => {
|
|
const {
|
|
exposedPorts,
|
|
environmentVariables,
|
|
labels,
|
|
mounts,
|
|
image_driver,
|
|
imageDocker,
|
|
imageGlance,
|
|
exitPolicy,
|
|
maxRetry,
|
|
networks,
|
|
ports,
|
|
hints,
|
|
securityGroup,
|
|
healthcheck,
|
|
healthcheck_cmd,
|
|
healthcheck_interval,
|
|
healthcheck_retries,
|
|
healthcheck_timeout,
|
|
command,
|
|
entrypoint,
|
|
...rest
|
|
} = values;
|
|
|
|
const body = {
|
|
image_driver,
|
|
...rest,
|
|
};
|
|
|
|
const requestExposedPorts = {};
|
|
const nets = [];
|
|
|
|
if (exposedPorts && exposedPorts.length) {
|
|
exposedPorts.forEach((item) => {
|
|
const key = `${item.value.port}/${item.value.protocol}`;
|
|
requestExposedPorts[key] = {};
|
|
});
|
|
body.exposed_ports = requestExposedPorts;
|
|
}
|
|
|
|
if (environmentVariables && environmentVariables.length) {
|
|
const requestEnvironment = environmentVariables.reduce(
|
|
(result, current) => {
|
|
const labelKey = current.value.key;
|
|
const labelValue = current.value.value;
|
|
result[labelKey] = labelValue;
|
|
return result;
|
|
},
|
|
{}
|
|
);
|
|
body.environment = requestEnvironment;
|
|
}
|
|
|
|
if (labels && labels.length) {
|
|
const requestLabels = labels.reduce((result, current) => {
|
|
const { key } = current.value;
|
|
const { value } = current.value;
|
|
result[key] = value;
|
|
return result;
|
|
}, {});
|
|
body.labels = requestLabels;
|
|
}
|
|
|
|
if (mounts && mounts.length) {
|
|
const requestVolumes = mounts.reduce((result, current) => {
|
|
const { type, source, size, destination, isNewVolume } = current.value;
|
|
if (isNewVolume) {
|
|
result.push({
|
|
type,
|
|
size,
|
|
destination,
|
|
});
|
|
} else {
|
|
result.push({
|
|
type,
|
|
source,
|
|
destination,
|
|
});
|
|
}
|
|
return result;
|
|
}, []);
|
|
body.mounts = requestVolumes;
|
|
}
|
|
|
|
if (networks && networks.selectedRowKeys.length) {
|
|
networks.selectedRowKeys.forEach((it) => {
|
|
nets.push({ network: it });
|
|
});
|
|
body.nets = nets;
|
|
}
|
|
|
|
if (ports && ports.selectedRowKeys.length) {
|
|
ports.selectedRowKeys.forEach((it) => {
|
|
nets.push({ port: it });
|
|
});
|
|
body.nets = nets;
|
|
}
|
|
|
|
if (hints && hints.length) {
|
|
const requestHints = hints.reduce((result, current) => {
|
|
const { key } = current.value;
|
|
const { value } = current.value;
|
|
result[key] = value;
|
|
return result;
|
|
}, {});
|
|
body.hints = requestHints;
|
|
}
|
|
|
|
if (
|
|
securityGroup &&
|
|
securityGroup.selectedRows.length &&
|
|
isEmpty(requestExposedPorts)
|
|
) {
|
|
const securityGroups = securityGroup.selectedRows.reduce(
|
|
(result, current) => {
|
|
result.push(current.name);
|
|
return result;
|
|
},
|
|
[]
|
|
);
|
|
body.security_groups = securityGroups;
|
|
}
|
|
|
|
if (healthcheck) {
|
|
body.healthcheck = {
|
|
cmd: healthcheck_cmd,
|
|
interval: healthcheck_interval,
|
|
retries: healthcheck_retries,
|
|
timeout: healthcheck_timeout,
|
|
};
|
|
}
|
|
|
|
if (command) {
|
|
body.command = [command];
|
|
}
|
|
|
|
if (entrypoint) {
|
|
body.entrypoint = [entrypoint];
|
|
}
|
|
|
|
if (imageDocker && image_driver === 'docker') {
|
|
body.image = imageDocker;
|
|
}
|
|
|
|
if (imageGlance && image_driver === 'glance') {
|
|
body.image = imageGlance.selectedRowKeys[0];
|
|
}
|
|
|
|
if (exitPolicy) {
|
|
body.restart_policy = {
|
|
Name: exitPolicy,
|
|
...(maxRetry ? { MaximumRetryCount: maxRetry } : {}),
|
|
};
|
|
}
|
|
|
|
return this.store.create(body);
|
|
};
|
|
}
|
|
|
|
export default inject('rootStore')(observer(StepCreate));
|