Merge pull request #1661 from loganhz/fix

workload port
This commit is contained in:
Vincent Fiduccia 2018-02-26 21:38:02 -07:00 committed by GitHub
commit 84b4bf2c7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 240 additions and 155 deletions

View File

@ -5,8 +5,8 @@ import Component from '@ember/component';
import layout from './template';
const protocolOptions = [
{label: 'TCP', value: 'TCP'},
{label: 'UDP', value: 'UDP'}
{ label: 'TCP', value: 'TCP' },
{ label: 'UDP', value: 'UDP' }
];
export default Component.extend({
@ -14,46 +14,34 @@ export default Component.extend({
intl: service(),
initialPorts: null,
showIp: null,
showNaming: null,
editing: false,
kindChoices: null,
ports: null,
protocolOptions : protocolOptions,
protocolOptions: protocolOptions,
init() {
this._super(...arguments);
let ports = get(this, 'initialPorts');
if ( ports ) {
ports = ports.map((obj) => {
const out = obj.cloneForNew()
set(out, 'existing', true);
if ( get(obj, 'hostIP') ) {
set(this, 'showIp', true);
}
return out;
});
} else {
ports = [];
}
set(this, 'ports', ports);
this.initPorts();
this.initKindChoices();
},
actions: {
addPort() {
this.get('ports').pushObject(get(this,'store').createRecord({
this.get('ports').pushObject(get(this, 'store').createRecord({
type: 'containerPort',
containerPort: '',
hostPort: '',
hostIP: '',
protocol: 'TCP'
dnsName: '',
hostIp: '',
kind: 'HostPort',
name: '',
protocol: 'TCP',
sourcePort: '',
}));
next(() => {
if ( this.isDestroyed || this.isDestroying ) {
if (this.isDestroyed || this.isDestroying) {
return;
}
@ -65,44 +53,53 @@ export default Component.extend({
this.get('ports').removeObject(obj);
},
showIp() {
this.set('showIp', true);
showNaming() {
this.set('showNaming', true);
},
},
portsChanged: observer('ports.@each.{containerPort,hostPort,hostIP,protocol}', function() {
initPorts: function () {
let ports = get(this, 'initialPorts');
if (ports) {
ports = ports.map((obj) => {
const out = obj.cloneForNew()
set(out, 'existing', true);
if (get(obj, 'dnsName') || get(obj, 'name')) {
set(this, 'showNaming', true);
}
return out;
});
} else {
ports = [];
}
set(this, 'ports', ports);
},
initKindChoices: function () {
const kindChoices = this.get('store').getById('schema', 'containerport').get('resourceFields.kind').options.sort();
set(this, 'kindChoices', kindChoices.map(k => {
return {
translationKey: `formPorts.kind.${k}`,
value: k
};
}));
},
portsChanged: observer('ports.@each.{containerPort,dnsName,hostIp,kind,name,protocol,sourcePort}', function() {
const errors = [];
const seen = {};
const intl = get(this, 'intl');
const ports = get(this, 'ports');
ports.forEach((obj) => {
let hostIP = obj.hostIP;
let containerPort = obj.containerPort;
let hostPort = obj.hostPort;
let protocol = obj.protocol;
errors.pushObjects(obj.validationErrors());
if ( !containerPort && (hostPort || hostIP) ) {
if ( !containerPort ) {
errors.push(intl.t('formPorts.error.privateRequired'));
}
if ( hostIP && !hostPort ) {
errors.push(intl.t('formPorts.error.publicRequired'));
}
if ( hostPort ) {
const key = '['+ (hostIP||'0.0.0.0') + ']:' + hostPort + '/' + protocol;
if ( seen[key] ) {
errors.push(intl.t('formPorts.error.'+(hostIP ? 'mixedIpPort' : 'mixedPort'), {
ip: hostIP,
port: hostPort,
proto: protocol
}));
} else {
seen[key] = true;
}
if ( !obj.sourcePort ) {
delete obj['sourcePort'];
}
});

View File

@ -1,85 +1,104 @@
<div class="clearfix {{unless editing 'box'}}">
<label class="{{if editing 'acc-label'}}">{{t 'formPorts.header'}}</label>
{{#if (and ports.length (not showIp))}}
{{#if (and ports.length (not showNaming))}}
{{#if editing}}
<div class="pull-right text-small">
<a role="button" class="btn bg-transparent p-0" {{action "showIp"}}>
{{t 'formPorts.showIpLink'}}
<a role="button" class="btn bg-transparent p-0" {{action "showNaming"}}>
{{t 'formPorts.showNamingLink'}}
</a>
</div>
{{/if}}
{{/if}}
{{#if ports.length}}
<table class="table fixed no-lines small mb-10">
<thead>
<tr class="hidden-sm">
{{#if showIp}}
<th>{{t 'formPorts.hostIp.label'}}</th>
<table class="table fixed no-lines small mb-10">
<thead>
<tr class="hidden-sm">
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.kind.label'}}</th>
<th width="10"></th>
{{/if}}
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.hostPort.label'}}</th>
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.containerPort.label'}}{{#if editing}}{{field-required}}{{/if}}</th>
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}" width="80">{{t 'formPorts.protocol.label'}}</th>
<th width="40">&nbsp;</th>
</tr>
</thead>
<tbody>
{{#each ports as |port|}}
<tr>
{{#if showIp}}
<td data-title="{{t 'formPorts.hostPort.label'}}">
{{#if port.existing}}
{{#if port.hostIP}}
{{port.hostIP}}
{{else}}
<span class="text-muted">{{t 'generic.any'}}</span>
{{/if}}
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.sourcePort.label'}}</th>
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.containerPort.label'}}{{#if editing}}{{field-required}}{{/if}}</th>
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}" width="80">{{t 'formPorts.protocol.label'}}</th>
{{#if showNaming}}
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.name.label'}}</th>
<th width="10"></th>
<th class="{{unless editing 'acc-label'}}">{{t 'formPorts.dnsName.label'}}</th>
{{/if}}
<th width="40">&nbsp;</th>
</tr>
</thead>
<tbody>
{{#each ports as |port|}}
<tr>
<td data-title="{{t 'formPorts.kind.label'}}">
{{#if editing}}
{{new-select
classNames="form-control"
optionValuePath="value"
optionLabelPath="translationKey"
localizedLabel=true
content=kindChoices
value=port.kind
}}
{{else}}
{{#if editing}}
{{input class="form-control input-sm" type="text" value=port.hostIP placeholder=(t 'formPorts.hostIp.placeholder')}}
{{#if port.kind}}
{{port.kind}}
{{else}}
{{#if port.hostIP}}
{{port.hostIP}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
{{/if}}
</td>
<td>&nbsp;</td>
<td data-title="{{t 'formPorts.sourcePort.label'}}">
{{#if (eq port.kind "HostPort")}}
{{#if editing}}
{{input-random-port min="30000" max="32767" value=port.sourcePort placeholder="formPorts.nodePort.placeholder"}}
{{else if port.sourcePort}}
{{port.sourcePort}}
{{else}}
{{t 'generic.random'}}
{{/if}}
{{else if (eq port.kind "NodePort")}}
<div class="row">
{{#if editing}}
<div class="col span-15-of-24 p-0">
{{input class="form-control input-sm" type="text" value=port.hostIp placeholder=(t 'formPorts.hostIp.placeholder')}}
</div>
<div class="col span-1-of-24 p-0 text-center mt-10">
:
</div>
<div class="col span-8-of-24 p-0">
{{input-integer class="form-control input-sm" min="1" max="65535" value=port.sourcePort placeholder=(t 'formPorts.sourcePort.placeholder')}}
</div>
{{else if port.hostIp}}
{{port.hostIp}}:{{port.sourcePort}}
{{else}}
{{port.sourcePort}}
{{/if}}
</div>
{{else}}
{{#if editing}}
{{input-integer class="form-control input-sm" min="1" max="65535" value=port.sourcePort placeholder=(t 'formPorts.sourcePort.placeholder')}}
{{else}}
{{port.sourcePort}}
{{/if}}
{{/if}}
</td>
<td>&nbsp;</td>
{{/if}}
<td data-title="{{t 'formPorts.hostPort.label'}}">
{{#if editing}}
{{input-integer class="form-control input-sm public" min="1" max="65535" value=port.hostPort placeholder=(t 'formPorts.hostPort.placeholder')}}
{{else}}
{{port.hostPort}}
{{/if}}
</td>
<td>&nbsp;</td>
<td data-title="{{t 'formPorts.containerPort.label'}}">
{{#if port.existing}}
<div class="text-muted">{{port.containerPort}}</div>
{{else}}
<td data-title="{{t 'formPorts.containerPort.label'}}">
{{#if editing}}
{{input-integer class="form-control input-sm" min="1" max="65535" value=port.containerPort placeholder=(t 'formPorts.containerPort.placeholder')}}
{{input-integer class="form-control input-sm public" min="1" max="65535" value=port.containerPort placeholder=(t 'formPorts.containerPort.placeholder')}}
{{else}}
{{port.containerPort}}
{{/if}}
{{/if}}
</td>
<td>&nbsp;</td>
</td>
<td>&nbsp;</td>
<td data-title="{{t 'formPorts.protocol.label'}}">
{{#if port.existing}}
<div class="text-muted">{{upper-case port.protocol}}</div>
{{else}}
<td data-title="{{t 'formPorts.protocol.label'}}">
{{#if editing}}
{{new-select
class="form-control input-sm"
@ -89,29 +108,42 @@
{{else}}
{{port.protocol}}
{{/if}}
{{/if}}
</td>
</td>
<td>
{{#if port.existing}}
&nbsp;
{{else}}
{{#if showNaming}}
<td>&nbsp;</td>
<td data-title="{{t 'formPorts.name.label'}}">
{{#if editing}}
{{input class="form-control input-sm" type="text" value=port.name placeholder=(t 'formPorts.name.placeholder')}}
{{else}}
{{port.name}}
{{/if}}
</td>
<td>&nbsp;</td>
<td data-title="{{t 'formPorts.dnsName.label'}}">
{{#if editing}}
{{input class="form-control input-sm" type="text" value=port.dnsName placeholder=(t 'formPorts.dnsName.placeholder')}}
{{else}}
{{port.dnsName}}
{{/if}}
</td>
{{/if}}
<td>
{{#if editing}}
<button class="btn bg-primary btn-sm" {{action "removePort" port}}>
<i class="icon icon-minus"/><span class="sr-only">{{t 'generic.remove'}}</span>
</button>
{{/if}}
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
{{#unless editing}}
<span class="text-center text-muted">{{t 'formPorts.noPorts'}}</span>
{{/unless}}
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
{{#unless editing}}
<span class="text-center text-muted">{{t 'formPorts.noPorts'}}</span>
{{/unless}}
{{/if}}
</div>
<div>

View File

@ -54,28 +54,27 @@
</div>
<hr class="mt-30 mb-30" />
<div class="row">
<div class="col span-11-of-23 mt-0 mb-0">
{{container/form-ports
initialPorts=launchConfig.ports
changed=(action (mut launchConfig.ports))
errors=portErrors
{{container/form-ports
initialPorts=launchConfig.ports
changed=(action (mut launchConfig.ports))
errors=portErrors
editing=true
}}
</div>
<hr class="mt-30 mb-30" />
<div class="row">
{{form-key-value
initialMap=launchConfig.environment
changed=(action (mut launchConfig.environment))
allowEmptyValue=true
editing=true
}}
</div>
<div class="col span-11-of-23 mt-0 mb-0 offset-1-of-23">
{{form-key-value
initialMap=launchConfig.environment
changed=(action (mut launchConfig.environment))
allowEmptyValue=true
editing=true
header=(t 'newContainer.environment.label')
addActionLabel="newContainer.environment.addAction"
keyLabel="newContainer.environment.keyLabel"
keyPlaceholder="newContainer.environment.keyPlaceholder"
valueLabel="newContainer.environment.valueLabel"
valuePlaceholder="newContainer.environment.valuePlaceholder"
}}
</div>
header=(t 'newContainer.environment.label')
addActionLabel="newContainer.environment.addAction"
keyLabel="newContainer.environment.keyLabel"
keyPlaceholder="newContainer.environment.keyPlaceholder"
valueLabel="newContainer.environment.valueLabel"
valuePlaceholder="newContainer.environment.valuePlaceholder"
}}
</div>
<hr class="mt-30 mb-30" />

View File

@ -0,0 +1,36 @@
import { set, get } from '@ember/object';
import Component from '@ember/component';
import layout from './template';
import { next } from '@ember/runloop';
export default Component.extend({
layout,
showEdit: false,
min: '1',
max: '65535',
value: null,
placeholder: null,
init() {
this._super(...arguments);
if (get(this, 'value')) {
set(this, 'showEdit', true);
}
},
actions: {
showEdit() {
set(this, 'showEdit', true);
next(() => {
if (this.isDestroyed || this.isDestroying) {
return;
}
this.$('INPUT').last()[0].focus();
});
}
}
});

View File

@ -0,0 +1,5 @@
{{#if showEdit}}
{{input-integer class="form-control input-sm" min=min max=max value=value placeholder=(t placeholder)}}
{{else}}
<div class="edit btn" {{action "showEdit"}}>{{t 'generic.random'}} <i class="icon icon-edit"></i></div>
{{/if}}

View File

@ -0,0 +1 @@
export { default } from 'shared/components/input-random-port/component';

View File

@ -66,6 +66,7 @@ generic:
ports: Ports
remove: Remove
role: Role
random: Random
save: Save
saved: Saved
saving: Saving
@ -2404,24 +2405,38 @@ formNetwork:
formPorts:
header: Port Mapping
addAction: Add Port
kind:
label: Publish on
HostPort: Every node
NodePort: Nodes running the pod
ClusterIP: Internal cluster IP
LoadBalancer: Load Balancer
hostIp:
label: Host IP
placeholder: "Default: All"
hostPort:
label: Host Port
placeholder: "Optional: Host IP e.g. 1.2.3.4"
sourcePort:
label: Source Port
placeholder: "e.g. 80"
nodePort:
placeholder: "e.g. 30000"
containerPort:
label: Container Port
placeholder: "e.g. 8080"
protocol:
label: Protocol
name:
label: Name
placeholder: "e.g. backend"
dnsName:
label: DNS Name
placeholder: "e.g. example"
noPorts: This container has no port maps.
error:
privateRequired: Private Container Port is required for each port rule.
publicRequired: Public Host Port is required if Host IP is specified.
mixedIpPort: "Port {ip}:{port}/{proto} has more than one mapping."
mixedPort: "Port {port}/{proto} has more than one mapping."
showIpLink: Customize Host IPs
showNamingLink: Show Port Naming Options
formScale:
label: Scale