mirror of https://github.com/rancher/ui.git
Rework for new requirements that node groups need the entire object.
This commit is contained in:
parent
42a8ce7cad
commit
79c00cf7d7
|
|
@ -18,6 +18,40 @@ const TRUE = 'True';
|
|||
const CLUSTER_TEMPLATE_ID_PREFIX = 'cattle-global-data:';
|
||||
const SCHEDULE_CLUSTER_SCAN_QUESTION_KEY = 'scheduledClusterScan.enabled';
|
||||
|
||||
export const DEFAULT_NODE_GROUP_CONFIG = {
|
||||
desiredSize: 2,
|
||||
diskSize: 20,
|
||||
ec2SshKey: '',
|
||||
gpu: false,
|
||||
instanceType: 't3.medium',
|
||||
maxSize: 2,
|
||||
minSize: 2,
|
||||
nodegroupName: '',
|
||||
subnets: [],
|
||||
type: 'nodeGroup',
|
||||
};
|
||||
|
||||
export const DEFAULT_EKS_CONFIG = {
|
||||
amazonCredentialSecret: '',
|
||||
displayName: '',
|
||||
imported: false,
|
||||
kmsKey: '',
|
||||
kubernetesVersion: '',
|
||||
loggingTypes: [],
|
||||
nodeGroups: [],
|
||||
privateAccess: false,
|
||||
publicAccess: true,
|
||||
publicAccessSources: [],
|
||||
region: 'us-west-2',
|
||||
secretsEncryption: false,
|
||||
securityGroups: [],
|
||||
serviceRole: '',
|
||||
subnets: [],
|
||||
tags: {},
|
||||
type: 'eksclusterconfigspec',
|
||||
};
|
||||
|
||||
|
||||
export default Resource.extend(Grafana, ResourceUsage, {
|
||||
globalStore: service(),
|
||||
growl: service(),
|
||||
|
|
@ -662,47 +696,45 @@ export default Resource.extend(Grafana, ResourceUsage, {
|
|||
if (get(this, 'driver') === 'EKS' || !this.isEmptyObject(get(this, 'eksConfig'))) {
|
||||
const options = ({
|
||||
...opt,
|
||||
data: {}
|
||||
data: {
|
||||
name: this.name,
|
||||
eksConfig: {},
|
||||
}
|
||||
});
|
||||
|
||||
const config = jsondiffpatch.clone(get(this, 'eksConfig'));
|
||||
const eksClusterConfigSpec = get(this, 'globalStore').getById('schema', 'eksclusterconfigspec');
|
||||
const nodeGroupConfigSpec = get(this, 'globalStore').getById('schema', 'nodegroup');
|
||||
|
||||
if (isEmpty(this.id)) {
|
||||
const eksClusterConfigSpec = get(this, 'globalStore').getById('schema', 'eksclusterconfigspec');
|
||||
const resourceFields = get(eksClusterConfigSpec, 'resourceFields');
|
||||
|
||||
Object.keys(config).forEach((ck) => {
|
||||
const configValue = get(config, ck);
|
||||
replaceNullWithEmptyDefaults(get(this, 'eksConfig'), get(eksClusterConfigSpec, 'resourceFields'));
|
||||
|
||||
if (configValue === null || typeof configValue === 'undefined') {
|
||||
const resourceField = resourceFields[ck];
|
||||
if (!isEmpty(get(this, 'eksConfig.nodeGroups'))) {
|
||||
get(this, 'eksConfig.nodeGroups').forEach((ng) => {
|
||||
replaceNullWithEmptyDefaults(ng, get(nodeGroupConfigSpec, 'resourceFields'));
|
||||
});
|
||||
}
|
||||
|
||||
if (resourceField.type === 'string') {
|
||||
set(config, ck, '');
|
||||
} else if (resourceField.type.includes('array')) {
|
||||
set(config, ck, []);
|
||||
} else if (resourceField.type.includes('map')) {
|
||||
set(config, ck, {});
|
||||
} else if (resourceField.type.includes('boolean')) {
|
||||
if (resourceField.default) {
|
||||
set(config, ck, resourceField.default);
|
||||
} else {
|
||||
// we shouldn't get here, there are not that many fields in EKS and I've set the defaults for bools that are there
|
||||
// but if we do hit this branch my some magic case imo a bool isn't something we can default cause its unknown...just dont do anything.
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return this._super(...arguments);
|
||||
} else {
|
||||
const config = jsondiffpatch.clone(get(this, 'eksConfig'));
|
||||
const upstreamSpec = jsondiffpatch.clone(get(this, 'eksStatus.upstreamSpec'));
|
||||
|
||||
if (isEmpty(upstreamSpec)) {
|
||||
return reject(this.intl('clusterNew.amazoneks.errors.clusterSpec'));
|
||||
}
|
||||
|
||||
set(options, 'data', diff(upstreamSpec, config));
|
||||
set(options, 'data.eksConfig', this.diffEksUpstream(upstreamSpec, config));
|
||||
|
||||
if (!isEmpty(get(options, 'data.eksConfig.nodeGroups'))) {
|
||||
get(options, 'data.eksConfig.nodeGroups').forEach((ng) => {
|
||||
replaceNullWithEmptyDefaults(ng, get(nodeGroupConfigSpec, 'resourceFields'));
|
||||
});
|
||||
}
|
||||
|
||||
if (get(options, 'qp._replace')) {
|
||||
delete options.qp['_replace'];
|
||||
}
|
||||
|
||||
return this._super(options);
|
||||
}
|
||||
|
|
@ -710,119 +742,162 @@ export default Resource.extend(Grafana, ResourceUsage, {
|
|||
return this._super(...arguments);
|
||||
}
|
||||
|
||||
function replaceNullWithEmptyDefaults(config, resourceFields) {
|
||||
Object.keys(config).forEach((ck) => {
|
||||
const configValue = get(config, ck);
|
||||
|
||||
if (configValue === null || typeof configValue === 'undefined') {
|
||||
const resourceField = resourceFields[ck];
|
||||
|
||||
if (resourceField.type === 'string') {
|
||||
set(config, ck, '');
|
||||
} else if (resourceField.type.includes('array')) {
|
||||
set(config, ck, []);
|
||||
} else if (resourceField.type.includes('map')) {
|
||||
set(config, ck, {});
|
||||
} else if (resourceField.type.includes('boolean')) {
|
||||
if (resourceField.default) {
|
||||
set(config, ck, resourceField.default);
|
||||
} else {
|
||||
if ( !isEmpty(get(DEFAULT_EKS_CONFIG, ck)) || !isEmpty(get(DEFAULT_NODE_GROUP_CONFIG, ck)) ) {
|
||||
let match = isEmpty(get(DEFAULT_EKS_CONFIG, ck)) ? get(DEFAULT_NODE_GROUP_CONFIG, ck) : get(DEFAULT_EKS_CONFIG, ck);
|
||||
|
||||
set(config, ck, match);
|
||||
}
|
||||
// we shouldn't get here, there are not that many fields in EKS and I've set the defaults for bools that are there
|
||||
// but if we do hit this branch my some magic case imo a bool isn't something we can default cause its unknown...just dont do anything.
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
},
|
||||
|
||||
diffEksUpstream(lhs, rhs) {
|
||||
// this is NOT a generic object diff.
|
||||
// It tries to be as generic as possible but it does make certain assumptions regarding nulls and emtpy arrays/objects
|
||||
// if LHS (upstream) is null and RHS (eks config) is empty we do not count this as a change
|
||||
// additionally null values on the RHS will be ignored as null cant be sent in this case
|
||||
function diff(lhs, rhs) {
|
||||
const delta = {};
|
||||
const rhsKeys = Object.keys(rhs);
|
||||
const delta = {};
|
||||
const rhsKeys = Object.keys(rhs);
|
||||
|
||||
rhsKeys.forEach((k) => {
|
||||
if (k === 'type') {
|
||||
rhsKeys.forEach((k) => {
|
||||
if (k === 'type') {
|
||||
return;
|
||||
}
|
||||
|
||||
const lhsMatch = get(lhs, k);
|
||||
const rhsMatch = get(rhs, k);
|
||||
|
||||
try {
|
||||
if (isEqual(JSON.stringify(lhsMatch), JSON.stringify(rhsMatch))) {
|
||||
return;
|
||||
}
|
||||
} catch (e){}
|
||||
|
||||
const lhsMatch = get(lhs, k);
|
||||
const rhsMatch = get(rhs, k);
|
||||
if (k === 'nodeGroups') {
|
||||
if (!isEmpty(lhsMatch)) {
|
||||
// node groups need ALL data so short circut and send it all
|
||||
set(delta, k, lhsMatch);
|
||||
} else {
|
||||
// all node groups were deleted
|
||||
set(delta, k, []);
|
||||
}
|
||||
|
||||
try {
|
||||
if (isEqual(JSON.stringify(lhsMatch), JSON.stringify(rhsMatch))) {
|
||||
return;
|
||||
}
|
||||
} catch (e){}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEmpty(lhsMatch) || this.isEmptyObject(lhsMatch)) {
|
||||
if (isEmpty(rhsMatch) || this.isEmptyObject(rhsMatch)) {
|
||||
if (lhsMatch !== null && (isArray(rhsMatch) || this.isObject(rhsMatch))) {
|
||||
// Empty Arrays and Empty Maps must be sent as such unless the upstream value is null, then the empty array or obj is just a init value from ember
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
// lhs is empty, rhs is not, just set
|
||||
if (isEmpty(lhsMatch) || this.isEmptyObject(lhsMatch)) {
|
||||
if (isEmpty(rhsMatch) || this.isEmptyObject(rhsMatch)) {
|
||||
if (lhsMatch !== null && (isArray(rhsMatch) || this.isObject(rhsMatch))) {
|
||||
// Empty Arrays and Empty Maps must be sent as such unless the upstream value is null, then the empty array or obj is just a init value from ember
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
if (rhsMatch !== null) {
|
||||
// entry in og obj
|
||||
if (isArray(lhsMatch)) {
|
||||
if (isArray(rhsMatch)) {
|
||||
if (rhsMatch.every((m) => this.isObject(m))) {
|
||||
// You have more diffing to do
|
||||
rhsMatch.forEach((match) => {
|
||||
// our most likely candiate for a match is node group name, but lets check the others just incase.
|
||||
const matchId = get(match, 'nodegroupName') || get(match, 'name') || get(match, 'id') || false;
|
||||
// lhs is empty, rhs is not, just set
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
} else {
|
||||
if (rhsMatch !== null) {
|
||||
// entry in og obj
|
||||
if (isArray(lhsMatch)) {
|
||||
if (isArray(rhsMatch)) {
|
||||
if (rhsMatch.every((m) => this.isObject(m))) {
|
||||
// You have more diffing to do
|
||||
rhsMatch.forEach((match) => {
|
||||
// our most likely candiate for a match is node group name, but lets check the others just incase.
|
||||
const matchId = get(match, 'name') || get(match, 'id') || false;
|
||||
|
||||
if (matchId) {
|
||||
let lmatchIdx;
|
||||
if (matchId) {
|
||||
let lmatchIdx;
|
||||
|
||||
// we have soime kind of identifier to find a match in the upstream, so we can diff and insert to new array
|
||||
const lMatch = lhsMatch.find((l, idx) => {
|
||||
const lmatchId = get(l, 'nodegroupName') || get(l, 'name') || get(l, 'id');
|
||||
// we have soime kind of identifier to find a match in the upstream, so we can diff and insert to new array
|
||||
const lMatch = lhsMatch.find((l, idx) => {
|
||||
const lmatchId = get(l, 'name') || get(l, 'id');
|
||||
|
||||
if (lmatchId === matchId) {
|
||||
lmatchIdx = idx;
|
||||
if (lmatchId === matchId) {
|
||||
lmatchIdx = idx;
|
||||
|
||||
return l;
|
||||
}
|
||||
});
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
if (lMatch) {
|
||||
// we have a match in the upstream, meaning we've probably made updates to the object itself
|
||||
const diffedMatch = diff(lMatch, match);
|
||||
if (lMatch) {
|
||||
// we have a match in the upstream, meaning we've probably made updates to the object itself
|
||||
const diffedMatch = this.diffEksUpstream(lMatch, match);
|
||||
|
||||
if (!isArray(get(delta, k))) {
|
||||
set(delta, k, [diffedMatch]);
|
||||
} else {
|
||||
// diff and push into new array
|
||||
delta[k].insertAt(lmatchIdx, diffedMatch);
|
||||
}
|
||||
if (!isArray(get(delta, k))) {
|
||||
set(delta, k, [diffedMatch]);
|
||||
} else {
|
||||
// no match in upstream, new entry
|
||||
if (!isArray(get(delta, k))) {
|
||||
set(delta, k, [match]);
|
||||
} else {
|
||||
delta[k].pushObject(match);
|
||||
}
|
||||
// diff and push into new array
|
||||
delta[k].insertAt(lmatchIdx, diffedMatch);
|
||||
}
|
||||
} else {
|
||||
// no match id, all we can do is dumb add
|
||||
// no match in upstream, new entry
|
||||
if (!isArray(get(delta, k))) {
|
||||
set(delta, k, [match]);
|
||||
} else {
|
||||
delta[k].pushObject(match);
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
} else {
|
||||
// no match id, all we can do is dumb add
|
||||
if (!isArray(get(delta, k))) {
|
||||
set(delta, k, [match]);
|
||||
} else {
|
||||
delta[k].pushObject(match);
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
} else if (this.isObject(lhsMatch)) {
|
||||
if (!isEmpty(rhsMatch) && !this.isEmptyObject(rhsMatch)) {
|
||||
if ((Object.keys(lhsMatch) || []).length > 0) {
|
||||
// You have more diffing to do
|
||||
set(delta, k, diff(lhsMatch, rhsMatch));
|
||||
} else if (this.isEmptyObject(lhsMatch)) {
|
||||
// we had a map now we have an empty map
|
||||
set(delta, k, {});
|
||||
}
|
||||
}
|
||||
} else { // lhsMatch not an array or object
|
||||
} else {
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
} else if (this.isObject(lhsMatch)) {
|
||||
if (!isEmpty(rhsMatch) && !this.isEmptyObject(rhsMatch)) {
|
||||
if ((Object.keys(lhsMatch) || []).length > 0) {
|
||||
// You have more diffing to do
|
||||
set(delta, k, this.diffEksUpstream(lhsMatch, rhsMatch));
|
||||
} else if (this.isEmptyObject(lhsMatch)) {
|
||||
// we had a map now we have an empty map
|
||||
set(delta, k, {});
|
||||
}
|
||||
}
|
||||
} else { // lhsMatch not an array or object
|
||||
set(delta, k, rhsMatch);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return delta;
|
||||
}
|
||||
return delta;
|
||||
},
|
||||
|
||||
isObject(obj) {
|
||||
return obj !== null && obj.constructor.name === 'Object';
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,39 +14,7 @@ import ClusterDriver from 'shared/mixins/cluster-driver';
|
|||
import { EKS_REGIONS, EKS_VERSIONS, INSTANCE_TYPES, nameFromResource } from 'shared/utils/amazon';
|
||||
import { randomStr } from 'shared/utils/util';
|
||||
import layout from './template';
|
||||
|
||||
const DEFAULT_NODE_GROUP_CONFIG = {
|
||||
desiredSize: 2,
|
||||
diskSize: 20,
|
||||
ec2SshKey: '',
|
||||
gpu: false,
|
||||
instanceType: 't3.medium',
|
||||
maxSize: 2,
|
||||
minSize: 2,
|
||||
nodegroupName: '',
|
||||
subnets: [],
|
||||
type: 'nodeGroup',
|
||||
};
|
||||
|
||||
const DEFAULT_EKS_CONFIG = {
|
||||
amazonCredentialSecret: '',
|
||||
displayName: '',
|
||||
imported: false,
|
||||
kmsKey: '',
|
||||
kubernetesVersion: '',
|
||||
loggingTypes: [],
|
||||
nodeGroups: [],
|
||||
privateAccess: false,
|
||||
publicAccess: true,
|
||||
publicAccessSources: [],
|
||||
region: 'us-west-2',
|
||||
secretsEncryption: false,
|
||||
securityGroups: [],
|
||||
serviceRole: '',
|
||||
subnets: [],
|
||||
tags: {},
|
||||
type: 'eksclusterconfigspec',
|
||||
};
|
||||
import { DEFAULT_NODE_GROUP_CONFIG, DEFAULT_EKS_CONFIG } from 'ui/models/cluster';
|
||||
|
||||
export default Component.extend(ClusterDriver, {
|
||||
intl: service(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue