@rancher/shell 2.0.2 → 2.0.3

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 (36) hide show
  1. package/assets/translations/en-us.yaml +9 -1
  2. package/components/ResourceDetail/index.vue +2 -1
  3. package/components/SideNav.vue +1 -1
  4. package/components/TableDataUserIcon.vue +1 -1
  5. package/components/fleet/FleetRepos.vue +0 -7
  6. package/components/formatter/ClusterProvider.vue +3 -3
  7. package/components/nav/TopLevelMenu.vue +12 -12
  8. package/config/labels-annotations.js +1 -0
  9. package/core/types-provisioning.ts +5 -0
  10. package/core/types.ts +26 -1
  11. package/detail/fleet.cattle.io.bundle.vue +5 -68
  12. package/detail/fleet.cattle.io.gitrepo.vue +2 -1
  13. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +109 -24
  14. package/edit/provisioning.cattle.io.cluster/index.vue +10 -4
  15. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -3
  16. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +1 -0
  17. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +177 -26
  18. package/models/__tests__/management.cattle.io.cluster.test.ts +3 -3
  19. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -86
  20. package/models/fleet.cattle.io.bundle.js +3 -1
  21. package/models/fleet.cattle.io.gitrepo.js +46 -48
  22. package/models/management.cattle.io.cluster.js +2 -5
  23. package/models/provisioning.cattle.io.cluster.js +25 -12
  24. package/package.json +1 -1
  25. package/pages/c/_cluster/fleet/index.vue +1 -0
  26. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +0 -2
  27. package/scripts/extension/parse-tag-name +21 -12
  28. package/scripts/publish-shell.sh +7 -0
  29. package/scripts/typegen.sh +3 -1
  30. package/store/features.js +1 -0
  31. package/types/resources/fleet.d.ts +40 -0
  32. package/types/shell/index.d.ts +97 -0
  33. package/utils/auth.js +1 -1
  34. package/utils/fleet.ts +159 -0
  35. package/utils/v-sphere.ts +31 -0
  36. package/vue.config.js +3 -3
@@ -64,6 +64,13 @@ function publish() {
64
64
  PUBLISH_ARGS="$PUBLISH_ARGS --tag legacy-v2"
65
65
  fi
66
66
 
67
+ # when testing the workflow, we don't want to actually do an npm publish but only a dry run
68
+ if [ ${DRY_RUN} == "true" ]; then
69
+ PUBLISH_ARGS="$PUBLISH_ARGS --dry-run"
70
+ fi
71
+
72
+ echo "Publish to NPM - arguments ::: ${PUBLISH_ARGS}"
73
+
67
74
  # Make a note of dependency versions, if required
68
75
  node ${SCRIPT_DIR}/record-deps.js
69
76
 
@@ -31,9 +31,11 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/normalize
31
31
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/resource-class.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
32
32
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/classify.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
33
33
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/actions.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
34
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/steve/steve-class.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/steve/ > /dev/null
34
35
 
35
36
  # # mixins
36
37
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/create-edit-view/index.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins/create-edit-view > /dev/null
38
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
37
39
 
38
40
  # # models
39
41
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/models/namespace.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/models/ > /dev/null
@@ -93,4 +95,4 @@ function processDir() {
93
95
 
94
96
  processDir ${SHELL_DIR}/tmp @shell
95
97
 
96
- rm -rf ${SHELL_DIR}/tmp
98
+ rm -rf ${SHELL_DIR}/tmp
package/store/features.js CHANGED
@@ -35,6 +35,7 @@ export const HARVESTER_CONTAINER = create('harvester-baremetal-container-workloa
35
35
  export const FLEET_WORKSPACE_BACK = create('provisioningv2-fleet-workspace-back-population', false);
36
36
  export const STEVE_CACHE = create('ui-sql-cache', false);
37
37
  export const UIEXTENSION = create('uiextension', true);
38
+ export const PROVISIONING_PRE_BOOTSTRAP = create('provisioningprebootstrap', false);
38
39
 
39
40
  // Not currently used.. no point defining ones we don't use
40
41
  // export const EMBEDDED_CLUSTER_API = create('embedded-cluster-api', true);
@@ -0,0 +1,40 @@
1
+ export interface BundleResourceKey {
2
+ kind: string,
3
+ apiVersion: string,
4
+ namespace?: string,
5
+ name: string,
6
+ }
7
+
8
+ export interface BundleDeploymentResource extends BundleResourceKey {
9
+ createdAt?: string,
10
+ }
11
+
12
+ export interface BundleModifiedResource extends BundleResourceKey {
13
+ missing?: boolean,
14
+ delete?: boolean,
15
+ patch: string,
16
+ }
17
+
18
+ export interface BundleNonReadyResource extends BundleResourceKey {
19
+ summary: { [state: string]: string }
20
+ }
21
+
22
+ export interface BundleNonReadyBundle {
23
+ modifiedStatus: BundleModifiedResource[],
24
+ nonReadyStatus: BundleNonReadyResource[],
25
+ }
26
+
27
+ export interface BundleDeploymentStatus {
28
+ resources?: BundleDeploymentResource[],
29
+ modifiedStatus?: BundleModifiedResource[],
30
+ nonReadyStatus?: BundleNonReadyResource[],
31
+ }
32
+
33
+ export interface BundleStatusSummary {
34
+ nonReadyResources?: BundleNonReadyBundle[],
35
+ }
36
+
37
+ export interface BundleStatus {
38
+ resourceKey?: BundleResourceKey[],
39
+ summary?: BundleStatusSummary,
40
+ }
@@ -125,6 +125,8 @@ export namespace FLEET {
125
125
  export const BUNDLE_ID: string;
126
126
  const MANAGED_1: string;
127
127
  export { MANAGED_1 as MANAGED };
128
+ const CLUSTER_NAMESPACE_1: string;
129
+ export { CLUSTER_NAMESPACE_1 as CLUSTER_NAMESPACE };
128
130
  export const CLUSTER: string;
129
131
  }
130
132
  export namespace RBAC {
@@ -2328,6 +2330,66 @@ declare var _default: import("vue").DefineComponent<{
2328
2330
  export default _default;
2329
2331
  }
2330
2332
 
2333
+ // @shell/mixins/resource-fetch
2334
+
2335
+ declare module '@shell/mixins/resource-fetch' {
2336
+ declare namespace _default {
2337
+ const mixins: any[];
2338
+ function data(): {
2339
+ perfConfig: {};
2340
+ init: boolean;
2341
+ multipleResources: any[];
2342
+ loadResources: any[];
2343
+ hasManualRefresh: boolean;
2344
+ watch: boolean;
2345
+ isTooManyItemsToAutoUpdate: boolean;
2346
+ force: boolean;
2347
+ incremental: boolean;
2348
+ fetchedResourceType: any[];
2349
+ paginating: any;
2350
+ };
2351
+ function data(): {
2352
+ perfConfig: {};
2353
+ init: boolean;
2354
+ multipleResources: any[];
2355
+ loadResources: any[];
2356
+ hasManualRefresh: boolean;
2357
+ watch: boolean;
2358
+ isTooManyItemsToAutoUpdate: boolean;
2359
+ force: boolean;
2360
+ incremental: boolean;
2361
+ fetchedResourceType: any[];
2362
+ paginating: any;
2363
+ };
2364
+ function beforeDestroy(): void;
2365
+ function beforeDestroy(): void;
2366
+ namespace computed {
2367
+ function rows(): any;
2368
+ function rows(): any;
2369
+ function loading(): any;
2370
+ function loading(): any;
2371
+ const refreshFlag: import("vuex").Computed;
2372
+ }
2373
+ namespace watch {
2374
+ function refreshFlag(neu: any): Promise<void>;
2375
+ function refreshFlag(neu: any): Promise<void>;
2376
+ }
2377
+ namespace methods {
2378
+ function $initializeFetchData(type: any, multipleResources: any[], storeType: any): void;
2379
+ function $initializeFetchData(type: any, multipleResources: any[], storeType: any): void;
2380
+ function $fetchType(type: any, multipleResources: any[], storeType: any): any;
2381
+ function $fetchType(type: any, multipleResources: any[], storeType: any): any;
2382
+ function __getCountForResources(resourceNames: any, namespace: any, storeType: any): any;
2383
+ function __getCountForResources(resourceNames: any, namespace: any, storeType: any): any;
2384
+ function __getCountForResource(resourceName: any, namespace: any, storeType: any): any;
2385
+ function __getCountForResource(resourceName: any, namespace: any, storeType: any): any;
2386
+ function __gatherResourceFetchData(resourceName: any, multipleResources: any, currStore: any): void;
2387
+ function __gatherResourceFetchData(resourceName: any, multipleResources: any, currStore: any): void;
2388
+ }
2389
+ }
2390
+ export default _default;
2391
+ }
2392
+
2331
2393
  // @shell/models/namespace
2332
2394
 
2333
2395
  declare module '@shell/models/namespace' {
@@ -3084,6 +3146,40 @@ export default class Resource {
3084
3146
  }
3085
3147
  }
3086
3148
 
3149
+ // @shell/plugins/steve/hybrid-class
3150
+
3151
+ declare module '@shell/plugins/steve/hybrid-class' {
3152
+ export function cleanHybridResources(data: any): any;
3153
+ export default class HybridModel {
3154
+ constructor(data: any, ctx: any, rehydrateNamespace?: any, setClone?: boolean);
3155
+ get labels(): any;
3156
+ setLabels(val: any): void;
3157
+ metadata: {};
3158
+ setLabel(key: any, val: any): void;
3159
+ get annotations(): any;
3160
+ setAnnotations(val: any): void;
3161
+ setAnnotation(key: any, val: any): void;
3162
+ get state(): any;
3163
+ }
3164
+ }
3165
+
3166
+ // @shell/plugins/steve/steve-class
3167
+
3168
+ declare module '@shell/plugins/steve/steve-class' {
3169
+ export default class SteveModel extends HybridModel {
3170
+ get name(): any;
3171
+ get namespace(): any;
3172
+ /**
3173
+ * Set description based on the type of model available with private fallback
3174
+ */
3175
+ set description(arg: any);
3176
+ get description(): any;
3177
+ _description: any;
3178
+ cleanForSave(data: any, forNew: any): any;
3179
+ }
3180
+ import HybridModel from "./hybrid-class";
3181
+ }
3182
+
3087
3183
  // @shell/store/features
3088
3184
 
3089
3185
  declare module '@shell/store/features' {
@@ -3103,6 +3199,7 @@ export const HARVESTER_CONTAINER: any;
3103
3199
  export const FLEET_WORKSPACE_BACK: any;
3104
3200
  export const STEVE_CACHE: any;
3105
3201
  export const UIEXTENSION: any;
3202
+ export const PROVISIONING_PRE_BOOTSTRAP: any;
3106
3203
  export namespace getters {
3107
3204
  function get(state: any, getters: any, rootState: any, rootGetters: any): (name: any) => any;
3108
3205
  }
package/utils/auth.js CHANGED
@@ -99,7 +99,7 @@ export const checkSchemasForFindAllHash = (types, store) => {
99
99
  const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema;
100
100
 
101
101
  if (validSchema) {
102
- hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type } );
102
+ hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type, opt: value.opt } );
103
103
  }
104
104
  }
105
105
 
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/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
 
@@ -88,10 +92,33 @@ class VSphereUtils {
88
92
  };
89
93
  }
90
94
 
95
+ /**
96
+ * Check that system is setup to handle vsphere secrets syncing downstream
97
+ *
98
+ * Do this via checking the provider and that the required FF is enabled.
99
+ */
100
+ private handleVsphereSecret({ $store, provider }: { $store: any, provider: string}): boolean {
101
+ if (provider !== VMWARE_VSPHERE) {
102
+ return false;
103
+ }
104
+
105
+ const isPrebootstrapEnabled = $store.getters['features/get'](PROVISIONING_PRE_BOOTSTRAP);
106
+
107
+ if (!isPrebootstrapEnabled) {
108
+ return false;
109
+ }
110
+
111
+ return true;
112
+ }
113
+
91
114
  /**
92
115
  * Create upstream vsphere cpi secret to sync downstream
93
116
  */
94
117
  async handleVsphereCpiSecret(rke2Component: Rke2Component) {
118
+ if (!this.handleVsphereSecret(rke2Component)) {
119
+ return;
120
+ }
121
+
95
122
  const generateName = `${ rootGenerateName }cpi-`;
96
123
  const downstreamName = 'rancher-vsphere-cpi-credentials';
97
124
  const downstreamNamespace = 'kube-system';
@@ -165,6 +192,10 @@ class VSphereUtils {
165
192
  * Create upstream vsphere csi secret to sync downstream
166
193
  */
167
194
  async handleVsphereCsiSecret(rke2Component: Rke2Component) {
195
+ if (!this.handleVsphereSecret(rke2Component)) {
196
+ return;
197
+ }
198
+
168
199
  const generateName = `${ rootGenerateName }csi-`;
169
200
  const downstreamName = 'rancher-vsphere-csi-credentials';
170
201
  const downstreamNamespace = 'kube-system';
package/vue.config.js CHANGED
@@ -120,11 +120,11 @@ const getLoaders = (SHELL_ABS) => {
120
120
  }
121
121
 
122
122
  return [
123
- // Ensure there is a fallback for browsers that don't support web workers
123
+ // no fallback for pre-2013 browsers https://caniuse.com/webworkers
124
124
  {
125
125
  test: /web-worker.[a-z-]+.js/i,
126
126
  loader: 'worker-loader',
127
- options: { inline: 'fallback' },
127
+ options: { inline: 'no-fallback' },
128
128
  },
129
129
  // Handler for csv files (e.g. ec2 instance data)
130
130
  {
@@ -512,7 +512,7 @@ module.exports = function(dir, _appConfig) {
512
512
  config.resolve.alias['@pkg'] = path.join(dir, 'pkg');
513
513
  config.resolve.alias['./node_modules'] = path.join(dir, 'node_modules');
514
514
  config.resolve.alias['@components'] = COMPONENTS_DIR;
515
- config.resolve.alias['vue$'] = path.resolve(process.cwd(), 'node_modules', 'vue', 'dist', dev ? 'vue.js' : 'vue.min.js');
515
+ config.resolve.alias['vue$'] = path.resolve(process.cwd(), 'node_modules', 'vue', 'dist', 'vue.js');
516
516
  config.resolve.modules.push(__dirname);
517
517
  config.plugins.push(getVirtualModules(dir, includePkg));
518
518
  config.plugins.push(getAutoImport());