mirror of https://github.com/rancher/ui.git
refactor form-versions logic to reduce complexity and bugs
I think the file it self may look more verbose as I've broken several of the confusing portions into pure(ish) functions. I think this reduces the complexity of the logic and makes it easier to read. Hopefully this will reduce the bugs that keep cropping up.
This commit is contained in:
parent
e8626832c0
commit
8058d3de4d
|
|
@ -1,6 +1,6 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
import { get, set, computed } from '@ember/object';
|
||||
import { get, set, computed, observer } from '@ember/object';
|
||||
import C from 'shared/utils/constants';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { alias, equal } from '@ember/object/computed';
|
||||
|
|
@ -9,6 +9,7 @@ import { sortVersions } from 'shared/utils/sort';
|
|||
import { scheduleOnce } from '@ember/runloop';
|
||||
import { lt, gt, minor } from 'semver';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
import { on } from '@ember/object/evented';
|
||||
|
||||
export default Component.extend({
|
||||
settings: service(),
|
||||
|
|
@ -24,20 +25,24 @@ export default Component.extend({
|
|||
value: null,
|
||||
mode: 'new',
|
||||
showNotAllowed: false,
|
||||
supportedVersionsRange: null,
|
||||
editing: equal('mode', 'edit'),
|
||||
isView: equal('mode', 'view'),
|
||||
|
||||
defaultK8sVersionRange: alias(`settings.${ C.SETTING.VERSION_SYSTEM_K8S_DEFAULT_RANGE }`),
|
||||
supportedVersionsRange: alias(`settings.${ C.SETTING.VERSION_K8S_SUPPORTED_RANGE }`),
|
||||
defaultK8sVersion: alias(`settings.${ C.SETTING.VERSION_RKE_K8S_DEFAULT }`),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
shouldRecomputInitalValues: on('init', observer('cluster.clusterTemplateRevisionId', function() {
|
||||
scheduleOnce('afterRender', () => {
|
||||
// we should set this everytime. we can potentially override it based on
|
||||
// satisfies overrides, so if we change templates while launching
|
||||
// a cluster from a satisfies to a non-satisfies override we should set
|
||||
// it back to the system setting
|
||||
set(this, 'supportedVersionsRange', get(this, `settings.${ C.SETTING.VERSION_K8S_SUPPORTED_RANGE }`));
|
||||
|
||||
this.initVersions();
|
||||
});
|
||||
},
|
||||
})),
|
||||
|
||||
isRke: computed('cluster', function() {
|
||||
const { cluster } = this;
|
||||
|
|
@ -49,148 +54,186 @@ export default Component.extend({
|
|||
return false;
|
||||
}),
|
||||
|
||||
initVersions() {
|
||||
k8sVersionOverride: computed('clusterTemplateQuestions.@each.variable', function() {
|
||||
return ( this.clusterTemplateQuestions || [] ).findBy('variable', 'rancherKubernetesEngineConfig.kubernetesVersion') || {};
|
||||
}),
|
||||
|
||||
getLabelSuffixKey: computed('showNotAllowed', function() {
|
||||
let {
|
||||
defaultK8sVersionRange,
|
||||
versions,
|
||||
supportedVersionsRange,
|
||||
editing,
|
||||
initialVersion,
|
||||
defaultK8sVersion,
|
||||
applyClusterTemplate = false,
|
||||
clusterTemplateCreate = false,
|
||||
showNotAllowed,
|
||||
applyClusterTemplate = false,
|
||||
clusterTemplateCreate = false,
|
||||
clusterTemplateQuestions = [],
|
||||
} = this;
|
||||
|
||||
let out = versions;
|
||||
let overrideMatch = null;
|
||||
|
||||
if (initialVersion) {
|
||||
if ( !out.includes(initialVersion) && editing ) {
|
||||
out.unshift(initialVersion);
|
||||
}
|
||||
} else {
|
||||
initialVersion = defaultK8sVersion;
|
||||
}
|
||||
|
||||
let initialWithoutX = initialVersion.endsWith('.x') ? initialVersion.replace(/x$/, '0') : initialVersion;
|
||||
let maxVersion = maxSatisfying(versions, defaultK8sVersionRange);
|
||||
|
||||
if ( applyClusterTemplate ) {
|
||||
overrideMatch = ( clusterTemplateQuestions || [] ).findBy('variable', 'rancherKubernetesEngineConfig.kubernetesVersion');
|
||||
|
||||
if (overrideMatch) {
|
||||
if (isEmpty(overrideMatch.satisfies) && initialVersion.endsWith('.x')) {
|
||||
// the template creator lets them override this but the initial version is a dot x so we should choose the biggest version in the .x range
|
||||
maxVersion = maxSatisfying(versions, initialVersion);
|
||||
} else {
|
||||
if (overrideMatch.satisfies) {
|
||||
supportedVersionsRange = overrideMatch.satisfies;
|
||||
}
|
||||
|
||||
maxVersion = maxSatisfying(versions, supportedVersionsRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
} = this;
|
||||
let suffix = ( showNotAllowed ? 'formVersions.notallowed' : 'formVersions.unsupported' );
|
||||
|
||||
// if we're not consuming or creating a cluster template we should use the default translation for the label
|
||||
if (!applyClusterTemplate && !clusterTemplateCreate) {
|
||||
showNotAllowed = false;
|
||||
suffix = 'formVersions.unsupported';
|
||||
}
|
||||
|
||||
out = [
|
||||
...sortVersions(out.filter((v) => v.endsWith('.x'))).reverse(),
|
||||
...sortVersions(out.filter((v) => !v.endsWith('.x'))).reverse(),
|
||||
return suffix;
|
||||
}),
|
||||
|
||||
initVersions() {
|
||||
let {
|
||||
versions,
|
||||
editing,
|
||||
initialVersion,
|
||||
defaultK8sVersion,
|
||||
k8sVersionOverride,
|
||||
intl,
|
||||
getLabelSuffixKey: suffix,
|
||||
} = this;
|
||||
|
||||
let clonedVersions = versions.slice();
|
||||
|
||||
if (isEmpty(initialVersion)) {
|
||||
initialVersion = defaultK8sVersion;
|
||||
}
|
||||
|
||||
if ( editing && !clonedVersions.includes(initialVersion) ) {
|
||||
clonedVersions.unshift(initialVersion);
|
||||
}
|
||||
|
||||
let initialWithoutX = initialVersion.endsWith('.x') ? initialVersion.replace(/x$/, '0') : initialVersion;
|
||||
let maxVersion = this.getMaxVersion(initialVersion, clonedVersions);
|
||||
|
||||
clonedVersions = [
|
||||
...sortVersions(clonedVersions.filter((v) => v.endsWith('.x'))).reverse(),
|
||||
...sortVersions(clonedVersions.filter((v) => !v.endsWith('.x'))).reverse(),
|
||||
];
|
||||
|
||||
let mappedVersions = out.map((v) => {
|
||||
let label = v;
|
||||
let out = null;
|
||||
let mappedVersions = clonedVersions.map((v) => {
|
||||
let label = this.parseLabelFromVersion(v);
|
||||
let disabled = false;
|
||||
let experimental = false;
|
||||
|
||||
const version = coerceVersion(v)
|
||||
const version = coerceVersion(v)
|
||||
|
||||
if (!label.startsWith('v')) {
|
||||
label = `v${ label }`;
|
||||
}
|
||||
let versionSatisfies = satisfies(version, this.supportedVersionsRange);
|
||||
|
||||
if ( label.endsWith('.x') ) {
|
||||
label = this.intl.t('formVersions.dotx', { minor: label.replace(/\.x$/, '') });
|
||||
}
|
||||
|
||||
if (satisfies(version, supportedVersionsRange)) {
|
||||
if (editing && lt(version, coerceVersion(initialWithoutX))) {
|
||||
if (minor(version) < minor(coerceVersion(initialWithoutX)) ) {
|
||||
out = {
|
||||
disabled: true,
|
||||
label: `${ label } ${ this.intl.t('formVersions.downgrade') }`,
|
||||
value: v
|
||||
};
|
||||
} else {
|
||||
out = {
|
||||
label,
|
||||
value: v
|
||||
};
|
||||
}
|
||||
} else {
|
||||
out = {
|
||||
label,
|
||||
value: v
|
||||
};
|
||||
if (versionSatisfies) {
|
||||
if (editing && isCurrentVersionLessThanInitial() ) {
|
||||
disabled = true;
|
||||
label = `${ label } ${ intl.t('formVersions.downgrade') }`;
|
||||
}
|
||||
} else {
|
||||
const suffix = ( showNotAllowed ? 'formVersions.notallowed' : 'formVersions.unsupported' );
|
||||
|
||||
if (gt(version, coerceVersion(maxVersion))) {
|
||||
if (overrideMatch && !isEmpty(overrideMatch.satisfies)) {
|
||||
out = {
|
||||
disabled: true,
|
||||
label: `${ label } ${ this.intl.t(suffix) }`,
|
||||
value: v
|
||||
};
|
||||
if (isEmpty(k8sVersionOverride.satisfies)) {
|
||||
if (!satisfies(coerceVersion(v), '>=1.16 <1.17')) {
|
||||
experimental = true;
|
||||
label = `${ label } ${ intl.t('formVersions.experimental') }`;
|
||||
}
|
||||
} else {
|
||||
out = {
|
||||
experimental: true,
|
||||
label: `${ label } ${ this.intl.t('formVersions.experimental') }`,
|
||||
value: v
|
||||
};
|
||||
disabled = true;
|
||||
label = `${ label } ${ intl.t(suffix) }`;
|
||||
}
|
||||
} else if (lt(version, coerceVersion(maxVersion))) {
|
||||
out = {
|
||||
disabled: true,
|
||||
label: `${ label } ${ this.intl.t(suffix) }`,
|
||||
value: v
|
||||
};
|
||||
disabled = true;
|
||||
label = `${ label } ${ intl.t(suffix) }`;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
function isCurrentVersionLessThanInitial() {
|
||||
if (lt(version, coerceVersion(initialWithoutX)) && minor(version) < minor(coerceVersion(initialWithoutX))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
disabled,
|
||||
experimental,
|
||||
label,
|
||||
value: v
|
||||
};
|
||||
});
|
||||
|
||||
if (!editing && defaultK8sVersionRange && this.value) {
|
||||
if (!applyClusterTemplate && this.value.endsWith('.x')) {
|
||||
set(this, 'value', this.intl.t('formVersions.dotx', { minor: this.value.replace(/\.x$/, '') }));
|
||||
} else {
|
||||
if ( maxVersion && !mappedVersions.findBy('value', get(this, 'value')) ) {
|
||||
set(this, 'value', maxVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (editing && this.value && this.value.endsWith('.x')) {
|
||||
if (applyClusterTemplate && overrideMatch && overrideMatch.satisfies) {
|
||||
if (!satisfies(initialVersion, overrideMatch.satisfies)) {
|
||||
set(this, 'value', maxVersion);
|
||||
} else {
|
||||
set(this, 'value', initialVersion);
|
||||
}
|
||||
} else {
|
||||
if (initialVersion) {
|
||||
set(this, 'value', initialVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set(this, 'versionChoices', mappedVersions);
|
||||
|
||||
this.initValue(initialWithoutX, maxVersion);
|
||||
},
|
||||
|
||||
initValue(initialVersion, maxVersion) {
|
||||
let {
|
||||
editing,
|
||||
value,
|
||||
k8sVersionOverride,
|
||||
applyClusterTemplate,
|
||||
intl,
|
||||
versionChoices: mappedVersions,
|
||||
} = this;
|
||||
let valueIsPatchVersion = false;
|
||||
let initialVersionDoesNotSatisfy = false;
|
||||
|
||||
if (isEmpty(value)) {
|
||||
value = initialVersion;
|
||||
}
|
||||
|
||||
if (value.endsWith('.x')) {
|
||||
valueIsPatchVersion = true;
|
||||
}
|
||||
|
||||
if (!isEmpty(k8sVersionOverride.satisfies) && !satisfies(initialVersion, k8sVersionOverride.satisfies)) {
|
||||
initialVersionDoesNotSatisfy = true;
|
||||
}
|
||||
|
||||
if (editing) {
|
||||
if (applyClusterTemplate && valueIsPatchVersion && initialVersionDoesNotSatisfy) {
|
||||
value = maxVersion;
|
||||
}
|
||||
} else {
|
||||
if (applyClusterTemplate && !mappedVersions.findBy('value', value)) {
|
||||
value = maxVersion;
|
||||
} else {
|
||||
if (valueIsPatchVersion) {
|
||||
value = intl.t('formVersions.dotx', { minor: value.replace(/\.x$/, '') });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set(this, 'value', value);
|
||||
},
|
||||
|
||||
getMaxVersion(initialVersion, versions) {
|
||||
let {
|
||||
applyClusterTemplate,
|
||||
defaultK8sVersionRange,
|
||||
supportedVersionsRange,
|
||||
k8sVersionOverride,
|
||||
} = this;
|
||||
let maxVersion = maxSatisfying(versions, defaultK8sVersionRange);
|
||||
|
||||
if ( applyClusterTemplate ) {
|
||||
if (isEmpty(k8sVersionOverride.satisfies) && initialVersion.endsWith('.x')) {
|
||||
// the template creator lets them override this but the initial version is a dot x so we should choose the biggest version in the .x range
|
||||
maxVersion = maxSatisfying(versions, initialVersion);
|
||||
} else {
|
||||
if (k8sVersionOverride.satisfies) {
|
||||
supportedVersionsRange = set(this, 'supportedVersionsRange', k8sVersionOverride.satisfies);
|
||||
}
|
||||
|
||||
maxVersion = maxSatisfying(versions, supportedVersionsRange);
|
||||
}
|
||||
}
|
||||
|
||||
return maxVersion;
|
||||
},
|
||||
|
||||
parseLabelFromVersion(version) {
|
||||
let { intl } = this;
|
||||
let label = version;
|
||||
|
||||
if (!label.startsWith('v')) {
|
||||
label = `v${ label }`;
|
||||
}
|
||||
|
||||
if ( label.endsWith('.x') ) {
|
||||
label = intl.t('formVersions.dotx', { minor: label.replace(/\.x$/, '') });
|
||||
}
|
||||
|
||||
return label;
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue