mirror of https://github.com/rancher/dashboard.git
277 lines
6.9 KiB
Vue
277 lines
6.9 KiB
Vue
<script>
|
|
import { DOCKER_JSON, OPAQUE, TLS } from '@/models/secret';
|
|
import { base64Encode, base64Decode } from '@/utils/crypto';
|
|
import { get } from '@/utils/object';
|
|
import { NAMESPACE } from '@/config/types';
|
|
import { DESCRIPTION } from '@/config/labels-annotations';
|
|
import CreateEditView from '@/mixins/create-edit-view';
|
|
import Footer from '@/components/form/Footer';
|
|
import KeyValue from '@/components/form/KeyValue';
|
|
import LabeledInput from '@/components/form/LabeledInput';
|
|
import RadioGroup from '@/components/form/RadioGroup';
|
|
import NameNsDescription from '@/components/form/NameNsDescription';
|
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
|
|
|
export default {
|
|
name: 'CruSecret',
|
|
|
|
components: {
|
|
KeyValue,
|
|
Footer,
|
|
LabeledInput,
|
|
LabeledSelect,
|
|
RadioGroup,
|
|
NameNsDescription
|
|
},
|
|
mixins: [CreateEditView],
|
|
data() {
|
|
const types = [
|
|
{ label: 'Certificate', value: TLS },
|
|
{ label: 'Registry', value: DOCKER_JSON },
|
|
{ label: 'Secret', value: OPAQUE },
|
|
];
|
|
const registryAddresses = [
|
|
'DockerHub', 'Quay.io', 'Artifactory', 'Custom'
|
|
];
|
|
const isNamespaced = !!this.value.metadata.namespace;
|
|
|
|
let username;
|
|
let password;
|
|
let registryFQDN;
|
|
|
|
if (this.value._type === DOCKER_JSON) {
|
|
const json = base64Decode(this.value.data['.dockerconfigjson']);
|
|
|
|
const { auths } = JSON.parse(json);
|
|
|
|
registryFQDN = Object.keys(auths)[0];
|
|
|
|
username = auths[registryFQDN].username;
|
|
password = auths[registryFQDN].password;
|
|
}
|
|
|
|
return {
|
|
types,
|
|
isNamespaced,
|
|
registryAddresses,
|
|
newNS: false,
|
|
registryProvider: registryAddresses[0],
|
|
username,
|
|
password,
|
|
registryFQDN,
|
|
toUpload: null,
|
|
key: null,
|
|
cert: null
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
certificate() {
|
|
return TLS;
|
|
},
|
|
|
|
name: {
|
|
get() {
|
|
return get(this.value, 'metadata.name');
|
|
},
|
|
set(neu) {
|
|
this.$set(this.value.metadata, 'name', neu);
|
|
}
|
|
},
|
|
|
|
description: {
|
|
get() {
|
|
const { metadata:{ annotations = {} } } = this.value;
|
|
|
|
return annotations[DESCRIPTION] || '';
|
|
},
|
|
set(neu) {
|
|
this.$set(this.value.metadata.annotations, DESCRIPTION, neu );
|
|
}
|
|
},
|
|
|
|
type: {
|
|
get() {
|
|
return this.value._type || OPAQUE;
|
|
},
|
|
set(neu) {
|
|
this.$set(this.value, '_type', neu.value);
|
|
}
|
|
},
|
|
|
|
namespace: {
|
|
get() {
|
|
if (this.isNamespaced) {
|
|
return get(this.value, 'metadata.namespace') || 'default';
|
|
} else {
|
|
return 'n/a';
|
|
}
|
|
},
|
|
set(neu) {
|
|
this.$set(this.value.metadata, 'namespace', neu);
|
|
}
|
|
},
|
|
|
|
dockerconfigjson() {
|
|
let dockerServer = this.registryProvider === 'DockerHub' ? 'index.dockerhub.io/v1/' : 'quay.io';
|
|
|
|
if (this.needsDockerServer) {
|
|
dockerServer = this.registryFQDN;
|
|
}
|
|
|
|
if (this.isRegistry && dockerServer) {
|
|
const config = {
|
|
auths: {
|
|
[dockerServer]: {
|
|
username: this.username,
|
|
password: this.password,
|
|
}
|
|
}
|
|
};
|
|
const json = JSON.stringify(config);
|
|
|
|
return json;
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
|
|
namespaces() {
|
|
return this.$store.getters['cluster/all'](NAMESPACE).map((obj) => {
|
|
return {
|
|
label: obj.nameDisplay,
|
|
value: obj.id,
|
|
};
|
|
});
|
|
},
|
|
|
|
isRegistry() {
|
|
return this.type === DOCKER_JSON;
|
|
},
|
|
|
|
needsDockerServer() {
|
|
return this.registryProvider === 'Artifactory' || this.registryProvider === 'Custom';
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
saveSecret(buttonCB) {
|
|
if (this.type === DOCKER_JSON) {
|
|
const data = { '.dockerconfigjson': base64Encode(this.dockerconfigjson) };
|
|
|
|
this.$set(this.value, 'data', data);
|
|
} else if (this.type === TLS) {
|
|
const data = { 'tls.cert': base64Encode(this.cert), 'tls.key': base64Encode(this.key) };
|
|
|
|
this.$set(this.value, 'data', data);
|
|
}
|
|
this.save(buttonCB);
|
|
},
|
|
|
|
fileUpload(field) {
|
|
this.toUpload = field;
|
|
this.$refs.uploader.click();
|
|
},
|
|
|
|
fileChange(event) {
|
|
const input = event.target;
|
|
const handles = input.files;
|
|
const names = [];
|
|
|
|
if ( handles ) {
|
|
for ( let i = 0 ; i < handles.length ; i++ ) {
|
|
const reader = new FileReader();
|
|
|
|
reader.onload = (loaded) => {
|
|
const value = loaded.target.result;
|
|
|
|
this[this.toUpload] = value;
|
|
};
|
|
|
|
reader.onerror = (err) => {
|
|
this.$dispatch('growl/fromError', { title: 'Error reading file', err }, { root: true });
|
|
};
|
|
|
|
names[i] = handles[i].name;
|
|
reader.readAsText(handles[i]);
|
|
}
|
|
|
|
input.value = '';
|
|
}
|
|
},
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<form>
|
|
<NameNsDescription v-model="value" :mode="mode" :extra-columns="['type']">
|
|
<template v-slot:type>
|
|
<LabeledSelect v-model="type" label="Type" :options="types" />
|
|
</template>
|
|
</NameNsDescription>
|
|
<template v-if="isRegistry">
|
|
<div id="registry-type" class="row">
|
|
Provider: <RadioGroup row :options="registryAddresses" :value="registryProvider" @input="e=>registryProvider = e" />
|
|
</div>
|
|
<div v-if="needsDockerServer" class="row">
|
|
<LabeledInput v-model="registryFQDN" label="Registry Domain Name" placeholder="e.g. index.docker.io" />
|
|
</div>
|
|
<div class="row">
|
|
<div class="col span-6">
|
|
<LabeledInput v-model="username" label="Username" />
|
|
</div>
|
|
<div class="col span-6">
|
|
<LabeledInput v-model="password" label="Password" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<div v-else-if="type===certificate" class="row">
|
|
<div class="col span-6">
|
|
<LabeledInput v-model="key" label="Private Key" />
|
|
<button type="button" class="btn btn-sm bg-primary mt-10" @click="fileUpload('key')">
|
|
READ FROM FILE
|
|
</button>
|
|
</div>
|
|
<div class="col span-6">
|
|
<LabeledInput v-model="cert" label="CA Certificate" />
|
|
<button type="button" class="btn btn-sm bg-primary mt-10" @click="fileUpload('cert')">
|
|
READ FROM FILE
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else class="row">
|
|
<KeyValue
|
|
key="data"
|
|
v-model="value.data"
|
|
:mode="mode"
|
|
title="Data"
|
|
:initial-empty-row="true"
|
|
:value-base64="true"
|
|
read-icon=""
|
|
add-icon=""
|
|
add-label="ADD"
|
|
read-label="READ FROM A FILE"
|
|
/>
|
|
</div>
|
|
|
|
<input
|
|
ref="uploader"
|
|
type="file"
|
|
class="hide"
|
|
@change="fileChange"
|
|
/>
|
|
|
|
<Footer :mode="mode" :errors="errors" @save="saveSecret" @done="done" />
|
|
</form>
|
|
</template>
|
|
|
|
<style>
|
|
#registry-type {
|
|
display: flex;
|
|
align-items:center;
|
|
}
|
|
</style>
|