diff --git a/electron/app/js/ipcRendererPreload.js b/electron/app/js/ipcRendererPreload.js
index f02f36895..8e757725e 100644
--- a/electron/app/js/ipcRendererPreload.js
+++ b/electron/app/js/ipcRendererPreload.js
@@ -92,6 +92,7 @@ contextBridge.exposeInMainWorld(
'start-verrazzano-install',
'start-get-verrazzano-install-status',
'start-deploy-verrazzano-component',
+ 'start-get-vz-application-status',
'start-undeploy-verrazzano-component',
'start-deploy-verrazzano-application',
'start-undeploy-verrazzano-application',
diff --git a/electron/app/js/wktWindow.js b/electron/app/js/wktWindow.js
index 9f0585676..05adf766e 100644
--- a/electron/app/js/wktWindow.js
+++ b/electron/app/js/wktWindow.js
@@ -408,7 +408,7 @@ class WktAppMenu {
if (!focusedWindow) {
return dialog.showErrorBox(
i18n.t('menu-go-domain-status-title'),
- i18n.t('menu-go-domain=status-error-message')
+ i18n.t('menu-go-domain-status-error-message')
);
}
sendToWindow(focusedWindow, 'start-get-k8s-domain-status');
@@ -550,6 +550,21 @@ class WktAppMenu {
sendToWindow(focusedWindow,'start-deploy-verrazzano-application');
}
},
+ {
+ id: 'checkVerrazzanoApplicationStatus',
+ label: i18n.t('menu-go-check-verrazzano-application-status'),
+ visible: !this._isWkoTarget,
+ enabled: !this._hasOpenDialog,
+ click(item, focusedWindow) {
+ if (!focusedWindow) {
+ return dialog.showErrorBox(
+ i18n.t('menu-go-check-verrazzano-application-status-error-title'),
+ i18n.t('menu-go-check-verrazzano-application-status-error-message')
+ );
+ }
+ sendToWindow(focusedWindow, 'start-get-vz-application-status');
+ }
+ },
{
id: 'undeployVerrazzanoApplication',
label: i18n.t('menu-go-undeploy-verrazzano-application'),
diff --git a/electron/app/locales/en/electron.json b/electron/app/locales/en/electron.json
index 67279e05e..6141c9e73 100644
--- a/electron/app/locales/en/electron.json
+++ b/electron/app/locales/en/electron.json
@@ -93,6 +93,9 @@
"menu-go-deploy-verrazzano-application": "Deploy Verrazzano Application",
"menu-go-deploy-verrazzano-application-error-title": "No Active Project Window",
"menu-go-deploy-verrazzano-application-error-message": "Cannot deploy Verrazzano application since there is no active window, and therefore no project with the Verrazzano application configuration to deploy.",
+ "menu-go-check-verrazzano-application-status": "Check Verrazzano Application Status",
+ "menu-go-check-verrazzano-application-status-error-title": "No Active Project Window",
+ "menu-go-check-verrazzano-application-status-error-message": "Cannot check Verrazzano application status since there is no active window, and therefore no project with the Verrazzano application configuration to check.",
"menu-go-undeploy-verrazzano-application": "Undeploy Verrazzano Application",
"menu-go-undeploy-verrazzano-application-error-title": "No Active Project Window",
"menu-go-undeploy-verrazzano-application-error-message": "Cannot undeploy Verrazzano application since there is no active window, and therefore no project with the Verrazzano application configuration to undeploy.",
diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json
index f6681d46c..cc6866109 100644
--- a/electron/app/locales/en/webui.json
+++ b/electron/app/locales/en/webui.json
@@ -102,11 +102,14 @@
"kubectl-helper-project-not-saved-error-prefix": "Unable to verify Kubernetes client connectivity because project save failed",
"kubectl-helper-set-context-error-message": "Unable to verify Kubernetes client connectivity because setting the Kubernetes client cluster context failed: {{error}}.",
"kubectl-helper-verify-connect-in-progress": "Verifying Kubernetes Client Connectivity",
- "kubectl-helper-verify-connect-success-title": "Verify Kubernetes Client Connectivity Success",
- "kubectl-helper-verify-connect-success-message": "Kubernetes client (version {{clientVersion}}) successfully connected to the Kubernetes cluster (version {{serverVersion}}).",
- "kubectl-helper-verify-connect-failed-title": "Verify Kubernetes Client Connectivity Failed",
- "kubectl-helper-verify-connect-failed-error-message": "Failed to verify Kubernetes client connectivity: {{error}}.",
+ "kubectl-helper-verify-connect-success-title": "Verify Kubernetes Client Connectivity Success to Cluster {{clusterName}}",
+ "kubectl-helper-verify-connect-success-message": "Kubernetes client (version {{clientVersion}}) successfully connected to the Kubernetes cluster {{clusterName}} (version {{serverVersion}}).",
+ "kubectl-helper-verify-connect-failed-title": "Verify Kubernetes Client Connectivity Failed for Cluster {{clusterName}}",
+ "kubectl-helper-verify-connect-failed-error-message": "Failed to verify Kubernetes client connectivity to cluster {{clusterName}}: {{error}}.",
"kubectl-helper-verify-connect-catch-all-error-message": "Failed to verify Kubernetes client connectivity due to an unexpected error: {{error}}.",
+ "kubectl-helper-choose-cluster-dialog-title": "Choose the Verrazzano cluster to verify connectivity",
+ "kubectl-helper-choose-cluster-name-label": "Verrazzano Cluster Name",
+ "kubectl-helper-choose-cluster-name-help": "The Verrazzano cluster name for which to verify connectivity.",
"project-settings-form-name": "Project Settings",
"project-settings-title": "Project Settings",
@@ -1642,6 +1645,7 @@
"vz-application-design-choose-clusters-flow-nane": "Choose Verrazzano Clusters",
"vz-application-design-choose-clusters-validation-error-title": "Choose Verrazzano Clusters for Application Placement Aborted",
"vz-application-design-get-clusters-in-progress": "Getting Verrazzano Clusters",
+ "vz-application-design-use-context-error-message": "Unable to choose clusters due to an error while switching the Kubernetes cluster context: {{error}}.",
"vz-application-design-get-clusters-error-message": "Unable to choose clusters due to an error while getting the list of available clusters: {{error}}.",
"vz-application-design-choose-clusters-dialog-title": "Choose Verrazzano Clusters for Application Placement",
"vz-application-design-choose-clusters-name-label": "Verrazzano Cluster Names",
@@ -1772,8 +1776,15 @@
"vz-application-status-checker-application-not-exist-error-message": "Unable to get the application status because the application {{application}} does not exist.",
"vz-application-status-checker-ns-not-exist-error-message": "Unable to get the application status because the application namespace {{namespace}} does not exist.",
"vz-application-status-checker-domain-not-exist-error-message": "Unable to get the application status because the domain UID {{domain}} does not exist.",
+ "vz-application-status-checker-vz-managed-cluster-not-found-error": "Unable to get the Verrazzano multicluster application status because the Verrazzano managed cluster connectivity configuration for managed cluster {{clusterName}} was not found",
+ "vz-application-status-checker-check-failed-title": "Verrazzano Application Status Check Failed",
+ "vz-application-status-checker-check-catch-all-error-message": "Verrazzano application status check failed with an unexpected error: {{error}}.",
- "vz-application-status-title": "Application Status for \"{{application}}\"",
+ "vz-application-status-choose-cluster-dialog-title": "Choose the Verrazzano Cluster to Check Application Status",
+ "vz-application-status-choose-cluster-name-label": "Verrazzano Cluster Name",
+ "vz-application-status-choose-cluster-name-help": "Choose the Verrazzano cluster on which to check the status of the deployed application.",
+
+ "vz-application-status-title": "Application Status for \"{{application}}\" in Cluster \"{{clusterName}}\"",
"vz-application-status-domain-title": "Domain \"{{domain}}\"",
"app-update-title": "Application Update",
diff --git a/webui/src/js/utils/k8s-helper.js b/webui/src/js/utils/k8s-helper.js
index 77d5401fc..676edb5a0 100644
--- a/webui/src/js/utils/k8s-helper.js
+++ b/webui/src/js/utils/k8s-helper.js
@@ -13,11 +13,11 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
super();
}
- async startVerifyClusterConnectivity(kubeConfig, kubeContext) {
- await this.executeAction(this.callVerifyClusterConnectivity, kubeConfig, kubeContext);
+ async startVerifyClusterConnectivity() {
+ await this.executeAction(this.callVerifyClusterConnectivity);
}
- async callVerifyClusterConnectivity(kubeConfig, kubeContext, options) {
+ async callVerifyClusterConnectivity(options) {
if (!options) {
options = {};
}
@@ -31,6 +31,27 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
return Promise.resolve(false);
}
+ let clusterToCheck;
+ const availableClusters = this._getTargetClusters();
+ if (availableClusters.length > 1) {
+ const args = [ ];
+ availableClusters.forEach(availableCluster => args.push({
+ name: availableCluster.name,
+ label: availableCluster.name
+ }));
+ const result = await dialogHelper.promptDialog('k8s-helper-choose-cluster-dialog',
+ { availableClusters: args });
+ if (result?.clusterName) {
+ clusterToCheck = result.clusterName;
+ } else {
+ return Promise.resolve(false);
+ }
+ } else if (availableClusters.length === 1) {
+ clusterToCheck = availableClusters[0].name;
+ }
+
+ const { targetClusterKubeConfig, targetClusterKubeContext } = this._getTargetCluster(clusterToCheck);
+
const totalSteps = 4.0;
try {
let busyDialogMessage = i18n.t('flow-validate-kubectl-exe-in-progress');
@@ -56,8 +77,8 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
busyDialogMessage = i18n.t('flow-kubectl-use-context-in-progress');
dialogHelper.updateBusyDialog(busyDialogMessage, 2/totalSteps);
- const kubectlContext = kubeContext || this.project.kubectl.kubeConfigContextToUse.value;
- const kubectlOptions = this.getKubectlOptions(kubeConfig);
+ const kubectlContext = targetClusterKubeContext || this.project.kubectl.kubeConfigContextToUse.value;
+ const kubectlOptions = this.getKubectlOptions(targetClusterKubeConfig);
if (!options.skipKubectlSetContext) {
if (! await this.useKubectlContext(kubectlExe, kubectlOptions, kubectlContext, errTitle, errPrefix)) {
return Promise.resolve(false);
@@ -66,7 +87,7 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
busyDialogMessage = i18n.t('kubectl-helper-verify-connect-in-progress');
dialogHelper.updateBusyDialog(busyDialogMessage, 3/totalSteps);
- const verifyConnectivityResult = await this.verifyConnectivity(kubectlExe, kubectlOptions);
+ const verifyConnectivityResult = await this.verifyConnectivity(kubectlExe, kubectlOptions, clusterToCheck);
return Promise.resolve(verifyConnectivityResult);
} catch (err) {
dialogHelper.closeBusyDialog();
@@ -76,18 +97,20 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
}
}
- async verifyConnectivity(kubectlExe, kubectlOptions) {
+ async verifyConnectivity(kubectlExe, kubectlOptions, clusterToCheck) {
try {
const verifyResult = await window.api.ipc.invoke('kubectl-verify-connection', kubectlExe, kubectlOptions);
dialogHelper.closeBusyDialog();
+ const clusterName = clusterToCheck || '';
if (verifyResult.isSuccess) {
- const title = i18n.t('kubectl-helper-verify-connect-success-title');
+ const title = i18n.t('kubectl-helper-verify-connect-success-title', { clusterName });
const message = i18n.t('kubectl-helper-verify-connect-success-message',
- {clientVersion: verifyResult.clientVersion, serverVersion: verifyResult.serverVersion});
+ { clientVersion: verifyResult.clientVersion, serverVersion: verifyResult.serverVersion, clusterName });
await window.api.ipc.invoke('show-info-message', title, message);
} else {
- const errTitle = i18n.t('kubectl-helper-verify-connect-failed-title');
- const errMessage = i18n.t('kubectl-helper-verify-connect-failed-error-message', {error: verifyResult.reason});
+ const errTitle = i18n.t('kubectl-helper-verify-connect-failed-title', { clusterName });
+ const errMessage = i18n.t('kubectl-helper-verify-connect-failed-error-message',
+ { error: verifyResult.reason, clusterName});
await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
return Promise.resolve(false);
}
@@ -107,6 +130,35 @@ function(WktActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, val
return validationObject;
}
+
+ _getTargetClusters() {
+ let clusters = [];
+ if (this.project.settings.wdtTargetType.value === 'vz') {
+ clusters.push({
+ name: 'local',
+ kubeConfig: this.project.kubectl.kubeConfig.value,
+ kubeContext: this.project.kubectl.kubeConfigContextToUse.value
+ });
+ this.project.kubectl.vzManagedClusters.observable()
+ .forEach(managedClusterData => clusters.push(managedClusterData));
+ }
+ return clusters;
+ }
+
+ _getTargetCluster(clusterToCheck) {
+ const result = {
+ targetClusterKubeConfig: undefined,
+ targetClusterKubeContext: undefined
+ };
+ if (clusterToCheck) {
+ const clusterData = this._getTargetClusters().find(cluster => clusterToCheck === cluster.name);
+ if (clusterData) {
+ result.targetClusterKubeConfig = clusterData.kubeConfig;
+ result.targetClusterKubeContext = clusterData.kubeContext;
+ }
+ }
+ return result;
+ }
}
return new KubernetesHelper();
diff --git a/webui/src/js/utils/view-helper.js b/webui/src/js/utils/view-helper.js
index 6f728418a..6a78951de 100644
--- a/webui/src/js/utils/view-helper.js
+++ b/webui/src/js/utils/view-helper.js
@@ -12,7 +12,6 @@ define(['ojs/ojcontext'],
// width of button column in WKT tables.
// ideally this could be specified as 'auto', but oj-table will not set below 100px.
this.BUTTON_COLUMN_WIDTH = '55px';
- this.TEXT_BUTTON_COLUMN_WIDTH = '175px';
const thisHelper = this;
diff --git a/webui/src/js/utils/vz-application-status-checker.js b/webui/src/js/utils/vz-application-status-checker.js
index 71df2edf1..18aead002 100644
--- a/webui/src/js/utils/vz-application-status-checker.js
+++ b/webui/src/js/utils/vz-application-status-checker.js
@@ -7,7 +7,7 @@
define(['utils/vz-actions-base', 'models/wkt-project', 'models/wkt-console', 'utils/i18n', 'utils/project-io',
'utils/dialog-helper', 'utils/k8s-domain-resource-generator', 'utils/k8s-domain-configmap-generator',
- 'utils/validation-helper', 'utils/wkt-logger', 'utils/helm-helper'],
+ 'utils/validation-helper', 'utils/wkt-logger'],
function (VzActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, K8sDomainResourceGenerator,
K8sDomainConfigMapGenerator, validationHelper, wktLogger) {
class VerrazzanoApplicationStatusChecker extends VzActionsBase {
@@ -29,11 +29,31 @@ function (VzActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, K8s
return Promise.resolve(false);
}
+ let clusterToCheck;
+ const targetClusters = this._getTargetClusters();
+ if (targetClusters.length > 1) {
+ const args = [ ];
+ targetClusters.forEach(targetCluster => args.push({ name:targetCluster, label: targetCluster }));
+ const result = await dialogHelper.promptDialog('vz-application-status-choose-cluster-dialog',
+ { targetClusters: args });
+ if (result?.clusterName) {
+ clusterToCheck = result.clusterName;
+ } else {
+ return Promise.resolve(false);
+ }
+ } else if (targetClusters.length === 1) {
+ clusterToCheck = targetClusters[0];
+ }
+
+ const managedClusterData = this._getTargetCluster(clusterToCheck);
+ const targetClusterKubeConfig = managedClusterData ? managedClusterData.kubeConfig : undefined;
+ const targetClusterKubeContext = managedClusterData ? managedClusterData.kubeContext : undefined;
+
const totalSteps = 8.0;
try {
const kubectlExe = this.getKubectlExe();
- const kubectlOptions = this.getKubectlOptions();
- const kubectlContext = this.getKubectlContext();
+ const kubectlOptions = this.getKubectlOptions(targetClusterKubeConfig);
+ const kubectlContext = targetClusterKubeContext || this.getKubectlContext();
let operatorMajorVersion = '';
let busyDialogMessage = i18n.t('flow-validate-kubectl-exe-in-progress');
@@ -113,6 +133,7 @@ function (VzActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, K8s
const results = this.buildDomainStatus(domainStatus, operatorMajorVersion);
results['domainStatus'] = domainStatus;
const options = {
+ clusterName: clusterToCheck,
domainStatus: results.domainStatus,
domainOverallStatus: results.domainOverallStatus,
applicationName: this.project.vzApplication.applicationName.value,
@@ -135,6 +156,10 @@ function (VzActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, K8s
this.project.vzApplication.applicationName.validate(true));
validationObject.addField('vz-application-design-namespace-label',
this.project.k8sDomain.kubernetesNamespace.validate(true));
+ if (this.project.vzApplication.useMultiClusterApplication.value) {
+ validationObject.addField('vz-application-design-cluster-names-label',
+ validationHelper.validateRequiredField(this.project.vzApplication.placementClusters.value));
+ }
const componentFormConfig = validationObject.getDefaultConfigObject();
componentFormConfig.formName = 'vz-component-design-form-name';
@@ -145,11 +170,52 @@ function (VzActionsBase, project, wktConsole, i18n, projectIo, dialogHelper, K8s
kubectlFormConfig.formName = 'kubectl-title';
validationObject.addField('kubectl-exe-file-path-label',
validationHelper.validateRequiredField(this.project.kubectl.executableFilePath.value), kubectlFormConfig);
- validationObject.addField('kubectl-helm-exe-file-path-label',
- validationHelper.validateRequiredField(this.project.kubectl.helmExecutableFilePath.value), kubectlFormConfig);
+
+ if (this.project.vzApplication.useMultiClusterApplication.value) {
+ const targetClusters = this.project.vzApplication.placementClusters.value;
+ if (targetClusters.length > 0) {
+ for (const targetCluster of targetClusters) {
+ if (targetCluster !== 'local') {
+ this._validateVerrazzanoManagedClusterConnectivityEntry(validationObject, kubectlFormConfig, targetCluster);
+ }
+ }
+ }
+ }
return validationObject;
}
+
+ _getTargetClusters() {
+ if (this.project.vzApplication.useMultiClusterApplication.value) {
+ return this.project.vzApplication.placementClusters.value;
+ } else {
+ return ['local'];
+ }
+ }
+
+ _getTargetCluster(clusterName) {
+ if (clusterName !== 'local') {
+ return this.project.kubectl.vzManagedClusters.observable().find(managedCluster =>
+ managedCluster.name === clusterName);
+ }
+ }
+
+ _validateVerrazzanoManagedClusterConnectivityEntry(validationObject, kubectlFormConfig, targetManagedClusterName) {
+ let found = false;
+ for (const managedClusterData of this.project.kubectl.vzManagedClusters.observable()) {
+ if (targetManagedClusterName === managedClusterData.name) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ const errorMessage = i18n.t('vz-application-status-checker-vz-managed-cluster-not-found-error',
+ { clusterName: targetManagedClusterName});
+ validationObject.addField('kubectl-vz-managed-cluster-name-heading',
+ [errorMessage], kubectlFormConfig);
+ }
+ }
}
return new VerrazzanoApplicationStatusChecker();
diff --git a/webui/src/js/viewModels/k8s-helper-choose-cluster-dialog.js b/webui/src/js/viewModels/k8s-helper-choose-cluster-dialog.js
new file mode 100644
index 000000000..153ac2888
--- /dev/null
+++ b/webui/src/js/viewModels/k8s-helper-choose-cluster-dialog.js
@@ -0,0 +1,52 @@
+/**
+ * @license
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ * Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
+ */
+'use strict';
+
+define(['accUtils', 'knockout', 'utils/i18n', 'utils/observable-properties', 'utils/validation-helper',
+ 'ojs/ojarraydataprovider', 'utils/wkt-logger', 'ojs/ojselectcombobox', 'ojs/ojinputtext', 'ojs/ojlabel',
+ 'ojs/ojbutton', 'ojs/ojdialog', 'ojs/ojformlayout', 'ojs/ojvalidationgroup'],
+function(accUtils, ko, i18n, props, validationHelper, ArrayDataProvider) {
+ function KubernetesHelperChooseClusterDialogModel(args) {
+ const DIALOG_SELECTOR = '#k8sHelperChooseClusterDialog';
+
+ this.i18n = i18n;
+ this.testClusterNames = args.availableClusters;
+ this.selectedTestClusterName = ko.observable();
+ this.testClusterNamesDP =
+ new ArrayDataProvider(this.testClusterNames, { keyAttributes: 'name' });
+
+ this.connected = () => {
+ accUtils.announce('Choose Verrazzano application status choose cluster dialog loaded.', 'assertive');
+ // open the dialog after the current thread, which is loading this view model.
+ // using oj-dialog initial-visibility="show" causes vertical centering issues.
+ setTimeout(function() {
+ $(DIALOG_SELECTOR)[0].open();
+ }, 1);
+ };
+
+ this.labelMapper = (labelId) => {
+ return i18n.t(`kubectl-helper-choose-cluster-${labelId}`);
+ };
+
+ this.okInput = () => {
+ $(DIALOG_SELECTOR)[0].close();
+
+ const result = {};
+ result.clusterName = this.selectedTestClusterName();
+ args.setValue(result);
+ };
+
+ this.cancelInput = () => {
+ $(DIALOG_SELECTOR)[0].close();
+ args.setValue();
+ };
+ }
+
+ /*
+ * Returns a constructor for the ViewModel.
+ */
+ return KubernetesHelperChooseClusterDialogModel;
+});
diff --git a/webui/src/js/viewModels/kubectl-page.js b/webui/src/js/viewModels/kubectl-page.js
index ab22da5a3..3cb2dd023 100644
--- a/webui/src/js/viewModels/kubectl-page.js
+++ b/webui/src/js/viewModels/kubectl-page.js
@@ -54,14 +54,6 @@ function(accUtils, ko, project, i18n, ArrayDataProvider, BufferingDataProvider,
headerText: this.labelMapper('vz-managed-cluster-kubecontext-heading'),
sortProperty: 'kubeContext'
},
- {
- 'className': 'wkt-table-delete-cell',
- // 'headerClassName': 'wkt-table-add-header',
- // 'headerTemplate': 'headerTemplate',
- 'template': 'actionTemplate',
- 'sortable': 'disable',
- width: viewHelper.TEXT_BUTTON_COLUMN_WIDTH
- },
{
'className': 'wkt-table-delete-cell',
'headerClassName': 'wkt-table-add-header',
@@ -256,13 +248,6 @@ function(accUtils, ko, project, i18n, ArrayDataProvider, BufferingDataProvider,
this.project.kubectl.vzManagedClusters.observable.splice(index, 1);
};
- this.verifyManagedClusterConnectivity = async (event, context) => {
- const index = context.item.index;
- const managedClusterData = this.project.kubectl.vzManagedClusters.observable()[index];
- await k8sHelper.startVerifyClusterConnectivity(managedClusterData.kubeConfig, managedClusterData.kubeContext);
- await k8sHelper.startVerifyClusterConnectivity(managedClusterData.kubeConfig, managedClusterData.kubeContext);
- };
-
this.createLink = function (url, label) {
return '' + label + '';
};
diff --git a/webui/src/js/viewModels/vz-application-design-view.js b/webui/src/js/viewModels/vz-application-design-view.js
index 7a003634a..5789bd1af 100644
--- a/webui/src/js/viewModels/vz-application-design-view.js
+++ b/webui/src/js/viewModels/vz-application-design-view.js
@@ -309,10 +309,20 @@ function (project, accUtils, utils, ko, i18n, BufferingDataProvider, ArrayDataPr
const kubectlExe = this.project.kubectl.executableFilePath.value;
const kubectlOptions = k8sHelper.getKubectlOptions();
+ const kubectlContext = this.project.kubectl.kubeConfigContextToUse.value;
+
+ let busyDialogMessage = i18n.t('flow-kubectl-use-context-in-progress');
+ dialogHelper.openBusyDialog(busyDialogMessage, 'bar', 0 / 2.0);
+ const useContextResult =
+ await window.api.ipc.invoke('kubectl-set-current-context', kubectlExe, kubectlContext, kubectlOptions);
+ if (!useContextResult.isSuccess) {
+ const errMessage = this.labelMapper('use-context-error-message', { error: useContextResult.reason });
+ await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
+ return Promise.resolve();
+ }
- const busyDialogMessage = this.labelMapper('get-deployments-in-progress');
- dialogHelper.openBusyDialog(busyDialogMessage, 'bar');
- dialogHelper.openBusyDialog(busyDialogMessage, 0);
+ busyDialogMessage = this.labelMapper('get-deployments-in-progress');
+ dialogHelper.openBusyDialog(busyDialogMessage, 'bar', 1 / 2.0);
const deploymentNamesResult =
await window.api.ipc.invoke('get-verrazzano-deployment-names-all-namespaces', kubectlExe, kubectlOptions);
dialogHelper.closeBusyDialog();
@@ -351,10 +361,21 @@ function (project, accUtils, utils, ko, i18n, BufferingDataProvider, ArrayDataPr
const kubectlExe = this.project.kubectl.executableFilePath.value;
const kubectlOptions = k8sHelper.getKubectlOptions();
+ const kubectlContext = this.project.kubectl.kubeConfigContextToUse.value;
+
+ let busyDialogMessage = i18n.t('flow-kubectl-use-context-in-progress');
+ dialogHelper.openBusyDialog(busyDialogMessage, 'bar', 0 / 2.0);
+ const useContextResult =
+ await window.api.ipc.invoke('kubectl-set-current-context', kubectlExe, kubectlContext, kubectlOptions);
+ if (!useContextResult.isSuccess) {
+ const errMessage = this.labelMapper('use-context-error-message', { error: useContextResult.reason });
+ await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
+ return Promise.resolve();
+ }
+
+ busyDialogMessage = this.labelMapper('get-clusters-in-progress');
+ dialogHelper.updateBusyDialog(busyDialogMessage, 1 / 2.0);
- const busyDialogMessage = this.labelMapper('get-clusters-in-progress');
- dialogHelper.openBusyDialog(busyDialogMessage, 'bar');
- dialogHelper.openBusyDialog(busyDialogMessage, 0);
const clusterNamesResult =
await window.api.ipc.invoke('get-verrazzano-cluster-names', kubectlExe, kubectlOptions);
dialogHelper.closeBusyDialog();
diff --git a/webui/src/js/viewModels/vz-application-status-choose-cluster-dialog.js b/webui/src/js/viewModels/vz-application-status-choose-cluster-dialog.js
new file mode 100644
index 000000000..5552ba4d2
--- /dev/null
+++ b/webui/src/js/viewModels/vz-application-status-choose-cluster-dialog.js
@@ -0,0 +1,52 @@
+/**
+ * @license
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ * Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
+ */
+'use strict';
+
+define(['accUtils', 'knockout', 'utils/i18n', 'utils/observable-properties', 'utils/validation-helper',
+ 'ojs/ojarraydataprovider', 'utils/wkt-logger', 'ojs/ojselectcombobox', 'ojs/ojinputtext', 'ojs/ojlabel',
+ 'ojs/ojbutton', 'ojs/ojdialog', 'ojs/ojformlayout', 'ojs/ojvalidationgroup'],
+function(accUtils, ko, i18n, props, validationHelper, ArrayDataProvider) {
+ function VerrazzanoApplicationStatusChooseClusterDialogModel(args) {
+ const DIALOG_SELECTOR = '#verrazzanoApplicationStatusChooseClusterDialog';
+
+ this.i18n = i18n;
+ this.targetClusterNames = args.targetClusters;
+ this.selectedTargetClusterName = ko.observable();
+ this.targetClusterNamesDP =
+ new ArrayDataProvider(this.targetClusterNames, { keyAttributes: 'name' });
+
+ this.connected = () => {
+ accUtils.announce('Choose Verrazzano application status choose cluster dialog loaded.', 'assertive');
+ // open the dialog after the current thread, which is loading this view model.
+ // using oj-dialog initial-visibility="show" causes vertical centering issues.
+ setTimeout(function() {
+ $(DIALOG_SELECTOR)[0].open();
+ }, 1);
+ };
+
+ this.labelMapper = (labelId) => {
+ return i18n.t(`vz-application-status-choose-cluster-${labelId}`);
+ };
+
+ this.okInput = () => {
+ $(DIALOG_SELECTOR)[0].close();
+
+ const result = {};
+ result.clusterName = this.selectedTargetClusterName();
+ args.setValue(result);
+ };
+
+ this.cancelInput = () => {
+ $(DIALOG_SELECTOR)[0].close();
+ args.setValue();
+ };
+ }
+
+ /*
+ * Returns a constructor for the ViewModel.
+ */
+ return VerrazzanoApplicationStatusChooseClusterDialogModel;
+});
diff --git a/webui/src/js/viewModels/vz-application-status-dialog.js b/webui/src/js/viewModels/vz-application-status-dialog.js
index 23b2bb965..162274b02 100644
--- a/webui/src/js/viewModels/vz-application-status-dialog.js
+++ b/webui/src/js/viewModels/vz-application-status-dialog.js
@@ -12,10 +12,12 @@ function(accUtils, ko, jsyaml, i18n, project, viewHelper) {
const DIALOG_SELECTOR = '#applicationStatusDialog';
this.project = project;
+ this.clusterName = args.clusterName;
this.domainStatus = args.domainStatus;
this.domainOverallStatus = args.domainOverallStatus;
- this.title = i18n.t('vz-application-status-title', { application: args.applicationName });
+ this.title = i18n.t('vz-application-status-title',
+ { clusterName: this.clusterName, application: args.applicationName });
this.dialogTitle = i18n.t('vz-application-status-domain-title', { domain: args.domainName });
this.domainMessage = this.domainStatus.message;
diff --git a/webui/src/js/viewModels/vz-install-design-view.js b/webui/src/js/viewModels/vz-install-design-view.js
index 46fc8f15b..907d090d2 100644
--- a/webui/src/js/viewModels/vz-install-design-view.js
+++ b/webui/src/js/viewModels/vz-install-design-view.js
@@ -20,7 +20,7 @@ function (project, accUtils, utils, ko, i18n, screenUtils, BufferingDataProvider
this.connected = () => {
accUtils.announce('Verrazzano Install Design View page loaded.', 'assertive');
- subscriptions.push(this.project.vzInstall.actualInstalledVersion.observable.subscribe(newTagValue => {
+ subscriptions.push(this.project.vzInstall.versionTag.observable.subscribe(newTagValue => {
this.computedArgoCDAvailabilityFromVersion(newTagValue);
}));
diff --git a/webui/src/js/views/choose-kubectl-context-dialog.html b/webui/src/js/views/choose-kubectl-context-dialog.html
index 9e6d7abad..7bd04d796 100644
--- a/webui/src/js/views/choose-kubectl-context-dialog.html
+++ b/webui/src/js/views/choose-kubectl-context-dialog.html
@@ -13,7 +13,7 @@