mirror of https://github.com/rancher/ui.git
Merge pull request #2640 from westlywright/cloud-keys
cloud credentials
This commit is contained in:
commit
542b348f75
|
|
@ -1,12 +1,20 @@
|
||||||
|
import { get } from '@ember/object';
|
||||||
|
|
||||||
export function initialize(application) {
|
export function initialize(application) {
|
||||||
// Monkey patch AWS SDK to go through our proxy
|
// Monkey patch AWS SDK to go through our proxy
|
||||||
var orig = AWS.XHRClient.prototype.handleRequest;
|
var orig = AWS.XHRClient.prototype.handleRequest;
|
||||||
|
|
||||||
AWS.XHRClient.prototype.handleRequest = function handleRequest(httpRequest, httpOptions, callback, errCallback) {
|
AWS.XHRClient.prototype.handleRequest = function handleRequest(httpRequest, httpOptions, callback, errCallback) {
|
||||||
|
httpRequest.headers['X-Api-Headers-Restrict'] = 'Content-Length';
|
||||||
|
|
||||||
|
if (get(httpOptions, 'cloudCredentialId')) {
|
||||||
|
httpRequest.headers['X-Api-CattleAuth-Header'] = `awsv4 credID=${ get(httpOptions, 'cloudCredentialId') }`;
|
||||||
|
} else {
|
||||||
httpRequest.endpoint.protocol = 'http:';
|
httpRequest.endpoint.protocol = 'http:';
|
||||||
httpRequest.endpoint.port = 80;
|
httpRequest.endpoint.port = 80;
|
||||||
httpRequest.headers['X-Api-Headers-Restrict'] = 'Content-Length';
|
|
||||||
httpRequest.headers['X-Api-Auth-Header'] = httpRequest.headers['Authorization'];
|
httpRequest.headers['X-Api-Auth-Header'] = httpRequest.headers['Authorization'];
|
||||||
|
}
|
||||||
|
|
||||||
delete httpRequest.headers['Authorization'];
|
delete httpRequest.headers['Authorization'];
|
||||||
httpRequest.headers['Content-Type'] = `rancher:${ httpRequest.headers['Content-Type'] }`;
|
httpRequest.headers['Content-Type'] = `rancher:${ httpRequest.headers['Content-Type'] }`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,7 @@ const rootNav = [
|
||||||
{
|
{
|
||||||
id: 'global-security-roles',
|
id: 'global-security-roles',
|
||||||
localizedLabel: 'nav.admin.security.roles',
|
localizedLabel: 'nav.admin.security.roles',
|
||||||
icon: 'icon icon-key',
|
icon: 'icon icon-users',
|
||||||
route: 'global-admin.security.roles',
|
route: 'global-admin.security.roles',
|
||||||
resource: ['roletemplate'],
|
resource: ['roletemplate'],
|
||||||
resourceScope: 'global',
|
resourceScope: 'global',
|
||||||
|
|
@ -366,6 +366,14 @@ const rootNav = [
|
||||||
resource: ['podsecuritypolicytemplate'],
|
resource: ['podsecuritypolicytemplate'],
|
||||||
resourceScope: 'global',
|
resourceScope: 'global',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'global-security-cloud-keys',
|
||||||
|
localizedLabel: 'nav.admin.security.cloudKeys',
|
||||||
|
icon: 'icon icon-secrets',
|
||||||
|
route: 'global-admin.security.cloud-keys',
|
||||||
|
resource: ['cloudcredential'],
|
||||||
|
resourceScope: 'global',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'global-security-authentication',
|
id: 'global-security-authentication',
|
||||||
localizedLabel: 'nav.admin.security.authentication',
|
localizedLabel: 'nav.admin.security.authentication',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import Resource from '@rancher/ember-api-store/models/resource';
|
||||||
|
import { computed } from '@ember/object';
|
||||||
|
import { notEmpty } from '@ember/object/computed';
|
||||||
|
|
||||||
|
const cloudCredential = Resource.extend({
|
||||||
|
type: 'cloudCredential',
|
||||||
|
|
||||||
|
canClone: false,
|
||||||
|
canEdit: false,
|
||||||
|
|
||||||
|
isAmazon: notEmpty('amazonec2credentialConfig'),
|
||||||
|
isAzure: notEmpty('azurecredentialConfig'),
|
||||||
|
isDo: notEmpty('digitaloceancredentialConfig'),
|
||||||
|
isVMware: notEmpty('vmwarevspherecredentialConfig'),
|
||||||
|
|
||||||
|
displayType: computed('amazonec2credentialConfig', 'azurecredentialConfig', 'digitaloceancredentialConfig', 'vmwarevspherecredentialConfig', function() {
|
||||||
|
const {
|
||||||
|
isAmazon,
|
||||||
|
isAzure,
|
||||||
|
isDo,
|
||||||
|
isVMware
|
||||||
|
} = this;
|
||||||
|
|
||||||
|
if (isAmazon) {
|
||||||
|
return 'Amazon';
|
||||||
|
} else if (isAzure) {
|
||||||
|
return 'Azure';
|
||||||
|
} else if (isDo) {
|
||||||
|
return 'Digital Ocean';
|
||||||
|
} else if (isVMware) {
|
||||||
|
return 'VMware vSphere';
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default cloudCredential;
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import NewOrEdit from 'shared/mixins/new-or-edit';
|
||||||
|
import layout from './template';
|
||||||
|
import { get, set, computed } from '@ember/object';
|
||||||
|
import { next } from '@ember/runloop';
|
||||||
|
|
||||||
|
const CRED_CONFIG_CHOICES = [
|
||||||
|
{
|
||||||
|
name: 'amazon',
|
||||||
|
displayName: 'Amazon',
|
||||||
|
driver: 'amazonec2',
|
||||||
|
configField: 'amazonec2credentialConfig',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'azure',
|
||||||
|
displayName: 'Azure',
|
||||||
|
driver: 'azure',
|
||||||
|
configField: 'azurecredentialConfig',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'digitalOcean',
|
||||||
|
displayName: 'Digital Ocean',
|
||||||
|
driver: 'digitalocean',
|
||||||
|
configField: 'digitaloceancredentialConfig',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vmware',
|
||||||
|
displayName: 'VMware vSphere',
|
||||||
|
driver: 'vmwarevsphere',
|
||||||
|
configField: 'vmwarevspherecredentialConfig',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default Component.extend(NewOrEdit, {
|
||||||
|
globalStore: service(),
|
||||||
|
layout,
|
||||||
|
nodeConfigTemplateType: null,
|
||||||
|
cloudKeyType: null,
|
||||||
|
model: null,
|
||||||
|
cancelAdd: null,
|
||||||
|
doneSavingCloudCredential: null,
|
||||||
|
disableHeader: false,
|
||||||
|
|
||||||
|
didReceiveAttrs() {
|
||||||
|
set(this, 'model', this.globalStore.createRecord({ type: 'cloudCredential' }));
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
selectConfig(configType) {
|
||||||
|
this.cleanupPreviousConfig();
|
||||||
|
|
||||||
|
set(this, 'cloudKeyType', configType);
|
||||||
|
|
||||||
|
this.initCloudCredentialConfig();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
config: computed('cloudKeyType', {
|
||||||
|
get() {
|
||||||
|
const { model } = this;
|
||||||
|
const type = this.getConfigField();
|
||||||
|
|
||||||
|
return get(model, type);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
configChoices: computed('driverName', function() {
|
||||||
|
if (get(this, 'driverName')) {
|
||||||
|
const { driverName } = this;
|
||||||
|
|
||||||
|
let match = CRED_CONFIG_CHOICES.findBy('driver', driverName);
|
||||||
|
|
||||||
|
|
||||||
|
next(() => {
|
||||||
|
set(this, 'cloudKeyType', get(match, 'name'));
|
||||||
|
this.initCloudCredentialConfig();
|
||||||
|
})
|
||||||
|
|
||||||
|
return [match];
|
||||||
|
} else {
|
||||||
|
return CRED_CONFIG_CHOICES.sortBy('displayName');
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
saveDisabled: computed('config.{amazonec2credentialConfig,azurecredentialConfig,digitaloceancredentialConfig,vmwarevspherecredentialConfig}', 'cloudKeyType', function() {
|
||||||
|
if (this.getConfigField()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}),
|
||||||
|
|
||||||
|
initCloudCredentialConfig() {
|
||||||
|
const { model } = this;
|
||||||
|
const type = this.getConfigField();
|
||||||
|
|
||||||
|
set(model, type, this.globalStore.createRecord({ type: type.toLowerCase() }));
|
||||||
|
},
|
||||||
|
|
||||||
|
doneSaving(neu) {
|
||||||
|
this.doneSavingCloudCredential(neu);
|
||||||
|
},
|
||||||
|
|
||||||
|
cleanupPreviousConfig() {
|
||||||
|
const { model } = this;
|
||||||
|
const configField = this.getConfigField();
|
||||||
|
|
||||||
|
if (configField) {
|
||||||
|
delete model[configField];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getConfigField() {
|
||||||
|
const { cloudKeyType, configChoices } = this;
|
||||||
|
|
||||||
|
if (cloudKeyType) {
|
||||||
|
const matchType = configChoices.findBy('name', cloudKeyType);
|
||||||
|
|
||||||
|
return get(matchType, 'configField');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
|
||||||
|
parseNodeTemplateConfigType(nodeTemplate) {
|
||||||
|
return Object.keys(nodeTemplate).find((f) => f.toLowerCase().indexOf('config') > -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
<section class="horizontal-form container-fluid">
|
||||||
|
{{#unless disableHeader}}
|
||||||
|
<h2>
|
||||||
|
{{t "modalAddCloudKey.header"}}
|
||||||
|
</h2>
|
||||||
|
{{/unless}}
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
{{form-name-description
|
||||||
|
model=primaryResource
|
||||||
|
namePlaceholder="newSecret.name.placeholder"
|
||||||
|
descriptionPlaceholder="newSecret.description.placeholder"
|
||||||
|
}}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "modalAddCloudKey.type"}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="form-control"
|
||||||
|
onchange={{action "selectConfig" value="target.value"}}
|
||||||
|
>
|
||||||
|
{{#if (not-eq cloudKeyType value)}}
|
||||||
|
<option value="" selected=true >
|
||||||
|
{{t "modalAddCloudKey.typeSelect.prompt"}}
|
||||||
|
</option>
|
||||||
|
{{/if}}
|
||||||
|
{{#each configChoices as |choice|}}
|
||||||
|
<option
|
||||||
|
value="{{choice.name}}"
|
||||||
|
selected={{eq choice.name cloudKeyType}}
|
||||||
|
>
|
||||||
|
{{choice.displayName}}
|
||||||
|
</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if (eq cloudKeyType "amazon")}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="amazonec2-accessKey">
|
||||||
|
{{t "modalAddCloudKey.amazonec2.accessKey.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
name="username"
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "modalAddCloudKey.amazonec2.accessKey.placeholder")
|
||||||
|
value=config.accessKey
|
||||||
|
id="amazonec2-accessKey"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="amazonec2-secretKey">
|
||||||
|
{{t "modalAddCloudKey.amazonec2.secretKey.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "modalAddCloudKey.amazonec2.secretKey.placeholder")
|
||||||
|
value=config.secretKey
|
||||||
|
id="amazonec2-secretKey"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if (eq cloudKeyType "azure")}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.azure.subscriptionId.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.subscriptionId
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.subscriptionId.placeholder")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="azure-clientId">
|
||||||
|
{{t "modalAddCloudKey.azure.clientId.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.clientId
|
||||||
|
classNames="form-control"
|
||||||
|
id="azure-clientId"
|
||||||
|
placeholder=(t "modalAddCloudKey.azure.clientId.placeholder")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="azure-clientSecret">
|
||||||
|
{{t "modalAddCloudKey.azure.clientSecret.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="password"
|
||||||
|
value=config.clientSecret
|
||||||
|
classNames="form-control"
|
||||||
|
id="azure-clientSecret"
|
||||||
|
placeholder=(t "modalAddCloudKey.azure.clientSecret.placeholder")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if (eq cloudKeyType "digitalOcean")}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="digitalocean-accessToken">
|
||||||
|
{{t "modalAddCloudKey.digitalocean.accessToken.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="password"
|
||||||
|
value=config.accessToken
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "modalAddCloudKey.digitalocean.accessToken.placeholder")
|
||||||
|
id="digitalocean-accessToken"
|
||||||
|
}}
|
||||||
|
<p class="text-info">
|
||||||
|
{{t "modalAddCloudKey.digitalocean.accessToken.help" htmlSafe=true}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if (eq cloudKeyType "vmware")}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.vmwarevsphere.vcenter.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
value=config.vcenter
|
||||||
|
placeholder=(t "nodeDriver.vmwarevsphere.vcenter.placeholder")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.vmwarevsphere.vcenterPort.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input-integer
|
||||||
|
min=1
|
||||||
|
max=65535
|
||||||
|
class="form-control"
|
||||||
|
value=config.vcenterPort
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.vmwarevsphere.username.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.username
|
||||||
|
classNames="form-control"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.vmwarevsphere.password.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="password"
|
||||||
|
value=config.password
|
||||||
|
classNames="form-control"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">{{t "nodeDriver.vmwarevsphere.access.help"}}</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="footer-actions">
|
||||||
|
{{save-cancel
|
||||||
|
saveDisabled=saveDisabled
|
||||||
|
save="save"
|
||||||
|
cancel=cancelAdd
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import ModalBase from 'shared/mixins/modal-base';
|
||||||
|
import layout from './template';
|
||||||
|
|
||||||
|
export default Component.extend(ModalBase, {
|
||||||
|
layout,
|
||||||
|
classNames: ['large-modal', 'alert'],
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{cru-cloud-credential
|
||||||
|
doneSavingCloudCredential=(action "close")
|
||||||
|
cancelAdd=(action "cancel")
|
||||||
|
}}
|
||||||
|
|
@ -69,5 +69,9 @@ export default buildRoutes(function() {
|
||||||
this.route('okta');
|
this.route('okta');
|
||||||
this.route('freeipa');
|
this.route('freeipa');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route('cloud-keys', function() {
|
||||||
|
this.route('index', { path: '/' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import Controller from '@ember/controller';
|
||||||
|
import { computed, get } from '@ember/object';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import layout from './template';
|
||||||
|
|
||||||
|
const HEADERS = [
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
sort: ['displayType'],
|
||||||
|
searchField: 'displayType',
|
||||||
|
translationKey: 'generic.type',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
sort: ['displayName'],
|
||||||
|
searchField: 'displayName',
|
||||||
|
translationKey: 'generic.name',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
classNames: 'text-right pr-20',
|
||||||
|
name: 'created',
|
||||||
|
sort: ['created'],
|
||||||
|
translationKey: 'generic.created',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
modal: service(),
|
||||||
|
|
||||||
|
layout,
|
||||||
|
sortBy: 'created',
|
||||||
|
searchText: '',
|
||||||
|
headers: HEADERS,
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
addCloudKey() {
|
||||||
|
this.modal.toggleModal('modal-add-cloud-key');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
filteredContent: computed('model.@each.{id}', function() {
|
||||||
|
return get(this, 'model').sortBy('id');
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import Route from '@ember/routing/route';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
// import { get } from '@ember/object';
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
globalStore: service(),
|
||||||
|
|
||||||
|
model(/* params */) {
|
||||||
|
return this.globalStore.findAll('cloudcredential');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<section class="header has-tabs clearfix p-0">
|
||||||
|
<div class="right-buttons">
|
||||||
|
<button
|
||||||
|
{{action "addCloudKey"}}
|
||||||
|
class="btn btn-sm bg-primary right-divider-btn"
|
||||||
|
disabled={{rbac-prevents resource="cloudcredential" scope="global" permission="create"}}
|
||||||
|
>
|
||||||
|
{{t "cloudKeysPage.addKey"}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="instances">
|
||||||
|
{{#sortable-table
|
||||||
|
bulkActions=true
|
||||||
|
classNames="grid sortable-table"
|
||||||
|
sortBy=sortBy
|
||||||
|
descending=descending
|
||||||
|
headers=headers
|
||||||
|
searchText=searchText
|
||||||
|
showHeader=true
|
||||||
|
body=filteredContent
|
||||||
|
rightActions=true
|
||||||
|
as |sortable kind row dt|
|
||||||
|
}}
|
||||||
|
{{#if (eq kind "row")}}
|
||||||
|
<tr class="main-row">
|
||||||
|
<td valign="middle" class="row-check" style="padding-top: 2px;">
|
||||||
|
{{check-box nodeId=row.id}}
|
||||||
|
</td>
|
||||||
|
<td data-title="{{t "generic.type"}}:" class="clip">
|
||||||
|
{{row.displayType}}
|
||||||
|
</td>
|
||||||
|
<td data-title="{{t "generic.name"}}:" class="clip">
|
||||||
|
{{row.displayName}}
|
||||||
|
</td>
|
||||||
|
<td data-title="{{t "generic.created"}}:" class="text-right pr-20">
|
||||||
|
{{date-calendar row.created}}
|
||||||
|
</td>
|
||||||
|
<td data-title="{{t "generic.actions"}}:" class="actions">
|
||||||
|
{{action-menu model=row}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{else if (eq kind "nomatch")}}
|
||||||
|
<td
|
||||||
|
colspan="5"
|
||||||
|
class="text-center text-muted lacsso pt-20 pb-20"
|
||||||
|
>
|
||||||
|
{{t "cloudKeysPage.index.table.noMatch"}}
|
||||||
|
</td>
|
||||||
|
{{else if (eq kind "norows")}}
|
||||||
|
<td
|
||||||
|
colspan="5"
|
||||||
|
class="text-center text-muted lacsso pt-20 pb-20"
|
||||||
|
>
|
||||||
|
{{t "cloudKeysPage.index.table.noData"}}
|
||||||
|
</td>
|
||||||
|
{{/if}}
|
||||||
|
{{/sortable-table}}
|
||||||
|
</section>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'global-admin/components/cru-cloud-credential/component';
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'global-admin/components/modal-add-cloud-key/component';
|
||||||
|
|
@ -9,6 +9,7 @@ import Component from '@ember/component';
|
||||||
import NodeDriver from 'shared/mixins/node-driver';
|
import NodeDriver from 'shared/mixins/node-driver';
|
||||||
import layout from './template';
|
import layout from './template';
|
||||||
import { INSTANCE_TYPES, nameFromResource, tagsFromResource, REGIONS } from 'shared/utils/amazon';
|
import { INSTANCE_TYPES, nameFromResource, tagsFromResource, REGIONS } from 'shared/utils/amazon';
|
||||||
|
import { randomStr } from 'shared/utils/util';
|
||||||
|
|
||||||
let RANCHER_GROUP = 'rancher-nodes';
|
let RANCHER_GROUP = 'rancher-nodes';
|
||||||
|
|
||||||
|
|
@ -84,21 +85,28 @@ export default Component.extend(NodeDriver, {
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
finishAndSelectCloudCredential(cred) {
|
||||||
|
if (cred) {
|
||||||
|
set(this, 'primaryResource.cloudCredentialId', get(cred, 'id'));
|
||||||
|
|
||||||
|
this.send('awsLogin');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
awsLogin(cb) {
|
awsLogin(cb) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
setProperties(this, {
|
set(this, 'errors', null);
|
||||||
'errors': null,
|
|
||||||
'config.accessKey': (get(this, 'config.accessKey') || '').trim(),
|
|
||||||
'config.secretKey': (get(this, 'config.secretKey') || '').trim(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let subnets = [];
|
let subnets = [];
|
||||||
let rName = get(this, 'config.region');
|
let rName = get(this, 'config.region');
|
||||||
|
|
||||||
|
// have to have something in there before we describe the request even though we are going to replace with the actual cred id
|
||||||
let ec2 = new AWS.EC2({
|
let ec2 = new AWS.EC2({
|
||||||
accessKeyId: get(this, 'config.accessKey'),
|
accessKeyId: randomStr(),
|
||||||
secretAccessKey: get(this, 'config.secretKey'),
|
secretAccessKey: randomStr(),
|
||||||
region: rName,
|
region: rName,
|
||||||
|
httpOptions: { cloudCredentialId: get(this, 'model.cloudCredentialId') },
|
||||||
});
|
});
|
||||||
|
|
||||||
let vpcNames = {};
|
let vpcNames = {};
|
||||||
|
|
@ -110,7 +118,9 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
errors.pushObject(err);
|
errors.pushObject(err);
|
||||||
set(this, 'errors', errors);
|
set(this, 'errors', errors);
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +136,9 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
errors.pushObject(err);
|
errors.pushObject(err);
|
||||||
set(this, 'errors', errors);
|
set(this, 'errors', errors);
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +166,9 @@ export default Component.extend(NodeDriver, {
|
||||||
'allSubnets': subnets,
|
'allSubnets': subnets,
|
||||||
'step': 2,
|
'step': 2,
|
||||||
});
|
});
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -164,14 +178,18 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
if ( !get(this, 'selectedZone') ) {
|
if ( !get(this, 'selectedZone') ) {
|
||||||
set(this, 'errors', ['Select an Availability Zone']);
|
set(this, 'errors', ['Select an Availability Zone']);
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !get(this, 'selectedSubnet') ) {
|
if ( !get(this, 'selectedSubnet') ) {
|
||||||
set(this, 'errors', ['Select a VPC or Subnet']);
|
set(this, 'errors', ['Select a VPC or Subnet']);
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +203,9 @@ export default Component.extend(NodeDriver, {
|
||||||
ec2.describeSecurityGroups({ Filters: [filter] }, (err, data) => {
|
ec2.describeSecurityGroups({ Filters: [filter] }, (err, data) => {
|
||||||
if ( err ) {
|
if ( err ) {
|
||||||
set(this, 'errors', [err]);
|
set(this, 'errors', [err]);
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -242,7 +262,9 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
setProperties(this, { step: 4, });
|
setProperties(this, { step: 4, });
|
||||||
|
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -257,11 +279,12 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
set(this, 'config.tags', array.join(','));
|
set(this, 'config.tags', array.join(','));
|
||||||
}),
|
}),
|
||||||
stepDidChange: function() {
|
|
||||||
|
stepDidChange: observer('context.step', function() {
|
||||||
scheduleOnce('afterRender', this, () => {
|
scheduleOnce('afterRender', this, () => {
|
||||||
document.body.scrollTop = document.body.scrollHeight;
|
document.body.scrollTop = document.body.scrollHeight;
|
||||||
});
|
});
|
||||||
}.observes('context.step'),
|
}),
|
||||||
|
|
||||||
selectedZone: computed('config.{region,zone}', {
|
selectedZone: computed('config.{region,zone}', {
|
||||||
get() {
|
get() {
|
||||||
|
|
@ -301,7 +324,7 @@ export default Component.extend(NodeDriver, {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
zoneChoices: function() {
|
zoneChoices: computed('allSubnets.@each.{zone}', function() {
|
||||||
const choices = (get(this, 'allSubnets') || []).map((subnet) => {
|
const choices = (get(this, 'allSubnets') || []).map((subnet) => {
|
||||||
return get(subnet, 'zone');
|
return get(subnet, 'zone');
|
||||||
}).sort().uniq();
|
}).sort().uniq();
|
||||||
|
|
@ -315,9 +338,9 @@ export default Component.extend(NodeDriver, {
|
||||||
}
|
}
|
||||||
|
|
||||||
return choices;
|
return choices;
|
||||||
}.property('allSubnets.@each.{zone}'),
|
}),
|
||||||
|
|
||||||
subnetChoices: function() {
|
subnetChoices: computed('selectedZone', 'allSubnets.@each.{subnetId,vpcId,zone}', function() {
|
||||||
let out = [];
|
let out = [];
|
||||||
let seenVpcs = [];
|
let seenVpcs = [];
|
||||||
|
|
||||||
|
|
@ -350,7 +373,7 @@ export default Component.extend(NodeDriver, {
|
||||||
});
|
});
|
||||||
|
|
||||||
return out.sortBy('sortKey');
|
return out.sortBy('sortKey');
|
||||||
}.property('selectedZone', 'allSubnets.@each.{subnetId,vpcId,zone}'),
|
}),
|
||||||
|
|
||||||
selectedSubnet: computed('config.{subnetId,vpcId}', {
|
selectedSubnet: computed('config.{subnetId,vpcId}', {
|
||||||
set(key, val) {
|
set(key, val) {
|
||||||
|
|
@ -390,7 +413,6 @@ export default Component.extend(NodeDriver, {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
bootstrap() {
|
bootstrap() {
|
||||||
let pref = get(this, 'prefs.amazonec2') || {};
|
|
||||||
let config = get(this, 'globalStore').createRecord({
|
let config = get(this, 'globalStore').createRecord({
|
||||||
type: 'amazonec2Config',
|
type: 'amazonec2Config',
|
||||||
region: 'us-west-2',
|
region: 'us-west-2',
|
||||||
|
|
@ -398,8 +420,6 @@ export default Component.extend(NodeDriver, {
|
||||||
securityGroup: '',
|
securityGroup: '',
|
||||||
zone: 'a',
|
zone: 'a',
|
||||||
rootSize: '16',
|
rootSize: '16',
|
||||||
accessKey: pref.accessKey || '',
|
|
||||||
secretKey: pref.secretKey || '',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
set(this, 'model.amazonec2Config', config);
|
set(this, 'model.amazonec2Config', config);
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@
|
||||||
<div class="over-hr"><span>{{driverOptionsTitle}}</span></div>
|
<div class="over-hr"><span>{{driverOptionsTitle}}</span></div>
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.amazonec2.access.title')
|
title=(t "nodeDriver.amazonec2.access.title")
|
||||||
detail=(t 'nodeDriver.amazonec2.access.detail')
|
detail=(t "nodeDriver.amazonec2.access.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-4">
|
<div class="col span-4">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.region.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.region.label"}}</label>
|
||||||
{{#if (eq step 1)}}
|
{{#if (eq step 1)}}
|
||||||
<select class="form-control" onchange={{action (mut config.region) value="target.value"}}>
|
<select class="form-control" onchange={{action (mut config.region) value="target.value"}}>
|
||||||
{{#each regionChoices as |choice|}}
|
{{#each regionChoices as |choice|}}
|
||||||
|
|
@ -22,55 +22,49 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col span-4">
|
</div>
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.accessKey.label'}}</label>
|
|
||||||
{{#if (eq step 1)}}
|
{{#if (eq step 1)}}
|
||||||
{{input type="text" name="username" classNames="form-control" placeholder=(t 'nodeDriver.amazonec2.accessKey.placeholder') value=config.accessKey}}
|
{{form-auth-cloud-credential
|
||||||
|
driverName=driverName
|
||||||
|
errors=errros
|
||||||
|
primaryResource=primaryResource
|
||||||
|
cloudCredentials=cloudCredentials
|
||||||
|
finishAndSelectCloudCredential=(action "finishAndSelectCloudCredential")
|
||||||
|
progressStep=(action "awsLogin")
|
||||||
|
cancel=(action "cancel")
|
||||||
|
}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-4">
|
||||||
|
<label class="acc-label">{{t "nodeDriver.amazonec2.accessKey.label"}}</label>
|
||||||
<div>{{config.accessKey}}</div>
|
<div>{{config.accessKey}}</div>
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col span-4">
|
<div class="col span-4">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.secretKey.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.secretKey.label"}}</label>
|
||||||
{{#if (eq step 1)}}
|
<div class="text-muted text-italic">{{t "nodeDriver.amazonec2.secretKey.provided"}}</div>
|
||||||
{{input type="password" name="password" classNames="form-control" placeholder=(t 'nodeDriver.amazonec2.secretKey.placeholder') value=config.secretKey}}
|
|
||||||
{{else}}
|
|
||||||
<div class="text-muted text-italic">{{t 'nodeDriver.amazonec2.secretKey.provided'}}</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if (eq step 1)}}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span-8 offset-4">
|
<div class="span-8 offset-4">
|
||||||
<p class="text-info text-small m-0">{{t 'nodeDriver.amazonec2.access.help'}}</p>
|
<p class="text-info text-small m-0">{{t "nodeDriver.amazonec2.access.help"}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{top-errors errors=errors}}
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
{{#if (eq step 1)}}
|
<div class="{{unless (gte step 2) "hide"}}">
|
||||||
{{top-errors errors=errors}}
|
|
||||||
{{save-cancel
|
|
||||||
save="awsLogin"
|
|
||||||
cancel="cancel"
|
|
||||||
createLabel="nodeDriver.amazonec2.access.next"
|
|
||||||
savingLabel="nodeDriver.amazonec2.access.loading"
|
|
||||||
}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="{{unless (gte step 2) 'hide'}}">
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.amazonec2.zone.title')
|
title=(t "nodeDriver.amazonec2.zone.title")
|
||||||
detail=(t 'nodeDriver.amazonec2.zone.detail')
|
detail=(t "nodeDriver.amazonec2.zone.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
{{#if (eq step 2)}}
|
{{#if (eq step 2)}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.availabilityZone'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.availabilityZone"}}</label>
|
||||||
<select class="form-control" onchange={{action (mut selectedZone) value="target.value"}}>
|
<select class="form-control" onchange={{action (mut selectedZone) value="target.value"}}>
|
||||||
{{#each zoneChoices as |choice|}}
|
{{#each zoneChoices as |choice|}}
|
||||||
<option value={{choice}} selected={{eq selectedZone choice}}>{{choice}}</option>
|
<option value={{choice}} selected={{eq selectedZone choice}}>{{choice}}</option>
|
||||||
|
|
@ -79,7 +73,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="acc-label pt-20">{{t 'nodeDriver.amazonec2.subnet'}}</label>
|
<label class="acc-label pt-20">{{t "nodeDriver.amazonec2.subnet"}}</label>
|
||||||
{{#if subnetChoices.length}}
|
{{#if subnetChoices.length}}
|
||||||
{{#each subnetChoices as |choice|}}
|
{{#each subnetChoices as |choice|}}
|
||||||
{{#if choice.isVpc}}
|
{{#if choice.isVpc}}
|
||||||
|
|
@ -115,11 +109,11 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span-6">
|
<div class="span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.availabilityZone'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.availabilityZone"}}</label>
|
||||||
{{config.region}}{{config.zone}}
|
{{config.region}}{{config.zone}}
|
||||||
</div>
|
</div>
|
||||||
<div class="span-6">
|
<div class="span-6">
|
||||||
<label class="acc-label pt-20">{{t 'nodeDriver.amazonec2.subnet'}}</label>
|
<label class="acc-label pt-20">{{t "nodeDriver.amazonec2.subnet"}}</label>
|
||||||
{{#if config.subnetId}}
|
{{#if config.subnetId}}
|
||||||
{{config.subnetId}}
|
{{config.subnetId}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
@ -141,10 +135,10 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="{{unless (gte step 3) 'hide'}}">
|
<div class="{{unless (gte step 3) "hide"}}">
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.amazonec2.securityGroup.title')
|
title=(t "nodeDriver.amazonec2.securityGroup.title")
|
||||||
detail=(t 'nodeDriver.amazonec2.securityGroup.detail')
|
detail=(t "nodeDriver.amazonec2.securityGroup.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
|
|
@ -154,23 +148,23 @@
|
||||||
<div class="radio pt-10">
|
<div class="radio pt-10">
|
||||||
<label>
|
<label>
|
||||||
{{radio-button selection=whichSecurityGroup value="default"}}
|
{{radio-button selection=whichSecurityGroup value="default"}}
|
||||||
{{t 'nodeDriver.amazonec2.securityGroup.defaultCreate' groupName=defaultSecurityGroupName htmlSafe=true}}
|
{{t "nodeDriver.amazonec2.securityGroup.defaultCreate" groupName=defaultSecurityGroupName htmlSafe=true}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if (and settings.isRancher (not isCustomSecurityGroup))}}
|
{{#if (and settings.isRancher (not isCustomSecurityGroup))}}
|
||||||
<p class="text-info ml-20"><a href="{{settings.docsBase}}/installation/references/" target="_blank">{{t 'nodeDriver.amazonec2.portHelp.link'}}</a> {{t 'nodeDriver.amazonec2.portHelp.text'}}</p>
|
<p class="text-info ml-20"><a href="{{settings.docsBase}}/installation/references/" target="_blank">{{t "nodeDriver.amazonec2.portHelp.link"}}</a> {{t "nodeDriver.amazonec2.portHelp.text"}}</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="radio pt-10">
|
<div class="radio pt-10">
|
||||||
<label>
|
<label>
|
||||||
{{radio-button selection=whichSecurityGroup value="custom"}}
|
{{radio-button selection=whichSecurityGroup value="custom"}}
|
||||||
{{t 'nodeDriver.amazonec2.securityGroup.choose'}}
|
{{t "nodeDriver.amazonec2.securityGroup.choose"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if isCustomSecurityGroup}}
|
{{#if isCustomSecurityGroup}}
|
||||||
<select class="form-control existing-security-groups" multiple="true" onchange={{action 'multiSecurityGroupSelect' ''}}>
|
<select class="form-control existing-security-groups" multiple="true" onchange={{action "multiSecurityGroupSelect" ""}}>
|
||||||
{{#each allSecurityGroups as |choice|}}
|
{{#each allSecurityGroups as |choice|}}
|
||||||
<option value={{choice.name}} selected={{array-includes selectedSecurityGroup choice.name}}>{{choice.name}} ({{choice.id}})</option>
|
<option value={{choice.name}} selected={{array-includes selectedSecurityGroup choice.name}}>{{choice.name}} ({{choice.id}})</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
@ -203,17 +197,17 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="{{unless (gte step 4) 'hide'}}">
|
<div class="{{unless (gte step 4) "hide"}}">
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.amazonec2.instance.title')
|
title=(t "nodeDriver.amazonec2.instance.title")
|
||||||
detail=(t 'nodeDriver.amazonec2.instance.detail')
|
detail=(t "nodeDriver.amazonec2.instance.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.instanceType.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.instanceType.label"}}</label>
|
||||||
{{new-select
|
{{new-select
|
||||||
classNames="form-control"
|
classNames="form-control"
|
||||||
value=config.instanceType
|
value=config.instanceType
|
||||||
|
|
@ -225,59 +219,59 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.rootSize.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.rootSize.label"}}</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
{{input type="text" classNames="form-control" placeholder="" value=config.rootSize}}
|
{{input type="text" classNames="form-control" placeholder="" value=config.rootSize}}
|
||||||
<span class="input-group-addon bg-default">{{t 'nodeDriver.amazonec2.rootSize.unit'}}</span>
|
<span class="input-group-addon bg-default">{{t "nodeDriver.amazonec2.rootSize.unit"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.ami.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.ami.label"}}</label>
|
||||||
{{input type="text" classNames="form-control" placeholder=(t 'nodeDriver.amazonec2.ami.placeholder') value=config.ami}}
|
{{input type="text" classNames="form-control" placeholder=(t "nodeDriver.amazonec2.ami.placeholder") value=config.ami}}
|
||||||
{{#if settings.isRancher}}
|
{{#if settings.isRancher}}
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
<a href="https://github.com/rancher/os/blob/master/README.md/#user-content-amazon" target="_blank">{{t 'nodeDriver.amazonec2.ami.rancherList'}}</a>
|
<a href="https://github.com/rancher/os/blob/master/README.md/#user-content-amazon" target="_blank">{{t "nodeDriver.amazonec2.ami.rancherList"}}</a>
|
||||||
</p>
|
</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.sshUser.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.sshUser.label"}}</label>
|
||||||
{{input type="text" classNames="form-control" placeholder=(t 'nodeDriver.amazonec2.sshUser.placeholder') value=config.sshUser}}
|
{{input type="text" classNames="form-control" placeholder=(t "nodeDriver.amazonec2.sshUser.placeholder") value=config.sshUser}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.iam.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.iam.label"}}</label>
|
||||||
{{input type="text" classNames="form-control" value=config.iamInstanceProfile placeholder=(t 'nodeDriver.amazonec2.iam.placeholder')}}
|
{{input type="text" classNames="form-control" value=config.iamInstanceProfile placeholder=(t "nodeDriver.amazonec2.iam.placeholder")}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.privateIp.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.privateIp.label"}}</label>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label class="acc-label">{{input type="checkbox" checked=config.privateAddressOnly}} {{t 'nodeDriver.amazonec2.onlyPrivate.label'}}</label>
|
<label class="acc-label">{{input type="checkbox" checked=config.privateAddressOnly}} {{t "nodeDriver.amazonec2.onlyPrivate.label"}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.requestSpotInstance.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.requestSpotInstance.label"}}</label>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label class="acc-label">{{input type="checkbox" checked=config.requestSpotInstance}} {{t 'nodeDriver.amazonec2.requestSpotInstance.enable'}}</label>
|
<label class="acc-label">{{input type="checkbox" checked=config.requestSpotInstance}} {{t "nodeDriver.amazonec2.requestSpotInstance.enable"}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if config.requestSpotInstance}}
|
{{#if config.requestSpotInstance}}
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.amazonec2.spotPrice.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.amazonec2.spotPrice.label"}}</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
{{input type="text" classNames="form-control" placeholder="" value=config.spotPrice}}
|
{{input type="text" classNames="form-control" placeholder="" value=config.spotPrice}}
|
||||||
<span class="input-group-addon bg-default">{{t 'nodeDriver.amazonec2.spotPrice.unit'}}</span>
|
<span class="input-group-addon bg-default">{{t "nodeDriver.amazonec2.spotPrice.unit"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
@ -303,7 +297,7 @@
|
||||||
|
|
||||||
{{form-user-labels
|
{{form-user-labels
|
||||||
initialLabels=labelResource.labels
|
initialLabels=labelResource.labels
|
||||||
setLabels=(action 'setLabels')
|
setLabels=(action "setLabels")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,12 @@ export default Component.extend(NodeDriver, {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
finishAndSelectCloudCredential(credential) {
|
||||||
|
set(this, 'model.cloudCredentialId', get(credential, 'id'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
evironmentChoiceObserver: observer('config.environment', function() {
|
evironmentChoiceObserver: observer('config.environment', function() {
|
||||||
let environment = get(this, 'config.environment');
|
let environment = get(this, 'config.environment');
|
||||||
|
|
||||||
|
|
@ -116,8 +122,6 @@ export default Component.extend(NodeDriver, {
|
||||||
let config = get(this, 'globalStore').createRecord({
|
let config = get(this, 'globalStore').createRecord({
|
||||||
type: CONFIG,
|
type: CONFIG,
|
||||||
subscriptionId: '',
|
subscriptionId: '',
|
||||||
clientId: '',
|
|
||||||
clientSecret: '',
|
|
||||||
openPort: ['6443/tcp', '2379/tcp', '2380/tcp', '8472/udp', '4789/udp', '10256/tcp', '10250/tcp', '10251/tcp', '10252/tcp'],
|
openPort: ['6443/tcp', '2379/tcp', '2380/tcp', '8472/udp', '4789/udp', '10256/tcp', '10250/tcp', '10251/tcp', '10252/tcp'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -146,18 +150,6 @@ export default Component.extend(NodeDriver, {
|
||||||
errors.push('Name is required');
|
errors.push('Name is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get(this, 'config.subscriptionId')) {
|
|
||||||
errors.push('Subscription ID is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get(this, 'config.clientId')) {
|
|
||||||
errors.push('Client ID is requried');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get(this, 'config.clientSecret')) {
|
|
||||||
errors.push('Client Secret is requried');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
set(this, 'errors', errors.uniq());
|
set(this, 'errors', errors.uniq());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,147 +1,264 @@
|
||||||
{{#accordion-list showExpandAll=false as | al expandFn |}}
|
{{#accordion-list showExpandAll=false as | al expandFn |}}
|
||||||
<div class="over-hr"><span>{{driverOptionsTitle}}</span></div>
|
<div class="over-hr">
|
||||||
|
<span>
|
||||||
|
{{driverOptionsTitle}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.azure.placement.title')
|
title=(t "nodeDriver.azure.access.title")
|
||||||
detail=(t 'nodeDriver.azure.placement.detail')
|
detail=(t "nodeDriver.azure.access.detail")
|
||||||
|
expandAll=expandAll
|
||||||
|
expand=(action expandFn)
|
||||||
|
expandOnInit=true
|
||||||
|
}}
|
||||||
|
{{form-auth-cloud-credential
|
||||||
|
driverName=driverName
|
||||||
|
errors=errros
|
||||||
|
primaryResource=primaryResource
|
||||||
|
cloudCredentials=cloudCredentials
|
||||||
|
finishAndSelectCloudCredential=(action "finishAndSelectCloudCredential")
|
||||||
|
progressStep=(action "finishAndSelectCloudCredential")
|
||||||
|
cancel=(action "cancel")
|
||||||
|
hideSave=true
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
|
{{#accordion-list-item
|
||||||
|
title=(t "nodeDriver.azure.placement.title")
|
||||||
|
detail=(t "nodeDriver.azure.placement.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.environment.label'}}</label>
|
<label class="acc-label">
|
||||||
{{new-select classNames="form-control" content=environments optionLabelPath='value' value=config.environment}}
|
{{t "nodeDriver.azure.environment.label"}}
|
||||||
|
</label>
|
||||||
|
{{new-select
|
||||||
|
classNames="form-control"
|
||||||
|
content=environments
|
||||||
|
optionLabelPath="value"
|
||||||
|
value=config.environment
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.region.label'}}</label>
|
<label class="acc-label">
|
||||||
{{new-select classNames="form-control" content=regionChoices optionLabelPath='displayName' optionValuePath='name' value=config.location}}
|
{{t "nodeDriver.azure.region.label"}}
|
||||||
|
</label>
|
||||||
|
{{new-select
|
||||||
|
classNames="form-control"
|
||||||
|
content=regionChoices
|
||||||
|
optionLabelPath="displayName"
|
||||||
|
optionValuePath="name"
|
||||||
|
value=config.location
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.availabilitySet.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.availabilitySet classNames="form-control" placeholder=(t 'nodeDriver.azure.availabilitySet.placeholder')}}
|
{{t "nodeDriver.azure.availabilitySet.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.availabilitySet
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.availabilitySet.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.resourceGroup.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.resourceGroup classNames="form-control" placeholder=(t 'nodeDriver.azure.resourceGroup.placeholder')}}
|
{{t "nodeDriver.azure.resourceGroup.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.resourceGroup
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.resourceGroup.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.azure.access.title')
|
title=(t "nodeDriver.azure.network.title")
|
||||||
detail=(t 'nodeDriver.azure.access.detail')
|
detail=(t "nodeDriver.azure.network.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.subscriptionId.label'}}{{field-required}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.subscriptionId classNames="form-control" placeholder=(t 'nodeDriver.azure.subscriptionId.placeholder')}}
|
{{t "nodeDriver.azure.subnet.label"}}
|
||||||
</div>
|
</label>
|
||||||
</div>
|
{{input
|
||||||
|
type="text"
|
||||||
<div class="row">
|
value=config.subnet
|
||||||
<div class="col span-6">
|
classNames="form-control"
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.clientId.label'}}{{field-required}}</label>
|
placeholder=(t "nodeDriver.azure.subnet.placeholder")
|
||||||
{{input type="text" value=config.clientId classNames="form-control"}}
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.clientSecret.label'}}{{field-required}}</label>
|
|
||||||
{{input type="password" value=config.clientSecret classNames="form-control"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/accordion-list-item}}
|
|
||||||
|
|
||||||
{{#accordion-list-item
|
|
||||||
title=(t 'nodeDriver.azure.network.title')
|
|
||||||
detail=(t 'nodeDriver.azure.network.detail')
|
|
||||||
expandAll=expandAll
|
|
||||||
expand=(action expandFn)
|
|
||||||
expandOnInit=true
|
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
|
||||||
<div class="col span-6">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.subnet.label'}}</label>
|
|
||||||
{{input type="text" value=config.subnet classNames="form-control" placeholder=(t 'nodeDriver.azure.subnet.placeholder')}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.subnetPrefix.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.subnetPrefix classNames="form-control" placeholder=(t 'nodeDriver.azure.subnetPrefix.placeholder')}}
|
{{t "nodeDriver.azure.subnetPrefix.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.subnetPrefix
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.subnetPrefix.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.vnet.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.vnet classNames="form-control" placeholder=(t 'nodeDriver.azure.vnet.placeholder')}}
|
{{t "nodeDriver.azure.vnet.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.vnet
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.vnet.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.staticPublicIp.label'}}</label>
|
<label class="acc-label">
|
||||||
{{new-select classNames="form-control" content=publicIpChoices optionLabelPath='name' optionValuePath='value' value=publicIpChoice}}
|
{{t "nodeDriver.azure.staticPublicIp.label"}}
|
||||||
|
</label>
|
||||||
|
{{new-select
|
||||||
|
classNames="form-control"
|
||||||
|
content=publicIpChoices
|
||||||
|
optionLabelPath="name"
|
||||||
|
optionValuePath="value"
|
||||||
|
value=publicIpChoice
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.privateIpAddress.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.privateIpAddress classNames="form-control" placeholder=(t 'nodeDriver.azure.privateIpAddress.placeholder')}}
|
{{t "nodeDriver.azure.privateIpAddress.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.privateIpAddress
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.privateIpAddress.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.usePrivateIp.label'}}</label>
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.azure.usePrivateIp.label"}}
|
||||||
|
</label>
|
||||||
<div>
|
<div>
|
||||||
{{input type="checkbox" checked=config.usePrivateIp disabled=privateSet}}
|
{{input
|
||||||
|
type="checkbox"
|
||||||
|
checked=config.usePrivateIp
|
||||||
|
disabled=privateSet
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.azure.instance.title')
|
title=(t "nodeDriver.azure.instance.title")
|
||||||
detail=(t 'nodeDriver.azure.instance.detail')
|
detail=(t "nodeDriver.azure.instance.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.image.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.image classNames="form-control" placeholder=(t 'nodeDriver.azure.image.placeholder')}}
|
{{t "nodeDriver.azure.image.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.image
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.image.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.size.label'}}</label>
|
<label class="acc-label">
|
||||||
{{new-select classNames="form-control" content=sizeChoices optionLabelPath='value' optionGroupPath='group' value=config.size}}
|
{{t "nodeDriver.azure.size.label"}}
|
||||||
|
</label>
|
||||||
|
{{new-select
|
||||||
|
classNames="form-control"
|
||||||
|
content=sizeChoices
|
||||||
|
optionLabelPath="value"
|
||||||
|
optionGroupPath="group"
|
||||||
|
value=config.size
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.dockerPort.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.dockerPort classNames="form-control" placeholder=(t 'nodeDriver.azure.dockerPort.placeholder')}}
|
{{t "nodeDriver.azure.dockerPort.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.dockerPort
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.dockerPort.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.openPort.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=openPorts classNames="form-control" placeholder=(t 'nodeDriver.azure.openPort.placeholder')}}
|
{{t "nodeDriver.azure.openPort.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=openPorts
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.openPort.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.sshUser.label'}}</label>
|
<label class="acc-label">
|
||||||
{{input type="text" value=config.sshUser classNames="form-control" placeholder=(t 'nodeDriver.azure.sshUser.placeholder')}}
|
{{t "nodeDriver.azure.sshUser.label"}}
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=config.sshUser
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.azure.sshUser.placeholder")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.azure.storageType.label'}}</label>
|
<label class="acc-label">
|
||||||
{{new-select classNames="form-control" content=storageTypeChoices optionLabelPath='name' optionValuePath='value' value=config.storageType}}
|
{{t "nodeDriver.azure.storageType.label"}}
|
||||||
|
</label>
|
||||||
|
{{new-select
|
||||||
|
classNames="form-control"
|
||||||
|
content=storageTypeChoices
|
||||||
|
optionLabelPath="name"
|
||||||
|
optionValuePath="value"
|
||||||
|
value=config.storageType
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
<div class="over-hr"><span>{{templateOptionsTitle}}</span></div>
|
<div class="over-hr">
|
||||||
|
<span>
|
||||||
|
{{templateOptionsTitle}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{form-name-description
|
{{form-name-description
|
||||||
model=model
|
model=model
|
||||||
|
|
@ -150,7 +267,7 @@
|
||||||
|
|
||||||
{{form-user-labels
|
{{form-user-labels
|
||||||
initialLabels=labelResource.labels
|
initialLabels=labelResource.labels
|
||||||
setLabels=(action 'setLabels')
|
setLabels=(action "setLabels")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
}}
|
}}
|
||||||
|
|
@ -160,6 +277,13 @@
|
||||||
showEngineUrl=showEngineUrl
|
showEngineUrl=showEngineUrl
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{{top-errors errors=errors}}
|
{{top-errors
|
||||||
{{save-cancel save="save" cancel="cancel" editing=editing}}
|
errors=errors
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{save-cancel
|
||||||
|
save="save"
|
||||||
|
cancel="cancel"
|
||||||
|
editing=editing
|
||||||
|
}}
|
||||||
{{/accordion-list}}
|
{{/accordion-list}}
|
||||||
|
|
|
||||||
|
|
@ -37,24 +37,28 @@ export default Component.extend(NodeDriver, {
|
||||||
driverName: 'digitalocean',
|
driverName: 'digitalocean',
|
||||||
regionChoices: null,
|
regionChoices: null,
|
||||||
model: null,
|
model: null,
|
||||||
|
|
||||||
step: 1,
|
step: 1,
|
||||||
sizeChoices: null,
|
sizeChoices: null,
|
||||||
imageChoices: null,
|
imageChoices: null,
|
||||||
tags: null,
|
tags: null,
|
||||||
|
|
||||||
config: alias('model.digitaloceanConfig'),
|
config: alias('primaryResource.digitaloceanConfig'),
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
const tags = get(this, 'config.tags');
|
this.initTags();
|
||||||
|
|
||||||
if (tags) {
|
|
||||||
set(this, 'tags', tags.split(','));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
finishAndSelectCloudCredential(cred) {
|
||||||
|
if (cred) {
|
||||||
|
set(this, 'primaryResource.cloudCredentialId', get(cred, 'id'));
|
||||||
|
|
||||||
|
this.send('getData');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getData(cb) {
|
getData(cb) {
|
||||||
let promises = {
|
let promises = {
|
||||||
regions: this.apiRequest('regions'),
|
regions: this.apiRequest('regions'),
|
||||||
|
|
@ -103,7 +107,9 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
setProperties(this, { errors, });
|
setProperties(this, { errors, });
|
||||||
|
|
||||||
|
if (cb && typeof cb === 'function') {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -134,6 +140,14 @@ export default Component.extend(NodeDriver, {
|
||||||
return out;
|
return out;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
initTags() {
|
||||||
|
const tags = get(this, 'config.tags');
|
||||||
|
|
||||||
|
if (tags) {
|
||||||
|
set(this, 'tags', tags.split(','));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
bootstrap() {
|
bootstrap() {
|
||||||
let config = get(this, 'globalStore').createRecord({
|
let config = get(this, 'globalStore').createRecord({
|
||||||
type: 'digitaloceanConfig',
|
type: 'digitaloceanConfig',
|
||||||
|
|
@ -143,15 +157,16 @@ export default Component.extend(NodeDriver, {
|
||||||
sshUser: 'root'
|
sshUser: 'root'
|
||||||
});
|
});
|
||||||
|
|
||||||
const model = get(this, 'model');
|
const primaryResource = get(this, 'primaryResource');
|
||||||
|
|
||||||
set(model, 'digitaloceanConfig', config);
|
set(primaryResource, 'digitaloceanConfig', config);
|
||||||
},
|
},
|
||||||
|
|
||||||
apiRequest(command, opt, out) {
|
apiRequest(command, opt, out) {
|
||||||
opt = opt || {};
|
opt = opt || {};
|
||||||
|
|
||||||
let url = `${ get(this, 'app.proxyEndpoint') }/`;
|
let url = `${ get(this, 'app.proxyEndpoint') }/`;
|
||||||
|
let cloudCredentialId = get(this, 'primaryResource.cloudCredentialId');
|
||||||
|
|
||||||
if ( opt.url ) {
|
if ( opt.url ) {
|
||||||
url += opt.url.replace(/^http[s]?\/\//, '');
|
url += opt.url.replace(/^http[s]?\/\//, '');
|
||||||
|
|
@ -164,7 +179,7 @@ export default Component.extend(NodeDriver, {
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'X-Api-Auth-Header': `Bearer ${ get(this, 'config.accessToken') }`,
|
'x-api-cattleauth-header': `Bearer credID=${ cloudCredentialId } passwordField=accessToken`,
|
||||||
},
|
},
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
let body = res.body;
|
let body = res.body;
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,40 @@
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
{{#if (eq step 1)}}
|
|
||||||
<div class="box mt-20">
|
|
||||||
<div class="row">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.digitalocean.accessToken.label'}}</label>
|
|
||||||
{{input type="password" value=config.accessToken classNames="form-control" placeholder=(t 'nodeDriver.digitalocean.accessToken.placeholder')}}
|
|
||||||
<p class="text-info">{{t 'nodeDriver.digitalocean.accessToken.help' htmlSafe=true}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{top-errors errors=errors}}
|
|
||||||
{{save-cancel
|
|
||||||
save="getData"
|
|
||||||
cancel="cancel"
|
|
||||||
createLabel="nodeDriver.digitalocean.authAccountButton"
|
|
||||||
savingLabel="generic.loading"
|
|
||||||
}}
|
|
||||||
{{else}}
|
|
||||||
{{#accordion-list showExpandAll=false as | al expandFn |}}
|
{{#accordion-list showExpandAll=false as | al expandFn |}}
|
||||||
|
|
||||||
|
{{#if (eq step 1)}}
|
||||||
|
{{#accordion-list-item
|
||||||
|
title=(t "nodeDriver.digitalocean.accessToken.label")
|
||||||
|
detail=(t "nodeDriver.digitalocean.accessToken.help" htmlSafe=true)
|
||||||
|
expandAll=expandAll
|
||||||
|
expand=(action expandFn)
|
||||||
|
expandOnInit=true
|
||||||
|
}}
|
||||||
|
{{form-auth-cloud-credential
|
||||||
|
driverName=driverName
|
||||||
|
errors=errros
|
||||||
|
primaryResource=primaryResource
|
||||||
|
cloudCredentials=cloudCredentials
|
||||||
|
finishAndSelectCloudCredential=(action "finishAndSelectCloudCredential")
|
||||||
|
progressStep=(action "getData")
|
||||||
|
cancel=(action "cancel")
|
||||||
|
createLabel="nodeDriver.digitalocean.authAccountButton"
|
||||||
|
}}
|
||||||
|
{{/accordion-list-item}}
|
||||||
|
{{top-errors errors=errors}}
|
||||||
|
{{else}}
|
||||||
<div class="over-hr mb-20"><span>{{driverOptionsTitle}}</span></div>
|
<div class="over-hr mb-20"><span>{{driverOptionsTitle}}</span></div>
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
title=(t 'nodeDriver.digitalocean.droplet.title')
|
title=(t "nodeDriver.digitalocean.droplet.title")
|
||||||
detail=(t 'nodeDriver.digitalocean.droplet.detail')
|
detail=(t "nodeDriver.digitalocean.droplet.detail")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.digitalocean.region.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.digitalocean.region.label"}}</label>
|
||||||
<select class="form-control" onchange={{action (mut config.region) value="target.value"}}>
|
<select class="form-control" onchange={{action (mut config.region) value="target.value"}}>
|
||||||
{{#each regionChoices as |choice|}}
|
{{#each regionChoices as |choice|}}
|
||||||
<option value={{choice.slug}} selected={{eq config.region choice.slug}}>{{choice.name}}</option>
|
<option value={{choice.slug}} selected={{eq config.region choice.slug}}>{{choice.name}}</option>
|
||||||
|
|
@ -35,17 +42,17 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.digitalocean.size.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.digitalocean.size.label"}}</label>
|
||||||
<select class="form-control" onchange={{action (mut config.size) value="target.value"}}>
|
<select class="form-control" onchange={{action (mut config.size) value="target.value"}}>
|
||||||
{{#each filteredSizeChoices as |choice|}}
|
{{#each filteredSizeChoices as |choice|}}
|
||||||
<option value={{choice.slug}} selected={{eq config.size choice.slug}}>{{t 'nodeDriver.digitalocean.sizeLabel' memoryGb=choice.memoryGb highMem=choice.highMem slug=choice.slug disk=choice.disk vcpus=choice.vcpus}}</option>
|
<option value={{choice.slug}} selected={{eq config.size choice.slug}}>{{t "nodeDriver.digitalocean.sizeLabel" memoryGb=choice.memoryGb highMem=choice.highMem slug=choice.slug disk=choice.disk vcpus=choice.vcpus}}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.digitalocean.image.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.digitalocean.image.label"}}</label>
|
||||||
<select class="form-control" onchange={{action (mut config.image) value="target.value"}}>
|
<select class="form-control" onchange={{action (mut config.image) value="target.value"}}>
|
||||||
{{#each imageChoices as |choice|}}
|
{{#each imageChoices as |choice|}}
|
||||||
<option value={{choice.slug}} disabled={{choice.disabled}} selected={{eq config.image choice.slug}}>{{choice.distribution}} {{choice.name}}</option>
|
<option value={{choice.slug}} disabled={{choice.disabled}} selected={{eq config.image choice.slug}}>{{choice.distribution}} {{choice.name}}</option>
|
||||||
|
|
@ -53,33 +60,33 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="acc-label">{{t 'nodeDriver.digitalocean.sshUser.label'}}</label>
|
<label class="acc-label">{{t "nodeDriver.digitalocean.sshUser.label"}}</label>
|
||||||
{{input type="text" value=config.sshUser classNames="form-control" placeholder=(t 'nodeDriver.digitalocean.sshUser.placeholder')}}
|
{{input type="text" value=config.sshUser classNames="form-control" placeholder=(t "nodeDriver.digitalocean.sshUser.placeholder")}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-3 text-center">
|
<div class="col span-3 text-center">
|
||||||
<label class="acc-label">
|
<label class="acc-label">
|
||||||
{{input type="checkbox" checked=config.backups}}
|
{{input type="checkbox" checked=config.backups}}
|
||||||
{{t 'nodeDriver.digitalocean.backups.label'}}
|
{{t "nodeDriver.digitalocean.backups.label"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-3 text-center">
|
<div class="col span-3 text-center">
|
||||||
<label class="acc-label">
|
<label class="acc-label">
|
||||||
{{input type="checkbox" checked=config.privateNetworking}}
|
{{input type="checkbox" checked=config.privateNetworking}}
|
||||||
{{t 'nodeDriver.digitalocean.privateNetworking.label'}}
|
{{t "nodeDriver.digitalocean.privateNetworking.label"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-3 text-center">
|
<div class="col span-3 text-center">
|
||||||
<label class="acc-label">
|
<label class="acc-label">
|
||||||
{{input type="checkbox" checked=config.ipv6}}
|
{{input type="checkbox" checked=config.ipv6}}
|
||||||
{{t 'nodeDriver.digitalocean.ipv6.label'}}
|
{{t "nodeDriver.digitalocean.ipv6.label"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-3 text-center">
|
<div class="col span-3 text-center">
|
||||||
<label class="acc-label">
|
<label class="acc-label">
|
||||||
{{input type="checkbox" checked=config.monitoring}}
|
{{input type="checkbox" checked=config.monitoring}}
|
||||||
{{t 'nodeDriver.digitalocean.monitoring.label'}}
|
{{t "nodeDriver.digitalocean.monitoring.label"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -87,9 +94,9 @@
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
{{form-value-array
|
{{form-value-array
|
||||||
initialValues=tags
|
initialValues=tags
|
||||||
addActionLabel='nodeDriver.digitalocean.tags.addActionLabel'
|
addActionLabel="nodeDriver.digitalocean.tags.addActionLabel"
|
||||||
valueLabel='nodeDriver.digitalocean.tags.valueLabel'
|
valueLabel="nodeDriver.digitalocean.tags.valueLabel"
|
||||||
valuePlaceholder='nodeDriver.digitalocean.tags.placeholder'
|
valuePlaceholder="nodeDriver.digitalocean.tags.placeholder"
|
||||||
changed=(action (mut tags))
|
changed=(action (mut tags))
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -105,7 +112,7 @@
|
||||||
|
|
||||||
{{form-user-labels
|
{{form-user-labels
|
||||||
initialLabels=labelResource.labels
|
initialLabels=labelResource.labels
|
||||||
setLabels=(action 'setLabels')
|
setLabels=(action "setLabels")
|
||||||
expandAll=expandAll
|
expandAll=expandAll
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
}}
|
}}
|
||||||
|
|
@ -114,9 +121,9 @@
|
||||||
machine=model
|
machine=model
|
||||||
showEngineUrl=showEngineUrl
|
showEngineUrl=showEngineUrl
|
||||||
}}
|
}}
|
||||||
{{/accordion-list}}
|
|
||||||
|
|
||||||
{{top-errors errors=errors}}
|
{{top-errors errors=errors}}
|
||||||
{{save-cancel save="save" cancel="cancel" editing=editing}}
|
{{save-cancel save="save" cancel="cancel" editing=editing}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/accordion-list}}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const stringsToParams = (params, str) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
};
|
||||||
|
|
||||||
const paramsToStrings = (strs, param) => {
|
const paramsToStrings = (strs, param) => {
|
||||||
if (param.value && param.key) {
|
if (param.value && param.key) {
|
||||||
|
|
@ -31,27 +31,35 @@ const paramsToStrings = (strs, param) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return strs;
|
return strs;
|
||||||
}
|
};
|
||||||
|
|
||||||
const initialVAppOptions = {
|
const initialVAppOptions = {
|
||||||
vappIpprotocol: '',
|
vappIpprotocol: '',
|
||||||
vappIpallocationpolicy: '',
|
vappIpallocationpolicy: '',
|
||||||
vappTransport: '',
|
vappTransport: '',
|
||||||
vappProperty: []
|
vappProperty: []
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDefaultVappOptions = (networks) => ({
|
const getDefaultVappOptions = (networks) => {
|
||||||
|
return {
|
||||||
vappIpprotocol: 'IPv4',
|
vappIpprotocol: 'IPv4',
|
||||||
vappIpallocationpolicy: 'fixedAllocated',
|
vappIpallocationpolicy: 'fixedAllocated',
|
||||||
vappTransport: 'com.vmware.guestInfo',
|
vappTransport: 'com.vmware.guestInfo',
|
||||||
vappProperty: networksToVappProperties(networks)
|
vappProperty: networksToVappProperties(networks)
|
||||||
})
|
};
|
||||||
const networksToVappProperties = (networks) => networks.length === 0
|
};
|
||||||
|
|
||||||
|
const networksToVappProperties = (networks) => {
|
||||||
|
return networks.length === 0
|
||||||
? []
|
? []
|
||||||
: networks.reduce(networkToVappProperties, [
|
: networks.reduce(networkToVappProperties, [
|
||||||
`guestinfo.dns.servers=\${ dns:${ networks[0] } }`,
|
`guestinfo.dns.servers=\${ dns:${ networks[0] } }`,
|
||||||
`guestinfo.dns.domains=\${ searchPath:${ networks[0] } }`
|
`guestinfo.dns.domains=\${ searchPath:${ networks[0] } }`
|
||||||
])
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const networkToVappProperties = (props, network, i) => {
|
const networkToVappProperties = (props, network, i) => {
|
||||||
const n = i.toString();
|
const n = i.toString();
|
||||||
|
|
||||||
|
|
@ -62,7 +70,7 @@ const networkToVappProperties = (props, network, i) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getInitialVappMode = (c) => {
|
const getInitialVappMode = (c) => {
|
||||||
const vappProperty = c.vappProperty || []
|
const vappProperty = c.vappProperty || []
|
||||||
|
|
@ -89,7 +97,7 @@ const getInitialVappMode = (c) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return VAPP_MODE_MANUAL;
|
return VAPP_MODE_MANUAL;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Component.extend(NodeDriver, {
|
export default Component.extend(NodeDriver, {
|
||||||
settings: service(),
|
settings: service(),
|
||||||
|
|
@ -103,6 +111,7 @@ export default Component.extend(NodeDriver, {
|
||||||
vappMode: VAPP_MODE_DISABLED,
|
vappMode: VAPP_MODE_DISABLED,
|
||||||
|
|
||||||
config: alias(`model.${ CONFIG }`),
|
config: alias(`model.${ CONFIG }`),
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.initKeyValueParams('config.cfgparam', 'initParamArray');
|
this.initKeyValueParams('config.cfgparam', 'initParamArray');
|
||||||
|
|
@ -116,6 +125,9 @@ export default Component.extend(NodeDriver, {
|
||||||
},
|
},
|
||||||
vappPropertyChanged(array) {
|
vappPropertyChanged(array) {
|
||||||
this.updateKeyValueParams('config.vappProperty', array);
|
this.updateKeyValueParams('config.vappProperty', array);
|
||||||
|
},
|
||||||
|
finishAndSelectCloudCredential(credential) {
|
||||||
|
set(this, 'model.cloudCredentialId', get(credential, 'id'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,29 +8,18 @@
|
||||||
expand=(action expandFn)
|
expand=(action expandFn)
|
||||||
expandOnInit=true
|
expandOnInit=true
|
||||||
}}
|
}}
|
||||||
<div class="row">
|
|
||||||
<div class="col span-6">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.vmwarevsphere.vcenter.label'}}{{field-required}}</label>
|
|
||||||
{{input type="text" class="form-control" value=config.vcenter placeholder=(t 'nodeDriver.vmwarevsphere.vcenter.placeholder')}}
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.vmwarevsphere.vcenterPort.label'}}{{field-required}}</label>
|
|
||||||
{{input-integer min=1 max=65535 class="form-control" value=config.vcenterPort}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
{{form-auth-cloud-credential
|
||||||
<div class="col span-6">
|
driverName=driverName
|
||||||
<label class="acc-label">{{t 'nodeDriver.vmwarevsphere.username.label'}}{{field-required}}</label>
|
errors=errros
|
||||||
{{input type="text" value=config.username classNames="form-control"}}
|
primaryResource=model
|
||||||
</div>
|
cloudCredentials=cloudCredentials
|
||||||
|
finishAndSelectCloudCredential=(action "finishAndSelectCloudCredential")
|
||||||
|
progressStep=(action "finishAndSelectCloudCredential")
|
||||||
|
cancel=(action "cancel")
|
||||||
|
hideSave=true
|
||||||
|
}}
|
||||||
|
|
||||||
<div class="col span-6">
|
|
||||||
<label class="acc-label">{{t 'nodeDriver.vmwarevsphere.password.label'}}{{field-required}}</label>
|
|
||||||
{{input type="password" value=config.password classNames="form-control"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="help-block">{{t 'nodeDriver.vmwarevsphere.access.help'}}</p>
|
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
||||||
{{#accordion-list-item
|
{{#accordion-list-item
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { hash } from 'rsvp';
|
import { hash } from 'rsvp';
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import { get } from '@ember/object';
|
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
globalStore: service(),
|
globalStore: service(),
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return hash({ nodeTemplates: get(this, 'globalStore').findAll('nodeTemplate') });
|
return hash({
|
||||||
|
nodeTemplates: this.globalStore.findAll('nodeTemplate'),
|
||||||
|
cloudCredential: this.globalStore.findAll('cloudcredential'),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import layout from './template';
|
||||||
|
import { get, set } from '@ember/object';
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
layout,
|
||||||
|
showAddCloudCredential: null,
|
||||||
|
errors: null,
|
||||||
|
hideSave: false,
|
||||||
|
|
||||||
|
createLabel: 'saveCancel.create',
|
||||||
|
savingLabel: 'generic.loading',
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
doneSavingCloudCredential(cred) {
|
||||||
|
if (cred) {
|
||||||
|
get(this, 'finishAndSelectCloudCredential')(cred)
|
||||||
|
|
||||||
|
set(this, 'showAddCloudCredential', false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addCloudCredential() {
|
||||||
|
set(this, 'showAddCloudCredential', true);
|
||||||
|
},
|
||||||
|
cancleNewCloudCredential() {
|
||||||
|
set(this, 'showAddCloudCredential', false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label" for="cloud-credential-selection">
|
||||||
|
{{t "formAuthCloudCredential.label"}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<select
|
||||||
|
id="cloud-credential-selection"
|
||||||
|
class="form-control inline-block"
|
||||||
|
onchange={{action (mut primaryResource.cloudCredentialId) value="target.value"}}
|
||||||
|
disabled={{if showAddCloudCredential true}}
|
||||||
|
style="max-width: 90%;"
|
||||||
|
>
|
||||||
|
|
||||||
|
{{#unless (not-eq primaryResource.cloudCredentialId primaryResource.cloudCredentialId)}}
|
||||||
|
<option
|
||||||
|
value=
|
||||||
|
selected=true
|
||||||
|
>
|
||||||
|
{{t "formAuthCloudCredential.selectCreds.prompt"}}
|
||||||
|
</option>
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
|
{{#each cloudCredentials as |choice|}}
|
||||||
|
<option
|
||||||
|
value={{choice.id}}
|
||||||
|
selected={{eq primaryResource.cloudCredentialId choice.id}}
|
||||||
|
>
|
||||||
|
{{choice.displayName}}
|
||||||
|
</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button
|
||||||
|
{{action "addCloudCredential"}}
|
||||||
|
class="btn btn-sm bg-primary inline-block"
|
||||||
|
style="margin-top: -5px;"
|
||||||
|
>
|
||||||
|
<i class="icon icon-plus"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
{{#if showAddCloudCredential}}
|
||||||
|
<div class="row">
|
||||||
|
{{cru-cloud-credential
|
||||||
|
driverName=driverName
|
||||||
|
errors=errors
|
||||||
|
disableHeader=true
|
||||||
|
doneSavingCloudCredential=(action "doneSavingCloudCredential")
|
||||||
|
cancelAdd=(action "cancleNewCloudCredential")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
{{else}}
|
||||||
|
{{#unless hideSave}}
|
||||||
|
{{save-cancel
|
||||||
|
saveDisabled=(unless primaryResource.cloudCredentialId true)
|
||||||
|
save=progressStep
|
||||||
|
cancel=cancel
|
||||||
|
createLabel=createLabel
|
||||||
|
savingLabel=savingLabel
|
||||||
|
}}
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
|
|
@ -4,20 +4,11 @@ import Mixin from '@ember/object/mixin';
|
||||||
import C from 'ui/utils/constants';
|
import C from 'ui/utils/constants';
|
||||||
|
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
classNames: ['modal-container'/* , 'alert' */],
|
classNames: ['modal-container'],
|
||||||
|
|
||||||
modalService: service('modal'),
|
modalService: service('modal'),
|
||||||
modalOpts: alias('modalService.modalOpts'),
|
modalOpts: alias('modalService.modalOpts'),
|
||||||
// Focus does not want to focus on modal el here, dont know why but
|
|
||||||
// esc wont work if a modal doesnt have a focused element
|
|
||||||
// init() {
|
|
||||||
// this._super(...arguments);
|
|
||||||
// Ember.run.scheduleOnce('afterRender', ()=> {
|
|
||||||
// console.log('Focused: ', this.$());
|
|
||||||
// this.$().focus();
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
keyUp(e) {
|
keyUp(e) {
|
||||||
if (e.which === C.KEY.ESCAPE && this.escToClose()) {
|
if (e.which === C.KEY.ESCAPE && this.escToClose()) {
|
||||||
this.get('modalService').toggleModal();
|
this.get('modalService').toggleModal();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import Mixin from '@ember/object/mixin';
|
||||||
import NewOrEdit from 'shared/mixins/new-or-edit';
|
import NewOrEdit from 'shared/mixins/new-or-edit';
|
||||||
import ManageLabels from 'shared/mixins/manage-labels';
|
import ManageLabels from 'shared/mixins/manage-labels';
|
||||||
import { addAction } from 'ui/utils/add-view-action';
|
import { addAction } from 'ui/utils/add-view-action';
|
||||||
import { get, set, computed } from '@ember/object';
|
import { get, set, computed, setProperties } from '@ember/object';
|
||||||
import { ucFirst } from 'shared/utils/util';
|
import { ucFirst } from 'shared/utils/util';
|
||||||
import C from 'ui/utils/constants';
|
import C from 'ui/utils/constants';
|
||||||
|
|
||||||
|
|
@ -68,11 +68,13 @@ export default Mixin.create(NewOrEdit, ManageLabels, {
|
||||||
|
|
||||||
driverName: null,
|
driverName: null,
|
||||||
showEngineUrl: true, // On some drivers this isn't configurable
|
showEngineUrl: true, // On some drivers this isn't configurable
|
||||||
|
|
||||||
model: null,
|
model: null,
|
||||||
labelResource: alias('model'),
|
labelResource: alias('model'),
|
||||||
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
finishAndSelectCloudCredential() {},
|
||||||
|
|
||||||
addLabel: addAction('addLabel', '.key'),
|
addLabel: addAction('addLabel', '.key'),
|
||||||
|
|
||||||
setLabels(labels) {
|
setLabels(labels) {
|
||||||
|
|
@ -94,13 +96,7 @@ export default Mixin.create(NewOrEdit, ManageLabels, {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
if ( !get(this, 'editing') && typeof get(this, 'bootstrap') === 'function') {
|
if ( !get(this, 'editing') && typeof get(this, 'bootstrap') === 'function') {
|
||||||
if ( get(this, 'showEngineUrl') ) {
|
this.initEngineUrl();
|
||||||
set(this, 'model.engineInstallURL', get(this, `settings.${ C.SETTING.ENGINE_URL }`) || '');
|
|
||||||
set(this, 'model.engineRegistryMirror', []);
|
|
||||||
} else {
|
|
||||||
set(this, 'model.engineInstallURL', null);
|
|
||||||
set(this, 'model.engineRegistryMirror', []);
|
|
||||||
}
|
|
||||||
this.bootstrap();
|
this.bootstrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +107,37 @@ export default Mixin.create(NewOrEdit, ManageLabels, {
|
||||||
// Populate the appropriate *Config field with defaults for your driver
|
// Populate the appropriate *Config field with defaults for your driver
|
||||||
},
|
},
|
||||||
|
|
||||||
|
cloudCredentials: computed('model.cloudCredentialId', 'driverName', function() {
|
||||||
|
const { driverName } = this;
|
||||||
|
|
||||||
|
return this.globalStore.all('cloudcredential').filter((cc) => {
|
||||||
|
switch (driverName) {
|
||||||
|
case 'digitalocean':
|
||||||
|
if (get(cc, 'isDO')) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'amazonec2':
|
||||||
|
if (get(cc, 'isAmazon')) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'azure':
|
||||||
|
if (get(cc, 'isAzure')) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'vmwarevsphere':
|
||||||
|
if (get(cc, 'isVMware')) {
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
driverOptionsTitle: computed('driverName', 'intl.locale', function() {
|
driverOptionsTitle: computed('driverName', 'intl.locale', function() {
|
||||||
const intl = get(this, 'intl');
|
const intl = get(this, 'intl');
|
||||||
const driver = get(this, 'driverName');
|
const driver = get(this, 'driverName');
|
||||||
|
|
@ -131,6 +158,20 @@ export default Mixin.create(NewOrEdit, ManageLabels, {
|
||||||
return intl.t('nodeDriver.templateOptions', { appName });
|
return intl.t('nodeDriver.templateOptions', { appName });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
initEngineUrl() {
|
||||||
|
let engineInstallURL = null;
|
||||||
|
let engineRegistryMirror = [];
|
||||||
|
|
||||||
|
if ( get(this, 'showEngineUrl') ) {
|
||||||
|
engineInstallURL = get(this, `settings.${ C.SETTING.ENGINE_URL }`) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
setProperties(this, {
|
||||||
|
'model.engineInstallURL': engineInstallURL,
|
||||||
|
'model.engineRegistryMirror': engineRegistryMirror,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'shared/components/form-auth-cloud-credential/component';
|
||||||
|
|
@ -643,6 +643,13 @@ catalogPage:
|
||||||
notCompatible: Not Compatible
|
notCompatible: Not Compatible
|
||||||
alreadyDeployed: Already Deployed
|
alreadyDeployed: Already Deployed
|
||||||
|
|
||||||
|
cloudKeysPage:
|
||||||
|
addKey: Add Cloud Key
|
||||||
|
index:
|
||||||
|
table:
|
||||||
|
noData: There are no cloud keys yet
|
||||||
|
noMatch: No cloud keys match the current search
|
||||||
|
|
||||||
clusterCatalogPage:
|
clusterCatalogPage:
|
||||||
header: Catalogs
|
header: Catalogs
|
||||||
|
|
||||||
|
|
@ -4690,6 +4697,13 @@ formAnnotations:
|
||||||
errors:
|
errors:
|
||||||
invalidJSON: Annotation JSON format is invalid.
|
invalidJSON: Annotation JSON format is invalid.
|
||||||
topLevelValueInvalid: Annotation JSON top-level value must be an object.
|
topLevelValueInvalid: Annotation JSON top-level value must be an object.
|
||||||
|
|
||||||
|
formAuthCloudCredential:
|
||||||
|
label: Cloud Credentials
|
||||||
|
selectCreds:
|
||||||
|
prompt: Select a cloud credential
|
||||||
|
|
||||||
|
|
||||||
formJobConfig:
|
formJobConfig:
|
||||||
title: Job Configuration
|
title: Job Configuration
|
||||||
detail: Configure the desired behavior of jobs.
|
detail: Configure the desired behavior of jobs.
|
||||||
|
|
@ -5182,6 +5196,35 @@ modalAddPayment:
|
||||||
euro: "Euro (€)"
|
euro: "Euro (€)"
|
||||||
dollar: "US Dollar ($)"
|
dollar: "US Dollar ($)"
|
||||||
|
|
||||||
|
modalAddCloudKey:
|
||||||
|
header: Add Cloud Credential
|
||||||
|
type: Cloud Credential Type
|
||||||
|
typeSelect:
|
||||||
|
prompt: Choose a cloud credential provider type
|
||||||
|
amazonec2:
|
||||||
|
accessKey:
|
||||||
|
label: Access Key
|
||||||
|
placeholder: Your AWS access key
|
||||||
|
secretKey:
|
||||||
|
label: Secret Key
|
||||||
|
placeholder: Your AWS secret key
|
||||||
|
azure:
|
||||||
|
clientId:
|
||||||
|
label: Client ID
|
||||||
|
placeholder: Your Client ID
|
||||||
|
clientSecret:
|
||||||
|
label: Client Secret
|
||||||
|
placeholder: Your Client Secret
|
||||||
|
digitalocean:
|
||||||
|
accessToken:
|
||||||
|
label: Access Token
|
||||||
|
placeholder: Your DigitalOcean API access token
|
||||||
|
help: |
|
||||||
|
Paste in a Personal Access Token from the DigitalOcean
|
||||||
|
<a href="https://cloud.digitalocean.com/settings/api/tokens" target="_blank" rel="nofollow noreferrer noopener">Applications & API</a> screen
|
||||||
|
vmwarevsphere:
|
||||||
|
password:
|
||||||
|
label: Password
|
||||||
|
|
||||||
modalContainerStop:
|
modalContainerStop:
|
||||||
header: "Are you sure you want to stop"
|
header: "Are you sure you want to stop"
|
||||||
|
|
@ -5190,6 +5233,7 @@ modalContainerStop:
|
||||||
label: Timeout
|
label: Timeout
|
||||||
button: Stop
|
button: Stop
|
||||||
|
|
||||||
|
|
||||||
modalConfirmDeactivate:
|
modalConfirmDeactivate:
|
||||||
header: Are you sure you want to
|
header: Are you sure you want to
|
||||||
protip: "ProTip: Hold the {key} key while clicking {isServiceButton} to bypass this confirmation."
|
protip: "ProTip: Hold the {key} key while clicking {isServiceButton} to bypass this confirmation."
|
||||||
|
|
@ -6735,6 +6779,7 @@ nav:
|
||||||
globalDnsProviders: Providers
|
globalDnsProviders: Providers
|
||||||
multiClusterApps: Multi-Cluster Apps
|
multiClusterApps: Multi-Cluster Apps
|
||||||
security:
|
security:
|
||||||
|
cloudKeys: Cloud Keys
|
||||||
tab: Security
|
tab: Security
|
||||||
roles: Roles
|
roles: Roles
|
||||||
members: Members
|
members: Members
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue