Import YAML

This commit is contained in:
Vincent Fiduccia 2018-04-20 19:43:50 -07:00
parent c090c46ccc
commit e711c0f46d
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
24 changed files with 235 additions and 184 deletions

View File

@ -15,18 +15,17 @@ export default Controller.extend({
}, },
}, },
projectsWithNamespaces: computed('rows.@each.{id,state,clusterId}', 'rows.@each.namespaces', function(){ rows: computed('model.namespaces.@each.displayName', 'scope.currentCluster.id', function() {
return get(this, 'rows').filter(p => get(p, 'namespaces.length') > 0); return get(this, 'model.namespaces')
.filterBy('displayName');
}), }),
projectsWithoutNamespaces: computed('rows.@each.{id,state,clusterId}', 'rows.@each.namespaces', function(){ projects: computed('model.projects.@each.clusterId', 'scope.currentCluster.id', function() {
return get(this, 'rows').filter(p => get(p, 'namespaces.length') <= 0);
}),
rows: computed('model.projects.@each.clusterId', function() {
return get(this,'model.projects').filterBy('clusterId', get(this,'scope.currentCluster.id')); return get(this,'model.projects').filterBy('clusterId', get(this,'scope.currentCluster.id'));
}), }),
namespaceRows: computed('model.namespaces.@each.{id,state}', function() {
return get(this, 'model.namespaces').filterBy('displayName'); projectsWithoutNamespaces: computed('projects.@each.{id,state,clusterId}', 'rows.@each.namespaces', function(){
return get(this, 'projects').filter(p => get(p, 'namespaces.length') <= 0);
}), }),
}); });

View File

@ -23,7 +23,7 @@
</section> </section>
{{#if (eq group 'project')}} {{#if (eq group 'project')}}
{{namespace-table model=model.namespaces prns=projectsWithoutNamespaces}} {{namespace-table model=rows prns=projectsWithoutNamespaces}}
{{else}} {{else}}
{{namespace-list model=namespaceRows}} {{namespace-list model=rows}}
{{/if}} {{/if}}

View File

@ -1,5 +1,5 @@
{{#containers-header showGroup=false}} {{#containers-header showGroup=false}}
{{#link-to "new-stack" classNames="btn btn-sm bg-default mr-10" disabled=(or true (rbac-prevents resource="dnsrecord" scope="project" permission="create"))}}{{t 'nav.containers.importCompose'}}{{/link-to}} <button {{action 'importYaml'}} class="btn btn-sm bg-default mr-10" disabled={{rbac-prevents resource="dnsrecord" scope="project" permission="create"}}>{{t 'nav.containers.importCompose'}}</button>
{{#link-to "authenticated.project.dns.new" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="dnsrecord" scope="project" permission="create")}}{{t 'nav.containers.addDns'}}{{/link-to}} {{#link-to "authenticated.project.dns.new" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="dnsrecord" scope="project" permission="create")}}{{t 'nav.containers.addDns'}}{{/link-to}}
{{/containers-header}} {{/containers-header}}

View File

@ -9,6 +9,7 @@ export default Route.extend(Preload,{
access: service(), access: service(),
scope: service(), scope: service(),
globalStore: service(), globalStore: service(),
modalService: service('modal'),
model(params, transition) { model(params, transition) {
const isPopup = this.controllerFor('application').get('isPopup'); const isPopup = this.controllerFor('application').get('isPopup');
@ -59,6 +60,10 @@ export default Route.extend(Preload,{
this.set('controller.group', neu); this.set('controller.group', neu);
}); });
}, },
importYaml() {
get(this,'modalService').toggleModal('modal-import', {mode: 'project', projectId: get(this,'scope.currentProject.id')});
},
}, },
shortcuts: { shortcuts: {

View File

@ -2,7 +2,7 @@
{{cluster-welcome}} {{cluster-welcome}}
{{else}} {{else}}
{{#containers-header}} {{#containers-header}}
{{#link-to "new-stack" classNames="btn btn-sm bg-default mr-10" disabled=(or true (rbac-prevents resource="workload" scope="project" permission="create"))}}{{t 'nav.containers.importCompose'}}{{/link-to}} <button {{action 'importYaml'}} class="btn btn-sm bg-default mr-10" disabled={{rbac-prevents resource="workload" scope="project" permission="create"}}>{{t 'nav.containers.importCompose'}}</button>
{{#link-to "containers.run" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="workload" scope="project" permission="create")}}{{t 'nav.containers.deploy'}}{{/link-to}} {{#link-to "containers.run" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="workload" scope="project" permission="create")}}{{t 'nav.containers.deploy'}}{{/link-to}}
{{/containers-header}} {{/containers-header}}

View File

@ -2,7 +2,7 @@
{{cluster-welcome}} {{cluster-welcome}}
{{else}} {{else}}
{{#containers-header showGroup=false}} {{#containers-header showGroup=false}}
{{#link-to "new-stack" classNames="btn btn-sm bg-default mr-10" disabled=(or true (rbac-prevents resource="ingress" scope="project" permission="create"))}}{{t 'nav.containers.importCompose'}}{{/link-to}} <button {{action 'importYaml'}} class="btn btn-sm bg-default mr-10" disabled={{rbac-prevents resource="ingress" scope="project" permission="create"}}>{{t 'nav.containers.importCompose'}}</button>
{{#link-to "ingresses.run" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="ingress" scope="project" permission="create")}}{{t 'nav.containers.addIngress'}}{{/link-to}} {{#link-to "ingresses.run" scope.currentProject.id class="btn btn-sm bg-primary" disabled=(rbac-prevents resource="ingress" scope="project" permission="create")}}{{t 'nav.containers.addIngress'}}{{/link-to}}
{{/containers-header}} {{/containers-header}}

View File

@ -34,8 +34,7 @@ var Principal = Resource.extend({
}), }),
logicalType: computed('parsedExternalType', function() { logicalType: computed('parsedExternalType', function() {
switch ( get(this, 'parsedExternalType') ) switch ( get(this, 'parsedExternalType') ) {
{
case C.PROJECT.TYPE_RANCHER: case C.PROJECT.TYPE_RANCHER:
case C.PROJECT.TYPE_AZURE_USER: case C.PROJECT.TYPE_AZURE_USER:
case C.PROJECT.TYPE_GITHUB_USER: case C.PROJECT.TYPE_GITHUB_USER:
@ -43,10 +42,10 @@ var Principal = Resource.extend({
case C.PROJECT.TYPE_OPENLDAP_USER: case C.PROJECT.TYPE_OPENLDAP_USER:
case C.PROJECT.TYPE_SHIBBOLETH_USER: case C.PROJECT.TYPE_SHIBBOLETH_USER:
case C.PROJECT.TYPE_ACTIVE_DIRECTORY_USER: case C.PROJECT.TYPE_ACTIVE_DIRECTORY_USER:
return C.PROJECT.PERSON; return C.PROJECT.PERSON;
case C.PROJECT.TYPE_GITHUB_TEAM: case C.PROJECT.TYPE_GITHUB_TEAM:
return C.PROJECT.TEAM; return C.PROJECT.TEAM;
case C.PROJECT.TYPE_GITHUB_ORG: case C.PROJECT.TYPE_GITHUB_ORG:
case C.PROJECT.TYPE_AZURE_GROUP: case C.PROJECT.TYPE_AZURE_GROUP:
@ -54,13 +53,12 @@ var Principal = Resource.extend({
case C.PROJECT.TYPE_OPENLDAP_GROUP: case C.PROJECT.TYPE_OPENLDAP_GROUP:
case C.PROJECT.TYPE_SHIBBOLETH_GROUP: case C.PROJECT.TYPE_SHIBBOLETH_GROUP:
case C.PROJECT.TYPE_ACTIVE_DIRECTORY_GROUP: case C.PROJECT.TYPE_ACTIVE_DIRECTORY_GROUP:
return C.PROJECT.ORG; return C.PROJECT.ORG;
} }
}), }),
logicalTypeSort: computed('logicalType', function() { logicalTypeSort: computed('logicalType', function() {
switch (get(this, 'logicalType') ) switch (get(this, 'logicalType') ) {
{
case C.PROJECT.ORG: return 1; case C.PROJECT.ORG: return 1;
case C.PROJECT.TEAM: return 2; case C.PROJECT.TEAM: return 2;
case C.PROJECT.PERSON: return 3; case C.PROJECT.PERSON: return 3;
@ -71,32 +69,36 @@ var Principal = Resource.extend({
displayType: computed('parsedExternalType','intl.locale', function() { displayType: computed('parsedExternalType','intl.locale', function() {
let key = 'model.identity.displayType.unknown'; let key = 'model.identity.displayType.unknown';
let type = get(this, 'parsedExternalType'); let type = get(this, 'parsedExternalType');
switch ( type )
{ switch ( type ) {
case C.PROJECT.TYPE_GITHUB_USER: case C.PROJECT.TYPE_GITHUB_USER:
case C.PROJECT.TYPE_AZURE_USER: case C.PROJECT.TYPE_AZURE_USER:
case C.PROJECT.TYPE_LDAP_USER: case C.PROJECT.TYPE_LDAP_USER:
case C.PROJECT.TYPE_OPENLDAP_USER: case C.PROJECT.TYPE_OPENLDAP_USER:
case C.PROJECT.TYPE_SHIBBOLETH_USER: case C.PROJECT.TYPE_SHIBBOLETH_USER:
case C.PROJECT.TYPE_ACTIVE_DIRECTORY_USER: case C.PROJECT.TYPE_ACTIVE_DIRECTORY_USER:
key = 'model.identity.displayType.user'; key = 'model.identity.displayType.user';
break; break;
case C.PROJECT.TYPE_AZURE_GROUP: case C.PROJECT.TYPE_AZURE_GROUP:
case C.PROJECT.TYPE_LDAP_GROUP: case C.PROJECT.TYPE_LDAP_GROUP:
case C.PROJECT.TYPE_OPENLDAP_GROUP: case C.PROJECT.TYPE_OPENLDAP_GROUP:
case C.PROJECT.TYPE_SHIBBOLETH_GROUP: case C.PROJECT.TYPE_SHIBBOLETH_GROUP:
case C.PROJECT.TYPE_ACTIVE_DIRECTORY_GROUP: case C.PROJECT.TYPE_ACTIVE_DIRECTORY_GROUP:
key = 'model.identity.displayType.group'; key = 'model.identity.displayType.group';
break; break;
case C.PROJECT.TYPE_GITHUB_TEAM: case C.PROJECT.TYPE_GITHUB_TEAM:
key = 'model.identity.displayType.team'; key = 'model.identity.displayType.team';
break; break;
case C.PROJECT.TYPE_GITHUB_ORG: case C.PROJECT.TYPE_GITHUB_ORG:
key = 'model.identity.displayType.org'; key = 'model.identity.displayType.org';
break; break;
case C.PROJECT.TYPE_RANCHER: case C.PROJECT.TYPE_RANCHER:
key = 'model.identity.displayType.localUser'; key = 'model.identity.displayType.localUser';
break; break;
} }
return get(this, 'intl').t(key, {type: type}); return get(this, 'intl').t(key, {type: type});

View File

@ -1,47 +0,0 @@
import Controller from '@ember/controller';
import NewOrEdit from 'ui/mixins/new-or-edit';
export default Controller.extend(NewOrEdit, {
error: null,
editing: false,
compose: null,
files: null,
answers: null,
allStacks: null,
init() {
this._super(...arguments);
this.set('allStacks', this.get('store').all('stack'));
},
actions: {
addTag(tag) {
let neu = this.get('model.tags')||[];
neu.addObject(tag);
this.set('model.tags', neu);
},
answersChanged(answers) {
this.set('primaryResource.answers', answers);
},
},
willSave() {
let outFiles = {};
let userFiles = this.get('files')||[];
Object.keys(userFiles).forEach((key) => {
let val = userFiles[key];
if ( key && val ) {
outFiles[key] = val;
}
});
this.set('primaryResource.templates', outFiles);
return this._super(...arguments);
},
doneSaving: function() {
return this.transitionToRoute('stack', this.get('primaryResource.id'));
},
});

View File

@ -1,25 +0,0 @@
import Route from '@ember/routing/route';
export default Route.extend({
model() {
var stack = this.get('store').createRecord({
type: 'stack',
templates: {
'compose.yml': ''
},
});
return stack;
},
setupController(controller, model) {
controller.set('originalModel',null);
controller.set('model', model);
},
actions: {
cancel() {
this.goToPrevious();
},
}
});

View File

@ -1,39 +0,0 @@
<section class="header clearfix">
<h1>{{t 'newStack.header'}}</h1>
</section>
<section>
{{form-name-description
model=primaryResource
namePlaceholder="newStack.name.placeholder"
descriptionPlaceholder="newStack.description.placeholder"
}}
{{input-files
accept=".yml, .yaml"
initialFiles=primaryResource.templates
changed=(action (mut files))
header='newStack.files.label'
addActionLabel='newStack.files.addActionLabel'
uploadActionLabel='newStack.files.uploadActionLabel'
namePlaceholder='newStack.files.namePlaceholder'
valuePlaceholder='newStack.files.valuePlaceholder'
protipLabel='newStack.files.protipLabel'
}}
{{#advanced-section}}
<hr class="mt-20 mb-20"/>
<div class="box mt-20">
{{form-key-value
header=(t 'newStack.answers.label')
changed=(action "answersChanged")
allowMultilineValue=true
addActionLabel="newStack.answers.addActionLabel"
}}
</div>
{{/advanced-section}}
</section>
{{top-errors errors=errors}}
{{save-cancel save="save" cancel="cancel"}}

View File

@ -144,7 +144,6 @@ Router.map(function() {
}); });
this.route('workload', {path: '/workload/:workload_id', resetNamespace: true}); this.route('workload', {path: '/workload/:workload_id', resetNamespace: true});
this.route('new-stack', {path: '/import-yaml', resetNamespace: true});
// Catalog // Catalog

View File

@ -51,3 +51,7 @@ pre {
color: white; color: white;
} }
} }
.CodeMirror-scroll {
overflow: auto !important;
}

View File

@ -317,8 +317,3 @@
.text-line-through{ .text-line-through{
text-decoration: line-through !important; text-decoration: line-through !important;
} }
.CodeMirror{
height: auto;
min-height: 300px;
}

View File

@ -1,5 +1,5 @@
{{#containers-header showGroup=false}} {{#containers-header showGroup=false}}
{{#link-to "new-stack" classNames="btn btn-sm bg-default mr-10" disabled=(or true (rbac-prevents resource="ingress" scope="project" permission="create"))}}{{t 'nav.containers.importCompose'}}{{/link-to}} <button {{action 'importYaml'}} class="btn btn-sm bg-default mr-10" disabled={{rbac-prevents resource="persistenvolumeclaim" scope="project" permission="create"}}>{{t 'nav.containers.importCompose'}}</button>
{{#link-to "volumes.new" class="btn btn-sm bg-primary"}}{{t 'nav.containers.addVolume'}}{{/link-to}} {{#link-to "volumes.new" class="btn btn-sm bg-primary"}}{{t 'nav.containers.addVolume'}}{{/link-to}}
{{/containers-header}} {{/containers-header}}

View File

@ -161,7 +161,7 @@ export default Component.extend(ViewNewEdit, ChildHook, {
didSave() { didSave() {
const originalCluster = get(this, 'cluster'); const originalCluster = get(this, 'cluster');
return originalCluster.waitForCondition('BackingNamespaceCreated').then(() => { return originalCluster.waitForCondition('InitialRolesPopulated').then(() => {
return this.applyHooks().then(() => { return this.applyHooks().then(() => {
const clone = originalCluster.clone(); const clone = originalCluster.clone();
set(this, 'cluster', clone); set(this, 'cluster', clone);

View File

@ -14,6 +14,9 @@ export default Component.extend({
intl: service(), intl: service(),
scope: service(), scope: service(),
createLabel: 'formNamespace.label.create',
reuseLabel: 'formNamespace.label.reuse',
// Outputs // Outputs
namespace: null, namespace: null,
errors: null, errors: null,
@ -25,6 +28,7 @@ export default Component.extend({
editing: true, editing: true,
required: true, required: true,
isReuse: equal('mode', REUSE), isReuse: equal('mode', REUSE),
hookName: 'saveNamespace',
classNames: ['inline-form'], classNames: ['inline-form'],
choices: alias('scope.currentProject.namespaces'), choices: alias('scope.currentProject.namespaces'),
@ -64,7 +68,7 @@ export default Component.extend({
}); });
} }
this.sendAction('registerHook', this.saveNamespace.bind(this), {name: 'saveNamespace', key: '_beforeSaveHooks'}); this.sendAction('registerHook', this.saveNamespace.bind(this), {name: get(this,'hookName'), key: '_beforeSaveHooks'});
}, },
actions: { actions: {

View File

@ -1,11 +1,7 @@
{{#if editing}} {{#if editing}}
<div class="clearfix"> <div class="clearfix">
<label class="acc-label pb-5"> <label class="acc-label pb-5">
{{#if isReuse}} {{t (if isReuse reuseLabel createLabel)}}
{{t 'formNamespace.label.reuse'}}
{{else}}
{{t 'formNamespace.label.create'}}
{{/if}}
{{field-required}} {{field-required}}
</label> </label>
<div class="pull-right text-small"> <div class="pull-right text-small">

View File

@ -19,13 +19,17 @@ export default Component.extend(ThrottledResize, {
accept: "text/*, .yml, .yaml", accept: "text/*, .yml, .yaml",
multiple: false, multiple: false,
viewportMargin: Infinity, viewportMargin: Infinity,
maxHeight: 200, autoResize: false,
resizeFooter: 130,
minHeight: 50,
inputName: false, inputName: false,
canChangeName: true, canChangeName: true,
canUpload: true, canUpload: true,
showUploadLabel: true, showUploadLabel: true,
gutters: ["CodeMirror-lint-markers"], gutters: ["CodeMirror-lint-markers"],
tagName: ['div'], tagName: ['div'],
showUpload: true,
showDownload: true,
_boundChange: null, _boundChange: null,
shouldChangeName: true, shouldChangeName: true,
@ -52,11 +56,13 @@ export default Component.extend(ThrottledResize, {
}, },
onResize() { onResize() {
this.fit(); if ( get(this,'autoResize') ) {
this.fit();
}
}, },
fit() { fit() {
if ( get(this, 'maxHeight') === 'auto' ) { if ( get(this, 'autoResize') ) {
var container = this.$('.codemirror-container'); var container = this.$('.codemirror-container');
if ( !container ) { if ( !container ) {
return; return;
@ -67,8 +73,8 @@ export default Component.extend(ThrottledResize, {
return; return;
} }
const desired = $(window).height() - position.top - 130; const desired = $(window).height() - position.top - get(this,'resizeFooter');
container.css('max-height', Math.max(400, desired)); container.css('max-height', Math.max(get(this,'minHeight'), desired));
} }
}, },

View File

@ -1,14 +1,18 @@
{{#if title}} {{#if title}}
<section class="header clearfix"> <section class="header clearfix">
<div class="right-buttons"> <div class="right-buttons">
<button class="btn bg-link icon-btn" {{action "click"}}> {{#if showUpload}}
<span class="darken"><i class="icon icon-upload text-small"/></span> <button class="btn bg-link icon-btn" {{action "click"}}>
<span>{{t 'inputTextFile.tooltip'}}</span> <span class="darken"><i class="icon icon-upload text-small"/></span>
</button> <span>{{t 'inputTextFile.tooltip'}}</span>
<button class="btn bg-link icon-btn p-0" {{action "download"}}> </button>
<span class="darken"><i class="icon icon-download text-small"/></span> {{/if}}
<span>{{t 'generic.download'}}</span> {{#if showDownload}}
</button> <button class="btn bg-link icon-btn p-0" {{action "download"}}>
<span class="darken"><i class="icon icon-download text-small"/></span>
<span>{{t 'generic.download'}}</span>
</button>
{{/if}}
</div> </div>
<h1>{{title}}</h1> <h1>{{title}}</h1>
</section> </section>

View File

@ -0,0 +1,95 @@
import Component from '@ember/component';
import { get, set, observer } from '@ember/object';
import { inject as service } from '@ember/service';
import CodeMirror from 'codemirror';
import jsyaml from 'npm:js-yaml';
import ModalBase from 'shared/mixins/modal-base';
import layout from './template';
import ChildHook from 'shared/mixins/child-hook';
export default Component.extend(ModalBase, ChildHook, {
layout,
intl: service(),
growl: service(),
scope: service(),
store: service('store'),
mode: 'project',
namespace: null,
yaml: '',
errors: null,
compose: null,
classNames: ['modal-container', 'large-modal', 'fullscreen-modal', 'modal-shell', 'alert'],
init() {
this._super(...arguments);
window.jsyaml||(window.jsyaml=jsyaml);
},
actions: {
cancel() {
return this._super(...arguments);
},
close() {
return this._super(...arguments);
},
save(cb) {
let yaml = get(this,'yaml');
let lintError = CodeMirror.lint.yaml(yaml);
if( lintError.length ) {
set(this,'errors', [get(this,'intl').t('yamlPage.errors')]);
cb(false);
return;
}
set(this,'errors', null);
const opts = {
yaml: get(this, 'yaml'),
};
switch ( get(this, 'mode') ) {
case 'namespace':
opts.namespace = get(this, 'namespace.name');
break;
case 'project':
opts.project = get(this, 'projectId');
opts.defaultNamespace = get(this, 'namespace.name');
break;
case 'cluster':
break;
}
if ( get(this, 'mode') === 'cluster' ) {
this.send('actuallySave', opts, cb);
} else {
return this.applyHooks('_beforeSaveHooks').then(() => {
this.send('actuallySave', opts, cb);
});
}
},
actuallySave(opts, cb) {
return get(this, 'scope.currentCluster').doAction('importYaml', opts).then(() => {
cb();
this.send('cancel');
}).catch(() => {
cb(false);
});
}
},
lintObserver: observer('yaml', function() {
const yaml = get(this,'yaml');
const lintError = CodeMirror.lint.yaml(yaml);
if ( lintError.length ) {
set(this,'errors', null);
}
}),
});

View File

@ -0,0 +1,38 @@
{{input-yaml
title=(t 'modalImport.title')
name="import.yaml"
canChangeName=false
value=yaml
autoResize=true
resizeFooter=250
showDownload=false
}}
<div class="mt-20 row">
<div class="col span-6">
<label class="acc-label">{{t 'modalImport.mode.label'}}</label>
<div>
<label>{{radio-button selection=mode value="cluster"}} {{t 'modalImport.mode.cluster'}}</label>
</div>
<div>
<label>{{radio-button selection=mode value="project"}} {{t 'modalImport.mode.project'}}</label>
</div>
<div>
<label>{{radio-button selection=mode value="namespace"}} {{t 'modalImport.mode.namespace'}}</label>
</div>
</div>
<div class="col span-6">
{{#unless (eq mode 'cluster')}}
{{form-namespace
reuseLabel=(if (eq mode 'project') 'formNamespace.label.default' 'formNamespace.label.reuse')
namespace=namespace
errors=namespaceErrors
registerHook=(action "registerHook")
}}
{{/unless}}
</div>
</div>
{{top-errors errors=errors}}
{{save-cancel save="save" cancel="cancel" editing=editing createLabel='generic.import'}}

View File

@ -33,6 +33,7 @@ export default Component.extend(NodeDriver, {
diskSize: 20000, diskSize: 20000,
vcenterPort: 443, vcenterPort: 443,
network: [], network: [],
boot2dockerUrl: 'https://github.com/boot2docker/boot2docker/releases/download/v17.03.2-ce/boot2docker.iso'
}); });
set(this, `model.${CONFIG}`, config); set(this, `model.${CONFIG}`, config);

View File

@ -0,0 +1 @@
export { default } from 'shared/components/modal-import/component';

View File

@ -46,6 +46,7 @@ generic:
help: Help help: Help
id: ID id: ID
image: Image image: Image
import: Import
internal: Internal internal: Internal
ipAddress: IP Address ipAddress: IP Address
key: Key key: Key
@ -3592,6 +3593,7 @@ formNamespace:
label: label:
reuse: Namespace reuse: Namespace
create: Namespace create: Namespace
default: Default Namespace
toggle: toggle:
simple: Customize simple: Customize
reuse: Use an existing namespace reuse: Use an existing namespace
@ -4151,6 +4153,17 @@ modalHostEvacuate:
protip: "ProTip: Hold the {key} key while clicking stop to bypass this confirmation." protip: "ProTip: Hold the {key} key while clicking stop to bypass this confirmation."
button: Evacuate button: Evacuate
modalImport:
title: Import YAML
mode:
label: Import Mode
cluster: "Cluster: Direct import of any resources into this cluster"
project: "Project: Import resources into this project"
namespace: "Namespace: Import resources into a specific namespace"
defaultNamespace:
label: Default namespace for resources that don't specify one
modalProcessError: modalProcessError:
header: Exception Info header: Exception Info
cause: "Cause:" cause: "Cause:"
@ -4552,7 +4565,7 @@ nodeDriver:
access: access:
title: 1. Account Access title: 1. Account Access
detail: Configure where to find the VCenter or ESXi server detail: Configure where to find the VCenter or ESXi server
help: "Note: The free ESXi liecense does not support API access. Only paid license servers are supported." help: "Note: The free ESXi liecense does not support API access. Only servers with a valid or evaluation license are supported."
instance: instance:
title: 2. Instance Options title: 2. Instance Options
detail: Choose the size and OS of the virtual machine detail: Choose the size and OS of the virtual machine
@ -4560,10 +4573,10 @@ nodeDriver:
title: 3. Scheduling title: 3. Scheduling
detail: Choose what hypervisor the virtual machine will be scheduled to detail: Choose what hypervisor the virtual machine will be scheduled to
vcenter: vcenter:
label: vCenter Host label: vCenter or ESXi Server
placeholder: vCenter or ESXi hostname/IP placeholder: vCenter or ESXi hostname/IP
vcenterPort: vcenterPort:
label: vCenter Port label: Port
username: username:
label: Username label: Username
password: password:
@ -4585,24 +4598,24 @@ nodeDriver:
schedulingSection: Scheduling schedulingSection: Scheduling
dataCenter: dataCenter:
label: Data Center label: Data Center
placeholder: "datacenter_name" placeholder: "e.g. datacenter_name"
help: "Datacenter for Docker VM (must be set to ha-datacenter when connecting to a single host)." help: "Data Center to create VM in (leave blank for standalone ESXi)"
pool: pool:
label: Pool label: Pool
placeholder: "/dc_name/host/host_name/Resources/pool_name" placeholder: "e.g. /dc_name/host/host_name/Resources/pool_name"
help: "Resource pool for Docker VM." help: "Resource Pool to create VM in (leave blank for standalone ESXi)"
host: host:
label: Host label: Host
placeholder: "cluster_name/host_name" placeholder: "e.g. cluster_name/host_name"
help: "vSphere compute resource where the docker VM is instantiated. This can be omitted if using a cluster with DRS." help: "Specific host to create VM on (leave blank for standalon ESXi or for cluster with DRS)"
network: network:
label: Network label: Network
placeholder: "VM Traffic" placeholder: "e.g. VM Network"
help: "Network where the Docker VM is attached." help: "Network to attach VM to"
dataStore: dataStore:
label: Data Store label: Data Store
placeholder: "datastore_cluster_name/datastore_name" placeholder: "e.g. datastore_cluster_name/datastore_name"
help: "Datastore for Docker VM." help: "Datastore to create VM disk on"
azure: azure:
placement: placement:
title: Placement title: Placement