From ad46fccb0dcac898804216c2695738d561483911 Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Wed, 29 Dec 2021 15:37:07 -0600 Subject: [PATCH 1/2] fixing model updates related to secret handling after prepare model action is run --- electron/app/locales/en/webui.json | 2 ++ webui/src/js/models/k8s-domain-definition.js | 23 +++++++++++--- webui/src/js/models/wdt-model-definition.js | 31 ++++++++++++++++--- webui/src/js/utils/observable-properties.js | 4 +-- .../js/viewModels/ingress-design-view-impl.js | 5 ++- 5 files changed, 52 insertions(+), 13 deletions(-) diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json index 181493eb2..14fa6ef5d 100644 --- a/electron/app/locales/en/webui.json +++ b/electron/app/locales/en/webui.json @@ -671,6 +671,8 @@ "ingress-design-add-route-label": "Add Route", "ingress-design-edit-route-label": "Edit Route", "ingress-design-delete-route-label": "Delete Route", + "ingress-design-delete-route-warning-title": "Deleting Ingress Route", + "ingress-design-delete-route-warning-message": "Ingress route is only deleted from the table. If it already exists in the Kubernetes cluster, you must manually delete it from the cluster", "ingress-installer-aborted-error-title": "Ingress Controller Installation Aborted", "ingress-installer-not-install-message": "The Install Ingress Controller option is off so there is nothing to do.", diff --git a/webui/src/js/models/k8s-domain-definition.js b/webui/src/js/models/k8s-domain-definition.js index 978ec9998..110763a4e 100644 --- a/webui/src/js/models/k8s-domain-definition.js +++ b/webui/src/js/models/k8s-domain-definition.js @@ -103,6 +103,7 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut // update the secrets list when any model content changes. wdtModel.modelContentChanged.subscribe(() => { + wktLogger.debug('modelContentChanged event calling updateSecrets()'); this.updateSecrets(); }); @@ -132,15 +133,20 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut }; this.setCredentialPathsForSecretsTable = (json) => { + wktLogger.debug('entering setCredentialPathsForSecretsTable() with secrets table length = %s', this.secrets.value.length); if (this.secrets.value.length > 0) { if (!json.credentialPaths) { + wktLogger.debug('creating credentialPaths array'); json.credentialPaths = []; } for (const secret of this.secrets.value) { + wktLogger.debug('working on secret path %s', `${name}.secrets.${secret.uid}`); if (secret.username) { + wktLogger.debug('setting secret %s', `${name}.secrets.${secret.uid}.username`); json.credentialPaths.push(`${name}.secrets.${secret.uid}.username`); } if (secret.password) { + wktLogger.debug('setting secret %s', `${name}.secrets.${secret.uid}.password`); json.credentialPaths.push(`${name}.secrets.${secret.uid}.password`); } } @@ -207,10 +213,18 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut this.handlePrepareModelSecrets = (secrets) => { if (secrets && secrets.secrets && secrets.secrets.length) { + wktLogger.debug('handlePrepareModelSecrets() working on %d secrets', secrets.secrets.length); for (const secret of secrets.secrets) { - const existingSecretObject = findSecretByName(secret.name, this.secrets.observable()); + wktLogger.debug('working on secret %s', secret.name); + + // The secret should always exist already because prepare model updated the model first, + // which triggers updating the secrets ListProperty. If not, something is broken... + // + const existingSecretObject = findSecretByName(this.uid.value, secret.name, this.secrets.observable()); updateSecretFromPrepareModelResults(existingSecretObject, secret.keys); } + } else { + wktLogger.debug('handlePrepareModelSecrets() has nothing to do'); } }; @@ -222,7 +236,7 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut this.getFieldValueFromExistingSecrets = (uid, fieldName, defaultValue) => { let result = defaultValue; - for (const domainSecret of this.secrets.value) { + for (const domainSecret of this.secrets.observable()) { if (domainSecret.uid === uid) { if (domainSecret[fieldName]) { result = domainSecret[fieldName]; @@ -269,10 +283,11 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut } } - function findSecretByName(secretName, secretsList) { + function findSecretByName(domainUid, secretName, secretsList) { let result; + const domainQualifiedSecretName = `${domainUid}-${secretName}`; for (const secret of secretsList) { - if (secret.name === secretName) { + if (secret.name === domainQualifiedSecretName || secret.name === secretName) { result = secret; break; } diff --git a/webui/src/js/models/wdt-model-definition.js b/webui/src/js/models/wdt-model-definition.js index 05aa77a86..7267ac16b 100644 --- a/webui/src/js/models/wdt-model-definition.js +++ b/webui/src/js/models/wdt-model-definition.js @@ -111,8 +111,24 @@ define(['knockout', 'utils/observable-properties', 'js-yaml', 'utils/validation- const secretName = matches.groups.name; const secretEnvVar = matches.groups.envvar; const secretField = matches.groups.field; - - const secretKey = secretEnvVar ? `${secretEnvVar}-${secretName}` : secretName; + wktLogger.debug('found matching secret %s with envVar = %s and field = %s', secretName, secretEnvVar, secretField); + + // While this key is never used outside this function, we need the key to + // match the resolved secret name. For example, if the DOMAIN_UID is mydomain, + // the following two secret fields should be part of the same secret: + // + // JDBCDriverParams: + // URL: '@@PROP:JDBC.myds.URL@@' + // PasswordEncrypted: '@@SECRET:@@ENV:DOMAIN_UID@@-jdbc-myds:password@@' + // DriverName: com.mysql.cj.jdbc.Driver + // Properties: + // user: + // Value: '@@SECRET:mydomain-jdbc-myds:username@@' + // + let secretKey = secretName; + if (secretEnvVar) { + secretKey = secretName.startsWith('-') ? `${secretEnvVar}${secretName}` : `${secretEnvVar}-${secretName}`; + } let secretData; if (secretsMap.has(secretKey)) { @@ -125,6 +141,8 @@ define(['knockout', 'utils/observable-properties', 'js-yaml', 'utils/validation- } secretData[secretField] = ''; secretsMap.set(secretKey, secretData); + } else { + wktLogger.debug('skipping matching secret %s', matches.groups.name); } }); return [...secretsMap.values()]; @@ -287,14 +305,19 @@ define(['knockout', 'utils/observable-properties', 'js-yaml', 'utils/validation- */ this.setModelFileContents = modelContent => { this.modelFileContents = {}; - this.modelContent(''); const models = modelContent['models']; - if(models) { + if (models) { for (const [file, contents] of Object.entries(models)) { this.recordModelFile(file, contents); } this.modelContent(this.getCurrentModelFileContents() || ''); + } else { + // Only empty the model content where explicitly told to do so + // since setting this field generates an event that triggers + // other code to run (e.g., k8s-domain-definition.updateSecrets()). + // + this.modelContent(''); } }; diff --git a/webui/src/js/utils/observable-properties.js b/webui/src/js/utils/observable-properties.js index 521af03c8..79ac25116 100644 --- a/webui/src/js/utils/observable-properties.js +++ b/webui/src/js/utils/observable-properties.js @@ -438,8 +438,8 @@ define(['knockout', 'utils/common-utilities', 'utils/validation-helper', 'utils/ } } - addNewItem() { - this.observable.push(this.createArrayItem(this, arguments.length === 0 ? {} : arguments[0])); + addNewItem(item) { + this.observable.push(this.createArrayItem(this, !!item ? item : {})); } get observable() { diff --git a/webui/src/js/viewModels/ingress-design-view-impl.js b/webui/src/js/viewModels/ingress-design-view-impl.js index 237a5788f..5111a9340 100644 --- a/webui/src/js/viewModels/ingress-design-view-impl.js +++ b/webui/src/js/viewModels/ingress-design-view-impl.js @@ -195,8 +195,8 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, this.handleDeleteRoute = (event, context) => { const index = context.item.index; this.routes.observable.splice(index, 1); - const title = i18n.t('ingress-installer-delete-route-warning-title'); - const message = i18n.t('ingress-installer-delete-route-warning-message'); + const title = i18n.t('ingress-design-delete-route-warning-title'); + const message = i18n.t('ingress-design-delete-route-warning-message'); window.api.ipc.invoke('show-error-message', title, message); }; @@ -235,7 +235,6 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, this.getEnabledText = (value) => { return this.anyLabelMapper(value ? 'dialog-button-yes' : 'dialog-button-no'); }; - } /* From 9aa1b3794a76b9260716a31a75f2e80da1e2d634 Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Wed, 29 Dec 2021 18:59:28 -0600 Subject: [PATCH 2/2] removing internal url from package-lock.json --- webui/package-lock.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/webui/package-lock.json b/webui/package-lock.json index 637f7a307..10725dcf8 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -181,9 +181,8 @@ }, "node_modules/@oracle/oraclejet": { "version": "11.1.4", - "resolved": "https://artifacthub-tip.oraclecorp.com/api/npm/npmjs-remote/@oracle/oraclejet/-/oraclejet-11.1.4.tgz", - "integrity": "sha1-K5DjUOFYmw3kt5QJ5IW5qNjd0Dk=", - "license": "UPL-1.0", + "resolved": "https://registry.npmjs.org/@oracle/oraclejet/-/oraclejet-11.1.4.tgz", + "integrity": "sha512-M6j+yrxsqHCQPkcDyP2uWOWRhsKXpXCxlloNgVGp2qJGpGfRas02euwI0wCL/VR2UTA1BTgjffu1Z9KAfreXyg==", "dependencies": { "@types/geojson": "latest", "@types/signals": "latest", @@ -6274,8 +6273,8 @@ }, "@oracle/oraclejet": { "version": "11.1.4", - "resolved": "https://artifacthub-tip.oraclecorp.com/api/npm/npmjs-remote/@oracle/oraclejet/-/oraclejet-11.1.4.tgz", - "integrity": "sha1-K5DjUOFYmw3kt5QJ5IW5qNjd0Dk=", + "resolved": "https://registry.npmjs.org/@oracle/oraclejet/-/oraclejet-11.1.4.tgz", + "integrity": "sha512-M6j+yrxsqHCQPkcDyP2uWOWRhsKXpXCxlloNgVGp2qJGpGfRas02euwI0wCL/VR2UTA1BTgjffu1Z9KAfreXyg==", "requires": { "@types/geojson": "latest", "@types/signals": "latest",