@rancher/shell 0.3.4 → 0.3.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/app.scss +1 -1
- package/assets/styles/fonts/_fontstack.scss +11 -11
- package/assets/styles/vendor/vue-js-modal.scss +3 -3
- package/assets/translations/en-us.yaml +92 -22
- package/assets/translations/zh-hans.yaml +84 -15
- package/babel.config.js +13 -0
- package/chart/gatekeeper.vue +77 -0
- package/chart/istio.vue +108 -111
- package/chart/logging/index.vue +13 -4
- package/chart/monitoring/index.vue +15 -5
- package/chart/monitoring/steps/uninstall-v1.vue +2 -2
- package/chart/rancher-backup/index.vue +10 -3
- package/cloud-credential/aws.vue +1 -1
- package/cloud-credential/digitalocean.vue +1 -1
- package/cloud-credential/gcp.vue +1 -1
- package/cloud-credential/generic.vue +2 -2
- package/cloud-credential/linode.vue +1 -1
- package/cloud-credential/pnap.vue +1 -1
- package/components/ActionMenu.vue +3 -4
- package/components/AssignTo.vue +1 -1
- package/components/AsyncButton.vue +1 -1
- package/components/BannerGraphic.vue +1 -1
- package/components/ButtonDropdown.vue +2 -3
- package/components/ChartPsp.vue +76 -0
- package/components/CruResource.vue +6 -2
- package/components/DashboardMetrics.vue +12 -10
- package/components/DetailText.vue +1 -1
- package/components/DisableAuthProviderModal.vue +1 -1
- package/components/EmberPage.vue +1 -1
- package/components/EtcdInfoBanner.vue +5 -4
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +14 -1
- package/components/FileDiff.vue +6 -7
- package/components/GrafanaDashboard.vue +18 -21
- package/components/LazyImage.vue +10 -12
- package/components/LogItem.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/PromptRemove.vue +2 -2
- package/components/PromptRestore.vue +1 -1
- package/components/ResourceDetail/Masthead.vue +16 -0
- package/components/ResourceDetail/index.vue +21 -4
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +4 -1
- package/components/SingleClusterInfo.vue +2 -2
- package/components/SortableTable/THead.vue +1 -1
- package/components/SortableTable/index.vue +5 -2
- package/components/__tests__/AsyncButton.test.ts +3 -1
- package/components/__tests__/ChartPsp.test.ts +75 -0
- package/components/__tests__/CruResource.test.ts +3 -1
- package/components/auth/Principal.vue +1 -1
- package/components/fleet/FleetBundles.vue +3 -1
- package/components/fleet/FleetClusters.vue +1 -2
- package/components/fleet/FleetIntro.vue +9 -1
- package/components/fleet/FleetNoWorkspaces.vue +62 -0
- package/components/fleet/FleetSummary.vue +7 -1
- package/components/form/LabeledSelect.vue +14 -11
- package/components/form/MatchExpressions.vue +17 -2
- package/components/form/NameNsDescription.vue +31 -45
- package/components/form/ResourceSelector.vue +1 -1
- package/components/form/SecretSelector.vue +5 -1
- package/components/form/ServiceNameSelect.vue +1 -1
- package/components/form/SimpleSecretSelector.vue +9 -9
- package/components/form/__tests__/LabeledSelect.test.ts +138 -0
- package/components/form/__tests__/NameNsDescription.ts +32 -0
- package/components/formatter/InternalExternalIP.vue +6 -0
- package/components/formatter/InvolvedObjectLink.vue +54 -0
- package/components/formatter/Link.vue +20 -4
- package/components/formatter/LinkName.vue +6 -1
- package/components/formatter/ServiceTargets.vue +1 -1
- package/components/nav/Group.vue +2 -2
- package/components/nav/NamespaceFilter.vue +15 -11
- package/components/nav/TopLevelMenu.vue +2 -4
- package/components/nav/Type.vue +1 -1
- package/components/nav/WorkspaceSwitcher.vue +46 -5
- package/config/labels-annotations.js +17 -0
- package/config/product/auth.js +3 -2
- package/config/product/explorer.js +11 -4
- package/config/product/fleet.js +2 -0
- package/config/router.js +414 -0
- package/config/table-headers.js +10 -2
- package/config/types.js +11 -8
- package/config/uiplugins.js +30 -0
- package/content/docs/en-us/whats-new.md +10 -0
- package/content/docs/zh-hans/whats-new.md +11 -1
- package/core/plugin-routes.ts +23 -0
- package/creators/app/app.package.json +2 -1
- package/creators/app/files/.eslintrc.js +1 -1
- package/creators/app/files/babel.config.js +1 -18
- package/creators/app/files/vue.config.js +7 -0
- package/creators/app/init +5 -5
- package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
- package/creators/pkg/init +35 -4
- package/creators/update/init +1 -1
- package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
- package/detail/fleet.cattle.io.gitrepo.vue +19 -11
- package/detail/harvesterhci.io.management.cluster.vue +3 -3
- package/detail/provisioning.cattle.io.cluster.vue +54 -12
- package/detail/workload/index.vue +3 -3
- package/dialog/AddClusterMemberDialog.vue +1 -1
- package/dialog/AddProjectMemberDialog.vue +2 -2
- package/dialog/AddonConfigConfirmationDialog.vue +27 -15
- package/dialog/DiagnosticTimingsDialog.vue +1 -1
- package/dialog/ForceMachineRemoveDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +18 -6
- package/dialog/RotateEncryptionKeyDialog.vue +1 -1
- package/dialog/SaveAsRKETemplateDialog.vue +1 -1
- package/dialog/ScaleMachineDownDialog.vue +1 -1
- package/edit/auth/github.vue +8 -8
- package/edit/auth/googleoauth.vue +5 -5
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +1 -1
- package/edit/auth/saml.vue +1 -1
- package/edit/cis.cattle.io.clusterscan.vue +1 -1
- package/edit/fleet.cattle.io.clustergroup.vue +6 -4
- package/edit/fleet.cattle.io.gitrepo.vue +16 -3
- package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
- package/edit/management.cattle.io.fleetworkspace.vue +141 -6
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
- package/edit/management.cattle.io.setting.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
- package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
- package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
- package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
- package/edit/namespace.vue +2 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
- package/edit/resources.cattle.io.backup.vue +1 -1
- package/edit/service.vue +1 -1
- package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
- package/edit/workload/__tests__/Job.test.ts +3 -1
- package/edit/workload/index.vue +8 -3
- package/edit/workload/mixins/workload.js +16 -0
- package/layouts/default.vue +7 -3
- package/list/fleet.cattle.io.bundle.vue +6 -3
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
- package/list/fleet.cattle.io.gitrepo.vue +44 -5
- package/list/management.cattle.io.fleetworkspace.vue +45 -0
- package/list/node.vue +69 -16
- package/list/provisioning.cattle.io.cluster.vue +30 -1
- package/machine-config/azure.vue +97 -38
- package/middleware/authenticated.js +34 -0
- package/mixins/chart.js +73 -2
- package/mixins/resource-fetch.js +2 -2
- package/models/apps.statefulset.js +28 -0
- package/models/cluster/node.js +23 -2
- package/models/cluster.x-k8s.io.machine.js +4 -2
- package/models/clusterroletemplatebinding.js +7 -0
- package/models/constraints.gatekeeper.sh.constraint.js +9 -0
- package/models/fleet.cattle.io.cluster.js +19 -10
- package/models/fleet.cattle.io.gitrepo.js +7 -2
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.fleetworkspace.js +12 -0
- package/models/management.cattle.io.gitreporestriction.js +5 -0
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
- package/models/provisioning.cattle.io.cluster.js +7 -5
- package/nuxt/App.js +210 -0
- package/nuxt/axios.js +186 -0
- package/nuxt/client.js +817 -0
- package/nuxt/components/nuxt-build-indicator.vue +143 -0
- package/nuxt/components/nuxt-child.js +122 -0
- package/nuxt/components/nuxt-error.vue +98 -0
- package/nuxt/components/nuxt-link.client.js +98 -0
- package/nuxt/components/nuxt-link.server.js +16 -0
- package/nuxt/components/nuxt-loading.vue +154 -0
- package/nuxt/components/nuxt.js +101 -0
- package/nuxt/cookie-universal-nuxt.js +9 -0
- package/nuxt/empty.js +1 -0
- package/nuxt/index.js +365 -0
- package/nuxt/jsonp.js +82 -0
- package/nuxt/loading.html +39 -0
- package/nuxt/middleware.js +12 -0
- package/nuxt/mixins/fetch.client.js +90 -0
- package/nuxt/mixins/fetch.server.js +69 -0
- package/nuxt/portal-vue.js +4 -0
- package/nuxt/server.js +312 -0
- package/nuxt/store.js +178 -0
- package/nuxt/utils.js +630 -0
- package/nuxt/views/app.template.html +9 -0
- package/nuxt/views/error.html +23 -0
- package/package.json +5 -9
- package/pages/auth/setup.vue +2 -2
- package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
- package/pages/c/_cluster/apps/charts/chart.vue +4 -4
- package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
- package/pages/c/_cluster/apps/charts/install.vue +40 -66
- package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
- package/pages/c/_cluster/explorer/index.vue +29 -25
- package/pages/c/_cluster/explorer/tools/index.vue +8 -8
- package/pages/c/_cluster/fleet/index.vue +95 -34
- package/pages/c/_cluster/gatekeeper/index.vue +1 -1
- package/pages/c/_cluster/istio/index.vue +5 -5
- package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +7 -0
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
- package/pages/c/_cluster/uiplugins/index.vue +49 -17
- package/pages/home.vue +9 -4
- package/pages/index.vue +10 -1
- package/plugins/clean-html-directive.js +31 -0
- package/plugins/dashboard-store/actions.js +32 -9
- package/plugins/dashboard-store/mutations.js +5 -2
- package/plugins/dashboard-store/resource-class.js +8 -1
- package/plugins/steve/mutations.js +3 -2
- package/plugins/steve/steve-description-class.js +5 -1
- package/plugins/steve/subscribe.js +63 -54
- package/plugins/steve-create-worker.js +14 -0
- package/promptRemove/management.cattle.io.globalrole.vue +2 -2
- package/promptRemove/management.cattle.io.project.vue +2 -2
- package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
- package/promptRemove/pod.vue +1 -1
- package/public/index.html +65 -0
- package/rancher-components/components/Banner/Banner.test.ts +9 -1
- package/rancher-components/components/Banner/Banner.vue +1 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
- package/scripts/build-pkg.sh +1 -0
- package/scripts/clean +6 -0
- package/scripts/extension/bundle +58 -0
- package/scripts/extension/helmpatch +89 -0
- package/scripts/extension/publish +314 -0
- package/scripts/test-plugins-build.sh +4 -0
- package/store/__tests__/index.test.ts +110 -0
- package/store/index.js +145 -58
- package/store/type-map.js +5 -1
- package/tsconfig.default.json +36 -0
- package/tsconfig.json +24 -0
- package/types/shell/index.d.ts +420 -343
- package/utils/__tests__/string.test.ts +12 -0
- package/utils/auth.js +65 -0
- package/utils/monitoring.js +2 -1
- package/utils/position.js +5 -8
- package/utils/router.scrollBehavior.js +80 -0
- package/utils/select.js +1 -3
- package/utils/socket.js +1 -0
- package/utils/string.js +13 -0
- package/utils/time.js +9 -0
- package/vue.config.js +679 -0
- package/chart/rancher-alerting-drivers.vue +0 -53
- package/chart/rancher-gatekeeper.vue +0 -37
- package/creators/app/files/nuxt.config.js +0 -6
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
- package/nuxt.config.js +0 -798
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
|
|
3
|
+
|
|
4
|
+
describe('component: LabeledSelect', () => {
|
|
5
|
+
describe('should display correct label', () => {
|
|
6
|
+
it('given an existing value and option', () => {
|
|
7
|
+
const label = 'Foo';
|
|
8
|
+
const value = 'foo';
|
|
9
|
+
const wrapper = mount(LabeledSelect, {
|
|
10
|
+
propsData: {
|
|
11
|
+
value,
|
|
12
|
+
options: [
|
|
13
|
+
{ label, value },
|
|
14
|
+
],
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Component is from a library and class is not going to be changed
|
|
19
|
+
expect(wrapper.find('.vs__selected').text()).toBe(label);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('using value as label if no options', () => {
|
|
23
|
+
const value = 'foo';
|
|
24
|
+
const wrapper = mount(LabeledSelect, {
|
|
25
|
+
propsData: {
|
|
26
|
+
value,
|
|
27
|
+
options: [],
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Component is from a library and class is not going to be changed
|
|
32
|
+
expect(wrapper.find('.vs__selected').text()).toBe(value);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('using custom key as label for option object', () => {
|
|
36
|
+
const value = 'foo';
|
|
37
|
+
const label = 'Foo';
|
|
38
|
+
const customLabelKey = 'bananas';
|
|
39
|
+
const wrapper = mount(LabeledSelect, {
|
|
40
|
+
propsData: {
|
|
41
|
+
value,
|
|
42
|
+
optionLabel: customLabelKey,
|
|
43
|
+
options: [{
|
|
44
|
+
[customLabelKey]: label,
|
|
45
|
+
value
|
|
46
|
+
}],
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Component is from a library and class is not going to be changed
|
|
51
|
+
expect(wrapper.find('.vs__selected').text()).toBe(label);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('translating localized cases', () => {
|
|
55
|
+
const value = 'foo';
|
|
56
|
+
const translation = 'bananas';
|
|
57
|
+
const wrapper = mount(LabeledSelect, {
|
|
58
|
+
propsData: {
|
|
59
|
+
localizedLabel: true,
|
|
60
|
+
value,
|
|
61
|
+
options: [{ label: 'whatever', value }],
|
|
62
|
+
},
|
|
63
|
+
mocks: { $store: { getters: { 'i18n/t': () => translation } } }
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Component is from a library and class is not going to be changed
|
|
67
|
+
expect(wrapper.find('.vs__selected').text()).toBe(translation);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('updating the value on options change', () => {
|
|
71
|
+
it('using new label', async() => {
|
|
72
|
+
const value = 'foo';
|
|
73
|
+
const oldLabel = 'Foo';
|
|
74
|
+
const newLabel = 'Baz';
|
|
75
|
+
const wrapper = mount(LabeledSelect, {
|
|
76
|
+
propsData: {
|
|
77
|
+
value,
|
|
78
|
+
options: [
|
|
79
|
+
{ label: oldLabel, value },
|
|
80
|
+
],
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await wrapper.setProps({
|
|
85
|
+
options: [
|
|
86
|
+
{ label: newLabel, value },
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Component is from a library and class is not going to be changed
|
|
91
|
+
expect(wrapper.find('.vs__selected').text()).toBe(newLabel);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('using values only and no labels', async() => {
|
|
95
|
+
const value = 'foo';
|
|
96
|
+
const newValue = 'bananas';
|
|
97
|
+
const wrapper = mount(LabeledSelect, {
|
|
98
|
+
propsData: {
|
|
99
|
+
value,
|
|
100
|
+
options: [value],
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await wrapper.setProps({ options: [newValue] });
|
|
105
|
+
|
|
106
|
+
// Component is from a library and class is not going to be changed
|
|
107
|
+
expect(wrapper.find('.vs__selected').text()).toBe(value);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('using translated value', async() => {
|
|
111
|
+
const value = 'foo';
|
|
112
|
+
const oldLabel = 'Foo';
|
|
113
|
+
const newLabel = 'Baz';
|
|
114
|
+
const translation = 'bananas';
|
|
115
|
+
const i18nMap: Record<string, string> = { [newLabel]: translation };
|
|
116
|
+
const wrapper = mount(LabeledSelect, {
|
|
117
|
+
propsData: {
|
|
118
|
+
value,
|
|
119
|
+
localizedLabel: true,
|
|
120
|
+
options: [
|
|
121
|
+
{ label: oldLabel, value },
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
mocks: { $store: { getters: { 'i18n/t': (text: string) => i18nMap[text] } } }
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await wrapper.setProps({
|
|
128
|
+
options: [
|
|
129
|
+
{ label: newLabel, value },
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Component is from a library and class is not going to be changed
|
|
134
|
+
expect(wrapper.find('.vs__selected').text()).toBe(translation);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import NameNsDescription from '@shell/components/form/NameNsDescription.vue';
|
|
3
|
+
|
|
4
|
+
describe('component: NameNsDescription', () => {
|
|
5
|
+
// Accessing to computed value due code complexity
|
|
6
|
+
it('should map namespaces to options', () => {
|
|
7
|
+
const namespaceName = 'test';
|
|
8
|
+
const result = [{
|
|
9
|
+
label: namespaceName,
|
|
10
|
+
value: namespaceName
|
|
11
|
+
}];
|
|
12
|
+
const wrapper = mount(NameNsDescription, {
|
|
13
|
+
propsData: {
|
|
14
|
+
value: {},
|
|
15
|
+
mode: 'create',
|
|
16
|
+
},
|
|
17
|
+
mocks: {
|
|
18
|
+
$store: {
|
|
19
|
+
getters: {
|
|
20
|
+
namespaces: jest.fn(),
|
|
21
|
+
allowedNamespaces: () => ({ [namespaceName]: true }),
|
|
22
|
+
currentStore: () => 'cluster',
|
|
23
|
+
'cluster/schemaFor': jest.fn(),
|
|
24
|
+
'i18n/t': jest.fn()
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect((wrapper.vm as any).options).toStrictEqual(result);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
import LinkName from '@shell/components/formatter/LinkName.vue';
|
|
4
|
+
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
components: { LinkName },
|
|
8
|
+
|
|
9
|
+
props: {
|
|
10
|
+
value: {
|
|
11
|
+
type: null,
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
product: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: EXPLORER,
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
computed: {
|
|
21
|
+
kind() {
|
|
22
|
+
// this cover most of the usecases for events
|
|
23
|
+
if (this.value?.apiVersion && typeof this.value?.apiVersion === 'string') {
|
|
24
|
+
const versionParts = this.value.apiVersion.split('/');
|
|
25
|
+
|
|
26
|
+
if (versionParts.length === 1) {
|
|
27
|
+
return this.value.kind.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return `${ versionParts[0] }.${ this.value.kind.toLowerCase() }`;
|
|
31
|
+
// covers Node events usecase
|
|
32
|
+
} else if (this.value?.kind && typeof this.value?.kind === 'string') {
|
|
33
|
+
return this.value?.kind.toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<span v-if="kind && value.kind && value.name">
|
|
44
|
+
<LinkName
|
|
45
|
+
:type="kind"
|
|
46
|
+
:value="`${value.kind} ${value.name}`"
|
|
47
|
+
:object-id="value.name"
|
|
48
|
+
:namespace="value.namespace"
|
|
49
|
+
:product="product"
|
|
50
|
+
:show-type="true"
|
|
51
|
+
/>
|
|
52
|
+
</span>
|
|
53
|
+
<span v-else />
|
|
54
|
+
</template>
|
|
@@ -138,17 +138,18 @@ export default {
|
|
|
138
138
|
<n-link
|
|
139
139
|
v-if="isInternal && href"
|
|
140
140
|
:to="href"
|
|
141
|
+
class="link-text-icon"
|
|
141
142
|
>
|
|
142
143
|
<i
|
|
143
144
|
v-if="beforeIconClass"
|
|
144
145
|
:class="beforeIconClass"
|
|
145
|
-
|
|
146
|
+
class="prefix"
|
|
146
147
|
/>
|
|
147
148
|
{{ label }}
|
|
148
149
|
<i
|
|
149
150
|
v-if="afterIconClass"
|
|
150
151
|
:class="afterIconClass"
|
|
151
|
-
|
|
152
|
+
class="suffix"
|
|
152
153
|
/>
|
|
153
154
|
</n-link>
|
|
154
155
|
<a
|
|
@@ -156,18 +157,33 @@ export default {
|
|
|
156
157
|
:href="href"
|
|
157
158
|
:rel="rel"
|
|
158
159
|
:target="target"
|
|
160
|
+
class="link-text-icon"
|
|
159
161
|
>
|
|
160
162
|
<i
|
|
161
163
|
v-if="beforeIconClass"
|
|
162
164
|
:class="beforeIconClass"
|
|
163
|
-
|
|
165
|
+
class="prefix"
|
|
164
166
|
/>
|
|
165
167
|
{{ label }}
|
|
166
168
|
<i
|
|
167
169
|
v-if="afterIconClass"
|
|
168
170
|
:class="afterIconClass"
|
|
169
|
-
|
|
171
|
+
class="suffix"
|
|
170
172
|
/>
|
|
171
173
|
</a>
|
|
172
174
|
<span v-else> {{ href }} {{ label }}</span>
|
|
173
175
|
</template>
|
|
176
|
+
<style lang="scss" scoped>
|
|
177
|
+
.link-text-icon {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: top;
|
|
180
|
+
|
|
181
|
+
.prefix {
|
|
182
|
+
margin: 2px 2px 0 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.suffix {
|
|
186
|
+
margin: 2px 0 0 2px;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
</style>
|
|
@@ -18,6 +18,11 @@ export default {
|
|
|
18
18
|
default: '',
|
|
19
19
|
},
|
|
20
20
|
|
|
21
|
+
objectId: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: '',
|
|
24
|
+
},
|
|
25
|
+
|
|
21
26
|
product: {
|
|
22
27
|
type: String,
|
|
23
28
|
default: EXPLORER,
|
|
@@ -31,7 +36,7 @@ export default {
|
|
|
31
36
|
const params = {
|
|
32
37
|
resource: this.type,
|
|
33
38
|
namespace: this.namespace,
|
|
34
|
-
id: this.value,
|
|
39
|
+
id: this.objectId ? this.objectId : this.value,
|
|
35
40
|
product: this.product || EXPLORER,
|
|
36
41
|
};
|
|
37
42
|
|
package/components/nav/Group.vue
CHANGED
|
@@ -202,11 +202,11 @@ export default {
|
|
|
202
202
|
:to="group.children[0].route"
|
|
203
203
|
:exact="group.children[0].exact"
|
|
204
204
|
>
|
|
205
|
-
<h6 v-html="group.labelDisplay || group.label" />
|
|
205
|
+
<h6 v-clean-html="group.labelDisplay || group.label" />
|
|
206
206
|
</n-link>
|
|
207
207
|
<h6
|
|
208
208
|
v-else
|
|
209
|
-
v-html="group.labelDisplay || group.label"
|
|
209
|
+
v-clean-html="group.labelDisplay || group.label"
|
|
210
210
|
/>
|
|
211
211
|
</slot>
|
|
212
212
|
<i
|
|
@@ -105,13 +105,27 @@ export default {
|
|
|
105
105
|
const t = this.$store.getters['i18n/t'];
|
|
106
106
|
let out = [];
|
|
107
107
|
|
|
108
|
+
const params = { ...this.$route.params };
|
|
109
|
+
const resource = params.resource;
|
|
110
|
+
// Sometimes, different pages may have different namespaces to filter
|
|
111
|
+
const notFilterNamespaces = this.$store.getters[`type-map/optionsFor`](resource).notFilterNamespace || [];
|
|
112
|
+
|
|
108
113
|
// TODO: Add return info
|
|
109
114
|
if (this.currentProduct?.customNamespaceFilter && this.currentProduct?.inStore) {
|
|
110
115
|
// Sometimes the component can show before the 'currentProduct' has caught up, so access the product via the getter rather
|
|
111
116
|
// than caching it in the `fetch`
|
|
117
|
+
|
|
118
|
+
// The namespace display on the list and edit pages should be the same as in the namespaceFilter component
|
|
119
|
+
if (this.$store.getters[`${ this.currentProduct.inStore }/filterNamespace`]) {
|
|
120
|
+
const allNamespaces = this.$store.getters[`${ this.currentProduct.inStore }/filterNamespace`](notFilterNamespaces);
|
|
121
|
+
|
|
122
|
+
this.$store.commit('changeAllNamespaces', allNamespaces);
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
return this.$store.getters[`${ this.currentProduct.inStore }/namespaceFilterOptions`]({
|
|
113
126
|
addNamespace,
|
|
114
|
-
divider
|
|
127
|
+
divider,
|
|
128
|
+
notFilterNamespaces
|
|
115
129
|
});
|
|
116
130
|
}
|
|
117
131
|
|
|
@@ -371,17 +385,7 @@ export default {
|
|
|
371
385
|
return namespaces;
|
|
372
386
|
}
|
|
373
387
|
|
|
374
|
-
const isVirtualCluster = this.$store.getters['isVirtualCluster'];
|
|
375
|
-
|
|
376
388
|
return namespaces.filter((namespace) => {
|
|
377
|
-
const isSettingSystemNamespace = this.$store.getters['systemNamespaces'].includes(namespace.metadata.name);
|
|
378
|
-
const systemNS = namespace.isSystem || namespace.isFleetManaged || isSettingSystemNamespace;
|
|
379
|
-
|
|
380
|
-
// For Harvester, filter out system namespaces AND obscure namespaces.
|
|
381
|
-
if (isVirtualCluster) {
|
|
382
|
-
return !systemNS && !namespace.isObscure;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
389
|
// Otherwise only filter out obscure namespaces, such as namespaces
|
|
386
390
|
// that Rancher uses to manage RBAC for projects, which should not be
|
|
387
391
|
// edited or deleted by Rancher users.
|
|
@@ -3,7 +3,6 @@ import BrandImage from '@shell/components/BrandImage';
|
|
|
3
3
|
import ClusterProviderIcon from '@shell/components/ClusterProviderIcon';
|
|
4
4
|
import IconOrSvg from '../IconOrSvg';
|
|
5
5
|
import { mapGetters } from 'vuex';
|
|
6
|
-
import $ from 'jquery';
|
|
7
6
|
import { CAPI, MANAGEMENT } from '@shell/config/types';
|
|
8
7
|
import { mapPref, MENU_MAX_CLUSTERS } from '@shell/store/prefs';
|
|
9
8
|
import { sortBy } from '@shell/utils/sort';
|
|
@@ -188,11 +187,10 @@ export default {
|
|
|
188
187
|
const max = Math.min(maxToShow, this.clusters.length);
|
|
189
188
|
|
|
190
189
|
if (el) {
|
|
191
|
-
const $el = $(el);
|
|
192
190
|
const h = 33 * max;
|
|
193
191
|
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
el.style.minHeight = `${ h }px`;
|
|
193
|
+
el.style.maxHeight = `${ h }px`;
|
|
196
194
|
}
|
|
197
195
|
},
|
|
198
196
|
handler(e) {
|
package/components/nav/Type.vue
CHANGED
|
@@ -90,9 +90,9 @@ export default {
|
|
|
90
90
|
><t :k="type.labelKey" /></span>
|
|
91
91
|
<span
|
|
92
92
|
v-else
|
|
93
|
+
v-clean-html="type.labelDisplay || type.label"
|
|
93
94
|
class="label"
|
|
94
95
|
:class="{'no-icon': !type.icon}"
|
|
95
|
-
v-html="type.labelDisplay || type.label"
|
|
96
96
|
/>
|
|
97
97
|
<span
|
|
98
98
|
v-if="showFavorite || showCount"
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { WORKSPACE } from '@shell/store/prefs';
|
|
2
|
+
import { LAST_NAMESPACE, WORKSPACE } from '@shell/store/prefs';
|
|
3
3
|
import { mapState } from 'vuex';
|
|
4
4
|
import Select from '@shell/components/form/Select';
|
|
5
|
+
import { WORKSPACE_ANNOTATION } from '@shell/config/labels-annotations';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
8
|
+
name: 'WorkspaceSwitcher',
|
|
7
9
|
components: { Select },
|
|
8
10
|
|
|
9
11
|
computed: {
|
|
10
|
-
...mapState(['allWorkspaces', 'workspace']),
|
|
12
|
+
...mapState(['allWorkspaces', 'workspace', 'allNamespaces', 'defaultNamespace', 'getActiveNamespaces']),
|
|
11
13
|
|
|
12
14
|
value: {
|
|
13
15
|
get() {
|
|
14
|
-
return this.workspace;
|
|
16
|
+
return this.workspace || this.namespace || this.options[0]?.value;
|
|
15
17
|
},
|
|
16
18
|
|
|
17
19
|
set(value) {
|
|
@@ -23,17 +25,56 @@ export default {
|
|
|
23
25
|
},
|
|
24
26
|
|
|
25
27
|
options() {
|
|
26
|
-
|
|
28
|
+
if (this.allWorkspaces.length) {
|
|
29
|
+
const out = this.allWorkspaces.map((obj) => {
|
|
30
|
+
return {
|
|
31
|
+
label: obj.nameDisplay,
|
|
32
|
+
value: obj.id,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// If doesn't have workspaces (e.g. no permissions)
|
|
40
|
+
// Then find the workspaces from the annotation.
|
|
41
|
+
return this.allNamespaces.filter((item) => {
|
|
42
|
+
return item.metadata.annotations[WORKSPACE_ANNOTATION] === WORKSPACE;
|
|
43
|
+
}).map((obj) => {
|
|
27
44
|
return {
|
|
28
45
|
label: obj.nameDisplay,
|
|
29
46
|
value: obj.id,
|
|
30
47
|
};
|
|
31
48
|
});
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
watch: {
|
|
53
|
+
options(curr, prev) {
|
|
54
|
+
if (curr.length === 0) {
|
|
55
|
+
this.value = '';
|
|
56
|
+
}
|
|
32
57
|
|
|
33
|
-
|
|
58
|
+
const currentExists = curr.find(item => item.value === this.value);
|
|
59
|
+
|
|
60
|
+
if (curr.length && !currentExists) {
|
|
61
|
+
this.value = curr[0]?.value;
|
|
62
|
+
}
|
|
34
63
|
},
|
|
35
64
|
},
|
|
36
65
|
|
|
66
|
+
created() {
|
|
67
|
+
// in fleet standard user with just the project owner and global git repo permissions
|
|
68
|
+
// returns 'default'
|
|
69
|
+
const initValue = !this.workspace ? this.$store.getters['prefs/get'](LAST_NAMESPACE) : '';
|
|
70
|
+
|
|
71
|
+
this.value = (initValue === 'default' || initValue === '') && this.options.length ? this.options[0].value : initValue;
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
data() {
|
|
75
|
+
return { namespace: this.$store.getters['prefs/get'](LAST_NAMESPACE) };
|
|
76
|
+
},
|
|
77
|
+
|
|
37
78
|
methods: {
|
|
38
79
|
focus() {
|
|
39
80
|
this.$refs.select.$refs.search.focus();
|
|
@@ -13,6 +13,7 @@ export const UI_MANAGED = 'management.cattle.io/ui-managed';
|
|
|
13
13
|
export const CREATOR_ID = 'field.cattle.io/creatorId';
|
|
14
14
|
export const RESOURCE_QUOTA = 'field.cattle.io/resourceQuota';
|
|
15
15
|
export const AZURE_MIGRATED = 'auth.cattle.io/azuread-endpoint-migrated';
|
|
16
|
+
export const WORKSPACE_ANNOTATION = 'objectset.rio.cattle.io/id';
|
|
16
17
|
|
|
17
18
|
export const KUBERNETES = {
|
|
18
19
|
SERVICE_ACCOUNT_UID: 'kubernetes.io/service-account.uid',
|
|
@@ -146,3 +147,19 @@ export const CLUSTER_BADGE = {
|
|
|
146
147
|
// Custom icon text - max 2 characters
|
|
147
148
|
ICON_TEXT: 'ui.rancher/badge-icon-text',
|
|
148
149
|
};
|
|
150
|
+
|
|
151
|
+
export const SYSTEM_LABELS = [
|
|
152
|
+
'io.cattle.lifecycle.',
|
|
153
|
+
'beta.kubernetes.io',
|
|
154
|
+
'failure-domain.beta.kubernetes.io',
|
|
155
|
+
'node-role.kubernetes.io',
|
|
156
|
+
'kubernetes.io',
|
|
157
|
+
'cattle.io',
|
|
158
|
+
'authz.management.cattle.io',
|
|
159
|
+
'rke.cattle.io',
|
|
160
|
+
'field.cattle.io',
|
|
161
|
+
'workload.user.cattle.io',
|
|
162
|
+
'k3s.io',
|
|
163
|
+
'node.kubernetes.io',
|
|
164
|
+
'egress.rke2.io'
|
|
165
|
+
];
|
package/config/product/auth.js
CHANGED
|
@@ -27,7 +27,7 @@ export function init(store) {
|
|
|
27
27
|
|
|
28
28
|
product({
|
|
29
29
|
ifHaveType: new RegExp(`${ MANAGEMENT.USER }|${ MANAGEMENT.AUTH_CONFIG }`, 'i'),
|
|
30
|
-
ifHaveVerb: '
|
|
30
|
+
ifHaveVerb: 'GET',
|
|
31
31
|
ifFeature: MULTI_CLUSTER,
|
|
32
32
|
inStore: 'management',
|
|
33
33
|
icon: 'user',
|
|
@@ -43,7 +43,8 @@ export function init(store) {
|
|
|
43
43
|
name: 'config',
|
|
44
44
|
weight: -1,
|
|
45
45
|
route: { name: 'c-cluster-auth-config' },
|
|
46
|
-
ifHaveType: MANAGEMENT.AUTH_CONFIG
|
|
46
|
+
ifHaveType: MANAGEMENT.AUTH_CONFIG,
|
|
47
|
+
ifHaveVerb: 'PUT'
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
virtualType({
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
STORAGE_CLASS_PROVISIONER, PERSISTENT_VOLUME_SOURCE,
|
|
19
19
|
HPA_REFERENCE, MIN_REPLICA, MAX_REPLICA, CURRENT_REPLICA,
|
|
20
20
|
ACCESS_KEY, DESCRIPTION, EXPIRES, EXPIRY_STATE, SUB_TYPE, AGE_NORMAN, SCOPE_NORMAN, PERSISTENT_VOLUME_CLAIM, RECLAIM_POLICY, PV_REASON, WORKLOAD_HEALTH_SCALE, POD_RESTARTS,
|
|
21
|
-
DURATION, LAST_SEEN_TIME,
|
|
21
|
+
DURATION, MESSAGE, REASON, LAST_SEEN_TIME, EVENT_TYPE, OBJECT,
|
|
22
22
|
} from '@shell/config/table-headers';
|
|
23
23
|
|
|
24
24
|
import { DSL } from '@shell/store/type-map';
|
|
@@ -175,6 +175,11 @@ export function init(store) {
|
|
|
175
175
|
},
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
+
/** This CRD is installed on provisioned clusters because rancher webhook, used for both local and provisioned clusters, expects it to be there
|
|
179
|
+
* Creating instances of this resource on downstream clusters wont do anything - Only show them for the local cluster
|
|
180
|
+
*/
|
|
181
|
+
configureType(MANAGEMENT.PSA, { localOnly: true });
|
|
182
|
+
|
|
178
183
|
headers(PV, [STATE, NAME_COL, RECLAIM_POLICY, PERSISTENT_VOLUME_CLAIM, PERSISTENT_VOLUME_SOURCE, PV_REASON, AGE]);
|
|
179
184
|
headers(CONFIG_MAP, [NAME_COL, NAMESPACE_COL, KEYS, AGE]);
|
|
180
185
|
headers(SECRET, [
|
|
@@ -192,7 +197,7 @@ export function init(store) {
|
|
|
192
197
|
]);
|
|
193
198
|
headers(INGRESS, [STATE, NAME_COL, NAMESPACE_COL, INGRESS_TARGET, INGRESS_DEFAULT_BACKEND, INGRESS_CLASS, AGE]);
|
|
194
199
|
headers(SERVICE, [STATE, NAME_COL, NAMESPACE_COL, TARGET_PORT, SELECTOR, SPEC_TYPE, AGE]);
|
|
195
|
-
headers(EVENT, [STATE, { ...LAST_SEEN_TIME, defaultSort: true },
|
|
200
|
+
headers(EVENT, [STATE, { ...LAST_SEEN_TIME, defaultSort: true }, EVENT_TYPE, REASON, OBJECT, 'Subobject', 'Source', MESSAGE, 'First Seen', 'Count', NAME_COL, NAMESPACE_COL]);
|
|
196
201
|
headers(HPA, [STATE, NAME_COL, HPA_REFERENCE, MIN_REPLICA, MAX_REPLICA, CURRENT_REPLICA, AGE]);
|
|
197
202
|
headers(WORKLOAD, [STATE, NAME_COL, NAMESPACE_COL, TYPE, WORKLOAD_IMAGES, WORKLOAD_ENDPOINTS, POD_RESTARTS, AGE, WORKLOAD_HEALTH_SCALE]);
|
|
198
203
|
headers(WORKLOAD_TYPES.DEPLOYMENT, [STATE, NAME_COL, NAMESPACE_COL, WORKLOAD_IMAGES, WORKLOAD_ENDPOINTS, 'Ready', 'Up-to-date', 'Available', POD_RESTARTS, AGE, WORKLOAD_HEALTH_SCALE]);
|
|
@@ -203,6 +208,10 @@ export function init(store) {
|
|
|
203
208
|
headers(WORKLOAD_TYPES.CRON_JOB, [STATE, NAME_COL, NAMESPACE_COL, WORKLOAD_IMAGES, WORKLOAD_ENDPOINTS, 'Schedule', 'Last Schedule', POD_RESTARTS, AGE, WORKLOAD_HEALTH_SCALE]);
|
|
204
209
|
headers(WORKLOAD_TYPES.REPLICATION_CONTROLLER, [STATE, NAME_COL, NAMESPACE_COL, WORKLOAD_IMAGES, WORKLOAD_ENDPOINTS, 'Ready', 'Current', 'Desired', POD_RESTARTS, AGE, WORKLOAD_HEALTH_SCALE]);
|
|
205
210
|
headers(POD, [STATE, NAME_COL, NAMESPACE_COL, POD_IMAGES, 'Ready', 'Restarts', 'IP', NODE_COL, AGE]);
|
|
211
|
+
headers(MANAGEMENT.PSA, [STATE, NAME_COL, {
|
|
212
|
+
...DESCRIPTION,
|
|
213
|
+
width: undefined
|
|
214
|
+
}, AGE]);
|
|
206
215
|
headers(STORAGE_CLASS, [STATE, NAME_COL, STORAGE_CLASS_PROVISIONER, STORAGE_CLASS_DEFAULT, AGE]);
|
|
207
216
|
|
|
208
217
|
headers(RBAC.ROLE, [
|
|
@@ -311,8 +320,6 @@ export function init(store) {
|
|
|
311
320
|
|
|
312
321
|
// Ignore these types as they are managed through the auth product
|
|
313
322
|
ignoreType(MANAGEMENT.USER);
|
|
314
|
-
|
|
315
|
-
// Ignore these types as they are managed through the auth product
|
|
316
323
|
ignoreType(MANAGEMENT.GLOBAL_ROLE);
|
|
317
324
|
ignoreType(MANAGEMENT.ROLE_TEMPLATE);
|
|
318
325
|
}
|