mirror of https://github.com/rancher/ui.git
Refactor new catalog to handle requiredNamespace correctly
rancher/rancher#19697
This commit is contained in:
parent
a296c3aad9
commit
9bd0980b81
|
|
@ -5,12 +5,14 @@ import Route from '@ember/routing/route';
|
||||||
import { get, set, setProperties } from '@ember/object';
|
import { get, set, setProperties } from '@ember/object';
|
||||||
import { randomStr } from 'shared/utils/util';
|
import { randomStr } from 'shared/utils/util';
|
||||||
import C from 'ui/utils/constants';
|
import C from 'ui/utils/constants';
|
||||||
|
import Util from 'ui/utils/util';
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
modalService: service('modal'),
|
modalService: service('modal'),
|
||||||
catalog: service(),
|
catalog: service(),
|
||||||
scope: service(),
|
scope: service(),
|
||||||
clusterStore: service(),
|
clusterStore: service(),
|
||||||
|
settings: service(),
|
||||||
|
|
||||||
parentRoute: 'catalog-tab',
|
parentRoute: 'catalog-tab',
|
||||||
|
|
||||||
|
|
@ -39,24 +41,49 @@ export default Route.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash(dependencies, 'Load dependencies').then((results) => {
|
return hash(dependencies, 'Load dependencies').then((results) => {
|
||||||
let neuNSN = results.tpl.get('displayName');
|
var def = get(results, 'tpl.defaultVersion');
|
||||||
let dupe = results.namespaces.findBy('id', neuNSN);
|
var links = get(results, 'tpl.versionLinks');
|
||||||
|
var app = get(results, 'app');
|
||||||
|
var catalogTemplateUrl = null;
|
||||||
|
|
||||||
if ( !results.namespace ) {
|
if (app && params.appId && !params.upgrade) {
|
||||||
let { newNamespaceName, newNS } = this.newNamespace(dupe, neuNSN);
|
def = get(app, 'externalIdInfo.version');
|
||||||
|
|
||||||
if ( dupe ) {
|
|
||||||
neuNSN = newNamespaceName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
results.namespace = newNS;
|
catalogTemplateUrl = links[def];
|
||||||
|
|
||||||
|
var version = get(this, 'settings.rancherVersion');
|
||||||
|
|
||||||
|
if ( version ) {
|
||||||
|
catalogTemplateUrl = Util.addQueryParam(catalogTemplateUrl, 'rancherVersion', version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.catalog.fetchByUrl(catalogTemplateUrl).then((catalogTemplate) => {
|
||||||
|
let { requiredNamespace } = catalogTemplate;
|
||||||
|
let neuNamespaceName = requiredNamespace ? requiredNamespace : results.tpl.get('displayName');
|
||||||
|
let existingNamespace = results.namespaces.findBy('id', neuNamespaceName);
|
||||||
|
let { namespace } = results;
|
||||||
let kind = 'helm';
|
let kind = 'helm';
|
||||||
let neuApp = null;
|
let neuApp = null;
|
||||||
var links;
|
|
||||||
|
|
||||||
links = results.tpl.versionLinks;
|
let newNamespaceName;
|
||||||
|
|
||||||
|
if ( !namespace ) {
|
||||||
|
if (requiredNamespace) {
|
||||||
|
if (existingNamespace) {
|
||||||
|
// we dont want a unique namespace in this case.
|
||||||
|
namespace = existingNamespace;
|
||||||
|
} else {
|
||||||
|
( { newNamespaceName: neuNamespaceName, newNS: namespace } = this.newNamespace(existingNamespace, neuNamespaceName) );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
( { newNamespaceName, newNS: namespace } = this.newNamespace(existingNamespace, neuNamespaceName) );
|
||||||
|
|
||||||
|
if ( existingNamespace ) {
|
||||||
|
neuNamespaceName = newNamespaceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var verArr = Object.keys(links).filter((key) => !!links[key])
|
var verArr = Object.keys(links).filter((key) => !!links[key])
|
||||||
.map((key) => ({
|
.map((key) => ({
|
||||||
|
|
@ -67,23 +94,16 @@ export default Route.extend({
|
||||||
|
|
||||||
if (results.app) {
|
if (results.app) {
|
||||||
if (get(params, 'clone')) {
|
if (get(params, 'clone')) {
|
||||||
let { newNamespaceName, newNS } = this.newNamespace(dupe, neuNSN);
|
|
||||||
|
|
||||||
if ( dupe ) {
|
|
||||||
neuNSN = newNamespaceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
results.namespace = newNS;
|
|
||||||
|
|
||||||
neuApp = results.app.cloneForNew();
|
neuApp = results.app.cloneForNew();
|
||||||
set(neuApp, 'name', results.namespace.name);
|
|
||||||
|
set(neuApp, 'name', this.dedupeName(get(namespace, 'displayName')));
|
||||||
} else {
|
} else {
|
||||||
neuApp = results.app;
|
neuApp = results.app;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
neuApp = store.createRecord({
|
neuApp = store.createRecord({
|
||||||
type: 'app',
|
type: 'app',
|
||||||
name: results.namespace.name,
|
name: neuNamespaceName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +117,9 @@ export default Route.extend({
|
||||||
return EmberObject.create({
|
return EmberObject.create({
|
||||||
allTemplates: this.modelFor(get(this, 'parentRoute')).get('catalog'),
|
allTemplates: this.modelFor(get(this, 'parentRoute')).get('catalog'),
|
||||||
catalogApp: neuApp,
|
catalogApp: neuApp,
|
||||||
namespace: results.namespace,
|
catalogTemplateUrl: links[def],
|
||||||
|
catalogTemplate,
|
||||||
|
namespace,
|
||||||
namespaces: results.namespaces,
|
namespaces: results.namespaces,
|
||||||
tpl: results.tpl,
|
tpl: results.tpl,
|
||||||
tplKind: kind,
|
tplKind: kind,
|
||||||
|
|
@ -106,6 +128,7 @@ export default Route.extend({
|
||||||
versionsArray: verArr,
|
versionsArray: verArr,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
resetController(controller, isExiting/* , transition*/) {
|
resetController(controller, isExiting/* , transition*/) {
|
||||||
|
|
@ -132,11 +155,15 @@ export default Route.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
newNamespace(duplicateName, newNamespaceName) {
|
dedupeName(name) {
|
||||||
const suffix = randomStr(5, 5, 'novowels');
|
const suffix = randomStr(5, 5, 'novowels');
|
||||||
|
|
||||||
if ( duplicateName ) {
|
return `${ name }-${ suffix }`;
|
||||||
newNamespaceName = `${ get(duplicateName, 'displayName') }-${ suffix }`;
|
},
|
||||||
|
|
||||||
|
newNamespace(duplicateNamespace, newNamespaceName) {
|
||||||
|
if ( duplicateNamespace ) {
|
||||||
|
newNamespaceName = this.dedupeName(get(duplicateNamespace, 'displayName'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const newNS = get(this, 'clusterStore').createRecord({
|
const newNS = get(this, 'clusterStore').createRecord({
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
{{new-catalog
|
{{new-catalog
|
||||||
allTemplates=model.allTemplates
|
allTemplates=model.allTemplates
|
||||||
namespaces=model.namespaces
|
|
||||||
cancel=(action "cancel")
|
cancel=(action "cancel")
|
||||||
catalogApp=model.catalogApp
|
catalogApp=model.catalogApp
|
||||||
|
catalogTemplate=model.catalogTemplate
|
||||||
namespaceResource=model.namespace
|
namespaceResource=model.namespace
|
||||||
|
namespaces=model.namespaces
|
||||||
parentRoute=parentRoute
|
parentRoute=parentRoute
|
||||||
upgrade=model.upgradeTemplate
|
selectedTemplateUrl=model.catalogTemplateUrl
|
||||||
templateResource=model.tpl
|
|
||||||
templateKind=model.tplKind
|
templateKind=model.tplKind
|
||||||
|
templateResource=model.tpl
|
||||||
|
upgrade=model.upgradeTemplate
|
||||||
versionLinks=model.versionLinks
|
versionLinks=model.versionLinks
|
||||||
versionsArray=model.versionsArray
|
versionsArray=model.versionsArray
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
questionsArray: null,
|
questionsArray: null,
|
||||||
selectedTemplateUrl: null,
|
selectedTemplateUrl: null,
|
||||||
selectedTemplateModel: null,
|
selectedTemplateModel: null,
|
||||||
|
catalogTemplate: null,
|
||||||
readmeContent: null,
|
readmeContent: null,
|
||||||
appReadmeContent: null,
|
appReadmeContent: null,
|
||||||
pastedAnswers: null,
|
pastedAnswers: null,
|
||||||
|
|
@ -75,7 +76,11 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
|
|
||||||
scheduleOnce('afterRender', () => {
|
scheduleOnce('afterRender', () => {
|
||||||
if ( get(this, 'selectedTemplateUrl') ) {
|
if ( get(this, 'selectedTemplateUrl') ) {
|
||||||
|
if (this.catalogTemplate) {
|
||||||
|
this.initTemplateModel(this.catalogTemplate);
|
||||||
|
} else {
|
||||||
this.templateChanged();
|
this.templateChanged();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var def = get(this, 'templateResource.defaultVersion');
|
var def = get(this, 'templateResource.defaultVersion');
|
||||||
var links = get(this, 'versionLinks');
|
var links = get(this, 'versionLinks');
|
||||||
|
|
@ -96,11 +101,12 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
|
|
||||||
didRender() {
|
didRender() {
|
||||||
if (!this.get('srcSet')) {
|
if (!this.get('srcSet')) {
|
||||||
this.set('srcSet', true);
|
set(this, 'srcSet', true);
|
||||||
|
|
||||||
const $icon = this.$('img');
|
const $icon = this.$('img');
|
||||||
|
|
||||||
$icon.attr('src', $icon.data('src'));
|
$icon.attr('src', $icon.data('src'));
|
||||||
|
|
||||||
this.$('img').on('error', () => {
|
this.$('img').on('error', () => {
|
||||||
$icon.attr('src', `${ this.get('app.baseAssets') }assets/images/generic-catalog.svg`);
|
$icon.attr('src', `${ this.get('app.baseAssets') }assets/images/generic-catalog.svg`);
|
||||||
});
|
});
|
||||||
|
|
@ -213,10 +219,57 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
var selectedTemplateModel = yield get(this, 'catalog').fetchByUrl(url)
|
var selectedTemplateModel = yield get(this, 'catalog').fetchByUrl(url)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.questions) {
|
if (response.questions) {
|
||||||
|
this.parseQuestionsAndAnswers(response, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedTemplateModel && selectedTemplateModel.requiredNamespace) {
|
||||||
|
set(this, 'primaryResource.name', selectedTemplateModel.requiredNamespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(this, 'selectedTemplateModel', selectedTemplateModel);
|
||||||
|
|
||||||
|
this.initPreviewTab(selectedTemplateModel);
|
||||||
|
} else {
|
||||||
|
setProperties(this, {
|
||||||
|
selectedTemplateModel: null,
|
||||||
|
readmeContent: null,
|
||||||
|
appReadmeContent: null,
|
||||||
|
noAppReadme: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateReadme();
|
||||||
|
}),
|
||||||
|
|
||||||
|
initTemplateModel(templateModel) {
|
||||||
|
let currentAnswers = get(this, 'catalogApp.answers') || {};
|
||||||
|
|
||||||
|
this.parseQuestionsAndAnswers(templateModel, currentAnswers);
|
||||||
|
this.initPreviewTab(templateModel);
|
||||||
|
|
||||||
|
set(this, 'selectedTemplateModel', templateModel);
|
||||||
|
|
||||||
|
this.updateReadme();
|
||||||
|
},
|
||||||
|
|
||||||
|
initPreviewTab(selectedTemplateModel) {
|
||||||
|
const files = Object.keys(selectedTemplateModel.get('files')) || [];
|
||||||
|
|
||||||
|
if ( files.length > 0 ) {
|
||||||
|
const valuesYaml = files.find((file) => file.endsWith('/values.yaml'));
|
||||||
|
|
||||||
|
set(this, 'previewTab', valuesYaml ? valuesYaml : files[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parseQuestionsAndAnswers(template, currentAnswers) {
|
||||||
const questions = [];
|
const questions = [];
|
||||||
const customAnswers = {};
|
const customAnswers = {};
|
||||||
|
|
||||||
response.questions.forEach((q) => {
|
template.questions.forEach((q) => {
|
||||||
questions.push(q);
|
questions.push(q);
|
||||||
const subquestions = get(q, 'subquestions');
|
const subquestions = get(q, 'subquestions');
|
||||||
|
|
||||||
|
|
@ -224,6 +277,7 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
questions.pushObjects(subquestions);
|
questions.pushObjects(subquestions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
questions.forEach((item) => {
|
questions.forEach((item) => {
|
||||||
// This will be the component that is rendered to edit this answer
|
// This will be the component that is rendered to edit this answer
|
||||||
item.inputComponent = `schema/input-${ item.type }`;
|
item.inputComponent = `schema/input-${ item.type }`;
|
||||||
|
|
@ -231,9 +285,9 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
// Only types marked supported will show the component, Ember will explode if the component doesn't exist
|
// Only types marked supported will show the component, Ember will explode if the component doesn't exist
|
||||||
item.supported = C.SUPPORTED_SCHEMA_INPUTS.indexOf(item.type) >= 0;
|
item.supported = C.SUPPORTED_SCHEMA_INPUTS.indexOf(item.type) >= 0;
|
||||||
|
|
||||||
if (typeof current[item.variable] !== 'undefined') {
|
if (typeof currentAnswers[item.variable] !== 'undefined') {
|
||||||
// If there's an existing value, use it (for upgrade)
|
// If there's an existing value, use it (for upgrade)
|
||||||
item.answer = current[item.variable];
|
item.answer = currentAnswers[item.variable];
|
||||||
} else if (item.type === 'service' || item.type === 'certificate') {
|
} else if (item.type === 'service' || item.type === 'certificate') {
|
||||||
// Loaded async and then the component picks the default
|
// Loaded async and then the component picks the default
|
||||||
} else if ( item.type === 'boolean' ) {
|
} else if ( item.type === 'boolean' ) {
|
||||||
|
|
@ -245,38 +299,16 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.keys(current).forEach((key) => {
|
Object.keys(currentAnswers).forEach((key) => {
|
||||||
const q = questions.findBy('variable', key);
|
const q = questions.findBy('variable', key);
|
||||||
|
|
||||||
if ( !q ) {
|
if ( !q ) {
|
||||||
customAnswers[key] = current[key];
|
customAnswers[key] = currentAnswers[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
response.customAnswers = customAnswers;
|
template.customAnswers = customAnswers;
|
||||||
}
|
},
|
||||||
|
|
||||||
return response;
|
|
||||||
});
|
|
||||||
|
|
||||||
set(this, 'selectedTemplateModel', selectedTemplateModel);
|
|
||||||
|
|
||||||
const files = Object.keys(selectedTemplateModel.get('files')) || [];
|
|
||||||
|
|
||||||
if ( files.length > 0 ) {
|
|
||||||
const valuesYaml = files.find((file) => file.endsWith('/values.yaml'));
|
|
||||||
|
|
||||||
set(this, 'previewTab', valuesYaml ? valuesYaml : files[0]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
set(this, 'selectedTemplateModel', null);
|
|
||||||
set(this, 'readmeContent', null);
|
|
||||||
set(this, 'appReadmeContent', null);
|
|
||||||
set(this, 'noAppReadme', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateReadme();
|
|
||||||
}),
|
|
||||||
|
|
||||||
validate() {
|
validate() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
@ -300,8 +332,6 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
||||||
|
|
||||||
if ( requiredNamespace && (get(this, 'namespaces') || []).findBy('id', requiredNamespace) ) {
|
if ( requiredNamespace && (get(this, 'namespaces') || []).findBy('id', requiredNamespace) ) {
|
||||||
return resolve(get(this, 'primaryResource'));
|
return resolve(get(this, 'primaryResource'));
|
||||||
} else if ( requiredNamespace ) {
|
|
||||||
set(this, 'primaryResource.name', requiredNamespace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._super(...arguments);
|
return this._super(...arguments);
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,23 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-12">
|
<div class="col span-12">
|
||||||
|
{{#if selectedTemplateModel.requiredNamespace}}
|
||||||
|
<label class="acc-label pb-5">
|
||||||
|
{{t "newCatalog.requiredNamespace"}}
|
||||||
|
</label>
|
||||||
|
<p class="mt-0">
|
||||||
|
{{primaryResource.displayName}}
|
||||||
|
</p>
|
||||||
|
<p class="help-block">
|
||||||
|
This app requires the specified namespace to be unchanged.
|
||||||
|
</p>
|
||||||
|
{{else}}
|
||||||
{{form-namespace
|
{{form-namespace
|
||||||
namespace=primaryResource
|
namespace=primaryResource
|
||||||
errors=namespaceErrors
|
errors=namespaceErrors
|
||||||
registerHook=(action "registerHook")
|
registerHook=(action "registerHook")
|
||||||
}}
|
}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5715,6 +5715,7 @@ newCatalog:
|
||||||
forceUpgrade: Delete and recreate resources if needed during the upgrade
|
forceUpgrade: Delete and recreate resources if needed during the upgrade
|
||||||
forceRollback: Delete and recreate resources if needed during the rollback
|
forceRollback: Delete and recreate resources if needed during the rollback
|
||||||
templateFiles: Template Files
|
templateFiles: Template Files
|
||||||
|
requiredNamespace: Required Namespace
|
||||||
seeMore: More information...
|
seeMore: More information...
|
||||||
saveConfigure: Configure
|
saveConfigure: Configure
|
||||||
saveNew: Launch
|
saveNew: Launch
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue