mirror of https://github.com/rancher/ui.git
Add scheduler rules on containers and services
This commit is contained in:
parent
188211a163
commit
2aba2351f5
|
|
@ -1,4 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
model: null,
|
||||
|
|
@ -8,7 +9,7 @@ export default Ember.Component.extend({
|
|||
var obj = this.get('model')||{};
|
||||
var keys = Ember.keys(obj);
|
||||
keys.forEach(function(key) {
|
||||
var isUser = key.indexOf('io.rancher') !== 0;
|
||||
var isUser = key.indexOf(C.LABEL.SYSTEM_PREFIX) !== 0;
|
||||
out.push(Ember.Object.create({
|
||||
key: key,
|
||||
value: obj[key],
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ export default Ember.Component.extend({
|
|||
tagName: 'input',
|
||||
type: 'radio',
|
||||
disabled: false,
|
||||
attributeBindings: ['name', 'type', 'value', 'checked:checked', 'disabled:disabled'],
|
||||
attributeBindings: ['name', 'type', 'checked:checked', 'disabled:disabled'],
|
||||
|
||||
click : function() {
|
||||
this.set('selection', this.$().val());
|
||||
this.set('selection', this.get('value'));
|
||||
},
|
||||
|
||||
checked : function() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,252 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
function splitEquals(str) {
|
||||
var idx = str.indexOf('=');
|
||||
if ( idx === -1 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return [ str.substr(0,idx) , str.substr(idx+1) ];
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
rule: null,
|
||||
instance: null,
|
||||
allHosts: null,
|
||||
|
||||
tagName: 'TR',
|
||||
|
||||
kind: null,
|
||||
suffix: null,
|
||||
userKey: null,
|
||||
userValue: null,
|
||||
|
||||
actions: {
|
||||
setKey: function(key) {
|
||||
this.set('userKey', key);
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this.set('userValue', value);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.sendAction('remove', this.get('rule'));
|
||||
}
|
||||
},
|
||||
|
||||
init: function() {
|
||||
this._super();
|
||||
|
||||
var key = this.get('rule.key')||'';
|
||||
var value = this.get('rule.value')||'';
|
||||
var splitValue = splitEquals(value);
|
||||
|
||||
var match = key.match(/((_soft)?(_ne)?)$/);
|
||||
if ( match )
|
||||
{
|
||||
this.set('suffix', match[1]);
|
||||
key = key.substr(0, key.length - match[1].length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.set('suffix','');
|
||||
}
|
||||
|
||||
// Convert from an existing key into the 4 fields
|
||||
switch ( key )
|
||||
{
|
||||
case C.LABEL.SCHED_CONTAINER:
|
||||
this.setProperties({
|
||||
kind: 'container_name',
|
||||
userKey: '',
|
||||
userValue: value,
|
||||
});
|
||||
break;
|
||||
case C.LABEL.SCHED_CONTAINER_LABEL:
|
||||
if ( splitValue[0] === C.LABEL.SERVICE_NAME )
|
||||
{
|
||||
this.setProperties({
|
||||
kind: 'service_name',
|
||||
userKey: '',
|
||||
userValue: splitValue[1],
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setProperties({
|
||||
kind: 'container_label',
|
||||
userKey: splitValue[0],
|
||||
userValue: splitValue[1],
|
||||
});
|
||||
}
|
||||
break;
|
||||
case C.LABEL.SCHED_HOST_LABEL:
|
||||
this.setProperties({
|
||||
kind: 'host_label',
|
||||
userKey: splitValue[0],
|
||||
userValue: splitValue[1],
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
valuesChanged: function() {
|
||||
var key = '';
|
||||
var value = null;
|
||||
|
||||
var userKey = this.get('userKey')||'';
|
||||
var userValue = this.get('userValue')||'';
|
||||
|
||||
switch ( this.get('kind') )
|
||||
{
|
||||
case 'host_label':
|
||||
key = C.LABEL.SCHED_HOST_LABEL;
|
||||
if ( userKey && userValue )
|
||||
{
|
||||
value = encodeURIComponent(userKey) + '=' + encodeURIComponent(userValue);
|
||||
}
|
||||
break;
|
||||
case 'container_label':
|
||||
key = C.LABEL.SCHED_CONTAINER_LABEL;
|
||||
if ( userKey && userValue )
|
||||
{
|
||||
value = encodeURIComponent(userKey) + '=' + encodeURIComponent(userValue);
|
||||
}
|
||||
break;
|
||||
case 'container_name':
|
||||
key = C.LABEL.SCHED_CONTAINER;
|
||||
if ( userValue )
|
||||
{
|
||||
value = encodeURIComponent(userValue);
|
||||
}
|
||||
break;
|
||||
case 'service_name':
|
||||
key = C.LABEL.SCHED_CONTAINER_LABEL;
|
||||
if ( userValue )
|
||||
{
|
||||
value = encodeURIComponent(C.LABEL.SERVICE_NAME) + '=' + encodeURIComponent(userValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
key += this.get('suffix');
|
||||
|
||||
Ember.setProperties(this.get('rule'),{
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
}.observes('kind','suffix','userKey','userValue'),
|
||||
|
||||
schedulingRuleSuffixChoices: [
|
||||
{label: 'must', value: ''},
|
||||
{label: 'should', value: '_soft'},
|
||||
{label: 'should not', value: '_soft_ne'},
|
||||
{label: 'must not', value: '_ne'},
|
||||
],
|
||||
|
||||
schedulingRuleKindChoices: [
|
||||
{label: 'host label', value: 'host_label'},
|
||||
{label: 'container with label', value: 'container_label'},
|
||||
{label: 'service with the name', value: 'service_name'},
|
||||
{label: 'container with the name', value: 'container_name'},
|
||||
],
|
||||
|
||||
hostLabelKeyChoices: function() {
|
||||
var out = [];
|
||||
this.get('allHosts').forEach((host) => {
|
||||
var keys = Ember.keys(host.get('labels')||{}).filter((key) => {
|
||||
return key.indexOf(C.LABEL.SYSTEM_PREFIX) !== 0;
|
||||
});
|
||||
out.pushObjects(keys);
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('allHosts.@each.labels'),
|
||||
|
||||
hostLabelValueChoices: function() {
|
||||
var key = this.get('userKey');
|
||||
|
||||
var out = [];
|
||||
this.get('allHosts').forEach((host) => {
|
||||
var label = (host.get('labels')||{})[key];
|
||||
if ( label )
|
||||
{
|
||||
var parts = label.split(/\s*,\s*/);
|
||||
out.pushObjects(parts);
|
||||
}
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('userKey','allHosts.@each.labels'),
|
||||
|
||||
allContainers: function() {
|
||||
var out = [];
|
||||
this.get('allHosts').map((host) => {
|
||||
var containers = (host.get('instances')||[]).filter(function(instance) {
|
||||
return instance.get('kind') === 'container' &&
|
||||
!instance.get('systemContainer');
|
||||
});
|
||||
|
||||
out.pushObjects(containers);
|
||||
});
|
||||
|
||||
return out.sortBy('name','id').uniq();
|
||||
}.property('allHosts.@each.instancesUpdated'),
|
||||
|
||||
containerLabelKeyChoices: function() {
|
||||
var out = [];
|
||||
this.get('allContainers').forEach((container) => {
|
||||
var keys = Ember.keys(container.get('labels')||{}).filter((key) => {
|
||||
return key.indexOf(C.LABEL.SYSTEM_PREFIX) !== 0;
|
||||
});
|
||||
out.pushObjects(keys);
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('allContainers.@each.labels'),
|
||||
|
||||
containerLabelValueChoices: function() {
|
||||
var key = this.get('userKey');
|
||||
var out = [];
|
||||
this.get('allContainers').forEach((container) => {
|
||||
var label = (container.get('labels')||{})[key];
|
||||
if ( label )
|
||||
{
|
||||
var parts = label.split(/\s*,\s*/);
|
||||
out.pushObjects(parts);
|
||||
}
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('userKey','allContainers.@each.labels'),
|
||||
|
||||
containerValueChoices: function() {
|
||||
var out = [];
|
||||
this.get('allContainers').forEach((container) => {
|
||||
var name = container.get('name');
|
||||
if ( name )
|
||||
{
|
||||
out.push(name);
|
||||
}
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('allContainers.@each.name'),
|
||||
|
||||
serviceValueChoices: function() {
|
||||
var out = [];
|
||||
this.get('allContainers').forEach((container) => {
|
||||
var label = (container.get('labels')||{})[C.LABEL.SERVICE_NAME];
|
||||
if ( label )
|
||||
{
|
||||
var parts = label.split(/\s*,\s*/);
|
||||
out.pushObjects(parts);
|
||||
}
|
||||
});
|
||||
|
||||
return out.sort().uniq();
|
||||
}.property('allContainers.@each.labels'),
|
||||
});
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
<td><div class="form-control-static input-sm">The host</div></td>
|
||||
<td>
|
||||
{{view "select"
|
||||
class="form-control input-sm"
|
||||
content=schedulingRuleSuffixChoices
|
||||
value=suffix
|
||||
optionValuePath="content.value"
|
||||
optionLabelPath="content.label"
|
||||
}}
|
||||
</td>
|
||||
<td><div class="form-control-static text-center input-sm">have a</div></td>
|
||||
<td>
|
||||
{{view "select"
|
||||
class="form-control input-sm"
|
||||
content=schedulingRuleKindChoices
|
||||
value=kind
|
||||
optionValuePath="content.value"
|
||||
optionLabelPath="content.label"
|
||||
}}
|
||||
</td>
|
||||
<td>
|
||||
{{#if (not (or (eq kind "service_name") (eq kind "container_name")))}}
|
||||
<div class="form-control-static text-center input-sm">of</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td>
|
||||
{{#if (eq kind "host_label")}}
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control input-sm" value=userKey}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each key in hostLabelKeyChoices}}
|
||||
<li><a {{action "setKey" key}}>{{key}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (eq kind "container_label")}}
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control input-sm" value=userKey}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each key in containerLabelKeyChoices}}
|
||||
<li><a {{action "setKey" key}}>{{key}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td>
|
||||
{{#if (not (or (eq kind "service_name") (eq kind "container_name")))}}
|
||||
<div class="form-control-static text-center input-sm">=</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td>
|
||||
{{#if (eq kind "host_label")}}
|
||||
<div {{bind-attr class="hostLabelValueChoices:input-group"}}>
|
||||
{{input type="text" class="form-control input-sm" value=userValue}}
|
||||
{{#if hostLabelValueChoices.length}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each value in hostLabelValueChoices}}
|
||||
<li><a {{action "setValue" value}}>{{value}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (eq kind "container_label")}}
|
||||
<div {{bind-attr class="containerLabelValueChoices:input-group"}}>
|
||||
{{input type="text" class="form-control input-sm" value=userValue}}
|
||||
{{#if containerLabelValueChoices.length}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each value in containerLabelValueChoices}}
|
||||
<li><a {{action "setValue" value}}>{{value}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (eq kind "service_name")}}
|
||||
<div {{bind-attr class="serviceValueChoices:input-group"}}>
|
||||
{{input type="text" class="form-control input-sm" value=userValue}}
|
||||
{{#if serviceValueChoices.length}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each value in serviceValueChoices}}
|
||||
<li><a {{action "setValue" value}}>{{value}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (eq kind "container_name")}}
|
||||
<div {{bind-attr class="containerValueChoices:input-group"}}>
|
||||
{{input type="text" class="form-control input-sm" value=userValue}}
|
||||
{{#if containerValueChoices.length}}
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
{{#each value in containerValueChoices}}
|
||||
<li><a {{action "setValue" value}}>{{value}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<div class="form-control-static input-sm">
|
||||
<button {{action "remove"}} class="btn-circle-x" type="button" tabindex="-1"></button>
|
||||
</div>
|
||||
</td>
|
||||
|
|
@ -12,6 +12,7 @@ export default Ember.View.extend({
|
|||
addDnsSearch: addAction('addDnsSearch', '.dns-search-value'),
|
||||
addDevice: addAction('addDevice', '.device-host'),
|
||||
addLabel: addAction('addLabel', '.label-key'),
|
||||
addSchedulingRule: addAction('addSchedulingRule', '.schedule-rule'),
|
||||
|
||||
selectTab: function(name) {
|
||||
this.set('context.tab',name);
|
||||
|
|
|
|||
|
|
@ -131,7 +131,15 @@ export default Ember.Mixin.create(Cattle.NewOrEditMixin, EditHealthCheck, EditLa
|
|||
ary.removeObject(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
addSchedulingRule: function() {
|
||||
this.send('addSystemLabel');
|
||||
},
|
||||
|
||||
removeSchedulingRule: function(obj) {
|
||||
this.send('removeLabel', obj);
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
|
|
@ -161,6 +169,7 @@ export default Ember.Mixin.create(Cattle.NewOrEditMixin, EditHealthCheck, EditLa
|
|||
this.initMemory();
|
||||
this.initLabels();
|
||||
this.initHealthCheck();
|
||||
this.initScheduling();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -835,6 +844,36 @@ export default Ember.Mixin.create(Cattle.NewOrEditMixin, EditHealthCheck, EditLa
|
|||
}.observes('strEntryPoint'),
|
||||
|
||||
// ----------------------------------
|
||||
// Scheduling
|
||||
// ----------------------------------
|
||||
initScheduling: function() {
|
||||
if ( this.get('instance.requestedHostId') )
|
||||
{
|
||||
this.set('isRequestedHost',true);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.set('isRequestedHost',false);
|
||||
}
|
||||
|
||||
// @TODO import existing for clone
|
||||
},
|
||||
|
||||
isRequestedHost: null,
|
||||
isRequestedHostDidChange: function() {
|
||||
if ( this.get('isRequestedHost') )
|
||||
{
|
||||
if ( !this.get('instance.requestedHostId') )
|
||||
{
|
||||
this.set('instance.requestedHostId', this.get('hostChoices.firstObject.id'));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.set('instance.requestedHostId', null);
|
||||
}
|
||||
}.observes('isRequestedHost'),
|
||||
|
||||
// ----------------------------------
|
||||
// Save
|
||||
// ----------------------------------
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
labelResource: Ember.computed.alias('primaryResource'),
|
||||
|
|
@ -82,6 +83,10 @@ export default Ember.Mixin.create({
|
|||
return (this.get('labelArray')||[]).filterProperty('isUser',true);
|
||||
}.property('labelArray.@each.isUser'),
|
||||
|
||||
systemLabelArray: function() {
|
||||
return (this.get('labelArray')||[]).filterProperty('isUser',false);
|
||||
}.property('labelArray.@each.isUser'),
|
||||
|
||||
initFields: function() {
|
||||
this._super();
|
||||
this.initLabels();
|
||||
|
|
@ -95,7 +100,7 @@ export default Ember.Mixin.create({
|
|||
out.push(Ember.Object.create({
|
||||
key: key,
|
||||
value: obj[key],
|
||||
isUser: key.indexOf('io.rancher') !== 0,
|
||||
isUser: key.indexOf(C.LABEL.SYSTEM_PREFIX) !== 0,
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
@ -108,7 +113,11 @@ export default Ember.Mixin.create({
|
|||
this.get('labelArray').forEach(function(row) {
|
||||
if ( row.key )
|
||||
{
|
||||
out[row.key] = row.value;
|
||||
// System labels have to have a value before they're added, users ones can be just key.
|
||||
if ( row.isUser || row.value )
|
||||
{
|
||||
out[row.key] = row.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.set('labelResource.labels', out);
|
||||
|
|
|
|||
|
|
@ -77,18 +77,22 @@ export default Ember.Mixin.create(EditLabels, {
|
|||
// ----------------------------------
|
||||
// Scheduling
|
||||
// ----------------------------------
|
||||
isScalePlural: Ember.computed.gt('service.scale', 1),
|
||||
isGlobalStr: null,
|
||||
isGlobal: Ember.computed.equal('isGlobalStr','yes'),
|
||||
isGlobal: null,
|
||||
initScheduling: function() {
|
||||
var existing = this.getLabel(C.LABEL.SCHED_GLOBAL);
|
||||
this.set('isGlobalStr', (!!existing ? 'yes' : 'no'));
|
||||
this.set('isGlobal', !!existing);
|
||||
this._super();
|
||||
if ( this.get('isRequestedHost') )
|
||||
{
|
||||
this.set('isGlobal', false);
|
||||
}
|
||||
},
|
||||
|
||||
globalDidChange: function() {
|
||||
if ( this.get('isGlobal') )
|
||||
{
|
||||
this.setLabel(C.LABEL.SCHED_GLOBAL,'true');
|
||||
this.set('isRequestedHost', false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -96,6 +100,13 @@ export default Ember.Mixin.create(EditLabels, {
|
|||
}
|
||||
}.observes('isGlobal'),
|
||||
|
||||
isRequestedHostDidChangeGlobal: function() {
|
||||
if ( this.get('isRequestedHost') )
|
||||
{
|
||||
this.set('isGlobal', false);
|
||||
}
|
||||
}.observes('isRequestedHost'),
|
||||
|
||||
// ----------------------------------
|
||||
// Save
|
||||
// ----------------------------------
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
labelResource: null,
|
||||
|
|
@ -8,7 +9,7 @@ export default Ember.Mixin.create({
|
|||
var obj = this.get('labelResource.labels')||{};
|
||||
var keys = Ember.keys(obj).sort();
|
||||
keys.forEach(function(key) {
|
||||
var isUser = key.indexOf('io.rancher') !== 0;
|
||||
var isUser = key.indexOf(C.LABEL.SYSTEM_PREFIX) !== 0;
|
||||
out.push(Ember.Object.create({
|
||||
key: key,
|
||||
value: obj[key],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Cattle from 'ui/utils/cattle';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
var Service = Cattle.TransitioningResource.extend({
|
||||
type: 'service',
|
||||
|
|
@ -9,9 +10,12 @@ var Service = Cattle.TransitioningResource.extend({
|
|||
}.observes('consumedservices.@each.{id,name,state}'),
|
||||
|
||||
healthState: function() {
|
||||
var isGlobal = Object.keys(this.get('labels')||{}).indexOf(C.LABEL.SCHED_GLOBAL) >= 0;
|
||||
var instances = this.get('instances')||[];
|
||||
|
||||
// Get the state of each instance
|
||||
var healthy = 0;
|
||||
(this.get('instances')||[]).forEach((instance) => {
|
||||
instances.forEach((instance) => {
|
||||
var resource = instance.get('state');
|
||||
var health = instance.get('healthState');
|
||||
|
||||
|
|
@ -21,7 +25,7 @@ var Service = Cattle.TransitioningResource.extend({
|
|||
}
|
||||
});
|
||||
|
||||
if ( healthy >= this.get('scale') )
|
||||
if ( (isGlobal && healthy >= instances.get('length')) || (!isGlobal && healthy >= this.get('scale')) )
|
||||
{
|
||||
return 'healthy';
|
||||
}
|
||||
|
|
@ -34,6 +38,7 @@ var Service = Cattle.TransitioningResource.extend({
|
|||
combinedState: function() {
|
||||
var service = this.get('state');
|
||||
var health = this.get('healthState');
|
||||
|
||||
if ( ['active','updating-active'].indexOf(service) === -1 )
|
||||
{
|
||||
// If the service isn't active, return its state
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
<div class="col-sm-3 col-md-2">
|
||||
<div class="radio small">
|
||||
<label>{{radio-button selection=isGlobalStr value="no"}} Run {{service.scale}} container{{#if isScalePlural}}s{{/if}}</label>
|
||||
<label>{{radio-button selection=isGlobal value=false}} Run {{service.scale}} container{{#if (not (eq service.scale 1))}}s{{/if}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9 col-md-6">
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-12 col-md-8 col-md-push-2">
|
||||
<div class="radio small">
|
||||
<label>{{radio-button selection=isGlobalStr value="yes"}} Always run one instance of this container on every host</label>
|
||||
<label>{{radio-button selection=isGlobal value=true}} Always run one instance of this container on every host</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ export default NewContainerView.extend({
|
|||
actions: {
|
||||
addVolumeFromService: addAction('addVolumeFromService', '.volumefromservice-container'),
|
||||
addServiceLink: addAction('addServiceLink', '.service-link'),
|
||||
addSchedulingRule: addAction('addSchedulingRule', '.schedule-rule'),
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -174,6 +174,8 @@ fieldset[disabled] .btn {
|
|||
}
|
||||
|
||||
.table {
|
||||
margin-bottom: 0;
|
||||
|
||||
& > THEAD > TR > TH,
|
||||
& > THEAD > TR > TD,
|
||||
& > TBODY > TR > TH,
|
||||
|
|
@ -418,3 +420,8 @@ FORM LABEL,
|
|||
.help-block {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ ASIDE {
|
|||
}
|
||||
|
||||
HR {
|
||||
margin: 0 0 15px 0;
|
||||
margin: 8px 0 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label for="description">Description</label>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<div class="row form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label class="form-control-static">Service Links</label>
|
||||
<label>Service Links</label>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-8">
|
||||
<div class="form-control-static">
|
||||
<div>
|
||||
{{#if serviceChoices.length}}
|
||||
<button class="btn-circle-plus" {{action "addServiceLink" target="view"}}></button>
|
||||
{{else}}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
<li role="presentation" class="tab" data-section="healthcheck" {{action "selectTab" "healthcheck" target=view}}><a>Health Check</a></li>
|
||||
<li role="presentation" class="tab" data-section="security" {{action "selectTab" "security" target=view}}><a>Security/Host</a></li>
|
||||
<li role="presentation" class="tab" data-section="labels" {{action "selectTab" "labels" target=view}}><a>Labels</a></li>
|
||||
<li role="presentation" class="tab" data-section="scheduling" {{action "selectTab" "scheduling" target=view}}><a>Scheduling</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
|
@ -46,11 +47,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{#if isService}}
|
||||
<div class="section" data-section="scheduling">
|
||||
{{partial "container/new-scheduling"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="section" data-section="scheduling">
|
||||
{{partial "container/new-scheduling"}}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@
|
|||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
<div class="text-muted" style="font-size: 12px; margin-top: -20px; margin-bottom: 12px;">
|
||||
<div class="text-muted" style="font-size: 12px; margin-bottom: 12px;">
|
||||
ProTip: Paste one or more lines of name=value pairs into any name field for easy bulk entry.
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="row form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label for="userImageUuid" class="form-control-static">Select Image</label>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<label class="form-control-static">{{radio-button selection=isRequestedHost value=true}}
|
||||
{{#if isService}}
|
||||
Run <b>all</b> containers on a specific host
|
||||
{{else}}
|
||||
Run on a specific host
|
||||
{{/if}}</label>
|
||||
{{#if isRequestedHost}}:
|
||||
{{view "select"
|
||||
class="form-control"
|
||||
content=hostChoices
|
||||
value=instance.requestedHostId
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"
|
||||
disabled=(not isRequestedHost)
|
||||
style="display: inline-block; width: auto;"
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="radio">
|
||||
<label>{{radio-button selection=isRequestedHost value=false}}
|
||||
{{#if isService}}
|
||||
Automatically pick hosts for each container matching scheduling rules :
|
||||
{{else}}
|
||||
Automatically pick a host matching scheduling rules :
|
||||
{{/if}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{{#unless isRequestedHost}}
|
||||
<div class="form-control-static">
|
||||
<button class="btn-circle-plus" {{action "addSchedulingRule" target="view"}}></button>
|
||||
</div>
|
||||
{{#if systemLabelArray.length}}
|
||||
<table class="table fixed no-lines no-top-padding tight small">
|
||||
<thead>
|
||||
<tr class="text-muted">
|
||||
<th width="70"></th>
|
||||
<th width="100">Condition</th>
|
||||
<th width="60"></th>
|
||||
<th width="180">Field</th>
|
||||
<th width="30"></th>
|
||||
<th>Key</th>
|
||||
<th width="30"></th>
|
||||
<th>Value</th>
|
||||
<th width="30"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each rule in labelArray}}
|
||||
{{#unless rule.isUser}}
|
||||
{{scheduling-rule-row rule=rule allHosts=allHosts remove="removeSchedulingRule"}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
|
@ -1,16 +1,11 @@
|
|||
<div class="row form-group">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label for="requestedHostId" class="form-control-static">Host</label>
|
||||
<label for="privileged" class="form-control-static">Privileged</label>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3 form-label">
|
||||
{{view "select"
|
||||
prompt="Automatically pick a host"
|
||||
class="form-control"
|
||||
content=hostChoices
|
||||
value=instance.requestedHostId
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"
|
||||
}}
|
||||
<div class="checkbox form-control-static">
|
||||
<label for="privileged">{{input type="checkbox" id="privileged" checked=instance.privileged}} Full access to the host</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
|
|
@ -41,18 +36,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label for="privileged" class="form-control-static">Privileged</label>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-8">
|
||||
<div class="checkbox form-control-static">
|
||||
<label for="privileged">{{input type="checkbox" id="privileged" checked=instance.privileged}} Give the container full access to the host</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-2 form-label">
|
||||
<label class="form-control-static">Capabilities</label>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
<div class="text-muted" style="font-size: 12px; margin-top: -20px; margin-bottom: 12px;">
|
||||
<div class="text-muted" style="font-size: 12px; margin-bottom: 12px;">
|
||||
ProTip: Paste one or more lines of key=value pairs into any key field for easy bulk entry.
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,11 @@ export default {
|
|||
},
|
||||
|
||||
LABEL: {
|
||||
SYSTEM_PREFIX: 'io.rancher.',
|
||||
SERVICE_NAME: 'io.rancher.service.name',
|
||||
SCHED_GLOBAL: 'io.rancher.scheduler.global',
|
||||
SCHED_CONTAINER: 'io.rancher.scheduler.affinity:container',
|
||||
SCHED_HOST_LABEL: 'io.rancher.scheduler.affinity:host_label',
|
||||
SCHED_CONTAINER_LABEL: 'io.rancher.scheduler.affinity:container_label',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"version": "0.23.0-rc1",
|
||||
"version": "0.23.0-rc4",
|
||||
"private": true,
|
||||
"directories": {
|
||||
"doc": "doc",
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
"ember-cli-uglify": "1.0.1",
|
||||
"ember-export-application-global": "^1.0.2",
|
||||
"ember-inline-svg": "^0.1.2",
|
||||
"ember-truth-helpers": "0.0.5",
|
||||
"express": "^4.8.5",
|
||||
"forever-agent": "^0.5.2",
|
||||
"glob": "^5.0.3",
|
||||
|
|
|
|||
Loading…
Reference in New Issue