@rancher/shell 0.3.3 → 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.
Files changed (249) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +15 -2
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-helpers.js +64 -61
  86. package/core/plugin-routes.ts +23 -0
  87. package/creators/app/app.package.json +2 -1
  88. package/creators/app/files/.eslintrc.js +1 -1
  89. package/creators/app/files/babel.config.js +1 -18
  90. package/creators/app/files/vue.config.js +7 -0
  91. package/creators/app/init +5 -5
  92. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  93. package/creators/pkg/init +35 -4
  94. package/creators/update/init +1 -1
  95. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  96. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  97. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  98. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  99. package/detail/workload/index.vue +3 -3
  100. package/dialog/AddClusterMemberDialog.vue +1 -1
  101. package/dialog/AddProjectMemberDialog.vue +2 -2
  102. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  103. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  104. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  105. package/dialog/GenericPrompt.vue +18 -6
  106. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  107. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  108. package/dialog/ScaleMachineDownDialog.vue +1 -1
  109. package/edit/auth/github.vue +8 -8
  110. package/edit/auth/googleoauth.vue +5 -5
  111. package/edit/auth/ldap/index.vue +1 -1
  112. package/edit/auth/oidc.vue +1 -1
  113. package/edit/auth/saml.vue +1 -1
  114. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  115. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  116. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  117. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  118. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  119. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  120. package/edit/management.cattle.io.setting.vue +1 -1
  121. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  122. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  124. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  125. package/edit/namespace.vue +2 -2
  126. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  127. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  128. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  129. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  130. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  131. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  132. package/edit/resources.cattle.io.backup.vue +1 -1
  133. package/edit/service.vue +1 -1
  134. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  135. package/edit/workload/__tests__/Job.test.ts +3 -1
  136. package/edit/workload/index.vue +8 -3
  137. package/edit/workload/mixins/workload.js +16 -0
  138. package/layouts/default.vue +7 -3
  139. package/list/fleet.cattle.io.bundle.vue +6 -3
  140. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  141. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  142. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  143. package/list/node.vue +69 -16
  144. package/list/provisioning.cattle.io.cluster.vue +30 -1
  145. package/machine-config/azure.vue +97 -38
  146. package/middleware/authenticated.js +34 -0
  147. package/mixins/chart.js +73 -2
  148. package/mixins/resource-fetch.js +2 -2
  149. package/models/apps.statefulset.js +28 -0
  150. package/models/cluster/node.js +23 -2
  151. package/models/cluster.x-k8s.io.machine.js +4 -2
  152. package/models/clusterroletemplatebinding.js +7 -0
  153. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  154. package/models/fleet.cattle.io.cluster.js +19 -10
  155. package/models/fleet.cattle.io.gitrepo.js +7 -2
  156. package/models/management.cattle.io.cluster.js +1 -1
  157. package/models/management.cattle.io.fleetworkspace.js +12 -0
  158. package/models/management.cattle.io.gitreporestriction.js +5 -0
  159. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  160. package/models/namespace.js +5 -5
  161. package/models/provisioning.cattle.io.cluster.js +7 -5
  162. package/nuxt/App.js +210 -0
  163. package/nuxt/axios.js +186 -0
  164. package/nuxt/client.js +817 -0
  165. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  166. package/nuxt/components/nuxt-child.js +122 -0
  167. package/nuxt/components/nuxt-error.vue +98 -0
  168. package/nuxt/components/nuxt-link.client.js +98 -0
  169. package/nuxt/components/nuxt-link.server.js +16 -0
  170. package/nuxt/components/nuxt-loading.vue +154 -0
  171. package/nuxt/components/nuxt.js +101 -0
  172. package/nuxt/cookie-universal-nuxt.js +9 -0
  173. package/nuxt/empty.js +1 -0
  174. package/nuxt/index.js +365 -0
  175. package/nuxt/jsonp.js +82 -0
  176. package/nuxt/loading.html +39 -0
  177. package/nuxt/middleware.js +12 -0
  178. package/nuxt/mixins/fetch.client.js +90 -0
  179. package/nuxt/mixins/fetch.server.js +69 -0
  180. package/nuxt/portal-vue.js +4 -0
  181. package/nuxt/server.js +312 -0
  182. package/nuxt/store.js +178 -0
  183. package/nuxt/utils.js +630 -0
  184. package/nuxt/views/app.template.html +9 -0
  185. package/nuxt/views/error.html +23 -0
  186. package/package.json +5 -9
  187. package/pages/auth/setup.vue +2 -2
  188. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  189. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  190. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  191. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  192. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  193. package/pages/c/_cluster/explorer/index.vue +29 -25
  194. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  195. package/pages/c/_cluster/fleet/index.vue +95 -34
  196. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  197. package/pages/c/_cluster/istio/index.vue +5 -5
  198. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  199. package/pages/c/_cluster/monitoring/index.vue +7 -0
  200. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  201. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  202. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  203. package/pages/home.vue +9 -4
  204. package/pages/index.vue +10 -1
  205. package/plugins/clean-html-directive.js +31 -0
  206. package/plugins/dashboard-store/actions.js +32 -9
  207. package/plugins/dashboard-store/mutations.js +5 -2
  208. package/plugins/dashboard-store/resource-class.js +8 -1
  209. package/plugins/steve/mutations.js +3 -2
  210. package/plugins/steve/steve-description-class.js +5 -1
  211. package/plugins/steve/subscribe.js +63 -54
  212. package/plugins/steve-create-worker.js +14 -0
  213. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  214. package/promptRemove/management.cattle.io.project.vue +2 -2
  215. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  216. package/promptRemove/pod.vue +1 -1
  217. package/public/index.html +65 -0
  218. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  219. package/rancher-components/components/Banner/Banner.vue +1 -1
  220. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  221. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  222. package/scripts/build-pkg.sh +1 -0
  223. package/scripts/clean +6 -0
  224. package/scripts/extension/bundle +58 -0
  225. package/scripts/extension/helmpatch +89 -0
  226. package/scripts/extension/publish +314 -0
  227. package/scripts/test-plugins-build.sh +4 -0
  228. package/store/__tests__/index.test.ts +110 -0
  229. package/store/index.js +145 -58
  230. package/store/type-map.js +26 -19
  231. package/tsconfig.default.json +36 -0
  232. package/tsconfig.json +24 -0
  233. package/types/shell/index.d.ts +420 -343
  234. package/utils/__tests__/string.test.ts +12 -0
  235. package/utils/auth.js +65 -0
  236. package/utils/monitoring.js +2 -1
  237. package/utils/position.js +5 -8
  238. package/utils/router.scrollBehavior.js +80 -0
  239. package/utils/select.js +1 -3
  240. package/utils/socket.js +1 -0
  241. package/utils/string.js +13 -0
  242. package/utils/time.js +9 -0
  243. package/vue.config.js +679 -0
  244. package/yarn-error.log +196 -0
  245. package/chart/rancher-alerting-drivers.vue +0 -53
  246. package/chart/rancher-gatekeeper.vue +0 -37
  247. package/creators/app/files/nuxt.config.js +0 -6
  248. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  249. 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
+ });
@@ -56,3 +56,9 @@ export default {
56
56
  </template>
57
57
  </span>
58
58
  </template>
59
+
60
+ <style lang='scss' scoped>
61
+ .icon-btn {
62
+ margin-left: 8px;
63
+ }
64
+ </style>
@@ -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
- style="position: relative; top: -2px;"
146
+ class="prefix"
146
147
  />
147
148
  {{ label }}
148
149
  <i
149
150
  v-if="afterIconClass"
150
151
  :class="afterIconClass"
151
- style="position: relative; top: -2px;"
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
- style="position: relative; top: -2px;"
165
+ class="prefix"
164
166
  />
165
167
  {{ label }}
166
168
  <i
167
169
  v-if="afterIconClass"
168
170
  :class="afterIconClass"
169
- style="position: relative; top: -2px;"
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
 
@@ -115,7 +115,7 @@ export default {
115
115
  :key="index"
116
116
  class="text-small"
117
117
  >
118
- <span v-html="port.label" />
118
+ <span v-clean-html="port.label" />
119
119
  </div>
120
120
  </div>
121
121
  </template>
@@ -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
- $el.css('min-height', `${ h }px`);
195
- $el.css('max-height', `${ h }px`);
192
+ el.style.minHeight = `${ h }px`;
193
+ el.style.maxHeight = `${ h }px`;
196
194
  }
197
195
  },
198
196
  handler(e) {
@@ -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
- const out = this.allWorkspaces.map((obj) => {
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
- return out;
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
+ ];
@@ -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: 'PUT',
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 }, 'EventType', 'Reason', 'Object', 'Subobject', 'Source', 'Message', 'First Seen', 'Count', 'Name', 'Namespace']);
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
  }
@@ -62,6 +62,8 @@ export function init(store) {
62
62
  FLEET.WORKSPACE,
63
63
  FLEET.BUNDLE,
64
64
  FLEET.TOKEN,
65
+ FLEET.BUNDLE_NAMESPACE_MAPPING,
66
+ FLEET.GIT_REPO_RESTRICTION
65
67
  ], 'advanced');
66
68
 
67
69
  headers(FLEET.WORKSPACE, [