@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
package/edit/auth/oidc.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import Loading from '@shell/components/Loading';
|
|
3
3
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
4
|
-
import AuthConfig from '@shell/mixins/auth-config';
|
|
4
|
+
import AuthConfig, { SLO_OPTION_VALUES } from '@shell/mixins/auth-config';
|
|
5
5
|
import CruResource from '@shell/components/CruResource';
|
|
6
6
|
import AllowedPrincipals from '@shell/components/auth/AllowedPrincipals';
|
|
7
7
|
import FileSelector from '@shell/components/form/FileSelector';
|
|
@@ -15,6 +15,7 @@ import { RadioGroup } from '@components/Form/Radio';
|
|
|
15
15
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
16
16
|
import { BASE_SCOPES } from '@shell/store/auth';
|
|
17
17
|
import CopyToClipboardText from '@shell/components/CopyToClipboardText.vue';
|
|
18
|
+
import isUrl from 'is-url';
|
|
18
19
|
|
|
19
20
|
export default {
|
|
20
21
|
components: {
|
|
@@ -33,6 +34,8 @@ export default {
|
|
|
33
34
|
CopyToClipboardText,
|
|
34
35
|
},
|
|
35
36
|
|
|
37
|
+
emits: ['validationChanged'],
|
|
38
|
+
|
|
36
39
|
mixins: [CreateEditView, AuthConfig],
|
|
37
40
|
|
|
38
41
|
data() {
|
|
@@ -56,7 +59,8 @@ export default {
|
|
|
56
59
|
userInfoEndpoint: null,
|
|
57
60
|
},
|
|
58
61
|
// TODO #13457: this is duplicated due wrong format
|
|
59
|
-
oidcScope: []
|
|
62
|
+
oidcScope: [],
|
|
63
|
+
SLO_OPTION_VALUES
|
|
60
64
|
};
|
|
61
65
|
},
|
|
62
66
|
|
|
@@ -89,6 +93,11 @@ export default {
|
|
|
89
93
|
return false;
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
// make sure that if SLO options are enabled on radio group, field "endSessionEndpoint" is required
|
|
97
|
+
if (this.isLogoutAllSupported && this.sloEndSessionEndpointUiEnabled && (!this.model.endSessionEndpoint || !isUrl(this.model.endSessionEndpoint))) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
if (this.isAmazonCognito) {
|
|
93
102
|
const { issuer } = this.model;
|
|
94
103
|
|
|
@@ -129,10 +138,36 @@ export default {
|
|
|
129
138
|
|
|
130
139
|
isAmazonCognito() {
|
|
131
140
|
return this.model?.id === 'cognito';
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
isLogoutAllSupported() {
|
|
144
|
+
return this.model?.logoutAllSupported;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
sloOptions() {
|
|
148
|
+
return [
|
|
149
|
+
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.slo.sloOptions.onlyRancher', { name: this.model?.nameDisplay }) },
|
|
150
|
+
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.slo.sloOptions.logoutAll', { name: this.model?.nameDisplay }) },
|
|
151
|
+
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.slo.sloOptions.choose') },
|
|
152
|
+
];
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
sloTypeText() {
|
|
156
|
+
const sloOptionSelected = this.sloOptions.find((item) => item.value === this.sloType);
|
|
157
|
+
|
|
158
|
+
return sloOptionSelected?.label || '';
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
sloEndSessionEndpointUiEnabled() {
|
|
162
|
+
return this.sloType === SLO_OPTION_VALUES.all || this.sloType === SLO_OPTION_VALUES.both;
|
|
132
163
|
}
|
|
133
164
|
},
|
|
134
165
|
|
|
135
166
|
watch: {
|
|
167
|
+
fvFormIsValid(newValue) {
|
|
168
|
+
this.$emit('validationChanged', !!newValue);
|
|
169
|
+
},
|
|
170
|
+
|
|
136
171
|
'oidcUrls.url'() {
|
|
137
172
|
this.updateEndpoints();
|
|
138
173
|
},
|
|
@@ -166,6 +201,25 @@ export default {
|
|
|
166
201
|
if (!old && neu) {
|
|
167
202
|
this.customEndpoint.value = !this.oidcUrls.url && !!this.model.issuer;
|
|
168
203
|
}
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// sloType is defined on shell/mixins/auth-config.js
|
|
207
|
+
sloType(neu) {
|
|
208
|
+
switch (neu) {
|
|
209
|
+
case SLO_OPTION_VALUES.rancher:
|
|
210
|
+
this.model.logoutAllEnabled = false;
|
|
211
|
+
this.model.logoutAllForced = false;
|
|
212
|
+
this.model.endSessionEndpoint = '';
|
|
213
|
+
break;
|
|
214
|
+
case SLO_OPTION_VALUES.all:
|
|
215
|
+
this.model.logoutAllEnabled = true;
|
|
216
|
+
this.model.logoutAllForced = true;
|
|
217
|
+
break;
|
|
218
|
+
case SLO_OPTION_VALUES.both:
|
|
219
|
+
this.model.logoutAllEnabled = true;
|
|
220
|
+
this.model.logoutAllForced = false;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
169
223
|
}
|
|
170
224
|
},
|
|
171
225
|
|
|
@@ -224,11 +278,19 @@ export default {
|
|
|
224
278
|
:edit="goToEdit"
|
|
225
279
|
>
|
|
226
280
|
<template #rows>
|
|
227
|
-
<tr><td>{{ t(
|
|
228
|
-
<tr><td>{{ t(
|
|
229
|
-
<tr><td>{{ t(
|
|
281
|
+
<tr><td>{{ t('authConfig.oidc.rancherUrl') }}: </td><td>{{ model.rancherUrl }}</td></tr>
|
|
282
|
+
<tr><td>{{ t('authConfig.oidc.clientId') }}: </td><td>{{ model.clientId }}</td></tr>
|
|
283
|
+
<tr><td>{{ t('authConfig.oidc.issuer') }}: </td><td>{{ model.issuer }}</td></tr>
|
|
230
284
|
<tr v-if="model.authEndpoint">
|
|
231
|
-
<td>{{ t(
|
|
285
|
+
<td>{{ t('authConfig.oidc.authEndpoint') }}: </td><td>{{ model.authEndpoint }}</td>
|
|
286
|
+
</tr>
|
|
287
|
+
<tr v-if="isLogoutAllSupported">
|
|
288
|
+
<td>{{ t('authConfig.slo.sloTitle') }}: </td><td>{{ sloTypeText }}</td>
|
|
289
|
+
</tr>
|
|
290
|
+
<tr v-if="isLogoutAllSupported && sloEndSessionEndpointUiEnabled">
|
|
291
|
+
<td>
|
|
292
|
+
{{ t('authConfig.oidc.endSessionEndpoint.title') }}:
|
|
293
|
+
</td><td>{{ model.endSessionEndpoint }}</td>
|
|
232
294
|
</tr>
|
|
233
295
|
</template>
|
|
234
296
|
</AuthBanner>
|
|
@@ -494,6 +556,44 @@ export default {
|
|
|
494
556
|
</div>
|
|
495
557
|
</div>
|
|
496
558
|
</template>
|
|
559
|
+
|
|
560
|
+
<!-- SLO logout -->
|
|
561
|
+
<div
|
|
562
|
+
v-if="isLogoutAllSupported"
|
|
563
|
+
class="mt-40 mb-20"
|
|
564
|
+
>
|
|
565
|
+
<div class="row">
|
|
566
|
+
<div class="col span-12">
|
|
567
|
+
<h3>{{ t('authConfig.slo.sloTitle') }}</h3>
|
|
568
|
+
</div>
|
|
569
|
+
</div>
|
|
570
|
+
<div class="row">
|
|
571
|
+
<div class="col span-4">
|
|
572
|
+
<RadioGroup
|
|
573
|
+
v-model:value="sloType"
|
|
574
|
+
:mode="mode"
|
|
575
|
+
:options="sloOptions"
|
|
576
|
+
:disabled="!model.logoutAllSupported"
|
|
577
|
+
name="sloTypeRadio"
|
|
578
|
+
/>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
<div
|
|
582
|
+
v-if="sloEndSessionEndpointUiEnabled"
|
|
583
|
+
class="row mt-20"
|
|
584
|
+
>
|
|
585
|
+
<div class="col span-6">
|
|
586
|
+
<LabeledInput
|
|
587
|
+
v-model:value="model.endSessionEndpoint"
|
|
588
|
+
:tooltip="t('authConfig.oidc.endSessionEndpoint.tooltip')"
|
|
589
|
+
:label="t('authConfig.oidc.endSessionEndpoint.title')"
|
|
590
|
+
:mode="mode"
|
|
591
|
+
required
|
|
592
|
+
data-testid="oidc-endSessionEndpoint"
|
|
593
|
+
/>
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
497
597
|
</template>
|
|
498
598
|
</CruResource>
|
|
499
599
|
</div>
|
package/edit/auth/saml.vue
CHANGED
|
@@ -73,9 +73,9 @@ export default {
|
|
|
73
73
|
|
|
74
74
|
sloOptions() {
|
|
75
75
|
return [
|
|
76
|
-
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.
|
|
77
|
-
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.
|
|
78
|
-
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.
|
|
76
|
+
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.slo.sloOptions.onlyRancher', { name: this.model?.nameDisplay }) },
|
|
77
|
+
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.slo.sloOptions.logoutAll', { name: this.model?.nameDisplay }) },
|
|
78
|
+
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.slo.sloOptions.choose') },
|
|
79
79
|
];
|
|
80
80
|
},
|
|
81
81
|
|
|
@@ -175,7 +175,7 @@ export default {
|
|
|
175
175
|
<tr><td>{{ t(`authConfig.saml.api`) }}: </td><td>{{ model.rancherApiHost }}</td></tr>
|
|
176
176
|
<tr><td>{{ t(`authConfig.saml.groups`) }}: </td><td>{{ model.groupsField }}</td></tr>
|
|
177
177
|
<tr v-if="isLogoutAllSupported">
|
|
178
|
-
<td>{{ t(`authConfig.
|
|
178
|
+
<td>{{ t(`authConfig.slo.sloTitle`) }}: </td><td>{{ sloTypeText }}</td>
|
|
179
179
|
</tr>
|
|
180
180
|
</template>
|
|
181
181
|
|
|
@@ -357,7 +357,7 @@ export default {
|
|
|
357
357
|
>
|
|
358
358
|
<div class="row">
|
|
359
359
|
<div class="col span-12">
|
|
360
|
-
<h3>{{ t('authConfig.
|
|
360
|
+
<h3>{{ t('authConfig.slo.sloTitle') }}</h3>
|
|
361
361
|
</div>
|
|
362
362
|
</div>
|
|
363
363
|
<div class="row">
|
package/edit/cloudcredential.vue
CHANGED
|
@@ -14,8 +14,6 @@ import SelectIconGrid from '@shell/components/SelectIconGrid';
|
|
|
14
14
|
import { sortBy } from '@shell/utils/sort';
|
|
15
15
|
import { ucFirst } from '@shell/utils/string';
|
|
16
16
|
import { set } from '@shell/utils/object';
|
|
17
|
-
import { mapFeature, RKE2 as RKE2_FEATURE } from '@shell/store/features';
|
|
18
|
-
import { rke1Supports } from '@shell/store/plugins';
|
|
19
17
|
|
|
20
18
|
export default {
|
|
21
19
|
name: 'CruCloudCredential',
|
|
@@ -35,7 +33,7 @@ export default {
|
|
|
35
33
|
async fetch() {
|
|
36
34
|
this.nodeDrivers = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE_DRIVER });
|
|
37
35
|
this.kontainerDrivers = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.KONTAINER_DRIVER });
|
|
38
|
-
|
|
36
|
+
this.extensions = this.getExtensions();
|
|
39
37
|
// Force reload the cloud cred schema and any missing subtypes because there aren't change events sent when drivers come/go
|
|
40
38
|
try {
|
|
41
39
|
const schema = await this.$store.dispatch('rancher/find', {
|
|
@@ -87,7 +85,8 @@ export default {
|
|
|
87
85
|
credCustomComponentValidation: false,
|
|
88
86
|
nameRequiredValidation: false,
|
|
89
87
|
nodeDrivers: null,
|
|
90
|
-
kontainerDrivers: null
|
|
88
|
+
kontainerDrivers: null,
|
|
89
|
+
extensions: null
|
|
91
90
|
};
|
|
92
91
|
},
|
|
93
92
|
|
|
@@ -98,12 +97,9 @@ export default {
|
|
|
98
97
|
},
|
|
99
98
|
|
|
100
99
|
computed: {
|
|
101
|
-
rke2Enabled: mapFeature(RKE2_FEATURE),
|
|
102
100
|
|
|
103
101
|
hasCustomCloudCredentialComponent() {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return this.$store.getters['type-map/hasCustomCloudCredentialComponent'](driverName);
|
|
102
|
+
return this.getCustomCloudCredentialComponent(this.driverName);
|
|
107
103
|
},
|
|
108
104
|
|
|
109
105
|
cloudCredentialComponent() {
|
|
@@ -140,15 +136,14 @@ export default {
|
|
|
140
136
|
secretSubTypes() {
|
|
141
137
|
const out = [];
|
|
142
138
|
|
|
143
|
-
const
|
|
139
|
+
const fromDrivers = [...this.nodeDrivers, ...this.kontainerDrivers]
|
|
144
140
|
.filter((x) => x.spec.active && x.id !== 'rancherkubernetesengine')
|
|
145
141
|
.map((x) => x.spec.displayName || x.id);
|
|
146
142
|
|
|
147
|
-
|
|
143
|
+
const fromExtensions = this.extensions?.filter((x) => !!this.getCustomCloudCredentialComponent(x?.id)).map((x) => x?.id) || [];
|
|
144
|
+
const providers = [...fromDrivers, ...fromExtensions];
|
|
148
145
|
|
|
149
|
-
|
|
150
|
-
types = types.filter((x) => rke1Supports.includes(x));
|
|
151
|
-
}
|
|
146
|
+
let types = uniq(providers.map((x) => this.$store.getters['plugins/credentialDriverFor'](x)));
|
|
152
147
|
|
|
153
148
|
const schema = this.$store.getters['rancher/schemaFor'](NORMAN.CLOUD_CREDENTIAL);
|
|
154
149
|
|
|
@@ -178,7 +173,7 @@ export default {
|
|
|
178
173
|
for ( const id of types ) {
|
|
179
174
|
let bannerAbbrv;
|
|
180
175
|
|
|
181
|
-
let bannerImage = this.$store.app.$
|
|
176
|
+
let bannerImage = this.$store.app.$extension.getDynamic('image', `providers/${ id }.svg`);
|
|
182
177
|
|
|
183
178
|
if (!bannerImage) {
|
|
184
179
|
try {
|
|
@@ -191,7 +186,7 @@ export default {
|
|
|
191
186
|
|
|
192
187
|
out.push({
|
|
193
188
|
id,
|
|
194
|
-
label: this.typeDisplay(
|
|
189
|
+
label: this.typeDisplay(id),
|
|
195
190
|
bannerImage,
|
|
196
191
|
bannerAbbrv
|
|
197
192
|
});
|
|
@@ -214,6 +209,25 @@ export default {
|
|
|
214
209
|
this.credCustomComponentValidation = passed;
|
|
215
210
|
},
|
|
216
211
|
|
|
212
|
+
getExtensions() {
|
|
213
|
+
const context = {
|
|
214
|
+
dispatch: this.$store.dispatch,
|
|
215
|
+
getters: this.$store.getters,
|
|
216
|
+
axios: this.$store.$axios,
|
|
217
|
+
$extension: this.$store.app.$extension,
|
|
218
|
+
t: (...args) => this.t.apply(this, args),
|
|
219
|
+
isCreate: this.isCreate,
|
|
220
|
+
isEdit: this.isEdit,
|
|
221
|
+
isView: this.isView,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
return this.$extension.getProviders(context);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
getCustomCloudCredentialComponent(driverName) {
|
|
228
|
+
return this.$store.getters['type-map/hasCustomCloudCredentialComponent'](driverName);
|
|
229
|
+
},
|
|
230
|
+
|
|
217
231
|
async saveCredential(btnCb) {
|
|
218
232
|
if ( this.errors ) {
|
|
219
233
|
clear(this.errors);
|
|
@@ -266,10 +280,10 @@ export default {
|
|
|
266
280
|
}
|
|
267
281
|
|
|
268
282
|
this.value['_type'] = type;
|
|
269
|
-
this.$emit('set-subtype', this.typeDisplay(
|
|
283
|
+
this.$emit('set-subtype', this.typeDisplay(driver));
|
|
270
284
|
},
|
|
271
285
|
|
|
272
|
-
typeDisplay(
|
|
286
|
+
typeDisplay(driver) {
|
|
273
287
|
return this.$store.getters['i18n/withFallback'](`cluster.provider."${ driver }"`, null, driver);
|
|
274
288
|
},
|
|
275
289
|
|
|
@@ -17,6 +17,7 @@ import { saferDump } from '@shell/utils/create-yaml';
|
|
|
17
17
|
import NamespaceList, { NAMESPACE_FILTERS_HELPER } from './NamespaceList';
|
|
18
18
|
import MatchKinds from './MatchKinds';
|
|
19
19
|
import Scope, { SCOPE_OPTIONS } from './Scope';
|
|
20
|
+
import Banner from '@components/Banner/Banner';
|
|
20
21
|
|
|
21
22
|
function findConstraintTypes(schemas) {
|
|
22
23
|
return schemas
|
|
@@ -43,7 +44,8 @@ export default {
|
|
|
43
44
|
Scope,
|
|
44
45
|
Tab,
|
|
45
46
|
Tabbed,
|
|
46
|
-
YamlEditor
|
|
47
|
+
YamlEditor,
|
|
48
|
+
Banner
|
|
47
49
|
},
|
|
48
50
|
|
|
49
51
|
mixins: [CreateEditView],
|
|
@@ -230,11 +232,17 @@ export default {
|
|
|
230
232
|
};
|
|
231
233
|
</script>
|
|
232
234
|
<template>
|
|
235
|
+
<Banner
|
|
236
|
+
v-if="templateSubtypes.length === 0"
|
|
237
|
+
color="warning"
|
|
238
|
+
>
|
|
239
|
+
{{ t('gatekeeperConstraint.templateRequired') }}
|
|
240
|
+
</Banner>
|
|
233
241
|
<CruResource
|
|
242
|
+
v-else
|
|
234
243
|
:done-route="doneRoute"
|
|
235
244
|
:mode="mode"
|
|
236
245
|
:resource="value"
|
|
237
|
-
:selected-subtype="value.kind"
|
|
238
246
|
:subtypes="templateSubtypes"
|
|
239
247
|
:validation-passed="true"
|
|
240
248
|
:errors="errors"
|
|
@@ -56,10 +56,14 @@ export default {
|
|
|
56
56
|
async save(buttonDone) {
|
|
57
57
|
try {
|
|
58
58
|
this.errors = [];
|
|
59
|
+
|
|
59
60
|
await this.value.save();
|
|
60
61
|
|
|
61
62
|
await this.normanCluster.save();
|
|
62
63
|
|
|
64
|
+
// Changes (such as labels or annotations fields) to normanCluster are reflected in the fleet cluster via Rancher services, so wait for that to occur
|
|
65
|
+
await this.waitForFleetClusterLastRevision();
|
|
66
|
+
|
|
63
67
|
this.done();
|
|
64
68
|
buttonDone(true);
|
|
65
69
|
} catch (e) {
|
|
@@ -67,6 +71,21 @@ export default {
|
|
|
67
71
|
buttonDone(false);
|
|
68
72
|
}
|
|
69
73
|
},
|
|
74
|
+
|
|
75
|
+
async waitForFleetClusterLastRevision() {
|
|
76
|
+
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
77
|
+
|
|
78
|
+
const currRev = this.value?.metadata?.resourceVersion;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
return await this.value.waitForTestFn(() => {
|
|
82
|
+
const rev = this.$store.getters[`${ inStore }/byId`](this.value.type, this.value.id)?.metadata?.resourceVersion;
|
|
83
|
+
|
|
84
|
+
return currRev && currRev !== rev;
|
|
85
|
+
}, `${ this.value.id } - wait for resourceVersion to change`, 1000, 200);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
70
89
|
},
|
|
71
90
|
};
|
|
72
91
|
</script>
|
|
@@ -58,25 +58,26 @@ export default {
|
|
|
58
58
|
mixins: [CreateEditView, FormValidation],
|
|
59
59
|
|
|
60
60
|
async fetch() {
|
|
61
|
-
|
|
61
|
+
this.currentUser = await this.value.getCurrentUser();
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
data() {
|
|
65
|
+
let tlsMode = _VERIFY;
|
|
66
|
+
let caBundle = null;
|
|
62
67
|
|
|
63
68
|
if ( this.value.spec.insecureSkipTLSVerify ) {
|
|
64
|
-
|
|
69
|
+
tlsMode = _SKIP;
|
|
65
70
|
} else if ( this.value.spec.caBundle ) {
|
|
66
71
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
caBundle = base64Decode(this.value.spec.caBundle);
|
|
73
|
+
tlsMode = _SPECIFY;
|
|
69
74
|
} catch (e) {
|
|
70
75
|
// Hmm...
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
this.correctDriftEnabled = this.value.spec?.correctDrift?.enabled || false;
|
|
77
|
-
},
|
|
79
|
+
const correctDriftEnabled = this.value.spec?.correctDrift?.enabled || false;
|
|
78
80
|
|
|
79
|
-
data() {
|
|
80
81
|
let pollingInterval = toSeconds(this.value.spec.pollingInterval) || this.value.spec.pollingInterval;
|
|
81
82
|
|
|
82
83
|
if (!pollingInterval) {
|
|
@@ -92,14 +93,15 @@ export default {
|
|
|
92
93
|
const refValue = this.value.spec?.[ref] || '';
|
|
93
94
|
|
|
94
95
|
return {
|
|
96
|
+
currentUser: {},
|
|
95
97
|
tempCachedValues: {},
|
|
96
98
|
username: null,
|
|
97
99
|
password: null,
|
|
98
100
|
publicKey: null,
|
|
99
101
|
privateKey: null,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
correctDriftEnabled
|
|
102
|
+
caBundle,
|
|
103
|
+
tlsMode,
|
|
104
|
+
correctDriftEnabled,
|
|
103
105
|
pollingInterval,
|
|
104
106
|
ref,
|
|
105
107
|
refValue,
|
|
@@ -179,8 +181,14 @@ export default {
|
|
|
179
181
|
},
|
|
180
182
|
|
|
181
183
|
watch: {
|
|
182
|
-
tlsMode:
|
|
183
|
-
|
|
184
|
+
tlsMode: {
|
|
185
|
+
handler: 'updateTls',
|
|
186
|
+
immediate: true
|
|
187
|
+
},
|
|
188
|
+
caBundle: {
|
|
189
|
+
handler: 'updateTls',
|
|
190
|
+
immediate: true
|
|
191
|
+
},
|
|
184
192
|
|
|
185
193
|
workspace(neu) {
|
|
186
194
|
if ( this.isCreate ) {
|
|
@@ -406,8 +414,7 @@ export default {
|
|
|
406
414
|
this.value.spec['correctDrift'] = { enabled: this.correctDriftEnabled };
|
|
407
415
|
|
|
408
416
|
if (this.mode === _CREATE) {
|
|
409
|
-
this.value.metadata.labels[FLEET_LABELS.CREATED_BY_USER_ID] = this.
|
|
410
|
-
this.value.metadata.labels[FLEET_LABELS.CREATED_BY_USER_NAME] = this.value.currentUser.username;
|
|
417
|
+
this.value.metadata.labels[FLEET_LABELS.CREATED_BY_USER_ID] = this.currentUser.id;
|
|
411
418
|
}
|
|
412
419
|
},
|
|
413
420
|
|
|
@@ -34,23 +34,24 @@ export default {
|
|
|
34
34
|
|
|
35
35
|
async fetch() {
|
|
36
36
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const { receiverSchema, routeSchema } = await fetchAlertManagerConfigSpecs(this.$store);
|
|
37
|
+
const { receiverSchema } = await fetchAlertManagerConfigSpecs(this.$store);
|
|
40
38
|
|
|
41
39
|
this.receiverSchema = receiverSchema;
|
|
42
|
-
this.routeSchema = routeSchema;
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
// The edit page is (mis)used as the detail page. When it's in create world none of the below is valid (there's no existing resource)
|
|
42
|
+
if (!this.isCreate) {
|
|
43
|
+
const alertmanagerConfigResource = await this.$store.dispatch(`${ inStore }/find`, { type: MONITORING.ALERTMANAGERCONFIG, id: this.value.id });
|
|
44
|
+
|
|
45
|
+
this.alertmanagerConfigId = this.value.id;
|
|
46
|
+
this.alertmanagerConfigResource = alertmanagerConfigResource;
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
this.alertmanagerConfigResource = alertmanagerConfigResource;
|
|
48
|
-
this.alertmanagerConfigDetailRoute = alertmanagerConfigResource?._detailLocation;
|
|
48
|
+
this.alertmanagerConfigDetailRoute = alertmanagerConfigResource._detailLocation;
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
const alertmanagerConfigActions = alertmanagerConfigResource.availableActions;
|
|
51
|
+
const receiverActions = alertmanagerConfigResource.getReceiverActions(alertmanagerConfigActions);
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
this.receiverActions = receiverActions;
|
|
54
|
+
}
|
|
54
55
|
},
|
|
55
56
|
|
|
56
57
|
data() {
|
|
@@ -128,6 +128,16 @@ export default {
|
|
|
128
128
|
const expectedFields = Object.keys(receiverSchema.resourceFields);
|
|
129
129
|
const suffix = {};
|
|
130
130
|
|
|
131
|
+
// Values contains multiple receivers of two types
|
|
132
|
+
// 1. Known (expected, from schema) shown in their own tabs with explicity forms
|
|
133
|
+
// 2. unknown (not expected, missing in schema) shown as a yaml blob
|
|
134
|
+
|
|
135
|
+
// - expectedFields and suffixYaml are only used if the receiver is of type `custom`
|
|
136
|
+
// - expectedFields are the known types
|
|
137
|
+
// - suffixYaml are the unknown types
|
|
138
|
+
// - usages,
|
|
139
|
+
// - for custom, we need to know only the unknown / yaml blog. so suffixYaml is created by extracting all known (expectedFields) from value
|
|
140
|
+
// - on edit of custom we then combine the two again and save to value
|
|
131
141
|
Object.keys(this.value).forEach((key) => {
|
|
132
142
|
if (!expectedFields.includes(key)) {
|
|
133
143
|
suffix[key] = this.value[key];
|
|
@@ -195,7 +205,7 @@ export default {
|
|
|
195
205
|
return {
|
|
196
206
|
duplicateName: () => {
|
|
197
207
|
const receiversArray = this.alertmanagerConfigResource.spec.receivers;
|
|
198
|
-
const receiverNamesArray = receiversArray
|
|
208
|
+
const receiverNamesArray = receiversArray?.map((R) => R.name) || [];
|
|
199
209
|
const receiversSet = new Set(receiverNamesArray);
|
|
200
210
|
|
|
201
211
|
if (receiversArray.length !== receiversSet.size) {
|
|
@@ -149,25 +149,20 @@ export default {
|
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
// Custom Providers from extensions - initialize each with the store and the i18n service
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
isView: this.isView,
|
|
167
|
-
}));
|
|
168
|
-
} catch (e) {
|
|
169
|
-
console.error('Error loading provisioner(s) from extensions', e); // eslint-disable-line no-console
|
|
170
|
-
}
|
|
152
|
+
// We can't pass in this.$store as this leads to a circular-reference that causes Vue to freeze,
|
|
153
|
+
// so pass in specific services that the provisioner extension may need
|
|
154
|
+
const context = {
|
|
155
|
+
dispatch: this.$store.dispatch,
|
|
156
|
+
getters: this.$store.getters,
|
|
157
|
+
axios: this.$store.$axios,
|
|
158
|
+
$extension: this.$store.app.$extension,
|
|
159
|
+
t: (...args) => this.t.apply(this, args),
|
|
160
|
+
isCreate: this.isCreate,
|
|
161
|
+
isEdit: this.isEdit,
|
|
162
|
+
isView: this.isView,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
this.extensions = this.$extension.getProviders(context);
|
|
171
166
|
},
|
|
172
167
|
|
|
173
168
|
data() {
|
|
@@ -221,6 +221,8 @@ export default {
|
|
|
221
221
|
},
|
|
222
222
|
|
|
223
223
|
data() {
|
|
224
|
+
const isGoogle = this.provider === GOOGLE;
|
|
225
|
+
|
|
224
226
|
return {
|
|
225
227
|
loadedOnce: false,
|
|
226
228
|
lastIdx: 0,
|
|
@@ -270,7 +272,8 @@ export default {
|
|
|
270
272
|
clusterAgentDefaultPC: null,
|
|
271
273
|
clusterAgentDefaultPDB: null,
|
|
272
274
|
activeTab: null,
|
|
273
|
-
|
|
275
|
+
isGoogle,
|
|
276
|
+
isAuthenticated: !isGoogle || this.mode === _EDIT,
|
|
274
277
|
projectId: null,
|
|
275
278
|
REGISTRIES_TAB_NAME,
|
|
276
279
|
labelForAddon,
|
|
@@ -861,7 +864,7 @@ export default {
|
|
|
861
864
|
}
|
|
862
865
|
},
|
|
863
866
|
hideFooter() {
|
|
864
|
-
return this.needCredential && !this.
|
|
867
|
+
return this.needCredential && !this.credentialId;
|
|
865
868
|
},
|
|
866
869
|
|
|
867
870
|
overallFormValidationPassed() {
|
|
@@ -1029,6 +1032,9 @@ export default {
|
|
|
1029
1032
|
|
|
1030
1033
|
if (!this.machinePools) {
|
|
1031
1034
|
await this.initMachinePools(this.value.spec.rkeConfig.machinePools);
|
|
1035
|
+
if (this.isEdit && this.isGoogle && this.machinePools?.length > 0 && this.machinePools[0]?.config?.project) {
|
|
1036
|
+
this.projectId = this.machinePools[0]?.config?.project;
|
|
1037
|
+
}
|
|
1032
1038
|
if (this.mode === _CREATE && !this.machinePools.length) {
|
|
1033
1039
|
await this.addMachinePool();
|
|
1034
1040
|
}
|
|
@@ -1437,6 +1443,8 @@ export default {
|
|
|
1437
1443
|
entry.pool.machineConfigRef.name = neu.metadata.name;
|
|
1438
1444
|
entry.create = false;
|
|
1439
1445
|
entry.update = true;
|
|
1446
|
+
|
|
1447
|
+
this.initialMachinePoolsValues[entry.config.id] = clone(neu);
|
|
1440
1448
|
} else if (entry.update) {
|
|
1441
1449
|
entry.config = await entry.config.save();
|
|
1442
1450
|
}
|
|
@@ -2219,7 +2227,7 @@ export default {
|
|
|
2219
2227
|
</div>
|
|
2220
2228
|
<AccountAccess
|
|
2221
2229
|
v-if="!isAuthenticated"
|
|
2222
|
-
v-model:credential="
|
|
2230
|
+
v-model:credential="credentialId"
|
|
2223
2231
|
v-model:project="projectId"
|
|
2224
2232
|
v-model:is-authenticated="isAuthenticated"
|
|
2225
2233
|
:mode="mode"
|