mirror of https://github.com/rancher/dashboard.git
275 lines
7.0 KiB
Vue
275 lines
7.0 KiB
Vue
<script>
|
|
import Labels from '@/components/form/Labels';
|
|
import Networking from '@/edit/rio.cattle.io.service//Networking';
|
|
import Command from '@/edit/rio.cattle.io.service/Command';
|
|
import HealthCheck from '@/components/form/HealthCheck';
|
|
import { get } from '@/utils/object';
|
|
import { CONFIG_MAP, SECRET, RIO } from '@/config/types';
|
|
import Loading from '@/components/Loading';
|
|
import Tab from '@/components/Tabbed/Tab';
|
|
import Tabbed from '@/components/Tabbed';
|
|
import CreateEditView from '@/mixins/create-edit-view';
|
|
import { _EDIT, EDIT_CONTAINER, DEMO } from '@/config/query-params';
|
|
import Footer from '@/components/form/Footer';
|
|
import { findBy, filterBy, removeObject } from '@/utils/array';
|
|
import { allHash } from '@/utils/promise';
|
|
import DEMOS from '@/config/demos';
|
|
import Volumes from './Volumes';
|
|
import Upgrading from './Upgrading';
|
|
import Security from './Security';
|
|
import Top from './Top';
|
|
|
|
export default {
|
|
name: 'CruService',
|
|
|
|
components: {
|
|
Loading,
|
|
Tabbed,
|
|
Tab,
|
|
Top,
|
|
Command,
|
|
HealthCheck,
|
|
Networking,
|
|
Labels,
|
|
Security,
|
|
Upgrading,
|
|
Volumes,
|
|
Footer
|
|
},
|
|
|
|
mixins: [CreateEditView],
|
|
|
|
props: {
|
|
realMode: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
},
|
|
|
|
async fetch() {
|
|
const hash = await allHash({
|
|
configMaps: this.$store.dispatch('cluster/findAll', { type: CONFIG_MAP }),
|
|
secrets: this.$store.dispatch('cluster/findAll', { type: SECRET }),
|
|
services: this.$store.dispatch('cluster/findAll', { type: RIO.SERVICE }),
|
|
});
|
|
|
|
this.allSecrets = hash.secrets;
|
|
this.allConfigMaps = hash.configMaps;
|
|
},
|
|
|
|
data() {
|
|
if ( !this.value.spec ) {
|
|
this.value.spec = {};
|
|
}
|
|
|
|
const containerName = this.$route.query[EDIT_CONTAINER];
|
|
const rootSpec = this.value.spec;
|
|
const multipleContainers = ( !!(rootSpec.containers && rootSpec.containers.length) );
|
|
let spec = rootSpec;
|
|
let isSidecar = false;
|
|
let nameResource = this.value.metadata;
|
|
|
|
if ( !nameResource ) {
|
|
nameResource = { name: '' };
|
|
this.value.metadata = nameResource;
|
|
}
|
|
|
|
if ( containerName ) {
|
|
nameResource = spec.containers[name];
|
|
spec = nameResource.spec;
|
|
isSidecar = true;
|
|
}
|
|
|
|
if ( typeof spec.imagePullPolicy === 'undefined' ) {
|
|
spec.imagePullPolicy = 'Always';
|
|
}
|
|
|
|
const demoName = this.$route.query[DEMO];
|
|
let isDemo = false;
|
|
|
|
if ( demoName && DEMOS[demoName] ) {
|
|
isDemo = true;
|
|
Object.assign(spec, DEMOS[demoName].spec);
|
|
}
|
|
|
|
return {
|
|
multipleContainers,
|
|
nameResource,
|
|
containerName,
|
|
isSidecar,
|
|
rootSpec,
|
|
spec,
|
|
isDemo,
|
|
allConfigMaps: null,
|
|
allSecrets: null,
|
|
showTabs: false
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
promptForContainer() {
|
|
return this.mode === _EDIT && this.multipleContainers && this.containerName === undefined;
|
|
},
|
|
|
|
namespace() {
|
|
return this.value.metadata.namespace;
|
|
},
|
|
|
|
configMaps() {
|
|
return matchingNamespaceGroupedByKey(this.allConfigMaps, this.namespace);
|
|
},
|
|
|
|
secrets() {
|
|
return matchingNamespaceGroupedByKey(this.allSecrets, this.namespace);
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
selectContainer(name) {
|
|
this.$router.applyQuery({ [EDIT_CONTAINER]: name });
|
|
this.containerName = name;
|
|
},
|
|
|
|
remove(name) {
|
|
const containers = this.value.spec.containers;
|
|
const entry = findBy(containers, 'name', name);
|
|
|
|
removeObject(containers, entry);
|
|
this.save();
|
|
},
|
|
|
|
toggleTabs() {
|
|
this.showTabs = !this.showTabs;
|
|
},
|
|
|
|
get
|
|
},
|
|
};
|
|
|
|
function matchingNamespaceGroupedByKey(ary, namespace) {
|
|
if ( !namespace ) {
|
|
return [];
|
|
}
|
|
|
|
const matching = filterBy((ary || []), 'metadata.namespace', namespace);
|
|
const out = [];
|
|
|
|
for ( const item of matching ) {
|
|
const name = item.metadata.name;
|
|
const keys = [];
|
|
|
|
for ( const k of Object.keys(item.data || {}) ) {
|
|
keys.push({ label: k, value: `${ name }/${ k }` });
|
|
}
|
|
|
|
for ( const k of Object.keys(item.binaryData || {}) ) {
|
|
keys.push({ label: k, value: `${ name }/${ k }` });
|
|
}
|
|
|
|
if ( keys.length ) {
|
|
out.push({
|
|
group: item.metadata.name,
|
|
items: keys
|
|
});
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<form>
|
|
<Loading v-if="$fetchState.pending" />
|
|
<div v-else-if="promptForContainer" class="clearfix">
|
|
<p>This service consists of multiple containers, which one do you want to edit?</p>
|
|
<div class="box">
|
|
<p>The primary container</p>
|
|
<p>{{ value.nameDisplay }}</p>
|
|
<button type="button" class="btn role-primary" @click="selectContainer('')">
|
|
Edit
|
|
</button>
|
|
</div>
|
|
<div v-for="choice in value.spec.containers" :key="choice.name" class="box">
|
|
<p>Sidecar</p>
|
|
<p>{{ choice.name }}</p>
|
|
<button type="button" class="btn role-primary" @click="selectContainer(choice.name)">
|
|
Edit
|
|
</button>
|
|
<button type="button" class="btn bg-error" @click="remove(choice.name)">
|
|
Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<Top
|
|
:value="value"
|
|
:spec="spec"
|
|
:name-resource="nameResource"
|
|
:is-sidecar="isSidecar"
|
|
:mode="mode"
|
|
:real-mode="realMode"
|
|
:is-demo="isDemo"
|
|
:register-after-hook="registerAfterHook"
|
|
:register-before-hook="registerBeforeHook"
|
|
/>
|
|
<div class="spacer"></div>
|
|
<a href="#" @click.prevent="toggleTabs">
|
|
<span v-if="!showTabs">Show</span> <span v-else>Hide</span> additional options
|
|
</a>
|
|
<Tabbed v-show="showTabs" default-tab="command">
|
|
<Tab name="command" label="Command">
|
|
<Command
|
|
:spec="spec"
|
|
:mode="mode"
|
|
:config-maps="configMaps"
|
|
:secrets="secrets"
|
|
:namespace="namespace"
|
|
:more-add="true"
|
|
/>
|
|
</Tab>
|
|
<Tab name="network" label="Network">
|
|
<Networking :spec="spec" :mode="mode" />
|
|
</Tab>
|
|
<Tab name="healthcheck" label="Health Check">
|
|
<HealthCheck :spec="spec" :mode="mode" />
|
|
</Tab>
|
|
<Tab v-if="!isSidecar" name="labels" label="Labels">
|
|
<Labels :value="value" :mode="mode" />
|
|
</Tab>
|
|
<Tab name="security" label="Security">
|
|
<Security :spec="spec" :mode="mode" />
|
|
</Tab>
|
|
<Tab name="upgrading" label="Scaling & Upgrading">
|
|
<Upgrading :spec="rootSpec" :concurrency="get(rootSpec, 'autoscale.concurrency')" :mode="mode" />
|
|
</Tab>
|
|
<Tab v-if="false" name="volumes" label="Volumes">
|
|
<Volumes :spec="spec" :mode="mode" />
|
|
</Tab>
|
|
</Tabbed>
|
|
|
|
<Footer :mode="mode" :errors="errors" @save="save" @done="done" />
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.box {
|
|
float: left;
|
|
border: 1px solid var(--border);
|
|
padding: 20px;
|
|
text-align: center;
|
|
width: 25%;
|
|
margin-right: 20px;
|
|
|
|
P {
|
|
margin: 0;
|
|
}
|
|
|
|
&:last-child {
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
</style>
|