@rancher/shell 3.0.0 → 3.0.1-rc.2

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 (92) hide show
  1. package/assets/brand/harvester/favicon.png +0 -0
  2. package/assets/brand/harvester/metadata.json +3 -0
  3. package/assets/images/pl/harvester.svg +1 -0
  4. package/assets/translations/en-us.yaml +26 -8
  5. package/assets/translations/zh-hans.yaml +1 -1
  6. package/components/BrandImage.vue +5 -1
  7. package/components/CopyToClipboardText.vue +2 -0
  8. package/components/CruResourceFooter.vue +1 -0
  9. package/components/DetailTop.vue +1 -1
  10. package/components/ExplorerMembers.vue +5 -1
  11. package/components/ExplorerProjectsNamespaces.vue +39 -15
  12. package/components/HardwareResourceGauge.vue +12 -2
  13. package/components/InputOrDisplay.vue +6 -2
  14. package/components/LandingPagePreference.vue +2 -2
  15. package/components/MessageLink.vue +1 -1
  16. package/components/ResourceDetail/Masthead.vue +22 -1
  17. package/components/ResourceDetail/index.vue +2 -8
  18. package/components/ResourceTable.vue +14 -6
  19. package/components/ResourceYaml.vue +1 -1
  20. package/components/SideNav.vue +6 -4
  21. package/components/TableDataUserIcon.vue +1 -1
  22. package/components/fleet/FleetRepos.vue +0 -7
  23. package/components/form/ArrayList.vue +5 -1
  24. package/components/form/ArrayListSelect.vue +5 -1
  25. package/components/form/KeyValue.vue +1 -1
  26. package/components/form/LabeledSelect.vue +26 -6
  27. package/components/form/Password.vue +7 -1
  28. package/components/form/UnitInput.vue +10 -1
  29. package/components/form/__tests__/UnitInput.test.ts +1 -0
  30. package/components/formatter/ClusterProvider.vue +3 -3
  31. package/components/formatter/ImagePercentageBar.vue +1 -1
  32. package/components/formatter/Si.vue +5 -1
  33. package/components/formatter/Translate.vue +1 -1
  34. package/components/nav/Header.vue +29 -5
  35. package/components/nav/NamespaceFilter.vue +5 -8
  36. package/components/nav/TopLevelMenu.vue +16 -14
  37. package/config/labels-annotations.js +2 -0
  38. package/config/table-headers.js +15 -0
  39. package/config/types.js +3 -0
  40. package/detail/fleet.cattle.io.bundle.vue +5 -68
  41. package/detail/fleet.cattle.io.gitrepo.vue +2 -1
  42. package/directives/clean-tooltip.js +4 -4
  43. package/edit/constraints.gatekeeper.sh.constraint/index.vue +5 -2
  44. package/edit/logging-flow/Match.vue +75 -42
  45. package/edit/logging-flow/index.vue +89 -10
  46. package/edit/logging.banzaicloud.io.output/index.vue +2 -2
  47. package/edit/management.cattle.io.project.vue +2 -2
  48. package/edit/namespace.vue +1 -1
  49. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +17 -7
  50. package/edit/provisioning.cattle.io.cluster/index.vue +2 -1
  51. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -3
  52. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +20 -6
  53. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +1 -1
  54. package/list/harvesterhci.io.management.cluster.vue +244 -0
  55. package/list/namespace.vue +16 -4
  56. package/models/__tests__/management.cattle.io.cluster.test.ts +45 -3
  57. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -86
  58. package/models/fleet.cattle.io.bundle.js +3 -1
  59. package/models/fleet.cattle.io.gitrepo.js +46 -48
  60. package/models/k8s.cni.cncf.io.networkattachmentdefinition.js +88 -0
  61. package/models/management.cattle.io.cluster.js +26 -5
  62. package/models/management.cattle.io.setting.js +25 -0
  63. package/models/provisioning.cattle.io.cluster.js +5 -14
  64. package/models/storage.k8s.io.storageclass.js +15 -4
  65. package/package.json +8 -6
  66. package/pages/auth/login.vue +8 -2
  67. package/pages/auth/setup.vue +1 -1
  68. package/pages/c/_cluster/fleet/index.vue +2 -4
  69. package/pages/c/_cluster/settings/brand.vue +4 -1
  70. package/pages/prefs.vue +22 -10
  71. package/plugins/dashboard-store/resource-class.js +11 -3
  72. package/plugins/steve/steve-pagination-utils.ts +1 -1
  73. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -2
  74. package/scripts/extension/parse-tag-name +19 -12
  75. package/scripts/publish-shell.sh +10 -2
  76. package/scripts/test-plugins-build.sh +8 -9
  77. package/scripts/typegen.sh +2 -0
  78. package/store/features.js +1 -0
  79. package/store/i18n.js +5 -1
  80. package/store/prefs.js +8 -0
  81. package/types/resources/fleet.d.ts +40 -0
  82. package/types/shell/index.d.ts +524 -396
  83. package/utils/auth.js +1 -1
  84. package/utils/create-yaml.js +1 -1
  85. package/utils/favicon.js +2 -0
  86. package/utils/fleet.ts +159 -0
  87. package/utils/gc/gc.ts +1 -1
  88. package/utils/v-sphere.ts +31 -0
  89. package/utils/validators/cron-schedule.js +1 -1
  90. package/utils/validators/formRules/index.ts +1 -1
  91. package/utils/version.js +1 -1
  92. package/vue.config.js +2 -2
package/utils/auth.js CHANGED
@@ -116,7 +116,7 @@ export const checkSchemasForFindAllHash = (types, store) => {
116
116
  const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema;
117
117
 
118
118
  if (validSchema) {
119
- hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type } );
119
+ hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type, opt: value.opt } );
120
120
  }
121
121
  }
122
122
 
@@ -176,7 +176,7 @@ export function createYaml(
176
176
  }
177
177
 
178
178
  // ACTIVELY_REMOVE are fields that should be removed even if they are defined in data
179
- for ( const entry of ACTIVELY_REMOVE ) {
179
+ for ( const entry of (dataOptions.activelyRemove || ACTIVELY_REMOVE) ) {
180
180
  const parts = entry.split(/\./);
181
181
  const key = parts[parts.length - 1];
182
182
  const prefix = parts.slice(0, -1).join('.');
package/utils/favicon.js CHANGED
@@ -19,6 +19,8 @@ export function setFavIcon(store) {
19
19
  brandImage = require('~shell/assets/brand/suse/favicon.png');
20
20
  } else if (brandSetting?.value === 'csp') {
21
21
  brandImage = require('~shell/assets/brand/csp/favicon.png');
22
+ } else if (brandSetting?.value === 'harvester') {
23
+ brandImage = require('~shell/assets/brand/harvester/favicon.png');
22
24
  }
23
25
 
24
26
  link.href = res?.value || brandImage || defaultFavIcon;
package/utils/fleet.ts ADDED
@@ -0,0 +1,159 @@
1
+ import {
2
+ BundleDeploymentResource,
3
+ BundleResourceKey,
4
+ BundleDeploymentStatus,
5
+ BundleStatus,
6
+ } from '@shell/types/resources/fleet';
7
+ import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
8
+ import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
9
+
10
+ interface Resource extends BundleDeploymentResource {
11
+ state: string,
12
+ }
13
+
14
+ type Labels = {
15
+ [key: string]: string,
16
+ }
17
+
18
+ interface StatesCounter { [state: string]: number }
19
+
20
+ function incr(counter: StatesCounter, state: string) {
21
+ if (!counter[state]) {
22
+ counter[state] = 0;
23
+ }
24
+ counter[state]++;
25
+ }
26
+
27
+ function resourceKey(r: BundleResourceKey): string {
28
+ return `${ r.kind }/${ r.namespace }/${ r.name }`;
29
+ }
30
+
31
+ class Fleet {
32
+ resourceId(r: BundleResourceKey): string {
33
+ return r.namespace ? `${ r.namespace }/${ r.name }` : r.name;
34
+ }
35
+
36
+ /**
37
+ * resourceType normalizes APIVersion and Kind from a Resources into a single string
38
+ */
39
+ resourceType(r: Resource): string {
40
+ // ported from https://github.com/rancher/fleet/blob/v0.10.0/internal/cmd/controller/grutil/resourcekey.go#L116-L128
41
+ const type = r.kind.toLowerCase();
42
+
43
+ if (!r.apiVersion || r.apiVersion === 'v1') {
44
+ return type;
45
+ }
46
+
47
+ return `${ r.apiVersion.split('/', 2)[0] }.${ type }`;
48
+ }
49
+
50
+ /**
51
+ * resourcesFromBundleDeploymentStatus extracts the list of resources deployed by a BundleDeployment
52
+ */
53
+ resourcesFromBundleDeploymentStatus(status: BundleDeploymentStatus): Resource[] {
54
+ // status.resources includes of resources that were deployed by Fleet *and still exist in the cluster*
55
+ // Use a map to avoid `find` over and over again
56
+ const resources = (status?.resources || []).reduce((res, r) => {
57
+ res[resourceKey(r)] = Object.assign({ state: STATES_ENUM.READY }, r);
58
+
59
+ return res;
60
+ }, {} as { [resourceKey: string]: Resource });
61
+
62
+ const modified: Resource[] = [];
63
+
64
+ for (const r of status?.modifiedStatus || []) {
65
+ const state = r.missing ? STATES_ENUM.MISSING : r.delete ? STATES_ENUM.ORPHANED : STATES_ENUM.MODIFIED;
66
+ const found: Resource = resources[resourceKey(r)];
67
+
68
+ // Depending on the state, the same resource can appear in both fields
69
+ if (found) {
70
+ found.state = state;
71
+ } else {
72
+ modified.push(Object.assign({ state }, r));
73
+ }
74
+ }
75
+ for (const r of status?.nonReadyStatus || []) {
76
+ const state = r.summary?.state || STATES_ENUM.UNKNOWN;
77
+ const found: Resource = resources[resourceKey(r)];
78
+
79
+ if (found) {
80
+ found.state = state;
81
+ }
82
+ }
83
+
84
+ return modified.concat(Object.values(resources));
85
+ }
86
+
87
+ /**
88
+ * resourcesFromBundleStatus extracts the list of resources deployed by a Bundle
89
+ */
90
+ resourcesFromBundleStatus(status: BundleStatus): Resource[] {
91
+ // The state of every resource is spread all over the bundle status.
92
+ // resourceKey contains one entry per resource AND cluster (built by Fleet from all the child BundleDeployments).
93
+ // However, those entries do not contain the cluster that they belong to, leading to duplicate entries
94
+
95
+ // 1. Fold resourceKey by using a unique key, initializing counters for multiple occurrences of the same resource
96
+ const resources = (status.resourceKey || []).reduce((res, r) => {
97
+ const k = resourceKey(r);
98
+
99
+ if (!res[k]) {
100
+ res[k] = { r, count: {} };
101
+ }
102
+ incr(res[k].count, STATES_ENUM.READY);
103
+
104
+ return res;
105
+ }, {} as { [resourceKey: string]: { r: BundleResourceKey, count: StatesCounter } });
106
+
107
+ // 2. Non-ready resources are counted differently and may also appear in resourceKey, depending on their state
108
+ for (const bundle of status.summary?.nonReadyResources || []) {
109
+ for (const r of bundle.modifiedStatus || []) {
110
+ const k = resourceKey(r);
111
+
112
+ if (!resources[k]) {
113
+ resources[k] = { r, count: {} };
114
+ }
115
+
116
+ if (r.missing) {
117
+ incr(resources[k].count, STATES_ENUM.MISSING);
118
+ } else if (r.delete) {
119
+ resources[k].count[STATES_ENUM.READY]--;
120
+ incr(resources[k].count, STATES_ENUM.ORPHANED);
121
+ } else {
122
+ resources[k].count[STATES_ENUM.READY]--;
123
+ incr(resources[k].count, STATES_ENUM.MODIFIED);
124
+ }
125
+ }
126
+ for (const r of bundle.nonReadyStatus || []) {
127
+ const k = resourceKey(r);
128
+ const state = r.summary?.state || STATES_ENUM.UNKNOWN;
129
+
130
+ resources[k].count[STATES_ENUM.READY]--;
131
+ incr(resources[k].count, state);
132
+ }
133
+ }
134
+
135
+ // 3. Unfold back to an array of resources for display
136
+ return Object.values(resources).reduce((res, e) => {
137
+ const { r, count } = e;
138
+
139
+ for (const state in count) {
140
+ for (let x = 0; x < count[state]; x++) {
141
+ res.push(Object.assign({ state }, r));
142
+ }
143
+ }
144
+
145
+ return res;
146
+ }, [] as Resource[]);
147
+ }
148
+
149
+ clusterIdFromBundleDeploymentLabels(labels?: Labels): string {
150
+ const clusterNamespace = labels?.[FLEET_ANNOTATIONS.CLUSTER_NAMESPACE];
151
+ const clusterName = labels?.[FLEET_ANNOTATIONS.CLUSTER];
152
+
153
+ return `${ clusterNamespace }/${ clusterName }`;
154
+ }
155
+ }
156
+
157
+ const instance = new Fleet();
158
+
159
+ export default instance;
package/utils/gc/gc.ts CHANGED
@@ -29,7 +29,7 @@ class GarbageCollect {
29
29
  * To avoid JSON.parse on the `ui-performance` setting keep a local cache
30
30
  */
31
31
  private getUiPerfGarbageCollection = (rootState: any) => {
32
- const uiPerfSetting = rootState.management.types[MANAGEMENT.SETTING]?.list.find((s: any) => s.id === SETTING.UI_PERFORMANCE);
32
+ const uiPerfSetting = rootState.management.types[MANAGEMENT.SETTING]?.list?.find((s: any) => s.id === SETTING.UI_PERFORMANCE);
33
33
 
34
34
  if (!uiPerfSetting || !uiPerfSetting.value) {
35
35
  // Could be in the process of logging out
package/utils/v-sphere.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import merge from 'lodash/merge';
2
2
  import { SECRET } from '@shell/config/types';
3
+ import { PROVISIONING_PRE_BOOTSTRAP } from '@shell/store/features';
4
+
5
+ export const VMWARE_VSPHERE = 'vmwarevsphere';
3
6
 
4
7
  type Rke2Component = {
5
8
  versionInfo: any;
@@ -7,6 +10,7 @@ type Rke2Component = {
7
10
  chartVersionKey: (chartName: string) => string;
8
11
  value: any;
9
12
  isEdit: boolean;
13
+ provider: string;
10
14
  $store: any,
11
15
  }
12
16
 
@@ -91,10 +95,33 @@ class VSphereUtils {
91
95
  };
92
96
  }
93
97
 
98
+ /**
99
+ * Check that system is setup to handle vsphere secrets syncing downstream
100
+ *
101
+ * Do this via checking the provider and that the required FF is enabled.
102
+ */
103
+ private handleVsphereSecret({ $store, provider }: { $store: any, provider: string}): boolean {
104
+ if (provider !== VMWARE_VSPHERE) {
105
+ return false;
106
+ }
107
+
108
+ const isPrebootstrapEnabled = $store.getters['features/get'](PROVISIONING_PRE_BOOTSTRAP);
109
+
110
+ if (!isPrebootstrapEnabled) {
111
+ return false;
112
+ }
113
+
114
+ return true;
115
+ }
116
+
94
117
  /**
95
118
  * Create upstream vsphere cpi secret to sync downstream
96
119
  */
97
120
  async handleVsphereCpiSecret(rke2Component: Rke2Component) {
121
+ if (!this.handleVsphereSecret(rke2Component)) {
122
+ return;
123
+ }
124
+
98
125
  const generateName = `${ rootGenerateName }cpi-`;
99
126
  const downstreamName = 'rancher-vsphere-cpi-credentials';
100
127
  const downstreamNamespace = 'kube-system';
@@ -168,6 +195,10 @@ class VSphereUtils {
168
195
  * Create upstream vsphere csi secret to sync downstream
169
196
  */
170
197
  async handleVsphereCsiSecret(rke2Component: Rke2Component) {
198
+ if (!this.handleVsphereSecret(rke2Component)) {
199
+ return;
200
+ }
201
+
171
202
  const generateName = `${ rootGenerateName }csi-`;
172
203
  const downstreamName = 'rancher-vsphere-csi-credentials';
173
204
  const downstreamNamespace = 'kube-system';
@@ -2,7 +2,7 @@ import cronstrue from 'cronstrue';
2
2
 
3
3
  export function cronSchedule(schedule = '', getters, errors) {
4
4
  try {
5
- cronstrue.toString(schedule);
5
+ cronstrue.toString(schedule, { verbose: true });
6
6
  } catch (e) {
7
7
  errors.push(getters['i18n/t']('validation.invalidCron'));
8
8
  }
@@ -131,7 +131,7 @@ export default function(t: Translation, { key = 'Value' }: ValidationOptions): {
131
131
 
132
132
  const cronSchedule: Validator = (val: string) => {
133
133
  try {
134
- cronstrue.toString(val);
134
+ cronstrue.toString(val, { verbose: true });
135
135
  } catch (e) {
136
136
  return t('validation.invalidCron');
137
137
  }
package/utils/version.js CHANGED
@@ -66,7 +66,7 @@ function comparePart(in1, in2) {
66
66
  return in1.localeCompare(in2);
67
67
  }
68
68
 
69
- export function isPrerelease(version) {
69
+ export function isPrerelease(version = '') {
70
70
  if (!semver.valid(version)) {
71
71
  version = semver.clean(version, { loose: true });
72
72
  }
package/vue.config.js CHANGED
@@ -131,11 +131,11 @@ const instrumentCode = () => {
131
131
  };
132
132
 
133
133
  const getLoaders = (SHELL_ABS) => [
134
- // Ensure there is a fallback for browsers that don't support web workers
134
+ // no fallback for pre-2013 browsers https://caniuse.com/webworkers
135
135
  {
136
136
  test: /web-worker.[a-z-]+.js/i,
137
137
  loader: 'worker-loader',
138
- options: { inline: 'fallback' },
138
+ options: { inline: 'no-fallback' },
139
139
  },
140
140
  // Handler for csv files (e.g. ec2 instance data)
141
141
  {