@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
@@ -28,6 +28,30 @@ const getPackageFromRoute = (route) => {
28
28
 
29
29
  let beforeEachSetup = false;
30
30
 
31
+ function findMeta(route, key) {
32
+ if (route?.meta) {
33
+ const meta = Array.isArray(route.meta) ? route.meta : [route.meta];
34
+
35
+ for (let i = 0; i < meta.length; i++) {
36
+ if (meta[i][key]) {
37
+ return meta[i][key];
38
+ }
39
+ }
40
+ }
41
+
42
+ return undefined;
43
+ }
44
+
45
+ export function getClusterFromRoute(to) {
46
+ let cluster = to.params?.cluster;
47
+
48
+ if (!cluster) {
49
+ cluster = findMeta(to, 'cluster');
50
+ }
51
+
52
+ return cluster;
53
+ }
54
+
31
55
  export function getProductFromRoute(to) {
32
56
  let product = to.params?.product;
33
57
 
@@ -39,6 +63,11 @@ export function getProductFromRoute(to) {
39
63
  }
40
64
  }
41
65
 
66
+ // If still no product, see if the route indicates the product via route metadata
67
+ if (!product) {
68
+ product = findMeta(to, 'product');
69
+ }
70
+
42
71
  return product;
43
72
  }
44
73
 
@@ -279,6 +308,11 @@ export default async function({
279
308
  try {
280
309
  let clusterId = get(route, 'params.cluster');
281
310
 
311
+ // Route can provide cluster ID via metadata
312
+ if (!clusterId && route) {
313
+ clusterId = getClusterFromRoute(route);
314
+ }
315
+
282
316
  const pkg = getPackageFromRoute(route);
283
317
  const product = getProductFromRoute(route);
284
318
 
package/mixins/chart.js CHANGED
@@ -292,7 +292,13 @@ export default {
292
292
  // use the first version provided by the Helm chart
293
293
  // as the default.
294
294
  if ( !this.query.versionName && this.chart.versions?.length ) {
295
- this.query.versionName = this.chart.versions[0].version;
295
+ if (this.showPreRelease) {
296
+ this.query.versionName = this.chart.versions[0].version;
297
+ } else {
298
+ const firstRelease = this.chart.versions.find(v => !isPrerelease(v.version));
299
+
300
+ this.query.versionName = firstRelease?.version || this.chart.versions[0].version;
301
+ }
296
302
  }
297
303
 
298
304
  if ( !this.query.versionName ) {
@@ -341,6 +347,71 @@ export default {
341
347
  }
342
348
  }, // End of fetchChart
343
349
 
350
+ // Charts have an annotation that specifies any additional charts that should be installed at the same time eg CRDs
351
+ async fetchAutoInstallInfo() {
352
+ const out = [];
353
+ /*
354
+ An example value for auto is ["rancher-monitoring-crd=match"].
355
+ It is an array of chart names that lets Rancher know of other
356
+ charts that should be auto-installed at the same time.
357
+ */
358
+ const auto = (this.version?.annotations?.[CATALOG_ANNOTATIONS.AUTO_INSTALL] || '').split(/\s*,\s*/).filter(x => !!x).reverse();
359
+
360
+ for ( const constraint of auto ) {
361
+ const provider = this.$store.getters['catalog/versionSatisfying']({
362
+ constraint,
363
+ repoName: this.chart.repoName,
364
+ repoType: this.chart.repoType,
365
+ chartVersion: this.version.version,
366
+ });
367
+ /* An example return value for "provider":
368
+ [
369
+ {
370
+ "name": "rancher-monitoring-crd",
371
+ "version": "100.1.3+up19.0.3",
372
+ "description": "Installs the CRDs for rancher-monitoring.",
373
+ "apiVersion": "v1",
374
+ "annotations": {
375
+ "catalog.cattle.io/certified": "rancher",
376
+ "catalog.cattle.io/hidden": "true",
377
+ "catalog.cattle.io/namespace": "cattle-monitoring-system",
378
+ "catalog.cattle.io/release-name": "rancher-monitoring-crd"
379
+ },
380
+ "type": "application",
381
+ "urls": [
382
+ "https://192.168.0.18:8005/k8s/clusters/c-m-hhpg69fv/v1/catalog.cattle.io.clusterrepos/rancher-charts?chartName=rancher-monitoring-crd&link=chart&version=100.1.3%2Bup19.0.3"
383
+ ],
384
+ "created": "2022-04-27T10:04:18.343124-07:00",
385
+ "digest": "ecf07ba23a9cdaa7ffbbb14345d94ea1240b7f3b8e0ce9be4640e3e585c484e2",
386
+ "key": "cluster/rancher-charts/rancher-monitoring-crd/100.1.3+up19.0.3",
387
+ "repoType": "cluster",
388
+ "repoName": "rancher-charts"
389
+ }
390
+ ]
391
+ */
392
+
393
+ if ( provider ) {
394
+ // more.push(provider);
395
+ try {
396
+ const crdVersionInfo = await this.$store.dispatch('catalog/getVersionInfo', {
397
+ repoType: provider.repoType,
398
+ repoName: provider.repoName,
399
+ chartName: provider.name,
400
+ versionName: provider.version
401
+ });
402
+
403
+ out.push(crdVersionInfo);
404
+ } catch (e) {
405
+ console.error('Unable to fetch VersionInfo: ', e); // eslint-disable-line no-console
406
+ }
407
+ } else {
408
+ this.errors.push(`This chart requires ${ constraint } but no matching chart was found`);
409
+ }
410
+ }
411
+
412
+ this.$set(this, 'autoInstallInfo', out);
413
+ },
414
+
344
415
  selectVersion({ id: version }) {
345
416
  this.$router.applyQuery({ [VERSION]: version });
346
417
  },
@@ -361,7 +432,7 @@ export default {
361
432
  repoType: this.chart.repoType,
362
433
  repoName: this.chart.repoName,
363
434
  name: this.chart.chartName,
364
- version: this.chart.versionName,
435
+ version: this.query.versionName,
365
436
  };
366
437
 
367
438
  return {
@@ -131,8 +131,8 @@ export default {
131
131
 
132
132
  const schema = this.$store.getters[`${ currStore }/schemaFor`](type);
133
133
 
134
- if (schema?.attributes?.namespaced) {
135
- opt.namespaced = this.namespaceFilter;
134
+ if (schema?.attributes?.namespaced) { // Is this specific resource namespaced (could be primary or secondary resource)?
135
+ opt.namespaced = this.namespaceFilter; // namespaceFilter will only be populated if applicable for primary resource
136
136
  }
137
137
 
138
138
  return this.$store.dispatch(`${ currStore }/findAll`, {
@@ -1,4 +1,6 @@
1
1
  import Workload from './workload';
2
+ import { WORKLOAD_TYPES, POD } from '@shell/config/types';
3
+ import { WORKLOAD_TYPE_TO_KIND_MAPPING } from '@shell/detail/workload/index';
2
4
 
3
5
  export default class StatefulSet extends Workload {
4
6
  async rollBack(cluster, statefulSet, revision) {
@@ -19,4 +21,30 @@ export default class StatefulSet extends Workload {
19
21
 
20
22
  await this.rollBackWorkload(cluster, statefulSet, 'statefulsets', body);
21
23
  }
24
+
25
+ // we need to provide a new pods getter for statefulsets because the relationship
26
+ // done on the parent model "workload" is not correct
27
+ get pods() {
28
+ const relationships = this.metadata?.relationships || [];
29
+ const podRelationship = relationships.filter(relationship => relationship.toType === POD)[0];
30
+
31
+ if (podRelationship) {
32
+ const pods = this.$getters['podsByNamespace'](this.metadata.namespace);
33
+
34
+ return pods.filter((pod) => {
35
+ // a bit of a duplication of podRelationship, but always safe to check...
36
+ if (pod.metadata?.ownerReferences?.length) {
37
+ const ownerReferencesStatefulSet = pod.metadata?.ownerReferences?.find(own => own.kind === WORKLOAD_TYPE_TO_KIND_MAPPING[WORKLOAD_TYPES.STATEFUL_SET]);
38
+
39
+ if (ownerReferencesStatefulSet) {
40
+ return `${ pod.metadata.namespace }/${ ownerReferencesStatefulSet.name }` === this.id;
41
+ }
42
+ }
43
+
44
+ return false;
45
+ });
46
+ }
47
+
48
+ return [];
49
+ }
22
50
  }
@@ -1,5 +1,5 @@
1
1
  import { formatPercent } from '@shell/utils/string';
2
- import { CAPI as CAPI_ANNOTATIONS, NODE_ROLES, RKE } from '@shell/config/labels-annotations.js';
2
+ import { CAPI as CAPI_ANNOTATIONS, NODE_ROLES, RKE, SYSTEM_LABELS } from '@shell/config/labels-annotations.js';
3
3
  import {
4
4
  CAPI, MANAGEMENT, METRIC, NORMAN, POD
5
5
  } from '@shell/config/types';
@@ -76,7 +76,8 @@ export default class ClusterNode extends SteveModel {
76
76
  }
77
77
 
78
78
  openSsh() {
79
- this.provisionedMachine.openSsh();
79
+ // Pass in the name of the node, so we display that rather than the name of the provisioned machine
80
+ this.provisionedMachine.openSsh(this.nameDisplay);
80
81
  }
81
82
 
82
83
  downloadKeys() {
@@ -109,6 +110,26 @@ export default class ClusterNode extends SteveModel {
109
110
  return this.metadata?.labels || {};
110
111
  }
111
112
 
113
+ get customLabelCount() {
114
+ return this.customLabels.length;
115
+ }
116
+
117
+ get customLabels() {
118
+ const parsedLabels = [];
119
+
120
+ if (this.labels) {
121
+ for (const k in this.labels) {
122
+ const [prefix] = k.split('/');
123
+
124
+ if (!SYSTEM_LABELS.includes(prefix)) {
125
+ parsedLabels.push(`${ k }=${ this.labels[k] }`);
126
+ }
127
+ }
128
+ }
129
+
130
+ return parsedLabels;
131
+ }
132
+
112
133
  get isWorker() {
113
134
  return this.managementNode ? this.managementNode.isWorker : `${ this.labels[NODE_ROLES.WORKER] }` === 'true';
114
135
  }
@@ -98,10 +98,12 @@ export default class CapiMachine extends SteveModel {
98
98
  return false;
99
99
  }
100
100
 
101
- openSsh() {
101
+ openSsh(name) {
102
+ const label = name || this.nameDisplay;
103
+
102
104
  this.$dispatch('wm/open', {
103
105
  id: `${ this.id }-ssh`,
104
- label: this.nameDisplay,
106
+ label,
105
107
  icon: 'terminal',
106
108
  component: 'MachineSsh',
107
109
  attrs: { machine: this, pod: {} }
@@ -21,4 +21,11 @@ export default class CRTB extends NormanModel {
21
21
  get clusterroletemplatebinding() {
22
22
  return this.$rootGetters[`management/byId`](MANAGEMENT.CLUSTER_ROLE_TEMPLATE_BINDING, this.id?.replace(':', '/'));
23
23
  }
24
+
25
+ get steve() {
26
+ return this.$dispatch(`management/find`, {
27
+ type: MANAGEMENT.CLUSTER_ROLE_TEMPLATE_BINDING,
28
+ id: this.id?.replace(':', '/')
29
+ }, { root: true });
30
+ }
24
31
  }
@@ -9,15 +9,20 @@ export const ENFORCEMENT_ACTION_VALUES = {
9
9
  export default class GateKeeperConstraint extends SteveModel {
10
10
  async save() {
11
11
  let constraint;
12
+ let resourceVersion;
12
13
 
13
14
  if (this.constraint) {
14
15
  constraint = await this.findLatestConstraint();
16
+ resourceVersion = constraint?.metadata?.resourceVersion;
15
17
  } else {
16
18
  constraint = await this.$dispatch('cluster/create', { type: `constraints.gatekeeper.sh.${ this.kind.toLowerCase() }` }, { root: true });
17
19
  }
18
20
 
19
21
  constraint.spec = this.spec;
20
22
  constraint.metadata = this.metadata;
23
+ if (resourceVersion) {
24
+ constraint.metadata.resourceVersion = resourceVersion;
25
+ }
21
26
 
22
27
  await constraint.save();
23
28
  }
@@ -50,6 +55,10 @@ export default class GateKeeperConstraint extends SteveModel {
50
55
  }, { root: true });
51
56
  }
52
57
 
58
+ get totalViolations() {
59
+ return this.status?.totalViolations || this.violations.length;
60
+ }
61
+
53
62
  get violations() {
54
63
  const violations = this.status?.violations || [];
55
64
 
@@ -1,8 +1,9 @@
1
1
  import { MANAGEMENT, NORMAN } from '@shell/config/types';
2
+ import { CAPI, FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
3
+ import { _RKE2 } from '@shell/store/prefs';
4
+ import SteveModel from '@shell/plugins/steve/steve-class';
2
5
  import { escapeHtml } from '@shell/utils/string';
3
6
  import { insertAt } from '@shell/utils/array';
4
- import { FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
5
- import SteveModel from '@shell/plugins/steve/steve-class';
6
7
 
7
8
  export default class FleetCluster extends SteveModel {
8
9
  get _availableActions() {
@@ -32,14 +33,16 @@ export default class FleetCluster extends SteveModel {
32
33
  enabled: !!this.links.update
33
34
  });
34
35
 
35
- insertAt(out, 3, {
36
- action: 'assignTo',
37
- label: 'Change workspace',
38
- icon: 'icon icon-copy',
39
- bulkable: true,
40
- bulkAction: 'assignToBulk',
41
- enabled: !!this.links.update && !!this.mgmt,
42
- });
36
+ if (!this.isRke2) {
37
+ insertAt(out, 3, {
38
+ action: 'assignTo',
39
+ label: 'Change workspace',
40
+ icon: 'icon icon-copy',
41
+ bulkable: true,
42
+ bulkAction: 'assignToBulk',
43
+ enabled: !!this.links.update && !!this.mgmt,
44
+ });
45
+ }
43
46
 
44
47
  insertAt(out, 4, { divider: true });
45
48
 
@@ -75,6 +78,12 @@ export default class FleetCluster extends SteveModel {
75
78
  return false;
76
79
  }
77
80
 
81
+ get isRke2() {
82
+ const provider = this?.metadata?.labels?.[CAPI.PROVIDER] || this?.status?.provider;
83
+
84
+ return provider === _RKE2;
85
+ }
86
+
78
87
  get nameDisplay() {
79
88
  return this.metadata?.labels?.[FLEET_LABELS.CLUSTER_DISPLAY_NAME] || this.metadata?.name || this.id;
80
89
  }
@@ -96,9 +96,8 @@ export default class GitRepo extends SteveModel {
96
96
  const workspace = this.$getters['byId'](FLEET.WORKSPACE, this.metadata.namespace);
97
97
  const clusters = workspace?.clusters || [];
98
98
  const groups = workspace?.clusterGroups || [];
99
- const out = [];
100
99
 
101
- if ( workspace.id === 'fleet-local' ) {
100
+ if ( workspace?.id === 'fleet-local' ) {
102
101
  const local = findBy(groups, 'id', 'fleet-local/default');
103
102
 
104
103
  if ( local ) {
@@ -108,6 +107,12 @@ export default class GitRepo extends SteveModel {
108
107
  return [];
109
108
  }
110
109
 
110
+ if (!this.spec.targets) {
111
+ return [];
112
+ }
113
+
114
+ const out = [];
115
+
111
116
  for ( const tgt of this.spec.targets ) {
112
117
  if ( tgt.clusterName ) {
113
118
  const cluster = findBy(clusters, 'metadata.name', tgt.clusterName);
@@ -196,7 +196,7 @@ export default class MgmtCluster extends HybridModel {
196
196
  }
197
197
 
198
198
  get kubernetesVersionExtension() {
199
- if ( this.kubernetesVersion.match(/[+-]]/) ) {
199
+ if ( this.kubernetesVersion.match(/[+-]/) ) {
200
200
  return this.kubernetesVersion.replace(/^.*([+-])/, '$1');
201
201
  }
202
202
 
@@ -66,6 +66,18 @@ export default class Workspace extends HybridModel {
66
66
  await norman.save();
67
67
  }
68
68
 
69
+ waitForWorkspaceSchema(timeout = 20000, schemaCallback) {
70
+ return this.waitForTestFn(() => {
71
+ const schema = this.$rootGetters['management/schemaFor'](FLEET.WORKSPACE);
72
+
73
+ if (!schemaCallback) {
74
+ return schema;
75
+ }
76
+
77
+ return schemaCallback(schema);
78
+ }, this.$rootGetters['i18n/t']('fleet.workspaces.timeout'), timeout);
79
+ }
80
+
69
81
  async remove() {
70
82
  const norman = await this.norman;
71
83
 
@@ -0,0 +1,5 @@
1
+ import SteveModel from '@shell/plugins/steve/steve-class';
2
+
3
+ export default class GitRepoRestriction extends SteveModel {
4
+
5
+ }
@@ -0,0 +1,3 @@
1
+ import SteveDescriptionModel from '@shell/plugins/steve/steve-description-class';
2
+
3
+ export default class PodSecurityAdmissionTemplate extends SteveDescriptionModel { }
@@ -187,11 +187,7 @@ export default class Namespace extends SteveModel {
187
187
  }
188
188
 
189
189
  get _detailLocation() {
190
- let _detailLocation = super._detailLocation;
191
-
192
- if (this.$rootGetters['currentProduct'].hideNamespaceLocation) {
193
- _detailLocation = false;
194
- }
190
+ const _detailLocation = super._detailLocation;
195
191
 
196
192
  return _detailLocation;
197
193
  }
@@ -260,4 +256,8 @@ export default class Namespace extends SteveModel {
260
256
  this.metadata.labels[PROJECT] = project;
261
257
  }
262
258
  }
259
+
260
+ get hideDetailLocation() {
261
+ return !!this.$rootGetters['currentProduct'].hideNamespaceLocation;
262
+ }
263
263
  }
@@ -103,7 +103,7 @@ export default class ProvCluster extends SteveModel {
103
103
  const clusterTemplatesSchema = this.$getters['schemaFor']('management.cattle.io.clustertemplate');
104
104
  let canUpdateClusterTemplate = false;
105
105
 
106
- if (clusterTemplatesSchema && (clusterTemplatesSchema.resourceMethods.includes('blocked-PUT') || clusterTemplatesSchema.resourceMethods.includes('PUT'))) {
106
+ if (clusterTemplatesSchema && (clusterTemplatesSchema.resourceMethods?.includes('blocked-PUT') || clusterTemplatesSchema.resourceMethods?.includes('PUT'))) {
107
107
  canUpdateClusterTemplate = true;
108
108
  }
109
109
 
@@ -272,7 +272,7 @@ export default class ProvCluster extends SteveModel {
272
272
  }
273
273
 
274
274
  get mgmtClusterId() {
275
- return this.mgmt?.id || this.id.replace(`${ this.metadata.namespace }/`, '');
275
+ return this.mgmt?.id || this.id?.replace(`${ this.metadata.namespace }/`, '');
276
276
  }
277
277
 
278
278
  get mgmt() {
@@ -291,8 +291,10 @@ export default class ProvCluster extends SteveModel {
291
291
  return !!this.mgmt?.isReady;
292
292
  }
293
293
 
294
+ // nodeGroups can be undefined for an EKS cluster that has just been created and has not
295
+ // had any node groups added to it
294
296
  get eksNodeGroups() {
295
- return this.mgmt?.spec?.eksConfig?.nodeGroups;
297
+ return this.mgmt?.spec?.eksConfig?.nodeGroups || [];
296
298
  }
297
299
 
298
300
  waitForProvisioner(timeout, interval) {
@@ -457,9 +459,9 @@ export default class ProvCluster extends SteveModel {
457
459
  return names.join('<br>');
458
460
  } else {
459
461
  const names = this.machines.filter((machine) => {
460
- return machine.status.conditions.find(c => c.error && c.type === 'NodeHealthy');
462
+ return machine.status?.conditions?.find(c => c.error && c.type === 'NodeHealthy');
461
463
  }).map((machine) => {
462
- if (machine.status.nodeRef?.name) {
464
+ if (machine.status?.nodeRef?.name) {
463
465
  return this.t('cluster.availabilityWarnings.node', { name: machine.status.nodeRef.name });
464
466
  }
465
467