mirror of https://github.com/rancher/ui.git
parent
cd5cdecb2c
commit
c8d5b3b640
|
|
@ -5,8 +5,11 @@ import { get, set, computed, observer } from '@ember/object';
|
|||
import { satisfies } from 'shared/utils/parse-version';
|
||||
import { sortVersions } from 'shared/utils/sort';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { validateEndpoint } from 'shared/utils/util';
|
||||
import { camelToUnderline, underlineToCamel, removeEmpty, keysToCamel, validateEndpoint } from 'shared/utils/util';
|
||||
import { isSafari } from 'ui/utils/platform';
|
||||
import C from 'shared/utils/constants';
|
||||
import YAML from 'npm:yamljs';
|
||||
import json2yaml from 'npm:json2yaml';
|
||||
import layout from './template';
|
||||
import { resolve } from 'rsvp';
|
||||
|
||||
|
|
@ -42,7 +45,9 @@ export default Component.extend(ClusterDriver, {
|
|||
clusterState: alias('model.originalCluster.state'),
|
||||
configField: 'rancherKubernetesEngineConfig',
|
||||
registry: 'default',
|
||||
accept: '.yml, .yaml',
|
||||
loading: false,
|
||||
pasteOrUpload: false,
|
||||
model: null,
|
||||
initialVersion: null,
|
||||
registryUrl: null,
|
||||
|
|
@ -81,6 +86,9 @@ export default Component.extend(ClusterDriver, {
|
|||
},
|
||||
|
||||
didInsertElement() {
|
||||
set(this, '_boundChange', (event) => { this.change(event); });
|
||||
this.$('INPUT[type=file]').on('change', get(this, '_boundChange'));
|
||||
|
||||
if ( ! get(this,'cluster.rancherKubernetesEngineConfig') ) {
|
||||
const globalStore = get(this, 'globalStore');
|
||||
let config = globalStore.createRecord({
|
||||
|
|
@ -140,10 +148,46 @@ export default Component.extend(ClusterDriver, {
|
|||
}
|
||||
},
|
||||
|
||||
change(event) {
|
||||
var input = event.target;
|
||||
if ( input.files && input.files[0] ) {
|
||||
let file = input.files[0];
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = (event2) => {
|
||||
var out = event2.target.result;
|
||||
|
||||
set(this, 'pastedConfig', out);
|
||||
input.value = '';
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
},
|
||||
|
||||
actualAccept: computed('accept', function() {
|
||||
if ( isSafari ) {
|
||||
return '';
|
||||
} else {
|
||||
return get(this, 'accept');
|
||||
}
|
||||
}),
|
||||
|
||||
actions: {
|
||||
setNodePoolErrors(errors) {
|
||||
set(this, 'nodePoolErrors', errors);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
set(this, 'pasteOrUpload', false);
|
||||
},
|
||||
|
||||
showPaste() {
|
||||
set(this, 'pasteOrUpload', true);
|
||||
},
|
||||
|
||||
upload() {
|
||||
this.$('INPUT[type=file]')[0].click();
|
||||
},
|
||||
},
|
||||
|
||||
willSave() {
|
||||
|
|
@ -315,4 +359,129 @@ export default Component.extend(ClusterDriver, {
|
|||
|
||||
return out;
|
||||
}),
|
||||
|
||||
getResourceFields: function(type) {
|
||||
const schema = get(this, 'globalStore').getById('schema', type.toLowerCase());
|
||||
return schema ? get(schema, 'resourceFields') : null;
|
||||
},
|
||||
|
||||
getFieldValue: function(field, type) {
|
||||
if ( type.startsWith('map[') ) {
|
||||
type = type.slice(4, type.length -1);
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
if ( field ) {
|
||||
const out = {};
|
||||
Object.keys(field).forEach((key) => {
|
||||
out[camelToUnderline(key)] = this.getFieldValue(field[key], type);
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if ( field ) {
|
||||
const out = {};
|
||||
Object.keys(field).forEach((key) => {
|
||||
out[camelToUnderline(key)] = field[key];
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else if ( type.startsWith('array[') ) {
|
||||
type = type.slice(6, type.length -1);
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
return field ? field.map((item) => {
|
||||
return this.getFieldValue(item, type);
|
||||
}) : null;
|
||||
} else {
|
||||
return field ? field.map((item) => {
|
||||
return item;
|
||||
}) : null;
|
||||
}
|
||||
} else {
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
const out = {};
|
||||
Object.keys(resourceFields).forEach((key) => {
|
||||
if ( field !== undefined && field !== null && (typeof field !== 'object' || Object.keys(field).length ) ) {
|
||||
out[camelToUnderline(key)] = this.getFieldValue(field[key], resourceFields[key].type);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getSupportedFields: function(source, tragetField) {
|
||||
const out = {};
|
||||
const resourceFields = this.getResourceFields(tragetField);
|
||||
|
||||
Object.keys(resourceFields).forEach((key) => {
|
||||
const field = get(source, key);
|
||||
const type = resourceFields[key].type;
|
||||
const value = this.getFieldValue(field, type);
|
||||
out[camelToUnderline(key)] = value;
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
pastedConfig: computed('pasteOrUpload', {
|
||||
get() {
|
||||
const intl = get(this, 'intl');
|
||||
let config = this.getSupportedFields(get(this, 'cluster.rancherKubernetesEngineConfig'), 'rancherKubernetesEngineConfig');
|
||||
if ( !config ) {
|
||||
return '';
|
||||
}
|
||||
config = removeEmpty(config);
|
||||
while ( JSON.stringify(config) !== JSON.stringify(removeEmpty(config)) ){
|
||||
config = removeEmpty(config);
|
||||
}
|
||||
|
||||
let yaml = json2yaml.stringify(config);
|
||||
const lines = yaml.split('\n');
|
||||
lines.shift();
|
||||
let out = '';
|
||||
lines.forEach((line) => {
|
||||
if ( line.trim() ) {
|
||||
const key = `rkeConfigComment.${line.split(':')[0].trim()}`
|
||||
if ( intl.exists(key) ) {
|
||||
const commentLines = intl.t(key).split('\n');
|
||||
commentLines.forEach((commentLine) => {
|
||||
out += `# ${commentLine.slice(1, commentLine.length - 1)}\n`;
|
||||
});
|
||||
}
|
||||
out += `${line.slice(2)}\n`;
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
set(key, value) {
|
||||
let configs;
|
||||
try {
|
||||
configs = YAML.parse(value);
|
||||
} catch ( err ) {
|
||||
set(this, 'clusterOptErrors', [`Cluster Options Parse Error: ${err.snippet} - ${err.message}`]);
|
||||
return value;
|
||||
}
|
||||
|
||||
set(this, 'clusterOptErrors', []);
|
||||
|
||||
const validFields = this.getResourceFields('rancherKubernetesEngineConfig');
|
||||
Object.keys(configs || {}).forEach((key) => {
|
||||
if ( validFields[underlineToCamel(key)] ) {
|
||||
set(this, `cluster.rancherKubernetesEngineConfig.${underlineToCamel(key)}`, keysToCamel(configs[key]));
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,88 +7,114 @@
|
|||
expand=(action expandFn)
|
||||
}}
|
||||
<div class="row">
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.version.label'}}</label>
|
||||
{{new-select
|
||||
content=versionChoices
|
||||
optionLabelPath='value'
|
||||
value=config.kubernetesVersion
|
||||
}}
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.network.label'}}</label>
|
||||
{{new-select
|
||||
classNames="form-control"
|
||||
content=networkChoices
|
||||
localizedLabel=true
|
||||
value=config.network.plugin
|
||||
}}
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.podSecurityPolicy.label'}}</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.services.kubeApi.podSecurityPolicy value=false disabled=(not model.psps.length)}}
|
||||
{{t 'generic.disabled'}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label class={{unless model.psps.length 'text-muted'}}>
|
||||
{{radio-button selection=config.services.kubeApi.podSecurityPolicy value=true disabled=(not model.psps.length)}}
|
||||
{{t 'generic.enabled'}}
|
||||
{{#unless model.psps.length}}
|
||||
— {{t 'clusterNew.psp.none'}}
|
||||
{{/unless}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-6">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.ignoreDockerVersion.label'}}</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.ignoreDockerVersion value=false}}
|
||||
{{t 'clusterNew.rke.ignoreDockerVersion.disabled'}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.ignoreDockerVersion value=true}}
|
||||
{{t 'clusterNew.rke.ignoreDockerVersion.enabled'}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-6">
|
||||
{{#if config.services.kubeApi.podSecurityPolicy}}
|
||||
<label class="acc-label">{{t 'clusterNew.psp.label'}}{{field-required}}</label>
|
||||
{{new-select
|
||||
content=model.psps
|
||||
optionLabelPath='displayName'
|
||||
optionValuePath='id'
|
||||
prompt='clusterNew.psp.prompt'
|
||||
localizedPrompt=true
|
||||
value=cluster.defaultPodSecurityPolicyTemplateId
|
||||
disabled=(not config.services.kubeApi.podSecurityPolicy)
|
||||
}}
|
||||
<div class="btn-group pull-right">
|
||||
{{#if pasteOrUpload}}
|
||||
<button class="btn btn-sm" {{action 'cancel'}}>{{t 'clusterNew.advanced.cancel'}}</button>
|
||||
{{else}}
|
||||
<label class="acc-label">{{t 'clusterNew.psp.label'}}</label>
|
||||
<div class="form-control-static">{{t 'generic.none'}}</div>
|
||||
<button class="btn btn-sm bg-primary" {{action 'showPaste'}}>{{t 'clusterNew.advanced.yaml'}} <span class="icon icon-copy"></span></button>
|
||||
{{/if}}
|
||||
<button class="btn btn-sm bg-primary" {{action 'upload'}}>{{t 'uploadFile.label'}} <span class="icon icon-upload"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
{{cru-cloud-provider
|
||||
cluster=model.cluster
|
||||
driver=nodeWhich
|
||||
|
||||
{{#if pasteOrUpload}}
|
||||
<div class="banner bg-info">
|
||||
<div class="banner-icon p-10"><i class="icon icon-info"></i></div>
|
||||
<div class="banner-message">
|
||||
{{t 'clusterNew.advanced.helpText'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-25">
|
||||
{{input-yaml
|
||||
showUpload=false
|
||||
showDownload=false
|
||||
canChangeName=false
|
||||
value=pastedConfig
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
{{#advanced-section advanced=advanced}}
|
||||
{{cluster-options-rke errors=clusterOptErrors config=cluster.rancherKubernetesEngineConfig advanced=advanced}}
|
||||
{{/advanced-section}}
|
||||
{{copy-to-clipboard tooltipText="" buttonText="copyToClipboard.tooltip" clipboardText=pastedConfig class="with-clip"}}
|
||||
{{else}}
|
||||
<div class="row">
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.version.label'}}</label>
|
||||
{{new-select
|
||||
content=versionChoices
|
||||
optionLabelPath='value'
|
||||
value=config.kubernetesVersion
|
||||
}}
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.network.label'}}</label>
|
||||
{{new-select
|
||||
classNames="form-control"
|
||||
content=networkChoices
|
||||
localizedLabel=true
|
||||
value=config.network.plugin
|
||||
}}
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.podSecurityPolicy.label'}}</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.services.kubeApi.podSecurityPolicy value=false disabled=(not model.psps.length)}}
|
||||
{{t 'generic.disabled'}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label class={{unless model.psps.length 'text-muted'}}>
|
||||
{{radio-button selection=config.services.kubeApi.podSecurityPolicy value=true disabled=(not model.psps.length)}}
|
||||
{{t 'generic.enabled'}}
|
||||
{{#unless model.psps.length}}
|
||||
— {{t 'clusterNew.psp.none'}}
|
||||
{{/unless}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-6">
|
||||
<label class="acc-label">{{t 'clusterNew.rke.ignoreDockerVersion.label'}}</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.ignoreDockerVersion value=false}}
|
||||
{{t 'clusterNew.rke.ignoreDockerVersion.disabled'}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=config.ignoreDockerVersion value=true}}
|
||||
{{t 'clusterNew.rke.ignoreDockerVersion.enabled'}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-6">
|
||||
{{#if config.services.kubeApi.podSecurityPolicy}}
|
||||
<label class="acc-label">{{t 'clusterNew.psp.label'}}{{field-required}}</label>
|
||||
{{new-select
|
||||
content=model.psps
|
||||
optionLabelPath='displayName'
|
||||
optionValuePath='id'
|
||||
prompt='clusterNew.psp.prompt'
|
||||
localizedPrompt=true
|
||||
value=cluster.defaultPodSecurityPolicyTemplateId
|
||||
disabled=(not config.services.kubeApi.podSecurityPolicy)
|
||||
}}
|
||||
{{else}}
|
||||
<label class="acc-label">{{t 'clusterNew.psp.label'}}</label>
|
||||
<div class="form-control-static">{{t 'generic.none'}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
{{cru-cloud-provider
|
||||
cluster=model.cluster
|
||||
driver=nodeWhich
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/accordion-list-item}}
|
||||
{{/accordion-list}}
|
||||
|
||||
|
|
@ -207,3 +233,4 @@
|
|||
<button {{action "close"}} class="btn bg-primary">{{t 'clusterNew.rke.done'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
<input type="file" accept="{{actualAccept}}" class="hide">
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
import { get, set, computed } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import YAML from 'npm:yamljs';
|
||||
import json2yaml from 'npm:json2yaml';
|
||||
|
||||
function removeEmpty(obj){
|
||||
return Object.keys(obj)
|
||||
.filter(k => obj[k] !== null && obj[k] !== undefined && (typeof obj[k] !== 'object' || (Object.keys(obj[k]).filter((key) => key !== 'type').length)))
|
||||
.reduce((newObj, k) =>
|
||||
typeof obj[k] === 'object' ?
|
||||
Object.assign(newObj, {[k]: removeEmpty(obj[k])}) :
|
||||
Object.assign(newObj, {[k]: obj[k]}),
|
||||
{});
|
||||
}
|
||||
|
||||
const BLACK_LIST_FIELD = ['kubernetesVersion', 'cloudProvider', 'ignoreDockerVersion'];
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
|
||||
globalStore: service(),
|
||||
intl: service(),
|
||||
|
||||
config: null,
|
||||
advanced: null,
|
||||
errors: null,
|
||||
|
||||
originConfigKeys: null,
|
||||
|
||||
getResourceFields: function(type) {
|
||||
const schema = get(this, 'globalStore').getById('schema', type.toLowerCase());
|
||||
return schema ? get(schema, 'resourceFields') : null;
|
||||
},
|
||||
|
||||
getFieldValue: function(field, type) {
|
||||
if ( type.startsWith('map[') ) {
|
||||
type = type.slice(4, type.length -1);
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
if ( field ) {
|
||||
const out = {};
|
||||
Object.keys(field).forEach((key) => {
|
||||
out[key] = this.getFieldValue(field[key], type);
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if ( field ) {
|
||||
const out = {};
|
||||
Object.keys(field).forEach((key) => {
|
||||
out[key] = field[key];
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else if ( type.startsWith('array[') ) {
|
||||
type = type.slice(6, type.length -1);
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
return field ? field.map((item) => {
|
||||
return this.getFieldValue(item, type);
|
||||
}) : null;
|
||||
} else {
|
||||
return field ? field.map((item) => {
|
||||
return item;
|
||||
}) : null;
|
||||
}
|
||||
} else {
|
||||
const resourceFields = this.getResourceFields(type);
|
||||
if ( resourceFields ) {
|
||||
const out = {};
|
||||
Object.keys(resourceFields).forEach((key) => {
|
||||
if ( field !== undefined && field !== null && (typeof field !== 'object' || Object.keys(field).length ) ) {
|
||||
out[key] = this.getFieldValue(field[key], resourceFields[key].type);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
} else {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getSupportedFields: function(source, tragetField) {
|
||||
const out = {};
|
||||
const resourceFields = this.getResourceFields(tragetField);
|
||||
|
||||
Object.keys(resourceFields).forEach((key) => {
|
||||
if ( BLACK_LIST_FIELD.indexOf(key) > -1 ) {
|
||||
return;
|
||||
}
|
||||
const field = get(source, key);
|
||||
const type = resourceFields[key].type;
|
||||
const value = this.getFieldValue(field, type);
|
||||
out[key] = value;
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
pastedConfig: computed('config', {
|
||||
get() {
|
||||
const intl = get(this, 'intl');
|
||||
let config = this.getSupportedFields(get(this, 'config'), 'rancherKubernetesEngineConfig');
|
||||
if ( !config ) {
|
||||
return '';
|
||||
}
|
||||
config = removeEmpty(config);
|
||||
while ( JSON.stringify(config) !== JSON.stringify(removeEmpty(config)) ){
|
||||
config = removeEmpty(config);
|
||||
}
|
||||
|
||||
if ( !get(this, 'originConfigKeys') ) {
|
||||
const originConfigKeys = [];
|
||||
Object.keys(config).forEach((key) => {
|
||||
originConfigKeys.push(key);
|
||||
});
|
||||
set(this, 'originConfigKeys', originConfigKeys);
|
||||
}
|
||||
|
||||
let yaml = json2yaml.stringify(config);
|
||||
const lines = yaml.split('\n');
|
||||
lines.shift();
|
||||
let out = '';
|
||||
lines.forEach((line) => {
|
||||
if ( line.trim() ) {
|
||||
const key = `rkeConfigComment.${line.split(':')[0].trim()}`
|
||||
if ( intl.exists(key) ) {
|
||||
const commentLines = intl.t(key).split('\n');
|
||||
commentLines.forEach((commentLine) => {
|
||||
out += `# ${commentLine.slice(1, commentLine.length - 1)}\n`;
|
||||
});
|
||||
}
|
||||
out += `${line.slice(2)}\n`;
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
set(key, value) {
|
||||
let configs;
|
||||
try {
|
||||
configs = YAML.parse(value);
|
||||
} catch ( err ) {
|
||||
set(this, 'errors', [`Cluster advanced options parse error: ${err.snippet} - ${err.message}`]);
|
||||
return value;
|
||||
}
|
||||
|
||||
set(this, 'errors', []);
|
||||
|
||||
const validFields = this.getResourceFields('rancherKubernetesEngineConfig');
|
||||
Object.keys(configs || {}).forEach((key) => {
|
||||
if ( validFields[key] ) {
|
||||
set(this, `config.${key}`, configs[key]);
|
||||
}
|
||||
});
|
||||
const originConfigKeys = get(this, 'originConfigKeys');
|
||||
if ( originConfigKeys ) {
|
||||
originConfigKeys.filter((key) => Object.keys(configs || {}).indexOf(key) === -1)
|
||||
.forEach((key) => {
|
||||
set(this, `config.${key}`, null);
|
||||
});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<hr class="mb-15"/>
|
||||
<label class="acc-label mt-5">{{t 'clusterNew.advanced.label'}}</label>
|
||||
<div class="banner bg-info">
|
||||
<div class="banner-icon p-10"><i class="icon icon-info"></i></div>
|
||||
<div class="banner-message">
|
||||
{{t 'clusterNew.advanced.helpText'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-25">
|
||||
{{#if advanced}}
|
||||
{{input-yaml
|
||||
showUpload=false
|
||||
showDownload=false
|
||||
canChangeName=false
|
||||
value=pastedConfig
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
@ -47,10 +47,10 @@
|
|||
<div class="row">
|
||||
<div class="col span-6">
|
||||
<label class="acc-label pb-0">{{key}}</label>
|
||||
<p class="help-block mt-0">{{t (get (get azureDescriptions key) "description")}}</p>
|
||||
<p class="help-block mt-0">{{t (get (get azureDescriptions key) "description")}}</p>
|
||||
</div>
|
||||
<div class="col span-6">
|
||||
{{input class="form-control input-sm value" spellcheck="false" type="text" value=value placeholder=(t 'generic.value')}}
|
||||
{{input class="form-control input-sm value" spellcheck="false" type="text" value=(mut (get configAnswers key)) placeholder=(t 'generic.value')}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each-in}}
|
||||
|
|
|
|||
|
|
@ -345,6 +345,52 @@ export function isBadTld(name) {
|
|||
}
|
||||
}
|
||||
|
||||
export function removeEmpty(obj){
|
||||
return Object.keys(obj)
|
||||
.filter(k => obj[k] !== null && obj[k] !== undefined && (typeof obj[k] !== 'object' || (Object.keys(obj[k]).filter((key) => key !== 'type').length)))
|
||||
.reduce((newObj, k) =>
|
||||
typeof obj[k] === 'object' ?
|
||||
Object.assign(newObj, {[k]: removeEmpty(obj[k])}) :
|
||||
Object.assign(newObj, {[k]: obj[k]}),
|
||||
{});
|
||||
}
|
||||
|
||||
export function camelToUnderline(str) {
|
||||
str = (str || '');
|
||||
if ( str.indexOf('-') > -1 ) {
|
||||
return str;
|
||||
} else {
|
||||
return (str || '').dasherize().split('-').join('_');
|
||||
}
|
||||
}
|
||||
|
||||
export function underlineToCamel(str) {
|
||||
return (str || '').split('_').map((t, i) => {
|
||||
if ( i === 0 ) {
|
||||
return t;
|
||||
} else {
|
||||
return t === 'qps' ? 'QPS' : t.capitalize();
|
||||
}
|
||||
}).join('');
|
||||
}
|
||||
|
||||
export function keysToCamel(obj) {
|
||||
if ( !typeof(obj) === "object" || typeof(obj) === "string" || typeof(obj) === "number" || typeof(obj) === "boolean" ) {
|
||||
return obj;
|
||||
}
|
||||
const keys = Object.keys(obj);
|
||||
let n = keys.length;
|
||||
while (n--) {
|
||||
const key = keys[n];
|
||||
const titleKey = underlineToCamel(key);
|
||||
obj[titleKey] = keysToCamel(obj[key]);
|
||||
if ( key !== titleKey ) {
|
||||
delete obj[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
var Util = {
|
||||
absoluteUrl: absoluteUrl,
|
||||
addAuthorization: addAuthorization,
|
||||
|
|
@ -353,6 +399,7 @@ var Util = {
|
|||
arrayDiff: arrayDiff,
|
||||
arrayIntersect: arrayIntersect,
|
||||
camelToTitle: camelToTitle,
|
||||
camelToUnderline: camelToUnderline,
|
||||
constructUrl: constructUrl,
|
||||
download: download,
|
||||
escapeHtml: escapeHtml,
|
||||
|
|
@ -366,18 +413,21 @@ var Util = {
|
|||
isBadTld: isBadTld,
|
||||
isNumeric: isNumeric,
|
||||
isPrivate: isPrivate,
|
||||
keysToCamel: keysToCamel,
|
||||
lcFirst: lcFirst,
|
||||
parseUrl: parseUrl,
|
||||
pluralize: pluralize,
|
||||
popupWindowOptions: popupWindowOptions,
|
||||
random32: random32,
|
||||
randomStr: randomStr,
|
||||
removeEmpty: removeEmpty,
|
||||
sortableNumericSuffix: sortableNumericSuffix,
|
||||
strPad: strPad,
|
||||
stripScheme: stripScheme,
|
||||
timerFuzz: timerFuzz,
|
||||
ucFirst: ucFirst,
|
||||
uniqKeys: uniqKeys,
|
||||
underlineToCamel: underlineToCamel,
|
||||
validateEndpoint: validateEndpoint,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1837,8 +1837,9 @@ clusterRow:
|
|||
|
||||
clusterNew:
|
||||
advanced:
|
||||
label: Advanced Options
|
||||
helpText: Tabs are not able to be used in the yaml file for parsing.
|
||||
cancel: Edit as a Form
|
||||
yaml: Edit as YAML
|
||||
name:
|
||||
label: Cluster Name
|
||||
placeholder: e.g. sandbox
|
||||
|
|
@ -5827,30 +5828,30 @@ rkeConfigComment:
|
|||
""
|
||||
" network:"
|
||||
" plugin: calico"
|
||||
" calicoNetworkProvider:"
|
||||
" cloudProvider: aws"
|
||||
" calico_network_provider:"
|
||||
" cloud_provider: aws"
|
||||
""
|
||||
" # To specify flannel interface"
|
||||
""
|
||||
" network:"
|
||||
" plugin: flannel"
|
||||
" flannelNetworkProvider:"
|
||||
" flannel_network_provider:"
|
||||
" iface: eth1"
|
||||
""
|
||||
" # To specify flannel interface for canal plugin"
|
||||
""
|
||||
" network:"
|
||||
" plugin: canal"
|
||||
" canalNetworkProvider:"
|
||||
" canal_network_provider:"
|
||||
" iface: eth1"
|
||||
services: |
|
||||
""
|
||||
" services:"
|
||||
" kubeApi:"
|
||||
" serviceClusterIpRange: 10.43.0.0/16"
|
||||
" kubeController:"
|
||||
" clusterCidr: 10.42.0.0/16"
|
||||
" serviceClusterIpRange: 10.43.0.0/16"
|
||||
" kube_api:"
|
||||
" service_cluster_ip_range: 10.43.0.0/16"
|
||||
" kube_controller:"
|
||||
" cluster_cidr: 10.42.0.0/16"
|
||||
" service_cluster_ip_range: 10.43.0.0/16"
|
||||
" kubelet:"
|
||||
" clusterDomain: cluster.local"
|
||||
" clusterDnsServer: 10.43.0.10"
|
||||
" cluster_domain: cluster.local"
|
||||
" cluster_dns_server: 10.43.0.10"
|
||||
|
|
|
|||
|
|
@ -1783,8 +1783,9 @@ clusterWelcome:
|
|||
<p>为容器提供安全的Overlay网络,使容器相互之间可以安全的进行跨主机通信。</p>
|
||||
clusterNew:
|
||||
advanced:
|
||||
label: 高级选项
|
||||
helpText: 不要使用Tabs,Tabs字符在yaml中不能解析
|
||||
cancel: 表单输入
|
||||
yaml: 编辑YAML
|
||||
name:
|
||||
label: 集群名称
|
||||
placeholder: 例如:Sandbox
|
||||
|
|
|
|||
Loading…
Reference in New Issue