mirror of https://github.com/rancher/ui.git
commit
dd32c5a049
|
|
@ -1,7 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
import ManageLabels from 'ui/mixins/manage-labels';
|
||||
import { parsePort } from 'ui/utils/parse-port';
|
||||
import { parsePortSpec, parseIpPort } from 'ui/utils/parse-port';
|
||||
|
||||
export default Ember.Component.extend(ManageLabels, {
|
||||
initialPorts: null,
|
||||
|
|
@ -46,7 +46,7 @@ export default Ember.Component.extend(ManageLabels, {
|
|||
var out = [];
|
||||
|
||||
function add(isPublic, str) {
|
||||
var obj = parsePort(str, 'http');
|
||||
var obj = parsePortSpec(str, 'http');
|
||||
obj.setProperties({
|
||||
isPublic: isPublic,
|
||||
ssl: sslPorts.indexOf(obj.get('hostPort')) >= 0,
|
||||
|
|
@ -73,9 +73,12 @@ export default Ember.Component.extend(ManageLabels, {
|
|||
}.observes('listenersArray.[]'),
|
||||
|
||||
sslChanged: function() {
|
||||
var sslPorts = this.get('listenersArray').
|
||||
filterBy('host').
|
||||
filterBy('ssl',true).map((listener) => { return listener.get('host');});
|
||||
var sslPorts = this.get('listenersArray')
|
||||
.filterBy('ssl',true)
|
||||
.map((listener) => { return parseIpPort(listener.get('host'),'http'); })
|
||||
.filterBy('port')
|
||||
.map((obj) => { return obj.port; })
|
||||
.sort().uniq();
|
||||
|
||||
if ( sslPorts.get('length') )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ export default Ember.Component.extend({
|
|||
// Inputs
|
||||
healthCheck: null,
|
||||
errors: null,
|
||||
isService: null,
|
||||
showStrategy: true,
|
||||
|
||||
tagName: '',
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{#if isService}}
|
||||
{{#if (and isService showStrategy)}}
|
||||
<div class="row form-group">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label>When Unhealthy</label>
|
||||
|
|
|
|||
|
|
@ -63,9 +63,9 @@ export default Ember.Component.extend({
|
|||
valuePlaceholder: 'Value',
|
||||
allowEmptyValue: false,
|
||||
addInitialEmptyRow: false,
|
||||
allowMultilineValue: true,
|
||||
|
||||
ary: null,
|
||||
asMap: null,
|
||||
|
||||
actions: {
|
||||
add() {
|
||||
|
|
@ -121,9 +121,17 @@ export default Ember.Component.extend({
|
|||
}
|
||||
},
|
||||
|
||||
asMapObserver: function() {
|
||||
aryObserver: function() {
|
||||
Ember.run.debounce(this,'fireChanged',100);
|
||||
}.observes('ary.@each.{key,value}'),
|
||||
|
||||
fireChanged() {
|
||||
if ( this._state === 'destroying' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var out = {};
|
||||
var outStr = '';
|
||||
|
||||
this.get('ary').forEach((row) => {
|
||||
var k = row.get('key').trim();
|
||||
|
|
@ -132,12 +140,9 @@ export default Ember.Component.extend({
|
|||
if ( k && (v || this.get('allowEmptyValue')) )
|
||||
{
|
||||
out[row.get('key').trim()] = row.get('value').trim();
|
||||
outStr += (outStr ? ',' : '') + k + '=' + v;
|
||||
}
|
||||
});
|
||||
|
||||
this.set('asMap', out);
|
||||
this.sendAction('changed', out);
|
||||
this.sendAction('changedStr', outStr);
|
||||
}.observes('ary.@each.{key,value}'),
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,19 +10,23 @@
|
|||
</tr>
|
||||
{{#each ary as |row|}}
|
||||
<tr>
|
||||
<td data-title="Key">
|
||||
<td class="valign-top" data-title="Key">
|
||||
{{input-paste pasted="pastedLabels" class="form-control input-sm key" type="text" value=row.key placeholder=keyPlaceholder}}
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
<td class="valign-top text-center">
|
||||
<p class="form-control-static input-sm">=</p>
|
||||
</td>
|
||||
|
||||
<td data-title="Value">
|
||||
{{input class="form-control input-sm value" type="text" value=row.value placeholder=valuePlaceholder}}
|
||||
<td class="valign-top" data-title="Value">
|
||||
{{#if allowMultilineValue}}
|
||||
{{textarea-autogrow class="form-control input-sm value" value=row.value placeholder=valuePlaceholder}}
|
||||
{{else}}
|
||||
{{input class="form-control input-sm value" type="text" value=row.value placeholder=valuePlaceholder}}
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class="text-right">
|
||||
<td class="valign-top text-right">
|
||||
<button class="btn btn-primary btn-sm" {{action "remove" row}}><i class="icon icon-minus"/></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import { parsePort } from 'ui/utils/parse-port';
|
||||
import { parsePortSpec } from 'ui/utils/parse-port';
|
||||
|
||||
const protocolOptions = [
|
||||
{label: 'TCP', value: 'tcp'},
|
||||
|
|
@ -34,18 +34,15 @@ export default Ember.Component.extend({
|
|||
if ( typeof value === 'object' )
|
||||
{
|
||||
var existing = !forceNew && !!value.id;
|
||||
var pub = '';
|
||||
if ( value.publicPort )
|
||||
var pub = value.publicPort+'';
|
||||
if ( !existing && value.bindAddress )
|
||||
{
|
||||
if ( value.bindAddress ) {
|
||||
pub += value.bindAddress + ':';
|
||||
}
|
||||
|
||||
pub += value.publicPort;
|
||||
pub = value.bindAddress + ':' + pub;
|
||||
}
|
||||
out.push({
|
||||
existing: existing,
|
||||
obj: value,
|
||||
bindAddress: value.bindAddress||null,
|
||||
public: pub,
|
||||
private: value.privatePort,
|
||||
protocol: value.protocol,
|
||||
|
|
@ -54,7 +51,7 @@ export default Ember.Component.extend({
|
|||
else if ( typeof value === 'string' )
|
||||
{
|
||||
// Strings, from clone
|
||||
var parsed = parsePort(value);
|
||||
var parsed = parsePortSpec(value);
|
||||
out.push({
|
||||
existing: false,
|
||||
public: parsed.host,
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
{{#if portsArray.length}}
|
||||
<table class="table fixed no-lines no-top-padding tight small">
|
||||
<tr class="text-muted">
|
||||
<th>Public (on Host) IP/Port</th>
|
||||
<th>Public Host [IP:]Port</th>
|
||||
<th width="30"> </th>
|
||||
<th>Private (in Container) Port</th>
|
||||
<th>Private Container Port</th>
|
||||
<th width="30"> </th>
|
||||
<th width="60">Protocol</th>
|
||||
<th width="30"> </th>
|
||||
|
|
@ -20,7 +20,16 @@
|
|||
{{#each portsArray as |port|}}
|
||||
<tr>
|
||||
<td>
|
||||
{{input class="form-control input-sm" type="text" value=port.public placeholder="e.g. 80 or 1.2.3.4:80"}}
|
||||
{{#if (and port.existing port.bindAddress)}}
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon input-sm">
|
||||
{{port.bindAddress}}:
|
||||
</span>
|
||||
{{input class="form-control input-sm" type="text" value=port.public placeholder="e.g. 80"}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{input class="form-control input-sm" type="text" value=port.public placeholder="e.g. 80 or 1.2.3.4:80"}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<p class="form-control-static"><i class="icon icon-chevron-right"></i></p>
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@
|
|||
<section class="horizontal-form container-fluid well">
|
||||
{{form-healthcheck
|
||||
isService=true
|
||||
showStrategy=false
|
||||
healthCheck=service.healthCheck
|
||||
}}
|
||||
<div class="alert alert-info">Note: This will only be used if the external service is a target of a load balancer.</div>
|
||||
</section>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ import Ember from 'ember';
|
|||
import { isGecko } from 'ui/utils/platform';
|
||||
|
||||
export default Ember.TextArea.extend({
|
||||
tagName: 'textarea',
|
||||
text: null,
|
||||
classNames: [],
|
||||
paddingAndBorder: null,
|
||||
minHeight: 43,
|
||||
minHeight: 0,
|
||||
maxHeight: 200,
|
||||
|
||||
tagName: 'textarea',
|
||||
classNames: ['no-resize'],
|
||||
|
||||
didInsertElement() {
|
||||
this.set('minHeight', ( this.get('isSmall') ? 31 : 43));
|
||||
this.autoSize();
|
||||
|
||||
this.$().on('paste', () => {
|
||||
|
|
@ -18,9 +19,13 @@ export default Ember.TextArea.extend({
|
|||
},
|
||||
|
||||
keyUp() {
|
||||
this.autoSize();
|
||||
Ember.run.debounce(this,'autoSize',100);
|
||||
},
|
||||
|
||||
isSmall: function() {
|
||||
return this.$().hasClass('input-sm');
|
||||
}.property(),
|
||||
|
||||
autoSize() {
|
||||
let el = this.element;
|
||||
let $el = $(el);
|
||||
|
|
@ -29,7 +34,7 @@ export default Ember.TextArea.extend({
|
|||
$el.css('height', '1px');
|
||||
|
||||
let border = parseInt($el.css('borderTopWidth'),10)||0 + parseInt($el.css('borderBottomWidth'),10)||0;
|
||||
let magic = ( isGecko ? 1 : 2); // Sigh, but it's wrong without magic fudge
|
||||
let magic = (this.get('isSmall') ? -2 : 0) + ( isGecko ? 1 : 2); // Sigh, but it's wrong without magic fudge
|
||||
let neu = Math.max(this.get('minHeight'), Math.min(el.scrollHeight + border + magic, this.get('maxHeight')));
|
||||
|
||||
$el.css('overflowY', (el.scrollHeight > neu ? 'auto' : 'hidden'));
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
<tr>
|
||||
<th width="90">State</th>
|
||||
<th width="150">IP Address</th>
|
||||
<th>Public (on Host)</th>
|
||||
<th>Private (in Container)</th>
|
||||
<th>Public on Host</th>
|
||||
<th>Private in Container</th>
|
||||
<th width="90">Protocol</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ import Service from 'ui/models/service';
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
import Util from 'ui/utils/util';
|
||||
import { parsePort } from 'ui/utils/parse-port';
|
||||
import { parsePortSpec } from 'ui/utils/parse-port';
|
||||
|
||||
const esc = Ember.Handlebars.Utils.escapeExpression;
|
||||
|
||||
function portToStr(spec) {
|
||||
var parts = parsePort(spec);
|
||||
var parts = parsePortSpec(spec);
|
||||
return parts.host + (parts.protocol === 'http' ? '' : '/' + parts.protocol);
|
||||
}
|
||||
|
||||
function specToPort(spec) {
|
||||
var parts = parsePort(spec);
|
||||
var parts = parsePortSpec(spec);
|
||||
return parts.hostPort;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,22 @@ B {
|
|||
background-color : $midGray;
|
||||
}
|
||||
|
||||
|
||||
.inline-block {
|
||||
display : inline-block;
|
||||
}
|
||||
|
||||
.valign-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.valign-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.valign-bottom {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
/**********
|
||||
* Articles (above the page info/warnings)
|
||||
**********/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Ember from 'ember';
|
|||
// hostIp::containerPort
|
||||
// hostPort:containerPort
|
||||
// containerPort
|
||||
export function parsePort(str, defaultProtocol='http') {
|
||||
export function parsePortSpec(str, defaultProtocol='http') {
|
||||
str = str.trim();
|
||||
|
||||
var match, parts, hostIp = '', hostPort, containerPort, protocol;
|
||||
|
|
@ -59,7 +59,7 @@ export function parsePort(str, defaultProtocol='http') {
|
|||
});
|
||||
}
|
||||
|
||||
export function stringifyPort(port, defaultProtocol='http') {
|
||||
export function stringifyPortSpec(port, defaultProtocol='http') {
|
||||
var hostStr = Ember.get(port,'host')||'';
|
||||
var match, hostIp, hostPort;
|
||||
if ( match = hostStr.match(/^((.*):)?([^:]+)$/) )
|
||||
|
|
@ -92,7 +92,81 @@ export function stringifyPort(port, defaultProtocol='http') {
|
|||
return out;
|
||||
}
|
||||
|
||||
// port
|
||||
// 1.2.3.4
|
||||
// 1.2.3.4:port
|
||||
// long:ip:v6::str
|
||||
// [long:ip:v6::str]
|
||||
// [long:ip:v6::str]:port
|
||||
export function parseIpPort(str) {
|
||||
str = str.trim();
|
||||
let colons = str.replace(/[^:]/g,'').length;
|
||||
let index;
|
||||
|
||||
// IPv6, IPv6+port
|
||||
index = str.indexOf(']');
|
||||
if ( colons > 1 )
|
||||
{
|
||||
let index = str.indexOf(']');
|
||||
if ( index > 0 )
|
||||
{
|
||||
let ip = str.substr(0,index+1);
|
||||
let port = null;
|
||||
if ( str.substr(index+1,1) === ':' ) {
|
||||
port = portToInt(str.substr(index+2));
|
||||
}
|
||||
|
||||
return ret(ip,port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret('['+str+']',null);
|
||||
}
|
||||
}
|
||||
|
||||
// IPv4+port
|
||||
index = str.indexOf(':');
|
||||
if ( index >= 0 )
|
||||
{
|
||||
return ret(str.substr(0,index), str.substr(index+1));
|
||||
}
|
||||
|
||||
// IPv4
|
||||
if ( str.match(/[^\d]/) )
|
||||
{
|
||||
return ret(str,null);
|
||||
}
|
||||
|
||||
// Port
|
||||
let port = portToInt(str);
|
||||
if ( port )
|
||||
{
|
||||
return ret(null,port);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
function ret(ip,port) {
|
||||
return {
|
||||
ip: ip || null,
|
||||
port: portToInt(port)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function portToInt(str) {
|
||||
str = (str+'').trim();
|
||||
if ( str.match(/^\d+$/) )
|
||||
{
|
||||
return parseInt(str,10) || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default {
|
||||
parsePort: parsePort,
|
||||
stringifyPort: stringifyPort,
|
||||
parsePortSpec: parsePortSpec,
|
||||
stringifyPortSpec: stringifyPortSpec,
|
||||
parseIpPort: parseIpPort,
|
||||
portToInt: portToInt
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import { parsePort, stringifyPort } from 'ui/utils/parse-port';
|
||||
import { parsePortSpec, stringifyPortSpec, parseIpPort } from 'ui/utils/parse-port';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Utils | parse-port');
|
||||
|
|
@ -21,28 +21,66 @@ var data = [
|
|||
|
||||
data.forEach(function(obj) {
|
||||
var input = obj.str;
|
||||
var actual = parsePort(input);
|
||||
var actual = parsePortSpec(input);
|
||||
|
||||
if ( obj.parsed )
|
||||
{
|
||||
test('it can parse: ' + obj.str, function(assert) {
|
||||
test('it can parse spec: ' + obj.str, function(assert) {
|
||||
var expected = obj.parsed;
|
||||
Object.keys(expected).forEach((key) => {
|
||||
assert.strictEqual(Ember.get(actual,key), Ember.get(expected, key), key + ' parses correctly');
|
||||
});
|
||||
});
|
||||
|
||||
test('it can stringify: ' + obj.str, function(assert) {
|
||||
test('it can stringify spec: ' + obj.str, function(assert) {
|
||||
var input = obj.parsed;
|
||||
var expected = obj.expected || obj.str;
|
||||
var actual = stringifyPort(input);
|
||||
var actual = stringifyPortSpec(input);
|
||||
assert.strictEqual(actual, expected, 'Objects are stringified correctly');
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
test("it can't parse: " + obj.str, function(assert) {
|
||||
test("it can't parse spec: " + obj.str, function(assert) {
|
||||
assert.strictEqual(actual, null, 'Invalid data is not parseable');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
data = [
|
||||
{str: '', parsed: null},
|
||||
{str: '80', parsed: {ip: null, port: 80 }},
|
||||
{str: 'asdf', parsed: {ip: 'asdf', port: null}},
|
||||
{str: '1.2.3.4', parsed: {ip: '1.2.3.4', port: null}},
|
||||
{str: '1.2.3.4:80', parsed: {ip: '1.2.3.4', port: 80 }},
|
||||
{str: '1.2.3.4:12ab', parsed: {ip: '1.2.3.4', port: null}},
|
||||
{str: 'asdf:12ab', parsed: {ip: 'asdf', port: null}},
|
||||
{str: '80asdf', parsed: {ip: '80asdf', port: null}},
|
||||
{str: '12:34:56::78', parsed: {ip: '[12:34:56::78]', port: null}},
|
||||
{str: '[12:34:56::78]', parsed: {ip: '[12:34:56::78]', port: null}},
|
||||
{str: '[12:34:56::78]:80', parsed: {ip: '[12:34:56::78]', port: 80 }},
|
||||
{str: '[12:34:56::78]:asdf', parsed: {ip: '[12:34:56::78]', port: null}},
|
||||
{str: '[12:34:56::78]:90:ab', parsed: {ip: '[12:34:56::78]', port: null}},
|
||||
{str: '2001:0db8:85a3:0000:0000:8a2e:0370:7334', parsed: {ip: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', port: null}},
|
||||
{str: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:80', parsed: {ip: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', port: 80}},
|
||||
];
|
||||
|
||||
data.forEach(function(obj) {
|
||||
var input = obj.str;
|
||||
var actual = parseIpPort(input);
|
||||
|
||||
test('it can parse: ' + obj.str, function(assert) {
|
||||
var expected = obj.parsed;
|
||||
|
||||
if ( expected === null )
|
||||
{
|
||||
assert.strictEqual(actual, null, input + ' cannot be parsed');
|
||||
}
|
||||
else
|
||||
{
|
||||
Object.keys(expected).forEach((key) => {
|
||||
assert.strictEqual(Ember.get(actual,key), Ember.get(expected, key), key + ' parses correctly');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue