@rancher/shell 3.0.5-rc.8 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/base/_color.scss +4 -1
- package/assets/styles/global/_tooltip.scss +7 -4
- package/assets/styles/themes/_dark.scss +11 -0
- package/assets/styles/themes/_light.scss +13 -1
- package/assets/styles/themes/_modern.scss +22 -0
- package/assets/translations/en-us.yaml +147 -19
- package/assets/translations/zh-hans.yaml +0 -1
- package/chart/monitoring/grafana/index.vue +8 -2
- package/components/ActionMenuShell.vue +3 -1
- package/components/Cron/CronExpressionEditor.vue +299 -0
- package/components/Cron/CronExpressionEditorModal.vue +247 -0
- package/components/Cron/CronTooltip.vue +87 -0
- package/components/Cron/types.ts +13 -0
- package/components/ForceDirectedTreeChart/composable.ts +11 -0
- package/components/PodSecurityAdmission.vue +2 -0
- package/components/PromptModal.vue +1 -1
- package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +1 -0
- package/components/Resource/Detail/CopyToClipboard.vue +78 -0
- package/components/Resource/Detail/FetchLoader/__tests__/composables.test.ts +69 -0
- package/components/Resource/Detail/FetchLoader/composables.ts +27 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/Metadata/Annotations/index.vue +1 -1
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +13 -61
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +33 -6
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +24 -38
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +25 -5
- package/components/Resource/Detail/Metadata/KeyValue.vue +12 -23
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +144 -0
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -0
- package/components/Resource/Detail/Metadata/Labels/index.vue +1 -0
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +30 -32
- package/components/Resource/Detail/Metadata/__tests__/KeyValueRow.test.ts +108 -0
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +0 -3
- package/components/Resource/Detail/Metadata/__tests__/index.test.ts +12 -5
- package/components/Resource/Detail/Metadata/composables.ts +1 -4
- package/components/Resource/Detail/Metadata/index.vue +1 -0
- package/components/Resource/Detail/Preview/Content.vue +63 -0
- package/components/Resource/Detail/Preview/Preview.vue +128 -0
- package/components/Resource/Detail/Preview/__tests__/Content.spec.ts +71 -0
- package/components/Resource/Detail/Preview/__tests__/Preview.spec.ts +121 -0
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +141 -0
- package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +136 -0
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +245 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +226 -0
- package/components/Resource/Detail/SpacedRow.vue +1 -0
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +0 -5
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
- package/components/Resource/Detail/TitleBar/composables.ts +1 -3
- package/components/Resource/Detail/TitleBar/index.vue +2 -29
- package/components/Resource/Detail/ViewOptions/composable.ts +9 -0
- package/components/Resource/Detail/ViewOptions/index.vue +41 -0
- package/components/Resource/Detail/__tests__/CopyToClipboard.spec.ts +82 -0
- package/components/ResourceDetail/Masthead/legacy.vue +0 -19
- package/components/ResourceDetail/index.vue +1 -26
- package/components/ResourceTable.vue +24 -0
- package/components/SortableTable/index.vue +7 -1
- package/components/SortableTable/paging.js +3 -0
- package/components/Tabbed/Tab.vue +43 -1
- package/components/Tabbed/index.vue +3 -1
- package/components/__tests__/Cron/CronExpressionEditor.test.ts +151 -0
- package/components/__tests__/Cron/CronExpressionEditorModal.test.ts +81 -0
- package/components/auth/login/saml.vue +86 -0
- package/components/form/LabeledSelect.vue +8 -8
- package/components/form/ProjectMemberEditor.vue +2 -0
- package/components/form/ResourceTabs/composable.ts +54 -0
- package/components/form/ResourceTabs/index.vue +10 -7
- package/components/form/Select.vue +13 -10
- package/components/form/__tests__/LabeledSelect.test.ts +133 -0
- package/components/form/__tests__/Select.test.ts +134 -0
- package/components/nav/Header.vue +6 -5
- package/composables/useExtensionManager.ts +17 -0
- package/config/home-links.js +12 -0
- package/config/labels-annotations.js +0 -1
- package/config/page-actions.js +0 -1
- package/config/product/explorer.js +3 -1
- package/config/product/fleet.js +2 -7
- package/config/product/manager.js +0 -5
- package/config/query-params.js +1 -0
- package/config/router/navigation-guards/clusters.js +2 -1
- package/config/router/navigation-guards/products.js +1 -1
- package/config/store.js +2 -0
- package/core/extension-manager-impl.js +518 -0
- package/core/plugins.js +35 -468
- package/core/types.ts +8 -2
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +1 -0
- package/detail/catalog.cattle.io.app.vue +7 -4
- package/detail/fleet.cattle.io.bundle.vue +1 -5
- package/detail/fleet.cattle.io.cluster.vue +3 -2
- package/detail/fleet.cattle.io.gitrepo.vue +76 -49
- package/detail/fleet.cattle.io.helmop.vue +78 -49
- package/dialog/AddonConfigConfirmationDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +1 -1
- package/dialog/ImportDialog.vue +9 -2
- package/dialog/InstallExtensionDialog.vue +18 -10
- package/dialog/SloDialog.vue +1 -1
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -1
- package/edit/__tests__/resources.cattle.io.restore.test.ts +106 -0
- package/edit/auth/oidc.vue +106 -6
- package/edit/auth/saml.vue +5 -5
- package/edit/cloudcredential.vue +31 -17
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +10 -2
- package/edit/fleet.cattle.io.cluster.vue +19 -0
- package/edit/fleet.cattle.io.gitrepo.vue +23 -16
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +12 -11
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +11 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +14 -19
- package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -3
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -0
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +6 -0
- package/edit/resources.cattle.io.restore.vue +5 -8
- package/initialize/install-plugins.js +1 -3
- package/list/__tests__/workload.test.ts +1 -0
- package/list/workload.vue +8 -1
- package/machine-config/components/GCEImage.vue +6 -5
- package/machine-config/google.vue +11 -6
- package/mixins/__tests__/auth-config.test.ts +4 -6
- package/mixins/__tests__/chart.test.ts +139 -1
- package/mixins/auth-config.js +33 -10
- package/mixins/chart.js +58 -18
- package/models/__tests__/namespace.test.ts +69 -0
- package/models/apps.statefulset.js +8 -10
- package/models/chart.js +5 -1
- package/models/fleet-application.js +16 -46
- package/models/fleet.cattle.io.bundle.js +1 -38
- package/models/fleet.cattle.io.gitrepo.js +4 -0
- package/models/fleet.cattle.io.helmop.js +4 -0
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.project.js +12 -0
- package/models/namespace.js +30 -0
- package/models/workload.js +4 -1
- package/package.json +10 -10
- package/pages/auth/login.vue +8 -3
- package/pages/auth/logout.vue +6 -5
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +26 -11
- package/pages/c/_cluster/apps/charts/chart.vue +29 -20
- package/pages/c/_cluster/apps/charts/index.vue +1 -0
- package/pages/c/_cluster/apps/charts/install.vue +6 -5
- package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +102 -12
- package/pages/c/_cluster/explorer/tools/index.vue +145 -254
- package/pages/c/_cluster/manager/cloudCredential/index.vue +18 -1
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +12 -2
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
- package/pages/c/_cluster/uiplugins/__tests__/index.spec.ts +318 -0
- package/pages/c/_cluster/uiplugins/index.vue +221 -363
- package/pages/home.vue +1 -9
- package/plugins/axios.js +3 -2
- package/plugins/dashboard-store/resource-class.js +49 -0
- package/plugins/ember-cookie.js +7 -3
- package/plugins/steve/subscribe.js +4 -2
- package/public/index.html +2 -1
- package/rancher-components/Card/Card.vue +1 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Form/Radio/RadioButton.vue +1 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +1 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -11
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.test.ts +53 -0
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +65 -0
- package/rancher-components/Pill/RcCounterBadge/index.ts +1 -0
- package/rancher-components/Pill/RcCounterBadge/types.ts +7 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +1 -1
- package/rancher-components/Pill/RcStatusBadge/index.ts +1 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -3
- package/rancher-components/Pill/RcStatusIndicator/types.ts +1 -1
- package/rancher-components/Pill/RcTag/RcTag.test.ts +64 -0
- package/rancher-components/Pill/RcTag/RcTag.vue +94 -0
- package/rancher-components/Pill/RcTag/index.ts +1 -0
- package/rancher-components/Pill/RcTag/types.ts +9 -0
- package/rancher-components/Pill/types.ts +1 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +1 -0
- package/rancher-components/RcItemCard/RcItemCardAction.vue +12 -0
- package/scripts/test-plugins-build.sh +0 -1
- package/store/__tests__/catalog.test.ts +63 -0
- package/store/__tests__/cookies.test.ts +72 -0
- package/store/auth.js +33 -10
- package/store/catalog.js +2 -2
- package/store/cookies.ts +30 -0
- package/store/prefs.js +10 -5
- package/store/type-map.js +3 -15
- package/types/extension-manager.ts +26 -0
- package/types/shell/index.d.ts +123 -27
- package/utils/__tests__/product.test.ts +129 -0
- package/utils/__tests__/resource.test.ts +87 -0
- package/utils/alertmanagerconfig.js +2 -2
- package/utils/auth.js +4 -77
- package/utils/product.ts +39 -0
- package/utils/resource.ts +35 -0
- package/utils/select.js +0 -24
- package/utils/validators/formRules/__tests__/index.test.ts +3 -0
- package/utils/validators/formRules/index.ts +2 -1
- package/vue.config.js +1 -1
- package/components/Resource/Detail/Metadata/Rectangle.vue +0 -34
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +0 -24
- package/components/ResourceDetail/Masthead/__tests__/legacy.test.ts +0 -65
- package/utils/cookie-universal.js +0 -10
- /package/components/{ForceDirectedTreeChart.vue → ForceDirectedTreeChart/index.vue} +0 -0
|
@@ -78,6 +78,7 @@ export default {
|
|
|
78
78
|
<div class="row">
|
|
79
79
|
<Checkbox
|
|
80
80
|
:value="showCustomRegistryInput"
|
|
81
|
+
:mode="mode"
|
|
81
82
|
:label="t('cluster.privateRegistry.label')"
|
|
82
83
|
data-testid="registries-enable-checkbox"
|
|
83
84
|
@update:value="$emit('custom-registry-changed', $event)"
|
|
@@ -90,6 +91,7 @@ export default {
|
|
|
90
91
|
<div class="col span-6">
|
|
91
92
|
<LabeledInput
|
|
92
93
|
:value="registryHost"
|
|
94
|
+
:mode="mode"
|
|
93
95
|
label-key="catalog.chart.registry.custom.inputLabel"
|
|
94
96
|
placeholder-key="catalog.chart.registry.custom.placeholder"
|
|
95
97
|
:min-height="30"
|
|
@@ -102,6 +102,7 @@ export default {
|
|
|
102
102
|
<div class="mt-20">
|
|
103
103
|
<Checkbox
|
|
104
104
|
v-model:value="deleteEmptyDirData"
|
|
105
|
+
:mode="mode"
|
|
105
106
|
label-key="cluster.rke2.drain.deleteEmptyDir.label"
|
|
106
107
|
tooltip-key="cluster.rke2.drain.deleteEmptyDir.tooltip"
|
|
107
108
|
@update:value="update"
|
|
@@ -110,6 +111,7 @@ export default {
|
|
|
110
111
|
<div>
|
|
111
112
|
<Checkbox
|
|
112
113
|
v-model:value="force"
|
|
114
|
+
:mode="mode"
|
|
113
115
|
label="Delete standalone pods"
|
|
114
116
|
label-key="cluster.rke2.drain.force.label"
|
|
115
117
|
tooltip="Delete standalone pods which are not managed by a Workload controller (Deployment, Job, etc). Draining will fail if this is not set and there are standalone pods."
|
|
@@ -120,12 +122,14 @@ export default {
|
|
|
120
122
|
<div>
|
|
121
123
|
<Checkbox
|
|
122
124
|
v-model:value="customGracePeriod"
|
|
125
|
+
:mode="mode"
|
|
123
126
|
label-key="cluster.rke2.drain.gracePeriod.checkboxLabel"
|
|
124
127
|
@update:value="update"
|
|
125
128
|
/>
|
|
126
129
|
<UnitInput
|
|
127
130
|
v-if="customGracePeriod"
|
|
128
131
|
v-model:value="gracePeriod"
|
|
132
|
+
:mode="mode"
|
|
129
133
|
label-key="cluster.rke2.drain.gracePeriod.inputLabel"
|
|
130
134
|
:suffix="t('suffix.seconds', {count: timeout})"
|
|
131
135
|
class="mb-10"
|
|
@@ -135,12 +139,14 @@ export default {
|
|
|
135
139
|
<div>
|
|
136
140
|
<Checkbox
|
|
137
141
|
v-model:value="customTimeout"
|
|
142
|
+
:mode="mode"
|
|
138
143
|
label-key="cluster.rke2.drain.timeout.checkboxLabel"
|
|
139
144
|
@update:value="update"
|
|
140
145
|
/>
|
|
141
146
|
<UnitInput
|
|
142
147
|
v-if="customTimeout"
|
|
143
148
|
v-model:value="timeout"
|
|
149
|
+
:mode="mode"
|
|
144
150
|
label-key="cluster.rke2.drain.timeout.inputLabel"
|
|
145
151
|
:suffix="t('suffix.seconds', {count: timeout})"
|
|
146
152
|
class="drain-timeout"
|
|
@@ -159,19 +159,16 @@ export default {
|
|
|
159
159
|
if (neu === 'useDefault') {
|
|
160
160
|
delete this.value.spec.storageLocation;
|
|
161
161
|
delete this.value.spec.backupFilename;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this.s3 = this.value.spec.storageLocation
|
|
165
|
-
|
|
166
|
-
if (neu === 'useBackup') {
|
|
162
|
+
this.s3 = {};
|
|
163
|
+
} else if (neu === 'configureS3') {
|
|
164
|
+
this.s3 = this.value.spec.storageLocation?.s3 || {};
|
|
165
|
+
this.value.spec.storageLocation = { s3: this.s3 };
|
|
166
|
+
} else if (neu === 'useBackup') {
|
|
167
167
|
delete this.value.spec.storageLocation;
|
|
168
168
|
|
|
169
169
|
if (this.availableBackups.length === 1) {
|
|
170
170
|
this.updateTargetBackup(this.availableBackups[0]);
|
|
171
171
|
}
|
|
172
|
-
} else {
|
|
173
|
-
delete this.value.spec.backupFilename;
|
|
174
|
-
this.value.spec.storageLocation = { s3: this.s3 };
|
|
175
172
|
}
|
|
176
173
|
},
|
|
177
174
|
|
|
@@ -12,7 +12,6 @@ import i18n from '@shell/plugins/i18n';
|
|
|
12
12
|
import globalFormatters from '@shell/plugins/global-formatters';
|
|
13
13
|
|
|
14
14
|
import axios from '@shell/utils/axios';
|
|
15
|
-
import cookieUniversal from '@shell/utils/cookie-universal';
|
|
16
15
|
import config from '@shell/utils/config';
|
|
17
16
|
import axiosShell from '@shell/plugins/axios';
|
|
18
17
|
import codeMirror from '@shell/plugins/codemirror-loader';
|
|
@@ -47,7 +46,7 @@ export async function installPlugins(vueApp) {
|
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
export async function installInjectedPlugins(app, vueApp) {
|
|
50
|
-
const pluginDefinitions = [config,
|
|
49
|
+
const pluginDefinitions = [config, axios, plugins, pluginsLoader, axiosShell, intNumber, codeMirror, nuxtClientInit, replaceAll, plugin, steveCreateWorker, emberCookie, internalApiPlugin];
|
|
51
50
|
|
|
52
51
|
const installations = pluginDefinitions.map(async(pluginDefinition) => {
|
|
53
52
|
if (typeof pluginDefinition === 'function') {
|
|
@@ -64,7 +63,6 @@ export async function installInjectedPlugins(app, vueApp) {
|
|
|
64
63
|
// If there's any performance reasons this can be done concurrently with all of the installation promises above but I felt it was organizationally better to keep both i18n items together.
|
|
65
64
|
await app.store.dispatch('i18n/init');
|
|
66
65
|
|
|
67
|
-
// Order matters here. This is coming after the other plugins specifically so $cookies can be installed. i18n/init relies on prefs/get which relies on $cookies.
|
|
68
66
|
vueApp.use(i18n, { store: app.store });
|
|
69
67
|
}
|
|
70
68
|
|
package/list/workload.vue
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '@shell/config/types';
|
|
6
6
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
7
7
|
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
|
|
8
|
+
import { STEVE_CACHE } from '@shell/store/features';
|
|
8
9
|
|
|
9
10
|
const workloadSchema = {
|
|
10
11
|
id: 'workload',
|
|
@@ -84,11 +85,17 @@ export default {
|
|
|
84
85
|
},
|
|
85
86
|
|
|
86
87
|
data() {
|
|
88
|
+
const allTypes = this.$route.params.resource === workloadSchema.id;
|
|
89
|
+
|
|
90
|
+
if (allTypes && this.$store.getters['features/get'](STEVE_CACHE)) {
|
|
91
|
+
this.$store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceListNotFound', { resource: workloadSchema.id }, true)));
|
|
92
|
+
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
87
95
|
// Ensure these are set on load (to determine if the NS filter is required) rather than too late on `fetch`
|
|
88
96
|
const { loadResources, loadIndeterminate } = $loadingResources(this.$route, this.$store);
|
|
89
97
|
|
|
90
98
|
const { params:{ resource: type } } = this.$route;
|
|
91
|
-
const allTypes = this.$route.params.resource === workloadSchema.id;
|
|
92
99
|
const schema = type !== workloadSchema.id ? this.$store.getters['cluster/schemaFor'](type) : workloadSchema;
|
|
93
100
|
const paginationEnabled = !allTypes && this.$store.getters[`cluster/paginationEnabled`]?.({ id: type });
|
|
94
101
|
|
|
@@ -43,6 +43,10 @@ export default {
|
|
|
43
43
|
type: String,
|
|
44
44
|
default: _CREATE,
|
|
45
45
|
},
|
|
46
|
+
poolCreateMode: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: true
|
|
49
|
+
},
|
|
46
50
|
location: {
|
|
47
51
|
type: Object,
|
|
48
52
|
required: true
|
|
@@ -85,7 +89,7 @@ export default {
|
|
|
85
89
|
},
|
|
86
90
|
created() {
|
|
87
91
|
this.debouncedLoadFamilies = debounce(this.getFamilies, 500);
|
|
88
|
-
if (this.
|
|
92
|
+
if (!this.poolCreateMode) {
|
|
89
93
|
this.imageProjects = `${ this.getProjectFromImage() }`;
|
|
90
94
|
}
|
|
91
95
|
},
|
|
@@ -111,9 +115,6 @@ export default {
|
|
|
111
115
|
|
|
112
116
|
};
|
|
113
117
|
},
|
|
114
|
-
isCreate() {
|
|
115
|
-
return this.mode === _CREATE;
|
|
116
|
-
},
|
|
117
118
|
project() {
|
|
118
119
|
return this.value.project;
|
|
119
120
|
},
|
|
@@ -284,7 +285,7 @@ export default {
|
|
|
284
285
|
async getImages(val) {
|
|
285
286
|
this.loadingImages = true;
|
|
286
287
|
try {
|
|
287
|
-
const isOriginal = !this.
|
|
288
|
+
const isOriginal = !this.poolCreateMode && this.machineImage === this.getImageNameFromImage(this.originalMachineImage);
|
|
288
289
|
|
|
289
290
|
this.machineImages = await this.getImagesInProject(val, this.showDeprecated);
|
|
290
291
|
// If we had to reload list of images, we need to reset selected image if it is no longer in the list,
|
|
@@ -79,7 +79,11 @@ export default {
|
|
|
79
79
|
disabled: {
|
|
80
80
|
type: Boolean,
|
|
81
81
|
default: false
|
|
82
|
-
}
|
|
82
|
+
},
|
|
83
|
+
poolCreateMode: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: true
|
|
86
|
+
},
|
|
83
87
|
},
|
|
84
88
|
|
|
85
89
|
async fetch() {
|
|
@@ -123,7 +127,7 @@ export default {
|
|
|
123
127
|
};
|
|
124
128
|
},
|
|
125
129
|
created() {
|
|
126
|
-
if (this.
|
|
130
|
+
if (this.poolCreateMode) {
|
|
127
131
|
this.$emit('validationChanged', false);
|
|
128
132
|
this.value.project = this.projectId;
|
|
129
133
|
for (const key in this.defaultConfig) {
|
|
@@ -157,7 +161,7 @@ export default {
|
|
|
157
161
|
'value.setExternalFirewallRulePrefix'(neu) {
|
|
158
162
|
if (!neu) {
|
|
159
163
|
this.value.openPort = [];
|
|
160
|
-
} else if (this.
|
|
164
|
+
} else if (this.poolCreateMode) {
|
|
161
165
|
this.value.openPort.push('6443');
|
|
162
166
|
} else {
|
|
163
167
|
this.value.openPort = this.originalOpenPort.length > 0 ? this.originalOpenPort : ['6443'];
|
|
@@ -334,7 +338,7 @@ export default {
|
|
|
334
338
|
|
|
335
339
|
if (!cur ) {
|
|
336
340
|
// If default is not actually available, reset
|
|
337
|
-
if (this.
|
|
341
|
+
if (this.poolCreateMode) {
|
|
338
342
|
this.value.diskType = '';
|
|
339
343
|
}
|
|
340
344
|
} else {
|
|
@@ -446,6 +450,7 @@ export default {
|
|
|
446
450
|
:credentialId="credentialId"
|
|
447
451
|
:projectId="value.project"
|
|
448
452
|
:originalMachineImage="originalMachineImage"
|
|
453
|
+
:pool-create-mode="poolCreateMode"
|
|
449
454
|
:mode="mode"
|
|
450
455
|
:location="location"
|
|
451
456
|
:rules="{machineImage: fvGetAndReportPathRules('machineImage')}"
|
|
@@ -494,7 +499,7 @@ export default {
|
|
|
494
499
|
label-key="cluster.machineConfig.gce.network.label"
|
|
495
500
|
:mode="mode"
|
|
496
501
|
:options="networkOptions"
|
|
497
|
-
:disabled="!
|
|
502
|
+
:disabled="!poolCreateMode"
|
|
498
503
|
option-key="name"
|
|
499
504
|
option-label="label"
|
|
500
505
|
:loading="loadingNetworks"
|
|
@@ -508,7 +513,7 @@ export default {
|
|
|
508
513
|
label-key="cluster.machineConfig.gce.subnetwork.label"
|
|
509
514
|
:mode="mode"
|
|
510
515
|
:options="subnetworkOptions"
|
|
511
|
-
:disabled="!
|
|
516
|
+
:disabled="!poolCreateMode"
|
|
512
517
|
option-key="name"
|
|
513
518
|
option-label="name"
|
|
514
519
|
:loading="loadingNetworks"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils';
|
|
2
2
|
import authConfigMixin from '@shell/mixins/auth-config';
|
|
3
|
-
|
|
3
|
+
import childHook from '@shell/mixins/child-hook';
|
|
4
|
+
//
|
|
4
5
|
describe('mixin: authConfigMixin', () => {
|
|
5
6
|
describe('method: save', () => {
|
|
6
7
|
const componentMock = (model: any) => ({
|
|
@@ -11,10 +12,7 @@ describe('mixin: authConfigMixin', () => {
|
|
|
11
12
|
computed: { principal: () => ({ me: {} }) },
|
|
12
13
|
global: {
|
|
13
14
|
mocks: {
|
|
14
|
-
$store: {
|
|
15
|
-
dispatch: () => model,
|
|
16
|
-
commit: () => ({ 'auth/loggedInAs': jest.fn() }),
|
|
17
|
-
},
|
|
15
|
+
$store: { dispatch: () => model },
|
|
18
16
|
$route: {
|
|
19
17
|
params: { id: '123' },
|
|
20
18
|
query: { mode: 'edit' },
|
|
@@ -24,7 +22,7 @@ describe('mixin: authConfigMixin', () => {
|
|
|
24
22
|
});
|
|
25
23
|
const FakeComponent = {
|
|
26
24
|
render() {},
|
|
27
|
-
mixins: [authConfigMixin],
|
|
25
|
+
mixins: [authConfigMixin, childHook],
|
|
28
26
|
methods: { applyHooks: jest.fn() },
|
|
29
27
|
};
|
|
30
28
|
|
|
@@ -29,7 +29,10 @@ describe('chartMixin', () => {
|
|
|
29
29
|
return () => 'repo';
|
|
30
30
|
},
|
|
31
31
|
'catalog/chart': () => {
|
|
32
|
-
return {
|
|
32
|
+
return {
|
|
33
|
+
id: chartId,
|
|
34
|
+
matchingInstalledApps: []
|
|
35
|
+
};
|
|
33
36
|
},
|
|
34
37
|
'i18n/t': () => jest.fn()
|
|
35
38
|
}
|
|
@@ -101,4 +104,139 @@ describe('chartMixin', () => {
|
|
|
101
104
|
expect(warnings).toHaveLength(expected as number);
|
|
102
105
|
}
|
|
103
106
|
);
|
|
107
|
+
|
|
108
|
+
describe('fetchChart', () => {
|
|
109
|
+
it('should call catalog/version with showDeprecated', async() => {
|
|
110
|
+
const mockStore = {
|
|
111
|
+
dispatch: jest.fn(() => Promise.resolve()),
|
|
112
|
+
getters: {
|
|
113
|
+
currentCluster: () => {},
|
|
114
|
+
isRancher: () => true,
|
|
115
|
+
'catalog/repo': () => {
|
|
116
|
+
return () => 'repo';
|
|
117
|
+
},
|
|
118
|
+
'catalog/chart': () => {
|
|
119
|
+
return {
|
|
120
|
+
id: 'chart-id', versions: [{ version: '1.0.0' }], matchingInstalledApps: []
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
'catalog/version': jest.fn(),
|
|
124
|
+
'prefs/get': () => {},
|
|
125
|
+
'i18n/t': () => jest.fn()
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const DummyComponent = {
|
|
130
|
+
mixins: [ChartMixin],
|
|
131
|
+
template: '<div></div>',
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const wrapper = mount(
|
|
135
|
+
DummyComponent,
|
|
136
|
+
{
|
|
137
|
+
global: {
|
|
138
|
+
mocks: {
|
|
139
|
+
$store: mockStore,
|
|
140
|
+
$route: {
|
|
141
|
+
query: {
|
|
142
|
+
chart: 'chart_name',
|
|
143
|
+
deprecated: 'true'
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await wrapper.vm.fetchChart();
|
|
151
|
+
|
|
152
|
+
expect(mockStore.getters['catalog/version']).toHaveBeenCalledWith(expect.objectContaining({ showDeprecated: true }));
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('action', () => {
|
|
157
|
+
const DummyComponent = {
|
|
158
|
+
mixins: [ChartMixin],
|
|
159
|
+
template: '<div></div>',
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const mockStore = {
|
|
163
|
+
dispatch: jest.fn(() => Promise.resolve()),
|
|
164
|
+
getters: { 'i18n/t': (key: string) => key }
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
it('should return "install" action when not installed', () => {
|
|
168
|
+
const wrapper = mount(DummyComponent, {
|
|
169
|
+
data: () => ({ existing: null }),
|
|
170
|
+
global: { mocks: { $store: mockStore } }
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
expect(wrapper.vm.action).toStrictEqual({
|
|
174
|
+
name: 'install',
|
|
175
|
+
tKey: 'install',
|
|
176
|
+
icon: 'icon-plus',
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should return "editVersion" action when installed and on same version', () => {
|
|
181
|
+
const wrapper = mount(DummyComponent, {
|
|
182
|
+
data: () => ({
|
|
183
|
+
existing: { spec: { chart: { metadata: { version: '1.0.0' } } } },
|
|
184
|
+
version: { version: '1.0.0' }
|
|
185
|
+
}),
|
|
186
|
+
global: {
|
|
187
|
+
mocks: {
|
|
188
|
+
$store: mockStore,
|
|
189
|
+
$route: { query: {} }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(wrapper.vm.action).toStrictEqual({
|
|
195
|
+
name: 'editVersion',
|
|
196
|
+
tKey: 'edit',
|
|
197
|
+
icon: 'icon-edit',
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should return "upgrade" action when installed and on a newer version', () => {
|
|
202
|
+
const wrapper = mount(DummyComponent, {
|
|
203
|
+
data: () => ({
|
|
204
|
+
existing: { spec: { chart: { metadata: { version: '1.0.0' } } } },
|
|
205
|
+
version: { version: '1.0.1' }
|
|
206
|
+
}),
|
|
207
|
+
global: {
|
|
208
|
+
mocks: {
|
|
209
|
+
$store: mockStore,
|
|
210
|
+
$route: { query: {} }
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(wrapper.vm.action).toStrictEqual({
|
|
216
|
+
name: 'upgradeVersion',
|
|
217
|
+
tKey: 'upgrade',
|
|
218
|
+
icon: 'icon-upgrade-alt',
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
it('should return "downgrade" action when installed and on an older version', () => {
|
|
222
|
+
const wrapper = mount(DummyComponent, {
|
|
223
|
+
data: () => ({
|
|
224
|
+
existing: { spec: { chart: { metadata: { version: '1.0.1' } } } },
|
|
225
|
+
version: { version: '1.0.0' }
|
|
226
|
+
}),
|
|
227
|
+
global: {
|
|
228
|
+
mocks: {
|
|
229
|
+
$store: mockStore,
|
|
230
|
+
$route: { query: {} }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
expect(wrapper.vm.action).toStrictEqual({
|
|
236
|
+
name: 'downgrade',
|
|
237
|
+
tKey: 'downgrade',
|
|
238
|
+
icon: 'icon-downgrade-alt',
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|
|
104
242
|
});
|
package/mixins/auth-config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { _EDIT } from '@shell/config/query-params';
|
|
2
2
|
import { NORMAN, MANAGEMENT } from '@shell/config/types';
|
|
3
3
|
import { AFTER_SAVE_HOOKS, BEFORE_SAVE_HOOKS } from '@shell/mixins/child-hook';
|
|
4
|
-
import { BASE_SCOPES } from '@shell/store/auth';
|
|
4
|
+
import { BASE_SCOPES, SLO_AUTH_PROVIDERS } from '@shell/store/auth';
|
|
5
5
|
import { addObject, findBy } from '@shell/utils/array';
|
|
6
6
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
7
7
|
import difference from 'lodash/difference';
|
|
@@ -30,6 +30,10 @@ export default {
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
|
|
33
|
+
created() {
|
|
34
|
+
this.registerAfterHook(this.updateAuthProviders, 'force-update-auth-providers');
|
|
35
|
+
},
|
|
36
|
+
|
|
33
37
|
async fetch() {
|
|
34
38
|
await this.mixinFetch();
|
|
35
39
|
},
|
|
@@ -88,6 +92,23 @@ export default {
|
|
|
88
92
|
},
|
|
89
93
|
|
|
90
94
|
methods: {
|
|
95
|
+
updateAuthProviders() {
|
|
96
|
+
// we need to forcefully re-fetch the authProviders list so that we can update the logout method
|
|
97
|
+
// this is to satisfy the SLO usecase where after setting an auth provider the logout method
|
|
98
|
+
// wasn't being updated because the resource is not watchable
|
|
99
|
+
this.$store.dispatch('auth/getAuthProviders', { force: true });
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
setSloType(selectedModel) {
|
|
103
|
+
if (!selectedModel.logoutAllEnabled && !selectedModel.logoutAllForced) {
|
|
104
|
+
this.sloType = SLO_OPTION_VALUES.rancher;
|
|
105
|
+
} else if (selectedModel.logoutAllEnabled && selectedModel.logoutAllForced) {
|
|
106
|
+
this.sloType = SLO_OPTION_VALUES.all;
|
|
107
|
+
} else if (selectedModel.logoutAllEnabled && !selectedModel.logoutAllForced) {
|
|
108
|
+
this.sloType = SLO_OPTION_VALUES.both;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
91
112
|
async mixinFetch() {
|
|
92
113
|
this.authConfigName = this.$route.params.id;
|
|
93
114
|
|
|
@@ -115,20 +136,16 @@ export default {
|
|
|
115
136
|
if (this.model.openLdapConfig) {
|
|
116
137
|
this.showLdap = true;
|
|
117
138
|
}
|
|
118
|
-
|
|
139
|
+
|
|
140
|
+
// Logic for Single Logout/SLO for auth providers
|
|
141
|
+
if (this.value?.configType && SLO_AUTH_PROVIDERS.includes(this.value?.configType)) {
|
|
119
142
|
if (!this.model.rancherApiHost || !this.model.rancherApiHost.length) {
|
|
120
143
|
this.model['rancherApiHost'] = this.serverUrl;
|
|
121
144
|
}
|
|
122
145
|
|
|
123
146
|
// setting data for SLO
|
|
124
147
|
if (this.model && Object.keys(this.model).includes('logoutAllSupported')) {
|
|
125
|
-
|
|
126
|
-
this.sloType = SLO_OPTION_VALUES.rancher;
|
|
127
|
-
} else if (this.model.logoutAllEnabled && this.model.logoutAllForced) {
|
|
128
|
-
this.sloType = SLO_OPTION_VALUES.all;
|
|
129
|
-
} else if (this.model.logoutAllEnabled && !this.model.logoutAllForced) {
|
|
130
|
-
this.sloType = SLO_OPTION_VALUES.both;
|
|
131
|
-
}
|
|
148
|
+
this.setSloType(this.model);
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
|
|
@@ -220,7 +237,7 @@ export default {
|
|
|
220
237
|
addObject(this.model.allowedPrincipalIds, this.principal.id);
|
|
221
238
|
}
|
|
222
239
|
// Session has switched to new 'me', ensure we react
|
|
223
|
-
this.$store.
|
|
240
|
+
this.$store.dispatch('auth/loggedInAs', this.principal.id);
|
|
224
241
|
} else {
|
|
225
242
|
console.warn(`Unable to find principal marked as 'me'`); // eslint-disable-line no-console
|
|
226
243
|
}
|
|
@@ -292,6 +309,12 @@ export default {
|
|
|
292
309
|
// must be cancelling edit of an enabled config; reset any changes and return to add users/groups view for that config
|
|
293
310
|
this.$store.dispatch(`rancher/clone`, { resource: this.originalModel }).then((cloned) => {
|
|
294
311
|
this.model = cloned;
|
|
312
|
+
|
|
313
|
+
// reset SLO type (radio option)
|
|
314
|
+
if (cloned && Object.keys(cloned).includes('logoutAllSupported')) {
|
|
315
|
+
this.setSloType(cloned);
|
|
316
|
+
}
|
|
317
|
+
|
|
295
318
|
this.editConfig = false;
|
|
296
319
|
});
|
|
297
320
|
}
|
package/mixins/chart.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
import { mapGetters } from 'vuex';
|
|
3
|
-
|
|
4
3
|
import {
|
|
5
4
|
REPO_TYPE, REPO, CHART, VERSION, NAMESPACE, NAME, DESCRIPTION as DESCRIPTION_QUERY, DEPRECATED as DEPRECATED_QUERY, HIDDEN, _FLAGGED, _CREATE, _EDIT
|
|
6
5
|
} from '@shell/config/query-params';
|
|
@@ -9,10 +8,9 @@ import { SHOW_PRE_RELEASE, mapPref } from '@shell/store/prefs';
|
|
|
9
8
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
10
9
|
import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
11
10
|
import { OPA_GATE_KEEPER_ID } from '@shell/pages/c/_cluster/gatekeeper/index.vue';
|
|
12
|
-
|
|
13
11
|
import { formatSi, parseSi } from '@shell/utils/units';
|
|
14
12
|
import { CAPI, CATALOG } from '@shell/config/types';
|
|
15
|
-
import { isPrerelease } from '@shell/utils/version';
|
|
13
|
+
import { isPrerelease, compare } from '@shell/utils/version';
|
|
16
14
|
import difference from 'lodash/difference';
|
|
17
15
|
import { LINUX, APP_UPGRADE_STATUS } from '@shell/store/catalog';
|
|
18
16
|
import { clone } from '@shell/utils/object';
|
|
@@ -230,11 +228,27 @@ export default {
|
|
|
230
228
|
},
|
|
231
229
|
|
|
232
230
|
action() {
|
|
233
|
-
if (this.existing) {
|
|
234
|
-
return
|
|
231
|
+
if (!this.existing) {
|
|
232
|
+
return {
|
|
233
|
+
name: 'install', tKey: 'install', icon: 'icon-plus'
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (this.currentVersion === this.targetVersion) {
|
|
238
|
+
return {
|
|
239
|
+
name: 'editVersion', tKey: 'edit', icon: 'icon-edit'
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (compare(this.currentVersion, this.targetVersion) < 0) {
|
|
244
|
+
return {
|
|
245
|
+
name: 'upgradeVersion', tKey: 'upgrade', icon: 'icon-upgrade-alt'
|
|
246
|
+
};
|
|
235
247
|
}
|
|
236
248
|
|
|
237
|
-
return
|
|
249
|
+
return {
|
|
250
|
+
name: 'downgrade', tKey: 'downgrade', icon: 'icon-downgrade-alt'
|
|
251
|
+
};
|
|
238
252
|
},
|
|
239
253
|
|
|
240
254
|
isChartTargeted() {
|
|
@@ -276,7 +290,10 @@ export default {
|
|
|
276
290
|
async fetchChart() {
|
|
277
291
|
this.versionInfoError = null;
|
|
278
292
|
|
|
279
|
-
await
|
|
293
|
+
await Promise.all([
|
|
294
|
+
this.$store.dispatch('catalog/load'),
|
|
295
|
+
this.$store.dispatch('cluster/findAll', { type: CATALOG.APP })
|
|
296
|
+
]);
|
|
280
297
|
|
|
281
298
|
this.fetchStoreChart();
|
|
282
299
|
|
|
@@ -316,6 +333,15 @@ export default {
|
|
|
316
333
|
this.mode = _CREATE;
|
|
317
334
|
this.existing = null;
|
|
318
335
|
}
|
|
336
|
+
} else if (this.chart) {
|
|
337
|
+
const matching = this.chart.matchingInstalledApps;
|
|
338
|
+
|
|
339
|
+
if (matching.length === 1) {
|
|
340
|
+
this.existing = matching[0];
|
|
341
|
+
this.mode = _EDIT;
|
|
342
|
+
} else {
|
|
343
|
+
this.mode = _CREATE;
|
|
344
|
+
}
|
|
319
345
|
} else {
|
|
320
346
|
// Regular create
|
|
321
347
|
|
|
@@ -345,10 +371,11 @@ export default {
|
|
|
345
371
|
|
|
346
372
|
try {
|
|
347
373
|
this.version = this.$store.getters['catalog/version']({
|
|
348
|
-
repoType:
|
|
349
|
-
repoName:
|
|
350
|
-
chartName:
|
|
351
|
-
versionName:
|
|
374
|
+
repoType: this.query.repoType,
|
|
375
|
+
repoName: this.query.repoName,
|
|
376
|
+
chartName: this.query.chartName,
|
|
377
|
+
versionName: this.query.versionName,
|
|
378
|
+
showDeprecated: this.showDeprecated
|
|
352
379
|
});
|
|
353
380
|
} catch (e) {
|
|
354
381
|
console.error('Unable to fetch Version: ', e); // eslint-disable-line no-console
|
|
@@ -503,18 +530,24 @@ export default {
|
|
|
503
530
|
version: this.query.versionName,
|
|
504
531
|
};
|
|
505
532
|
|
|
533
|
+
const query = {
|
|
534
|
+
[REPO_TYPE]: provider.repoType,
|
|
535
|
+
[REPO]: provider.repoName,
|
|
536
|
+
[CHART]: provider.name,
|
|
537
|
+
[VERSION]: provider.version,
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
if (this.showDeprecated) {
|
|
541
|
+
query[DEPRECATED_QUERY] = this.query.deprecated;
|
|
542
|
+
}
|
|
543
|
+
|
|
506
544
|
return {
|
|
507
545
|
name: install ? 'c-cluster-apps-charts-install' : 'c-cluster-apps-charts-chart',
|
|
508
546
|
params: {
|
|
509
547
|
cluster: this.$route.params.cluster,
|
|
510
548
|
product: this.$store.getters['productId'],
|
|
511
549
|
},
|
|
512
|
-
query
|
|
513
|
-
[REPO_TYPE]: provider.repoType,
|
|
514
|
-
[REPO]: provider.repoName,
|
|
515
|
-
[CHART]: provider.name,
|
|
516
|
-
[VERSION]: provider.version,
|
|
517
|
-
}
|
|
550
|
+
query
|
|
518
551
|
};
|
|
519
552
|
},
|
|
520
553
|
|
|
@@ -530,13 +563,20 @@ export default {
|
|
|
530
563
|
},
|
|
531
564
|
|
|
532
565
|
clusterToolsLocation() {
|
|
566
|
+
const query = {};
|
|
567
|
+
|
|
568
|
+
if (this.showDeprecated) {
|
|
569
|
+
query[DEPRECATED_QUERY] = this.query.deprecated;
|
|
570
|
+
}
|
|
571
|
+
|
|
533
572
|
return {
|
|
534
573
|
name: `c-cluster-explorer-tools`,
|
|
535
574
|
params: {
|
|
536
575
|
product: EXPLORER,
|
|
537
576
|
cluster: this.$store.getters['clusterId'],
|
|
538
577
|
resource: CATALOG.APP,
|
|
539
|
-
}
|
|
578
|
+
},
|
|
579
|
+
query
|
|
540
580
|
};
|
|
541
581
|
},
|
|
542
582
|
|