@rancher/shell 3.0.2-rc.2 → 3.0.2-rc.4
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/_basic.scss +7 -8
- package/assets/styles/global/_button.scss +10 -0
- package/assets/styles/global/_form.scss +2 -1
- package/assets/styles/global/_tooltip.scss +2 -2
- package/assets/styles/themes/_dark.scss +15 -3
- package/assets/styles/themes/_light.scss +7 -2
- package/assets/styles/vendor/vue-select.scss +4 -0
- package/assets/translations/en-us.yaml +66 -9
- package/assets/translations/zh-hans.yaml +2 -3
- package/components/AppModal.vue +50 -0
- package/components/BannerGraphic.vue +0 -42
- package/components/ButtonMultiAction.vue +1 -1
- package/components/Carousel.vue +88 -74
- package/components/CommunityLinks.vue +6 -1
- package/components/CopyToClipboardText.vue +3 -0
- package/components/Dialog.vue +20 -1
- package/components/GrowlManager.vue +9 -2
- package/components/LocaleSelector.vue +8 -1
- package/components/PaginatedResourceTable.vue +4 -7
- package/components/ProgressBarMulti.vue +14 -0
- package/components/PromptChangePassword.vue +3 -0
- package/components/Questions/Reference.vue +57 -28
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/SelectIconGrid.vue +12 -1
- package/components/SideNav.vue +12 -38
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/index.vue +9 -1
- package/components/YamlEditor.vue +1 -0
- package/components/__tests__/Carousel.test.ts +56 -27
- package/components/auth/Principal.vue +5 -3
- package/components/fleet/FleetClusters.vue +82 -1
- package/components/fleet/FleetRepos.vue +13 -30
- package/components/fleet/ForceDirectedTreeChart/index.vue +2 -2
- package/components/form/ChangePassword.vue +2 -0
- package/components/form/ColorInput.vue +24 -1
- package/components/form/FileSelector.vue +2 -0
- package/components/form/KeyValue.vue +230 -160
- package/components/form/LabeledSelect.vue +2 -2
- package/components/form/PlusMinus.vue +14 -2
- package/components/form/ResourceLabeledSelect.vue +13 -53
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +79 -36
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +192 -0
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +104 -0
- package/components/form/SSHKnownHosts/index.vue +101 -0
- package/components/form/SecretSelector.vue +2 -2
- package/components/form/Select.vue +1 -1
- package/components/form/SelectOrCreateAuthSecret.vue +43 -11
- package/components/form/__tests__/KeyValue.test.ts +1 -1
- package/components/form/__tests__/SSHKnownHosts.test.ts +59 -0
- package/components/formatter/FleetClusterSummaryGraph.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +6 -7
- package/components/formatter/WorkloadHealthScale.vue +7 -0
- package/components/nav/Group.vue +30 -4
- package/components/nav/Header.vue +82 -114
- package/components/nav/HeaderPageActionMenu.vue +27 -131
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/Type.vue +15 -0
- package/composables/focusTrap.ts +68 -0
- package/config/home-links.js +21 -13
- package/config/labels-annotations.js +2 -0
- package/config/page-actions.js +1 -0
- package/config/pagination-table-headers.js +15 -1
- package/config/product/explorer.js +7 -17
- package/config/table-headers.js +6 -0
- package/config/version.js +5 -1
- package/core/plugin.ts +41 -1
- package/core/plugins.js +125 -72
- package/core/types-provisioning.ts +91 -2
- package/core/types.ts +55 -0
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +12 -3
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/fleet.cattle.io.cluster.vue +3 -3
- package/detail/namespace.vue +13 -19
- package/detail/networking.k8s.io.ingress.vue +13 -53
- package/detail/provisioning.cattle.io.cluster.vue +12 -1
- package/detail/secret.vue +25 -0
- package/detail/workload/index.vue +3 -3
- package/dialog/AddCustomBadgeDialog.vue +5 -1
- package/edit/auth/ldap/__tests__/config.test.ts +18 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/auth/saml.vue +8 -6
- package/edit/fleet.cattle.io.gitrepo.vue +34 -23
- package/edit/logging-flow/index.vue +4 -19
- package/edit/networking.k8s.io.ingress/index.vue +18 -65
- package/edit/networking.k8s.io.networkpolicy/index.vue +4 -5
- package/edit/provisioning.cattle.io.cluster/index.vue +27 -8
- package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -115
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue +14 -28
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +25 -12
- package/edit/secret/index.vue +1 -1
- package/edit/secret/ssh.vue +21 -3
- package/edit/service.vue +1 -2
- package/list/networking.k8s.io.ingress.vue +1 -1
- package/list/node.vue +15 -8
- package/list/persistentvolume.vue +12 -4
- package/list/provisioning.cattle.io.cluster.vue +1 -0
- package/list/service.vue +1 -1
- package/list/workload.vue +4 -0
- package/mixins/chart.js +4 -1
- package/models/catalog.cattle.io.app.js +3 -1
- package/models/catalog.cattle.io.clusterrepo.js +56 -7
- package/models/fleet.cattle.io.bundle.js +0 -11
- package/models/fleet.cattle.io.cluster.js +17 -1
- package/models/fleet.cattle.io.gitrepo.js +88 -52
- package/models/provisioning.cattle.io.cluster.js +36 -1
- package/models/secret.js +5 -0
- package/models/service.js +1 -0
- package/models/workload.js +19 -1
- package/package.json +5 -4
- package/pages/account/index.vue +4 -0
- package/pages/c/_cluster/apps/charts/index.vue +4 -0
- package/pages/c/_cluster/explorer/ConfigBadge.vue +4 -2
- package/pages/c/_cluster/explorer/index.vue +13 -6
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +3 -3
- package/pages/c/_cluster/fleet/index.vue +75 -89
- package/pages/c/_cluster/settings/links.vue +2 -2
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +3 -1
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +3 -0
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +7 -1
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +3 -1
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +10 -7
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +7 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +181 -106
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +2 -0
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +9 -1
- package/pages/c/_cluster/uiplugins/index.vue +50 -12
- package/pages/diagnostic.vue +17 -15
- package/pages/home.vue +32 -6
- package/plugins/clean-html.js +50 -0
- package/plugins/dashboard-store/resource-class.js +4 -0
- package/plugins/plugin.js +54 -49
- package/plugins/steve/mutations.js +1 -1
- package/plugins/steve/steve-class.js +8 -0
- package/plugins/steve/steve-pagination-utils.ts +3 -1
- package/rancher-components/Accordion/Accordion.vue +4 -4
- package/rancher-components/BadgeState/BadgeState.vue +7 -0
- package/rancher-components/Card/Card.vue +12 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +9 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +19 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +39 -2
- package/rancher-components/RcButton/RcButton.vue +90 -0
- package/rancher-components/RcButton/index.ts +2 -0
- package/rancher-components/RcButton/types.ts +17 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +122 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +127 -0
- package/rancher-components/RcDropdown/RcDropdownSeparator.vue +6 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +42 -0
- package/rancher-components/RcDropdown/index.ts +4 -0
- package/rancher-components/RcDropdown/types.ts +22 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +46 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +110 -0
- package/scripts/test-plugins-build.sh +2 -0
- package/scripts/typegen.sh +2 -0
- package/store/catalog.js +1 -1
- package/tsconfig.json +2 -1
- package/types/components/paginatedResourceTable.ts +25 -0
- package/types/components/resourceLabeledSelect.ts +48 -0
- package/types/resources/fleet.d.ts +17 -0
- package/types/shell/index.d.ts +61 -0
- package/utils/auth.js +5 -1
- package/utils/cluster.js +106 -0
- package/utils/fleet.ts +35 -3
- package/utils/ingress.ts +64 -0
- package/utils/uiplugins.ts +56 -44
- package/utils/validators/cron-schedule.js +7 -2
- package/utils/validators/formRules/__tests__/index.test.ts +53 -17
- package/utils/validators/formRules/index.ts +20 -5
- package/vue.config.js +1 -1
- package/components/RelatedWorkloadsTable.vue +0 -50
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { allHash } from '@shell/utils/promise';
|
|
3
|
-
import { SECRET, SERVICE } from '@shell/config/types';
|
|
4
3
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
5
4
|
import Rules from '@shell/edit/networking.k8s.io.ingress/Rules';
|
|
6
5
|
import ResourceTabs from '@shell/components/form/ResourceTabs';
|
|
7
6
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
8
|
-
import
|
|
9
|
-
import { FilterArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
7
|
+
import IngressDetailEditHelper from '@shell/utils/ingress';
|
|
10
8
|
|
|
11
9
|
export default {
|
|
12
10
|
name: 'CRUIngress',
|
|
@@ -18,76 +16,38 @@ export default {
|
|
|
18
16
|
},
|
|
19
17
|
mixins: [CreateEditView],
|
|
20
18
|
async fetch() {
|
|
19
|
+
this.ingressHelper = new IngressDetailEditHelper({
|
|
20
|
+
$store: this.$store,
|
|
21
|
+
namespace: this.value.metadata.namespace
|
|
22
|
+
});
|
|
21
23
|
const promises = {
|
|
22
|
-
services: this
|
|
24
|
+
services: this.ingressHelper.fetchServices(),
|
|
25
|
+
secrets: this.ingressHelper.fetchSecrets(),
|
|
23
26
|
resourceFields: this.schema.fetchResourceFields(),
|
|
24
27
|
};
|
|
25
28
|
|
|
26
|
-
if (this.$store.getters[`cluster/paginationEnabled`](SECRET)) {
|
|
27
|
-
const findPageArgs = { // Of type ActionFindPageArgs
|
|
28
|
-
namespaced: this.value.metadata.namespace,
|
|
29
|
-
pagination: new FilterArgs({
|
|
30
|
-
filters: PaginationParamFilter.createSingleField({
|
|
31
|
-
field: 'metadata.fields.1',
|
|
32
|
-
value: TYPES.TLS
|
|
33
|
-
})
|
|
34
|
-
}),
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
promises.filteredSecrets = this.$store.dispatch(`cluster/findPage`, { type: SECRET, opt: findPageArgs });
|
|
38
|
-
} else {
|
|
39
|
-
promises.secrets = this.$store.dispatch('cluster/findAll', { type: SECRET });
|
|
40
|
-
}
|
|
41
29
|
const hash = await allHash(promises);
|
|
42
30
|
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
this.filteredSecrets = hash.filteredSecrets;
|
|
31
|
+
this.services = hash.services;
|
|
32
|
+
this.secrets = hash.secrets;
|
|
46
33
|
},
|
|
47
34
|
data() {
|
|
48
35
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
allServices: [],
|
|
36
|
+
secrets: [],
|
|
37
|
+
services: [],
|
|
52
38
|
};
|
|
53
39
|
},
|
|
54
40
|
computed: {
|
|
55
41
|
serviceTargets() {
|
|
56
|
-
return this.
|
|
57
|
-
.map((service) => ({
|
|
58
|
-
label: service.metadata.name,
|
|
59
|
-
value: service.metadata.name,
|
|
60
|
-
ports: service.spec.ports?.map((p) => p.port)
|
|
61
|
-
}));
|
|
42
|
+
return this.ingressHelper.findAndMapServiceTargets(this.services);
|
|
62
43
|
},
|
|
63
44
|
firstTabLabel() {
|
|
64
45
|
return this.isView ? this.t('ingress.rulesAndCertificates.title') : this.t('ingress.rules.title');
|
|
65
46
|
},
|
|
66
47
|
certificates() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (this.filteredSecrets) {
|
|
70
|
-
filteredSecrets = this.filteredSecrets;
|
|
71
|
-
} else if (this.allSecrets ) {
|
|
72
|
-
filteredSecrets = this.filterByCurrentResourceNamespace(this.allSecrets.filter((secret) => secret._type === TYPES.TLS));
|
|
73
|
-
} else {
|
|
74
|
-
return [];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return filteredSecrets.map((secret) => {
|
|
78
|
-
const { id } = secret;
|
|
79
|
-
|
|
80
|
-
return id.slice(id.indexOf('/') + 1);
|
|
81
|
-
});
|
|
48
|
+
return this.ingressHelper.findAndMapCerts(this.secrets);
|
|
82
49
|
},
|
|
83
50
|
},
|
|
84
|
-
methods: {
|
|
85
|
-
filterByCurrentResourceNamespace(resources) {
|
|
86
|
-
return resources.filter((resource) => {
|
|
87
|
-
return resource.metadata.namespace === this.value.metadata.namespace;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
51
|
};
|
|
92
52
|
</script>
|
|
93
53
|
<template>
|
|
@@ -84,6 +84,7 @@ export default {
|
|
|
84
84
|
async fetch() {
|
|
85
85
|
await this.value.waitForProvisioner();
|
|
86
86
|
|
|
87
|
+
// Support for the 'provisioner' extension
|
|
87
88
|
const extClass = this.$plugin.getDynamic('provisioner', this.value.machineProvider);
|
|
88
89
|
|
|
89
90
|
if (extClass) {
|
|
@@ -94,6 +95,7 @@ export default {
|
|
|
94
95
|
$plugin: this.$store.app.$plugin,
|
|
95
96
|
$t: this.t
|
|
96
97
|
});
|
|
98
|
+
|
|
97
99
|
this.extDetailTabs = {
|
|
98
100
|
...this.extDetailTabs,
|
|
99
101
|
...this.extProvider.detailTabs
|
|
@@ -101,6 +103,15 @@ export default {
|
|
|
101
103
|
this.extCustomParams = { provider: this.value.machineProvider };
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
// Support for a model extension
|
|
107
|
+
if (this.value.customProvisionerHelper) {
|
|
108
|
+
this.extDetailTabs = {
|
|
109
|
+
...this.extDetailTabs,
|
|
110
|
+
...this.value.customProvisionerHelper.detailTabs
|
|
111
|
+
};
|
|
112
|
+
this.extCustomParams = { provider: this.value.machineProvider };
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
const schema = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);
|
|
105
116
|
const fetchOne = { schemaDefinitions: schema.fetchResourceFields() };
|
|
106
117
|
|
|
@@ -379,7 +390,7 @@ export default {
|
|
|
379
390
|
},
|
|
380
391
|
|
|
381
392
|
showNodes() {
|
|
382
|
-
return !this.showMachines && this.haveNodes && !!this.nodes.length;
|
|
393
|
+
return !this.showMachines && this.haveNodes && !!this.nodes.length && this.extDetailTabs.machines;
|
|
383
394
|
},
|
|
384
395
|
|
|
385
396
|
showSnapshots() {
|
package/detail/secret.vue
CHANGED
|
@@ -122,6 +122,10 @@ export default {
|
|
|
122
122
|
return this.value._type === TYPES.SSH;
|
|
123
123
|
},
|
|
124
124
|
|
|
125
|
+
showKnownHosts() {
|
|
126
|
+
return this.isSsh && this.value.supportsSshKnownHosts;
|
|
127
|
+
},
|
|
128
|
+
|
|
125
129
|
isBasicAuth() {
|
|
126
130
|
return this.value._type === TYPES.BASIC;
|
|
127
131
|
},
|
|
@@ -142,6 +146,12 @@ export default {
|
|
|
142
146
|
return rows;
|
|
143
147
|
},
|
|
144
148
|
|
|
149
|
+
knownHosts() {
|
|
150
|
+
const { data = {} } = this.value;
|
|
151
|
+
|
|
152
|
+
return data.known_hosts ? base64Decode(data.known_hosts) : '';
|
|
153
|
+
},
|
|
154
|
+
|
|
145
155
|
dataLabel() {
|
|
146
156
|
switch (this.value._type) {
|
|
147
157
|
case TYPES.TLS:
|
|
@@ -274,6 +284,21 @@ export default {
|
|
|
274
284
|
</div>
|
|
275
285
|
</div>
|
|
276
286
|
</Tab>
|
|
287
|
+
<Tab
|
|
288
|
+
v-if="showKnownHosts"
|
|
289
|
+
name="known_hosts"
|
|
290
|
+
label-key="secret.ssh.knownHosts"
|
|
291
|
+
>
|
|
292
|
+
<div class="row">
|
|
293
|
+
<div class="col span-12">
|
|
294
|
+
<DetailText
|
|
295
|
+
:value="knownHosts"
|
|
296
|
+
label-key="secret.ssh.knownHosts"
|
|
297
|
+
:conceal="false"
|
|
298
|
+
/>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</Tab>
|
|
277
302
|
</ResourceTabs>
|
|
278
303
|
</template>
|
|
279
304
|
|
|
@@ -47,8 +47,9 @@ export default {
|
|
|
47
47
|
} catch {}
|
|
48
48
|
|
|
49
49
|
const hash = {
|
|
50
|
-
//
|
|
50
|
+
// Used in conjunction with `matches/match/label selectors`. Requires https://github.com/rancher/dashboard/issues/10417 to fix
|
|
51
51
|
allPods: this.$store.dispatch('cluster/findAll', { type: POD }),
|
|
52
|
+
// Used in conjunction with `matches/match/label selectors`. Requires https://github.com/rancher/dashboard/issues/10417 to fix
|
|
52
53
|
allServices: this.$store.dispatch('cluster/findAll', { type: SERVICE }),
|
|
53
54
|
allIngresses: this.$store.dispatch('cluster/findAll', { type: INGRESS }),
|
|
54
55
|
// Nodes should be fetched because they may be referenced in the target
|
|
@@ -57,7 +58,7 @@ export default {
|
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
if (this.value.type === WORKLOAD_TYPES.CRON_JOB) {
|
|
60
|
-
hash.
|
|
61
|
+
hash.jobs = this.value.matchingJobs();
|
|
61
62
|
}
|
|
62
63
|
const res = await allHash(hash);
|
|
63
64
|
|
|
@@ -91,7 +92,6 @@ export default {
|
|
|
91
92
|
allIngresses: [],
|
|
92
93
|
matchingServices: [],
|
|
93
94
|
matchingIngresses: [],
|
|
94
|
-
allJobs: [],
|
|
95
95
|
allNodes: [],
|
|
96
96
|
WORKLOAD_METRICS_DETAIL_URL,
|
|
97
97
|
WORKLOAD_METRICS_SUMMARY_URL,
|
|
@@ -213,6 +213,7 @@ export default {
|
|
|
213
213
|
<Card
|
|
214
214
|
class="prompt-badge"
|
|
215
215
|
:show-highlight-border="false"
|
|
216
|
+
:trigger-focus-trap="true"
|
|
216
217
|
>
|
|
217
218
|
<template #title>
|
|
218
219
|
<h4 class="text-default-text">
|
|
@@ -258,7 +259,6 @@ export default {
|
|
|
258
259
|
<Checkbox
|
|
259
260
|
v-model:value="badgeAsIcon"
|
|
260
261
|
:label="t('clusterBadge.modal.badgeAsIcon')"
|
|
261
|
-
|
|
262
262
|
:tooltip="t('clusterBadge.modal.maxCharsTooltip')"
|
|
263
263
|
/>
|
|
264
264
|
|
|
@@ -312,7 +312,9 @@ export default {
|
|
|
312
312
|
/>
|
|
313
313
|
<div class="buttons">
|
|
314
314
|
<button
|
|
315
|
+
role="button"
|
|
315
316
|
class="btn role-secondary mr-10"
|
|
317
|
+
:aria-label="t('generic.cancel')"
|
|
316
318
|
@click="close"
|
|
317
319
|
>
|
|
318
320
|
{{ t('generic.cancel') }}
|
|
@@ -320,6 +322,8 @@ export default {
|
|
|
320
322
|
<AsyncButton
|
|
321
323
|
:action-label="t('clusterBadge.modal.buttonAction')"
|
|
322
324
|
:disabled="!canSubmit"
|
|
325
|
+
role="button"
|
|
326
|
+
:aria-label="t('generic.cancel')"
|
|
323
327
|
@click="apply"
|
|
324
328
|
/>
|
|
325
329
|
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import LDAPConfig from '@shell/edit/auth/ldap/config.vue';
|
|
3
|
+
|
|
4
|
+
describe('lDAP config', () => {
|
|
5
|
+
it.each([
|
|
6
|
+
'openldap', 'freeipa'
|
|
7
|
+
])('should display searchUsingServiceAccount checkbox if type %p', (type) => {
|
|
8
|
+
const wrapper = mount(LDAPConfig, {
|
|
9
|
+
propsData: {
|
|
10
|
+
value: {},
|
|
11
|
+
type,
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
const checkbox = wrapper.find('[data-testid="searchUsingServiceAccount"]');
|
|
15
|
+
|
|
16
|
+
expect(checkbox).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -11,6 +11,8 @@ const DEFAULT_TLS_PORT = 636;
|
|
|
11
11
|
|
|
12
12
|
export const SHIBBOLETH = 'shibboleth';
|
|
13
13
|
export const OKTA = 'okta';
|
|
14
|
+
export const OPEN_LDAP = 'openldap';
|
|
15
|
+
export const FREE_IPA = 'freeipa';
|
|
14
16
|
|
|
15
17
|
export default {
|
|
16
18
|
emits: ['update:value'],
|
|
@@ -64,6 +66,11 @@ export default {
|
|
|
64
66
|
// Does the auth provider support LDAP for search in addition to SAML?
|
|
65
67
|
isSamlProvider() {
|
|
66
68
|
return this.type === SHIBBOLETH || this.type === OKTA;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// Allow to enable user search just for these providers
|
|
72
|
+
isSearchAllowed() {
|
|
73
|
+
return this.type === OPEN_LDAP || this.type === FREE_IPA;
|
|
67
74
|
}
|
|
68
75
|
},
|
|
69
76
|
|
|
@@ -226,6 +233,23 @@ export default {
|
|
|
226
233
|
/>
|
|
227
234
|
</div>
|
|
228
235
|
</div>
|
|
236
|
+
|
|
237
|
+
<div
|
|
238
|
+
v-if="isSearchAllowed"
|
|
239
|
+
class="row mb-20"
|
|
240
|
+
>
|
|
241
|
+
<div class="col">
|
|
242
|
+
<Checkbox
|
|
243
|
+
v-model:value="model.searchUsingServiceAccount"
|
|
244
|
+
:mode="mode"
|
|
245
|
+
data-testid="searchUsingServiceAccount"
|
|
246
|
+
class="full-height"
|
|
247
|
+
:label="t('authConfig.ldap.searchUsingServiceAccount.label')"
|
|
248
|
+
:tooltip="t('authConfig.ldap.searchUsingServiceAccount.tip')"
|
|
249
|
+
/>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
229
253
|
<div class="row mb-20">
|
|
230
254
|
<div class="col span-6">
|
|
231
255
|
<LabeledInput
|
package/edit/auth/saml.vue
CHANGED
|
@@ -211,12 +211,14 @@ export default {
|
|
|
211
211
|
</Banner>
|
|
212
212
|
|
|
213
213
|
<table v-if="showLdapDetails && model.openLdapConfig">
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
<tbody>
|
|
215
|
+
<tr><td>{{ t('authConfig.ldap.hostname.label') }}:</td><td>{{ ldapHosts }}</td></tr>
|
|
216
|
+
<tr><td>{{ t('authConfig.ldap.port') }}:</td><td>{{ model.openLdapConfig.port }}</td></tr>
|
|
217
|
+
<tr><td>{{ t('authConfig.ldap.protocol') }}:</td><td>{{ ldapProtocol }}</td></tr>
|
|
218
|
+
<tr><td>{{ t('authConfig.ldap.serviceAccountDN') }}:</td><td>{{ model.openLdapConfig.serviceAccountDistinguishedName }}</td></tr>
|
|
219
|
+
<tr><td>{{ t('authConfig.ldap.userSearchBase.label') }}:</td><td>{{ model.openLdapConfig.userSearchBase }}</td></tr>
|
|
220
|
+
<tr><td>{{ t('authConfig.ldap.groupSearchBase.label') }}:</td><td>{{ model.openLdapConfig.groupSearchBase }}</td></tr>
|
|
221
|
+
</tbody>
|
|
220
222
|
</table>
|
|
221
223
|
</template>
|
|
222
224
|
</AuthBanner>
|
|
@@ -153,7 +153,13 @@ export default {
|
|
|
153
153
|
stepRepoInfo,
|
|
154
154
|
stepTargetInfo,
|
|
155
155
|
displayHelmRepoURLRegex: false,
|
|
156
|
-
fvFormRuleSets: [{
|
|
156
|
+
fvFormRuleSets: [{
|
|
157
|
+
path: 'spec.repo',
|
|
158
|
+
rules: [
|
|
159
|
+
'required',
|
|
160
|
+
'gitRepository'
|
|
161
|
+
],
|
|
162
|
+
}]
|
|
157
163
|
};
|
|
158
164
|
},
|
|
159
165
|
|
|
@@ -402,7 +408,12 @@ export default {
|
|
|
402
408
|
},
|
|
403
409
|
|
|
404
410
|
async doCreate(name, credentials) {
|
|
405
|
-
const {
|
|
411
|
+
const {
|
|
412
|
+
selected,
|
|
413
|
+
publicKey,
|
|
414
|
+
privateKey,
|
|
415
|
+
sshKnownHosts
|
|
416
|
+
} = credentials;
|
|
406
417
|
|
|
407
418
|
if ( ![AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3].includes(selected) ) {
|
|
408
419
|
return;
|
|
@@ -450,6 +461,11 @@ export default {
|
|
|
450
461
|
[publicField]: base64Encode(publicKey),
|
|
451
462
|
[privateField]: base64Encode(privateKey),
|
|
452
463
|
};
|
|
464
|
+
|
|
465
|
+
// Add ssh known hosts
|
|
466
|
+
if (selected === AUTH_TYPE._SSH && sshKnownHosts) {
|
|
467
|
+
secret.data.known_hosts = base64Encode(sshKnownHosts);
|
|
468
|
+
}
|
|
453
469
|
}
|
|
454
470
|
|
|
455
471
|
await secret.save();
|
|
@@ -540,17 +556,7 @@ export default {
|
|
|
540
556
|
@update:value="$emit('input', $event)"
|
|
541
557
|
/>
|
|
542
558
|
|
|
543
|
-
<
|
|
544
|
-
<div class="col span-6">
|
|
545
|
-
<Banner
|
|
546
|
-
color="info col span-6"
|
|
547
|
-
>
|
|
548
|
-
<div>
|
|
549
|
-
{{ t('fleet.gitRepo.repo.protocolBanner') }}
|
|
550
|
-
</div>
|
|
551
|
-
</Banner>
|
|
552
|
-
</div>
|
|
553
|
-
</div>
|
|
559
|
+
<h2 v-t="'fleet.gitRepo.repo.title'" />
|
|
554
560
|
<div
|
|
555
561
|
class="row"
|
|
556
562
|
:class="{'mt-20': isView}"
|
|
@@ -580,6 +586,10 @@ export default {
|
|
|
580
586
|
/>
|
|
581
587
|
</div>
|
|
582
588
|
</div>
|
|
589
|
+
|
|
590
|
+
<div class="spacer" />
|
|
591
|
+
<h2 v-t="'fleet.gitRepo.auth.title'" />
|
|
592
|
+
|
|
583
593
|
<SelectOrCreateAuthSecret
|
|
584
594
|
:value="value.spec.clientSecretName"
|
|
585
595
|
:register-before-hook="registerBeforeHook"
|
|
@@ -627,8 +637,7 @@ export default {
|
|
|
627
637
|
</div>
|
|
628
638
|
|
|
629
639
|
<template v-if="isTls">
|
|
630
|
-
<div class="
|
|
631
|
-
<div class="row">
|
|
640
|
+
<div class="row mt-20">
|
|
632
641
|
<div class="col span-6">
|
|
633
642
|
<LabeledSelect
|
|
634
643
|
:label="t('fleet.gitRepo.tls.label')"
|
|
@@ -657,7 +666,7 @@ export default {
|
|
|
657
666
|
<div class="resource-handling">
|
|
658
667
|
<Checkbox
|
|
659
668
|
v-model:value="correctDriftEnabled"
|
|
660
|
-
:tooltip="t('fleet.gitRepo.resources.
|
|
669
|
+
:tooltip="t('fleet.gitRepo.resources.correctDriftTooltip')"
|
|
661
670
|
data-testid="GitRepo-correctDrift-checkbox"
|
|
662
671
|
class="check"
|
|
663
672
|
type="checkbox"
|
|
@@ -666,7 +675,7 @@ export default {
|
|
|
666
675
|
/>
|
|
667
676
|
<Checkbox
|
|
668
677
|
v-model:value="value.spec.keepResources"
|
|
669
|
-
:tooltip="t('fleet.gitRepo.resources.
|
|
678
|
+
:tooltip="t('fleet.gitRepo.resources.keepResourcesTooltip')"
|
|
670
679
|
data-testid="GitRepo-keepResources-checkbox"
|
|
671
680
|
class="check"
|
|
672
681
|
type="checkbox"
|
|
@@ -675,19 +684,16 @@ export default {
|
|
|
675
684
|
/>
|
|
676
685
|
</div>
|
|
677
686
|
<div class="spacer" />
|
|
678
|
-
<h2 v-t="'fleet.gitRepo.paths.label'" />
|
|
679
687
|
<ArrayList
|
|
680
688
|
v-model:value="value.spec.paths"
|
|
681
689
|
data-testid="gitRepo-paths"
|
|
690
|
+
:title="t('fleet.gitRepo.paths.label')"
|
|
682
691
|
:mode="mode"
|
|
683
692
|
:initial-empty-row="false"
|
|
684
693
|
:value-placeholder="t('fleet.gitRepo.paths.placeholder')"
|
|
685
694
|
:add-label="t('fleet.gitRepo.paths.addLabel')"
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
<Banner label-key="fleet.gitRepo.paths.empty" />
|
|
689
|
-
</template>
|
|
690
|
-
</ArrayList>
|
|
695
|
+
:protip="t('fleet.gitRepo.paths.empty')"
|
|
696
|
+
/>
|
|
691
697
|
</template>
|
|
692
698
|
<template #stepTargetInfo>
|
|
693
699
|
<h2 v-t="isLocal ? 'fleet.gitRepo.target.labelLocal' : 'fleet.gitRepo.target.label'" />
|
|
@@ -765,6 +771,11 @@ export default {
|
|
|
765
771
|
</template>
|
|
766
772
|
|
|
767
773
|
<style lang="scss" scoped>
|
|
774
|
+
:deep() .select-or-create-auth-secret {
|
|
775
|
+
.row {
|
|
776
|
+
margin-top: 10px !important;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
768
779
|
.resource-handling {
|
|
769
780
|
display: flex;
|
|
770
781
|
flex-direction: column;
|
|
@@ -6,14 +6,12 @@ import Loading from '@shell/components/Loading';
|
|
|
6
6
|
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
|
7
7
|
import Tabbed from '@shell/components/Tabbed';
|
|
8
8
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
9
|
-
import {
|
|
10
|
-
LOGGING, NAMESPACE, NODE, POD, SCHEMA
|
|
11
|
-
} from '@shell/config/types';
|
|
9
|
+
import { LOGGING, NAMESPACE, NODE, SCHEMA } from '@shell/config/types';
|
|
12
10
|
import jsyaml from 'js-yaml';
|
|
13
11
|
import { createYaml } from '@shell/utils/create-yaml';
|
|
14
12
|
import YamlEditor, { EDITOR_MODES } from '@shell/components/YamlEditor';
|
|
15
13
|
import { allHash } from '@shell/utils/promise';
|
|
16
|
-
import { isArray
|
|
14
|
+
import { isArray } from '@shell/utils/array';
|
|
17
15
|
import { matchRuleIsPopulated } from '@shell/models/logging.banzaicloud.io.flow';
|
|
18
16
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
19
17
|
import { clone } from '@shell/utils/object';
|
|
@@ -67,7 +65,6 @@ export default {
|
|
|
67
65
|
const hasAccessToOutputs = this.$store.getters[`${ inStore }/schemaFor`](LOGGING.OUTPUT);
|
|
68
66
|
const hasAccessToNamespaces = this.$store.getters[`cluster/schemaFor`](NAMESPACE);
|
|
69
67
|
const hasAccessToNodes = this.$store.getters[`${ inStore }/schemaFor`](NODE);
|
|
70
|
-
const hasAccessToPods = this.$store.getters[`${ inStore }/schemaFor`](POD);
|
|
71
68
|
const isFlow = this.value.type === LOGGING.FLOW;
|
|
72
69
|
|
|
73
70
|
const getAllOrDefault = (type, hasAccess) => {
|
|
@@ -77,9 +74,10 @@ export default {
|
|
|
77
74
|
const hash = await allHash({
|
|
78
75
|
allOutputs: getAllOrDefault(LOGGING.OUTPUT, isFlow && hasAccessToOutputs),
|
|
79
76
|
allClusterOutputs: getAllOrDefault(LOGGING.CLUSTER_OUTPUT, hasAccessToClusterOutputs),
|
|
77
|
+
// Can't remove allNamespaces yet given https://github.com/harvester/harvester/issues/7342 and
|
|
78
|
+
// https://github.com/harvester/harvester-ui-extension/blob/main/pkg/harvester/edit/harvesterhci.io.logging.clusteroutput.vue
|
|
80
79
|
allNamespaces: getAllOrDefault(NAMESPACE, hasAccessToNamespaces),
|
|
81
80
|
allNodes: getAllOrDefault(NODE, hasAccessToNodes),
|
|
82
|
-
allPods: getAllOrDefault(POD, hasAccessToPods),
|
|
83
81
|
});
|
|
84
82
|
|
|
85
83
|
for ( const k of Object.keys(hash) ) {
|
|
@@ -134,7 +132,6 @@ export default {
|
|
|
134
132
|
allClusterOutputs: null,
|
|
135
133
|
allNamespaces: null,
|
|
136
134
|
allNodes: null,
|
|
137
|
-
allPods: null,
|
|
138
135
|
filtersYaml,
|
|
139
136
|
initialFiltersYaml: filtersYaml,
|
|
140
137
|
globalOutputRefs,
|
|
@@ -239,18 +236,6 @@ export default {
|
|
|
239
236
|
return out;
|
|
240
237
|
},
|
|
241
238
|
|
|
242
|
-
containerChoices() {
|
|
243
|
-
const out = [];
|
|
244
|
-
|
|
245
|
-
for ( const pod of this.allPods ) {
|
|
246
|
-
for ( const c of (pod.spec?.containers || []) ) {
|
|
247
|
-
out.push(c.name);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return uniq(out).sort();
|
|
252
|
-
},
|
|
253
|
-
|
|
254
239
|
isHarvester() {
|
|
255
240
|
return this.$store.getters['currentProduct'].inStore === VIRTUAL;
|
|
256
241
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { allHash } from '@shell/utils/promise';
|
|
3
|
-
import {
|
|
3
|
+
import { INGRESS_CLASS } from '@shell/config/types';
|
|
4
4
|
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
|
5
5
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
6
6
|
import FormValidation from '@shell/mixins/form-validation';
|
|
@@ -10,13 +10,12 @@ import Labels from '@shell/components/form/Labels';
|
|
|
10
10
|
import Error from '@shell/components/form/Error';
|
|
11
11
|
import Tabbed from '@shell/components/Tabbed';
|
|
12
12
|
import { get, set } from '@shell/utils/object';
|
|
13
|
-
import { SECRET_TYPES as TYPES } from '@shell/config/secret';
|
|
14
13
|
import DefaultBackend from './DefaultBackend';
|
|
15
14
|
import Certificates from './Certificates';
|
|
16
15
|
import Rules from './Rules';
|
|
17
16
|
import IngressClass from './IngressClass';
|
|
18
17
|
import Loading from '@shell/components/Loading';
|
|
19
|
-
import
|
|
18
|
+
import IngressDetailEditHelper from '@shell/utils/ingress';
|
|
20
19
|
|
|
21
20
|
export default {
|
|
22
21
|
name: 'CRUIngress',
|
|
@@ -50,36 +49,32 @@ export default {
|
|
|
50
49
|
},
|
|
51
50
|
|
|
52
51
|
async fetch() {
|
|
52
|
+
this.ingressHelper = new IngressDetailEditHelper({
|
|
53
|
+
$store: this.$store,
|
|
54
|
+
namespace: this.value.metadata.namespace
|
|
55
|
+
});
|
|
56
|
+
|
|
53
57
|
this.ingressClassSchema = this.$store.getters[`cluster/schemaFor`](INGRESS_CLASS);
|
|
54
58
|
|
|
55
59
|
const promises = {
|
|
56
|
-
|
|
60
|
+
secrets: this.ingressHelper.fetchSecrets(),
|
|
61
|
+
services: this.ingressHelper.fetchServices(),
|
|
57
62
|
ingressClasses: this.ingressClassSchema ? this.$store.dispatch('cluster/findAll', { type: INGRESS_CLASS }) : Promise.resolve([]),
|
|
58
63
|
ingressResourceFields: this.schema.fetchResourceFields(),
|
|
59
64
|
};
|
|
60
65
|
|
|
61
|
-
this.filterByApi = this.$store.getters[`cluster/paginationEnabled`](SECRET);
|
|
62
|
-
|
|
63
|
-
if (this.filterByApi) {
|
|
64
|
-
promises.filteredSecrets = this.filterSecretsByApi();
|
|
65
|
-
} else {
|
|
66
|
-
promises.secrets = this.$store.dispatch('cluster/findAll', { type: SECRET });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
66
|
const hash = await allHash(promises);
|
|
70
67
|
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.filteredSecrets = hash.filteredSecrets;
|
|
68
|
+
this.secrets = hash.secrets;
|
|
69
|
+
this.services = hash.services;
|
|
74
70
|
this.allIngressClasses = hash.ingressClasses;
|
|
75
71
|
},
|
|
76
72
|
data() {
|
|
77
73
|
return {
|
|
78
74
|
filterByApi: null,
|
|
79
75
|
ingressClassSchema: null,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
allServices: [],
|
|
76
|
+
secrets: [],
|
|
77
|
+
services: [],
|
|
83
78
|
allIngressClasses: [],
|
|
84
79
|
fvFormRuleSets: [
|
|
85
80
|
{
|
|
@@ -111,10 +106,9 @@ export default {
|
|
|
111
106
|
},
|
|
112
107
|
|
|
113
108
|
watch: {
|
|
114
|
-
async 'value.metadata.namespace'() {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
109
|
+
async 'value.metadata.namespace'(neu) {
|
|
110
|
+
this.services = await this.ingressHelper.fetchServices({ namespace: neu });
|
|
111
|
+
this.secrets = await this.ingressHelper.fetchSecrets({ namespace: neu });
|
|
118
112
|
}
|
|
119
113
|
},
|
|
120
114
|
|
|
@@ -162,32 +156,13 @@ export default {
|
|
|
162
156
|
return { name: [], port: [] };
|
|
163
157
|
},
|
|
164
158
|
serviceTargets() {
|
|
165
|
-
return this.
|
|
166
|
-
.map((service) => ({
|
|
167
|
-
label: service.metadata.name,
|
|
168
|
-
value: service.metadata.name,
|
|
169
|
-
ports: service.spec.ports?.map((p) => p.port)
|
|
170
|
-
}));
|
|
159
|
+
return this.ingressHelper.findAndMapServiceTargets(this.services);
|
|
171
160
|
},
|
|
172
161
|
firstTabLabel() {
|
|
173
162
|
return this.isView ? this.t('ingress.rulesAndCertificates.title') : this.t('ingress.rules.title');
|
|
174
163
|
},
|
|
175
164
|
certificates() {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (this.filteredSecrets) {
|
|
179
|
-
filteredSecrets = this.filteredSecrets;
|
|
180
|
-
} else if (this.allSecrets ) {
|
|
181
|
-
filteredSecrets = this.filterByCurrentResourceNamespace(this.allSecrets.filter((secret) => secret._type === TYPES.TLS));
|
|
182
|
-
} else {
|
|
183
|
-
return [];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return filteredSecrets.map((secret) => {
|
|
187
|
-
const { id } = secret;
|
|
188
|
-
|
|
189
|
-
return id.slice(id.indexOf('/') + 1);
|
|
190
|
-
});
|
|
165
|
+
return this.ingressHelper.findAndMapCerts(this.secrets);
|
|
191
166
|
},
|
|
192
167
|
ingressClasses() {
|
|
193
168
|
return this.allIngressClasses.map((ingressClass) => ({
|
|
@@ -210,28 +185,6 @@ export default {
|
|
|
210
185
|
},
|
|
211
186
|
|
|
212
187
|
methods: {
|
|
213
|
-
filterSecretsByApi() {
|
|
214
|
-
const findPageArgs = { // Of type ActionFindPageArgs
|
|
215
|
-
namespaced: this.value.metadata.namespace,
|
|
216
|
-
pagination: new FilterArgs({
|
|
217
|
-
filters: PaginationParamFilter.createSingleField({
|
|
218
|
-
field: 'metadata.fields.1',
|
|
219
|
-
value: TYPES.TLS
|
|
220
|
-
})
|
|
221
|
-
}),
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
return this.$store.dispatch(`cluster/findPage`, { type: SECRET, opt: findPageArgs });
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
filterByCurrentResourceNamespace(resources) {
|
|
228
|
-
// When configuring an Ingress, the options for Secrets and
|
|
229
|
-
// default backend Services are limited to the namespace of the Ingress.
|
|
230
|
-
return resources.filter((resource) => {
|
|
231
|
-
return resource.metadata.namespace === this.value.metadata.namespace;
|
|
232
|
-
});
|
|
233
|
-
},
|
|
234
|
-
|
|
235
188
|
willSave() {
|
|
236
189
|
const backend = get(this.value.spec, this.value.defaultBackendPath);
|
|
237
190
|
const serviceName = get(backend, this.value.serviceNamePath);
|