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 { randomStr } from 'shared/utils/util';
|
||||
import C from 'ui/utils/constants';
|
||||
import Util from 'ui/utils/util';
|
||||
|
||||
export default Route.extend({
|
||||
modalService: service('modal'),
|
||||
catalog: service(),
|
||||
scope: service(),
|
||||
clusterStore: service(),
|
||||
settings: service(),
|
||||
|
||||
parentRoute: 'catalog-tab',
|
||||
|
||||
|
|
@ -39,24 +41,49 @@ export default Route.extend({
|
|||
}
|
||||
|
||||
return hash(dependencies, 'Load dependencies').then((results) => {
|
||||
let neuNSN = results.tpl.get('displayName');
|
||||
let dupe = results.namespaces.findBy('id', neuNSN);
|
||||
var def = get(results, 'tpl.defaultVersion');
|
||||
var links = get(results, 'tpl.versionLinks');
|
||||
var app = get(results, 'app');
|
||||
var catalogTemplateUrl = null;
|
||||
|
||||
if ( !results.namespace ) {
|
||||
let { newNamespaceName, newNS } = this.newNamespace(dupe, neuNSN);
|
||||
|
||||
if ( dupe ) {
|
||||
neuNSN = newNamespaceName;
|
||||
if (app && params.appId && !params.upgrade) {
|
||||
def = get(app, 'externalIdInfo.version');
|
||||
}
|
||||
|
||||
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 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])
|
||||
.map((key) => ({
|
||||
|
|
@ -67,23 +94,16 @@ export default Route.extend({
|
|||
|
||||
if (results.app) {
|
||||
if (get(params, 'clone')) {
|
||||
let { newNamespaceName, newNS } = this.newNamespace(dupe, neuNSN);
|
||||
|
||||
if ( dupe ) {
|
||||
neuNSN = newNamespaceName;
|
||||
}
|
||||
|
||||
results.namespace = newNS;
|
||||
|
||||
neuApp = results.app.cloneForNew();
|
||||
set(neuApp, 'name', results.namespace.name);
|
||||
|
||||
set(neuApp, 'name', this.dedupeName(get(namespace, 'displayName')));
|
||||
} else {
|
||||
neuApp = results.app;
|
||||
}
|
||||
} else {
|
||||
neuApp = store.createRecord({
|
||||
type: 'app',
|
||||
name: results.namespace.name,
|
||||
name: neuNamespaceName,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +117,9 @@ export default Route.extend({
|
|||
return EmberObject.create({
|
||||
allTemplates: this.modelFor(get(this, 'parentRoute')).get('catalog'),
|
||||
catalogApp: neuApp,
|
||||
namespace: results.namespace,
|
||||
catalogTemplateUrl: links[def],
|
||||
catalogTemplate,
|
||||
namespace,
|
||||
namespaces: results.namespaces,
|
||||
tpl: results.tpl,
|
||||
tplKind: kind,
|
||||
|
|
@ -106,6 +128,7 @@ export default Route.extend({
|
|||
versionsArray: verArr,
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
resetController(controller, isExiting/* , transition*/) {
|
||||
|
|
@ -132,11 +155,15 @@ export default Route.extend({
|
|||
},
|
||||
},
|
||||
|
||||
newNamespace(duplicateName, newNamespaceName) {
|
||||
dedupeName(name) {
|
||||
const suffix = randomStr(5, 5, 'novowels');
|
||||
|
||||
if ( duplicateName ) {
|
||||
newNamespaceName = `${ get(duplicateName, 'displayName') }-${ suffix }`;
|
||||
return `${ name }-${ suffix }`;
|
||||
},
|
||||
|
||||
newNamespace(duplicateNamespace, newNamespaceName) {
|
||||
if ( duplicateNamespace ) {
|
||||
newNamespaceName = this.dedupeName(get(duplicateNamespace, 'displayName'));
|
||||
}
|
||||
|
||||
const newNS = get(this, 'clusterStore').createRecord({
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
{{new-catalog
|
||||
allTemplates=model.allTemplates
|
||||
namespaces=model.namespaces
|
||||
cancel=(action "cancel")
|
||||
catalogApp=model.catalogApp
|
||||
catalogTemplate=model.catalogTemplate
|
||||
namespaceResource=model.namespace
|
||||
namespaces=model.namespaces
|
||||
parentRoute=parentRoute
|
||||
upgrade=model.upgradeTemplate
|
||||
templateResource=model.tpl
|
||||
selectedTemplateUrl=model.catalogTemplateUrl
|
||||
templateKind=model.tplKind
|
||||
templateResource=model.tpl
|
||||
upgrade=model.upgradeTemplate
|
||||
versionLinks=model.versionLinks
|
||||
versionsArray=model.versionsArray
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
|||
questionsArray: null,
|
||||
selectedTemplateUrl: null,
|
||||
selectedTemplateModel: null,
|
||||
catalogTemplate: null,
|
||||
readmeContent: null,
|
||||
appReadmeContent: null,
|
||||
pastedAnswers: null,
|
||||
|
|
@ -75,7 +76,11 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
|||
|
||||
scheduleOnce('afterRender', () => {
|
||||
if ( get(this, 'selectedTemplateUrl') ) {
|
||||
if (this.catalogTemplate) {
|
||||
this.initTemplateModel(this.catalogTemplate);
|
||||
} else {
|
||||
this.templateChanged();
|
||||
}
|
||||
} else {
|
||||
var def = get(this, 'templateResource.defaultVersion');
|
||||
var links = get(this, 'versionLinks');
|
||||
|
|
@ -96,11 +101,12 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
|||
|
||||
didRender() {
|
||||
if (!this.get('srcSet')) {
|
||||
this.set('srcSet', true);
|
||||
set(this, 'srcSet', true);
|
||||
|
||||
const $icon = this.$('img');
|
||||
|
||||
$icon.attr('src', $icon.data('src'));
|
||||
|
||||
this.$('img').on('error', () => {
|
||||
$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)
|
||||
.then((response) => {
|
||||
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 customAnswers = {};
|
||||
|
||||
response.questions.forEach((q) => {
|
||||
template.questions.forEach((q) => {
|
||||
questions.push(q);
|
||||
const subquestions = get(q, 'subquestions');
|
||||
|
||||
|
|
@ -224,6 +277,7 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
|||
questions.pushObjects(subquestions);
|
||||
}
|
||||
});
|
||||
|
||||
questions.forEach((item) => {
|
||||
// This will be the component that is rendered to edit this answer
|
||||
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
|
||||
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)
|
||||
item.answer = current[item.variable];
|
||||
item.answer = currentAnswers[item.variable];
|
||||
} else if (item.type === 'service' || item.type === 'certificate') {
|
||||
// Loaded async and then the component picks the default
|
||||
} 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);
|
||||
|
||||
if ( !q ) {
|
||||
customAnswers[key] = current[key];
|
||||
customAnswers[key] = currentAnswers[key];
|
||||
}
|
||||
});
|
||||
|
||||
response.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();
|
||||
}),
|
||||
template.customAnswers = customAnswers;
|
||||
},
|
||||
|
||||
validate() {
|
||||
this._super();
|
||||
|
|
@ -300,8 +332,6 @@ export default Component.extend(NewOrEdit, CatalogApp, ChildHook, {
|
|||
|
||||
if ( requiredNamespace && (get(this, 'namespaces') || []).findBy('id', requiredNamespace) ) {
|
||||
return resolve(get(this, 'primaryResource'));
|
||||
} else if ( requiredNamespace ) {
|
||||
set(this, 'primaryResource.name', requiredNamespace);
|
||||
}
|
||||
|
||||
return this._super(...arguments);
|
||||
|
|
|
|||
|
|
@ -120,11 +120,23 @@
|
|||
|
||||
<div class="row">
|
||||
<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
|
||||
namespace=primaryResource
|
||||
errors=namespaceErrors
|
||||
registerHook=(action "registerHook")
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -5715,6 +5715,7 @@ newCatalog:
|
|||
forceUpgrade: Delete and recreate resources if needed during the upgrade
|
||||
forceRollback: Delete and recreate resources if needed during the rollback
|
||||
templateFiles: Template Files
|
||||
requiredNamespace: Required Namespace
|
||||
seeMore: More information...
|
||||
saveConfigure: Configure
|
||||
saveNew: Launch
|
||||
|
|
|
|||
Loading…
Reference in New Issue