Containers back to an array

This commit is contained in:
Vincent Fiduccia 2017-12-19 15:45:31 -07:00
parent 4fce6b95d6
commit df1cf5f08e
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
17 changed files with 169 additions and 63 deletions

View File

@ -1,5 +1,6 @@
import EmberObject from '@ember/object';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import Route from '@ember/routing/route';
import Ember from 'ember';
import C from 'ui/utils/constants';
@ -55,7 +56,7 @@ export default Route.extend({
}
const clone = _workload.clone();
const containerNames = Object.keys(service.containers);
const containerNames = service.containers.map(x => get(x, name));
let containerName = params.containerName;
// Add a sidekick
@ -90,10 +91,10 @@ export default Route.extend({
let container;
if ( containerName === "" ) {
// The primary/only container
container = service.containers[containerNames[0]];
container = service.containers[0];
} else {
// Existing container
container = service.containers[containerName];
container = service.containers.findBy('name', containerName);
}
if ( params.upgrade ) {
@ -145,7 +146,7 @@ export default Route.extend({
namespaceId: namespaceId,
scale: 1,
restart: 'Always',
containers: {},
containers: [],
});
},

View File

@ -1,6 +1,7 @@
import { later, cancel } from '@ember/runloop';
import { computed, get } from '@ember/object';
import { alias } from '@ember/object/computed';
import { alias, gt } from '@ember/object/computed';
import Resource from 'ember-api-store/models/resource';
import C from 'ui/utils/constants';
import { sortableNumericSuffix } from 'shared/utils/util';
@ -365,9 +366,7 @@ var Workload = Resource.extend(DisplayImage, StateCounts, EndpointPorts, {
return this.get('intl').t('servicePage.type.'+ type);
}.property('lcType','isSelector','intl.locale'),
hasSidekicks: function() {
return Object.keys(get(this,'containers')).length > 1;
}.property('containers'),
hasSidekicks: gt('containers.length', 1),
activeIcon: function() {
return activeIcon(this);

View File

@ -14,11 +14,11 @@ export default Route.extend({
setupController(controller, model) {
this._super(...arguments);
let containers = model.get('workload.containers');
let keys = Object.keys(containers);
let lc = model.get('workload.containers.firstObject');
controller.setProperties({
fixedLaunchConfig: containers[keys[0]],
activeLaunchConfig: containers[keys[0]],
fixedLaunchConfig: lc,
activeLaunchConfig: lc,
});
}
});

View File

@ -49,7 +49,7 @@ export default Component.extend({
type: 'googleKubernetesEngineConfig',
diskSizeGb: 100,
enableAlphaFeature: false,
masterVersion: '1.8.4-gke.0',
masterVersion: '1.8.4-gke.1',
nodeCount: 3,
machineType: 'n1-standard-1',
zone: 'us-central1-f',

View File

@ -1,7 +1,7 @@
export const versions = {
"defaultClusterVersion": "1.7.8-gke.0",
"validNodeVersions": [
"1.8.4-gke.0",
"1.8.4-gke.1",
"1.8.3-gke.0",
"1.8.2-gke.0",
"1.8.1-gke.1",
@ -25,7 +25,7 @@ export const versions = {
"UBUNTU"
],
"validMasterVersions": [
"1.8.4-gke.0",
"1.8.4-gke.1",
"1.8.3-gke.0",
"1.8.2-gke.0",
"1.8.1-gke.1",

View File

@ -46,7 +46,8 @@ export default Component.extend(NewOrEdit, {
imageErrors: null,
portErrors: null,
namespaceErrors: null,
metadataErrors: null,
labelErrors: null,
annotationErrors: null,
actions: {
setImage(uuid) {
@ -206,7 +207,8 @@ export default Component.extend(NewOrEdit, {
errors.pushObjects(this.get('imageErrors')||[]);
errors.pushObjects(this.get('portErrors')||[]);
errors.pushObjects(this.get('namespaceErrors')||[]);
errors.pushObjects(this.get('metadataErrors')||[]);
errors.pushObjects(this.get('labelErrors')||[]);
errors.pushObjects(this.get('annotationErrors')||[]);
errors = errors.uniq();
@ -287,10 +289,16 @@ export default Component.extend(NewOrEdit, {
nameResource = pr;
}
pr.containers[this.get('name')] = this.get('launchConfig').clone();
const existing = pr.containers.findBy('name', name);
if ( existing ) {
pr.removeObject(existing);
}
set(lc, 'name', name);
pr.containers.push(lc);
nameResource.setProperties({
name: this.get('name'),
name: name,
description: this.get('description'),
});

View File

@ -183,16 +183,17 @@
{{form-user-labels
classNames="accordion-wrapper"
errors=labelErrors
initialLabels=launchConfig.labels
setLabels=(action 'setLabels' 'user')
expandAll=al.expandAll
expandFn=expandFn
}}
{{form-metadata
{{form-annotations
classNames="accordion-wrapper"
instance=launchConfig
errors=metadataErrors
errors=annotationErrors
expandAll=al.expandAll
expandFn=expandFn
}}

View File

@ -13,7 +13,7 @@ export default Component.extend({
intl: service(),
instance: null,
detailKey: 'formMetadata.detail',
detailKey: 'formAnnotations.detail',
errors: null,
valid: true,
@ -30,22 +30,22 @@ export default Component.extend({
validate: function () {
let intl = this.get('intl');
if ( this.get('valid') ) {
if ( ['object', 'null'].indexOf(typeOf(this.get('instance.metadata'))) === -1 ) {
this.set('errors', [intl.t('formMetadata.errors.topLevelValueInvalid')]);
if ( ['object', 'null'].indexOf(typeOf(this.get('instance.annotations'))) === -1 ) {
this.set('errors', [intl.t('formAnnotations.errors.topLevelValueInvalid')]);
} else {
this.set('errors', []);
}
} else {
this.set('errors', [intl.t('formMetadata.errors.invalidJSON')]);
this.set('errors', [intl.t('formAnnotations.errors.invalidJSON')]);
}
}.observes('valid', 'instance.metadata'),
}.observes('valid', 'instance.annotations'),
statusClass: null,
status: function () {
let k;
if (this.get('errors.length') ) {
k = STATUS.ERROR;
} else if (!isNone(this.get('instance.metadata')) && Object.keys(this.get('instance.metadata')).length > 0) {
} else if (!isNone(this.get('instance.annotations')) && Object.keys(this.get('instance.annotations')).length > 0) {
k = STATUS.CONFIGURED;
} else {
k = STATUS.NOTCONFIGURED;

View File

@ -1,10 +1,10 @@
{{#accordion-list-item
title=(t 'formMetadata.title')
title=(t 'formAnnotations.title')
detail=(t detailKey appName=settings.appName)
status=status
statusClass=statusClass
expandAll=expandAll
expand=(action expandFn)
}}
{{json-editor json=instance.metadata isValid=valid}}
{{json-editor json=instance.annotations isValid=valid}}
{{/accordion-list-item}}

View File

@ -1,4 +1,5 @@
import { next } from '@ember/runloop';
import { get, set } from '@ember/object';
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import ManageLabels from 'shared/mixins/manage-labels';
@ -24,6 +25,13 @@ export default Component.extend(ManageLabels, {
// Inputs
initialLabels: null,
init() {
this._super(...arguments);
this.initLabels(this.get('initialLabels'),'user', null, this.get('readonlyLabels'));
this.labelsChanged();
},
actions: {
addUserLabel() {
this._super();
@ -45,16 +53,18 @@ export default Component.extend(ManageLabels, {
}
},
init() {
this._super(...arguments);
this.initLabels(this.get('initialLabels'),'user', null, this.get('readonlyLabels'));
this.labelsChanged();
},
updateLabels(labels) {
this.sendAction('setLabels', labels);
this.validate();
},
validate() {
let errors = [];
(this.get('labelArray')||[]).forEach((obj) => {
});
set(this, 'errors', errors);
},
statusClass: null,

View File

@ -31,12 +31,12 @@ export default Component.extend({
const out = [];
get(this, 'pods').forEach((pod) => {
const containers = get(pod, 'containers');
Object.keys(containers).forEach((name) => {
containers.forEach((container) => {
out.push(EmberObject.create({
pod: pod,
name: name,
name: get(container, 'name'),
podId: get(pod, 'id'),
container: containers[name],
container: container,
sortStr: get(pod,'name') + '_' + name,
}));
});

View File

@ -1,5 +1,6 @@
import { inject as service } from '@ember/service';
import { computed, get } from '@ember/object';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import C from 'ui/utils/constants';
import layout from './template';
@ -29,14 +30,12 @@ export default Component.extend({
},
canExpand: computed('expandPlaceholder', 'model.containers', function() {
return get(this,'expandPlaceholder') && Object.keys(get(this,'model.containers')).length > 1;
return get(this,'expandPlaceholder') && get(this,'model.containers.length') > 1;
}),
statsAvailable: computed('model.{state,healthState}', function() {
return C.ACTIVEISH_STATES.indexOf(this.get('model.state')) >= 0 && this.get('model.healthState') !== 'started-once';
}),
containers: computed('model.containers', function() {
return Object.values(get(this,'model.containers'));
}),
containers: alias('model.containers'),
});

View File

@ -6,15 +6,15 @@ export default Mixin.create({
intl: service(),
displayImage: computed('containers', function() {
const containers = get(this, 'containers')||{};
const names = Object.keys(containers);
const containers = get(this, 'containers')||[];
const count = get(containers, 'length');
if ( names.length > 1 ) {
return get(this,'intl').t('pagination.image', {pages: 1, count: names.length});
} else if ( names.length ) {
return get(containers[names[0]], 'image');
if ( count > 1 ) {
return get(this,'intl').t('pagination.image', {pages: 1, count: count});
} else if ( count ) {
return get(containers, 'firstObject.image');
} else {
return 'Unknown';
return get(this, 'intl').t('generic.unknown');
}
}),
});

View File

@ -0,0 +1,78 @@
import { validateChars, validateHostname } from 'ember-api-store/utils/validate';
export function parseKey(str) {
str = str||'';
const idx = str.indexOf('/');
if ( idx > 0 ) {
const prefix = str.substr(0,idx);
const key = str.substr(idx+1);
return {
str,
prefix,
key
}
} else {
return {
str,
prefix: null,
key: str,
}
}
}
const MIDDLE_ONLY = ['_','.','-'];
export function validateIdentifier(str, displayKey, intl, errors=[]) {
validateChars(str, {validChars: 'A-Za-z0-9_.-'}, displayKey, intl, errors);
// Indentifier cannot begin with a hyphen
let chr = str.slice(0,1);
if ( MIDDLE_ONLY.includes(chr) ) {
errors.push(intl.t(`validation.k8s.identifier.startLetter`, {key: displayKey}));
}
// Label cannot end with a hyphen
chr = str.slice(-1);
if ( MIDDLE_ONLY.includes(chr) ) {
errors.push(intl.t(`validation.k8s.identifier.endLetter`, {key: displayKey}));
}
// Label must be 1-63 characters
const min = 1;
const max = 63;
if ( str.length < min ) {
errors.push(intl.t(`validation.k8s.identifier.emptyKey`, {key: displayKey, min: min}));
} else if ( str.length > max ) {
errors.push(intl.t(`validation.k8s.identifier}.tooLongKey`, {key: displayKey, max: max}));
}
}
export function validatePrefix(str, displayKey, intl, errors=[]) {
const intlKey = intl.t('generic.key');
const min = 1;
const max = 253;
if ( str.length < min ) {
errors.push(intl.t(`validation.k8s.identifier.emptyPrefix`, {key: displayKey, min: min}));
} else if ( str.length > max ) {
errors.push(intl.t(`validation.k8s.identifier}.tooLongPRefix`, {key: displayKey, max: max}));
} else {
validateHostname(str, intlKey, intl, errors);
}
}
export function validateKey(str, intl, errors=[]) {
const parts = parseKey(str);
const intlKey = intl.t('generic.key');
if ( parts.prefix ) {
validatePrefix(parts.prefix, intlKey, intl, errors);
}
validateIdentifier(parts.key, intlKey, intl, errors);
}
export function validateValue(str, intl, errors=[]) {
const intlKey = intl.t('generic.value');
validateIdentifier(str, intlKey, intl, errors);
}

View File

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

View File

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

View File

@ -42,6 +42,7 @@ generic:
image: Image
internal: Internal
ipAddress: IP Address
key: Key
limit: Limit
limits: Limits
loading: "Loading..."
@ -78,6 +79,7 @@ generic:
unknown: Unknown
upload: Upload
uuid: UUID
value: Value
yes: "Yes"
realmNames:
@ -2415,12 +2417,12 @@ formUserLabels:
placeholder: e.g. bar
protip: "ProTip: Paste one or more lines of key=value pairs into any key field for easy bulk entry."
formMetadata:
title: Metadata
detail: Configure the metadata for the container.
formAnnotations:
title: Annotations
detail: Configure annotations (key/value metadata) for the container.
errors:
invalidJSON: Metadata JSON format is invalid.
topLevelValueInvalid: Metadata JSON top-level value should be an object.
invalidJSON: Annotation JSON format is invalid.
topLevelValueInvalid: Annotation JSON top-level value must be an object.
formUpgrade:
title: Upgrade Policy
@ -4106,15 +4108,23 @@ validation:
startDot: '"{key}" cannot start with a dot'
empty: '"{key}" must be at least one character'
tooLong: '"{key}" cannot be longer than {max} characters'
startHyphen: '"{key}" cannot have a section starting with a hyphen'
endHyphen: '"{key}" cannot have a section ending with a hyphen'
startHyphen: '"{key}" must start with a letter or number'
endHyphen: '"{key}" must end with a letter or number'
emptyLabel: '"{key}" cannot have two consecutive dots'
labelTooLong: '"{key}" cannot have a section longer than {max} characters'
tooLongLabel: '"{key}" cannot have a section longer than {max} characters'
label:
startHyphen: '"{key}" cannot start with a hyphen'
endHyphen: '"{key}" cannot end with a hyphen'
startHyphen: '"{key}" must start with a letter or number'
endHyphen: '"{key}" must end with a letter or number'
emptyLabel: '"{key}" cannot be empty'
labelTooLong: '"{key}" cannot be more than {max} characters'
tooLongLabel: '"{key}" cannot be more than {max} characters'
k8s:
identifier:
startLetter: '"{key}" must start with a letter or number'
endLetter: '"{key}" must end with a letter or number'
emptyPrefix: '"{key}" cannot have an empty prefix'
tooLongPrefix: '"{key}" cannot have a prefix longer than {max} characters'
emptyLabel: '"{key}" cannot have an empty key'
tooLongKey: '"{key}" cannot have a key longer than {max} characters'
##############################
# Model Properties