@rancher/shell 2.0.2-rc.1 → 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 (59) hide show
  1. package/assets/translations/en-us.yaml +53 -31
  2. package/components/PromptRemove.vue +8 -3
  3. package/components/ResourceDetail/Masthead.vue +1 -0
  4. package/components/ResourceDetail/index.vue +2 -1
  5. package/components/SideNav.vue +1 -1
  6. package/components/TableDataUserIcon.vue +1 -1
  7. package/components/fleet/FleetClusters.vue +0 -3
  8. package/components/fleet/FleetRepos.vue +0 -7
  9. package/components/formatter/CloudCredExpired.vue +69 -0
  10. package/components/formatter/ClusterProvider.vue +3 -3
  11. package/components/formatter/Date.vue +1 -1
  12. package/components/nav/Header.vue +9 -5
  13. package/components/nav/TopLevelMenu.vue +127 -63
  14. package/components/nav/__tests__/TopLevelMenu.test.ts +53 -27
  15. package/config/labels-annotations.js +3 -0
  16. package/core/types-provisioning.ts +5 -0
  17. package/core/types.ts +26 -1
  18. package/detail/catalog.cattle.io.app.vue +17 -4
  19. package/detail/fleet.cattle.io.bundle.vue +5 -68
  20. package/detail/fleet.cattle.io.cluster.vue +11 -9
  21. package/detail/fleet.cattle.io.gitrepo.vue +3 -2
  22. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +109 -24
  23. package/edit/provisioning.cattle.io.cluster/index.vue +10 -4
  24. package/edit/provisioning.cattle.io.cluster/rke2.vue +13 -2
  25. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +1 -0
  26. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +177 -26
  27. package/list/provisioning.cattle.io.cluster.vue +56 -5
  28. package/mixins/chart.js +6 -2
  29. package/models/__tests__/management.cattle.io.cluster.test.ts +3 -3
  30. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -86
  31. package/models/catalog.cattle.io.app.js +108 -21
  32. package/models/cloudcredential.js +159 -2
  33. package/models/fleet.cattle.io.bundle.js +3 -1
  34. package/models/fleet.cattle.io.gitrepo.js +50 -61
  35. package/models/management.cattle.io.cluster.js +15 -7
  36. package/models/provisioning.cattle.io.cluster.js +62 -15
  37. package/package.json +1 -1
  38. package/pages/c/_cluster/apps/charts/install.vue +2 -1
  39. package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
  40. package/pages/c/_cluster/explorer/index.vue +1 -2
  41. package/pages/c/_cluster/fleet/index.vue +12 -5
  42. package/pages/c/_cluster/manager/cloudCredential/index.vue +68 -4
  43. package/pages/c/_cluster/uiplugins/index.vue +4 -2
  44. package/pages/home.vue +1 -0
  45. package/scripts/extension/bundle +1 -1
  46. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +0 -2
  47. package/scripts/extension/parse-tag-name +21 -12
  48. package/scripts/publish-shell.sh +10 -4
  49. package/scripts/typegen.sh +27 -22
  50. package/store/features.js +1 -0
  51. package/types/resources/fleet.d.ts +40 -0
  52. package/types/shell/index.d.ts +4692 -0
  53. package/utils/auth.js +1 -1
  54. package/utils/cluster.js +1 -1
  55. package/utils/fleet.ts +159 -0
  56. package/utils/string.js +9 -0
  57. package/utils/v-sphere.ts +282 -0
  58. package/vue.config.js +3 -3
  59. package/shell/types/shell/index.d.ts +0 -2
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/cluster.js CHANGED
@@ -94,7 +94,7 @@ export function abbreviateClusterName(input) {
94
94
 
95
95
  export function labelForAddon(name, configuration = true) {
96
96
  const addon = camelToTitle(name.replace(/^(rke|rke2|rancher)-/, ''));
97
- const fallback = `${ addon } ${ configuration ? 'Configuration' : '' }`;
97
+ const fallback = `${ configuration ? '' : 'Add-on: ' }${ addon }`;
98
98
  const key = `cluster.addonChart."${ name }"${ configuration ? '.configuration' : '.label' }`;
99
99
 
100
100
  return this.$store.getters['i18n/withFallback'](key, null, fallback);
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/string.js CHANGED
@@ -321,3 +321,12 @@ export function sanitizeValue(v) {
321
321
  export function sanitizeIP(v) {
322
322
  return (v || '').replace(/[^a-z0-9.:_-]/ig, '');
323
323
  }
324
+
325
+ /**
326
+ * Return the string `<x> / <y>`
327
+ *
328
+ * Each param should be a number, otherwise `?` is used
329
+ */
330
+ export function xOfy(x, y) {
331
+ return `${ typeof x === 'number' ? x : '?' }/${ typeof y === 'number' ? y : '?' }`;
332
+ }
@@ -0,0 +1,282 @@
1
+ import merge from 'lodash/merge';
2
+ import { SECRET } from '@shell/config/types';
3
+ import { PROVISIONING_PRE_BOOTSTRAP } from '@shell/store/features';
4
+
5
+ export const VMWARE_VSPHERE = 'vmwarevsphere';
6
+
7
+ type Rke2Component = {
8
+ versionInfo: any;
9
+ userChartValues: any;
10
+ chartVersionKey: (chartName: string) => string;
11
+ value: any;
12
+ isEdit: boolean;
13
+ provider: string;
14
+ $store: any,
15
+ }
16
+
17
+ type SecretDetails = {
18
+ generateName: string,
19
+ upstreamClusterName: string,
20
+ upstreamNamespace: string,
21
+ downstreamName: string,
22
+ downstreamNamespace: string,
23
+ json?: object,
24
+ }
25
+ type Values = any;
26
+
27
+ type ChartValues = {
28
+ defaultValues: Values,
29
+ userValues: Values,
30
+ combined: Values,
31
+ };
32
+
33
+ const rootGenerateName = 'vsphere-secret-';
34
+
35
+ type SecretJson = any;
36
+
37
+ class VSphereUtils {
38
+ private async findSecret(
39
+ { $store }: Rke2Component, {
40
+ generateName, upstreamClusterName, upstreamNamespace, downstreamName, downstreamNamespace
41
+ }: SecretDetails): Promise<SecretJson | undefined> {
42
+ const secrets = await $store.dispatch('management/request', { url: `/v1/${ SECRET }/${ upstreamNamespace }?filter=metadata.name=${ generateName }` });
43
+
44
+ const applicableSecret = secrets.data?.filter((s: any) => {
45
+ return s.metadata.annotations['provisioning.cattle.io/sync-target-namespace'] === downstreamNamespace &&
46
+ s.metadata.annotations['provisioning.cattle.io/sync-target-name'] === downstreamName &&
47
+ s.metadata.annotations['rke.cattle.io/object-authorized-for-clusters'].includes(upstreamClusterName);
48
+ });
49
+
50
+ if (applicableSecret.length > 1) {
51
+ return Promise.reject(new Error(`Found multiple matching secrets (${ upstreamNamespace }/${ upstreamNamespace } for ${ upstreamClusterName }), this will cause synchronizing mishaps. Consider removing stale secrets from old clusters`));
52
+ }
53
+
54
+ return applicableSecret[0];
55
+ }
56
+
57
+ private async findOrCreateSecret(
58
+ rke2Component: Rke2Component,
59
+ {
60
+ generateName, upstreamClusterName, upstreamNamespace, downstreamName, downstreamNamespace, json
61
+ }: SecretDetails
62
+ ) {
63
+ const { $store } = rke2Component;
64
+
65
+ const secretJson = await this.findSecret(rke2Component, {
66
+ generateName,
67
+ upstreamClusterName,
68
+ upstreamNamespace,
69
+ downstreamName,
70
+ downstreamNamespace
71
+ }) || json;
72
+
73
+ return await $store.dispatch('management/create', secretJson);
74
+ }
75
+
76
+ private findChartValues({
77
+ versionInfo,
78
+ userChartValues,
79
+ chartVersionKey,
80
+ }: Rke2Component, chartName: string): ChartValues | undefined {
81
+ const chartValues = versionInfo[chartName]?.values;
82
+
83
+ if (!chartValues) {
84
+ return;
85
+ }
86
+ const userValues = userChartValues[chartVersionKey(chartName)];
87
+
88
+ return {
89
+ defaultValues: chartValues,
90
+ userValues,
91
+ combined: merge({}, chartValues || {}, userValues || {})
92
+ };
93
+ }
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
+
114
+ /**
115
+ * Create upstream vsphere cpi secret to sync downstream
116
+ */
117
+ async handleVsphereCpiSecret(rke2Component: Rke2Component) {
118
+ if (!this.handleVsphereSecret(rke2Component)) {
119
+ return;
120
+ }
121
+
122
+ const generateName = `${ rootGenerateName }cpi-`;
123
+ const downstreamName = 'rancher-vsphere-cpi-credentials';
124
+ const downstreamNamespace = 'kube-system';
125
+ const { value } = rke2Component;
126
+
127
+ // check values for cpi chart has 'use our method' checkbox
128
+ const { userValues, combined } = this.findChartValues(rke2Component, 'rancher-vsphere-cpi') || {};
129
+
130
+ if (!combined?.vCenter?.credentialsSecret?.generate) {
131
+ if (userValues?.vCenter?.username) {
132
+ userValues.vCenter.username = '';
133
+ }
134
+ if (userValues?.vCenter?.password) {
135
+ userValues.vCenter.password = '';
136
+ }
137
+
138
+ return;
139
+ }
140
+
141
+ // find values needed in cpi chart value - https://github.com/rancher/vsphere-charts/blob/main/charts/rancher-vsphere-cpi/questions.yaml#L16-L42
142
+ const { username, password, host } = combined.vCenter;
143
+
144
+ if (!username || !password || !host) {
145
+ throw new Error('vSphere CPI username, password and host are all required when generating a new secret');
146
+ }
147
+
148
+ // create secret as per https://github.com/rancher/vsphere-charts/blob/main/charts/rancher-vsphere-cpi/templates/secret.yaml
149
+ const upstreamClusterName = value.metadata.name;
150
+ const upstreamNamespace = value.metadata.namespace;
151
+ const secret = await this.findOrCreateSecret(rke2Component, {
152
+ generateName,
153
+ upstreamClusterName,
154
+ upstreamNamespace,
155
+ downstreamName,
156
+ downstreamNamespace,
157
+ json: {
158
+ type: SECRET,
159
+ metadata: {
160
+ namespace: upstreamNamespace,
161
+ generateName,
162
+ labels: {
163
+ 'vsphere-cpi-infra': 'secret',
164
+ component: 'rancher-vsphere-cpi-cloud-controller-manager'
165
+ },
166
+ annotations: {
167
+ 'provisioning.cattle.io/sync-target-namespace': downstreamNamespace,
168
+ 'provisioning.cattle.io/sync-target-name': downstreamName,
169
+ 'rke.cattle.io/object-authorized-for-clusters': upstreamClusterName,
170
+ 'provisioning.cattle.io/sync-bootstrap': 'true'
171
+ }
172
+ },
173
+ }
174
+ });
175
+
176
+ secret.setData(`${ host }.username`, username);
177
+ secret.setData(`${ host }.password`, password);
178
+
179
+ await secret.save();
180
+
181
+ // reset cpi chart values
182
+ if (!userValues.vCenter.credentialsSecret) {
183
+ userValues.vCenter.credentialsSecret = {};
184
+ }
185
+ userValues.vCenter.credentialsSecret.generate = false;
186
+ userValues.vCenter.credentialsSecret.name = downstreamName;
187
+ userValues.vCenter.username = '';
188
+ userValues.vCenter.password = '';
189
+ }
190
+
191
+ /**
192
+ * Create upstream vsphere csi secret to sync downstream
193
+ */
194
+ async handleVsphereCsiSecret(rke2Component: Rke2Component) {
195
+ if (!this.handleVsphereSecret(rke2Component)) {
196
+ return;
197
+ }
198
+
199
+ const generateName = `${ rootGenerateName }csi-`;
200
+ const downstreamName = 'rancher-vsphere-csi-credentials';
201
+ const downstreamNamespace = 'kube-system';
202
+ const { value } = rke2Component;
203
+
204
+ // check values for cpi chart has 'use our method' checkbox
205
+ const { userValues, combined } = this.findChartValues(rke2Component, 'rancher-vsphere-csi') || {};
206
+
207
+ if (!combined?.vCenter?.configSecret?.generate) {
208
+ if (userValues?.vCenter?.username) {
209
+ userValues.vCenter.username = '';
210
+ }
211
+ if (userValues?.vCenter?.password) {
212
+ userValues.vCenter.password = '';
213
+ }
214
+
215
+ return;
216
+ }
217
+
218
+ // find values needed in cpi chart value - https://github.com/rancher/vsphere-charts/blob/main/charts/rancher-vsphere-csi/questions.yaml#L1-L36
219
+ const {
220
+ username, password, host, datacenters, port, insecureFlag
221
+ } = combined.vCenter;
222
+
223
+ if (!username || !password || !host || !datacenters) {
224
+ throw new Error('vSphere CSI username, password, host and datacenters are all required when generating a new secret');
225
+ }
226
+
227
+ // This is a copy of https://github.com/rancher/vsphere-charts/blob/a5c99d716df960dc50cf417d9ecffad6b55ca0ad/charts/rancher-vsphere-csi/values.yaml#L12-L21
228
+ // Which makes it's way into the secret via https://github.com/rancher/vsphere-charts/blob/main/charts/rancher-vsphere-csi/templates/secret.yaml#L8
229
+ let configTemplateString = ' [Global]\n cluster-id = {{ required \".Values.vCenter.clusterId must be provided\" (default .Values.vCenter.clusterId .Values.global.cattle.clusterId) | quote }}\n user = {{ .Values.vCenter.username | quote }}\n password = {{ .Values.vCenter.password | quote }}\n port = {{ .Values.vCenter.port | quote }}\n insecure-flag = {{ .Values.vCenter.insecureFlag | quote }}\n\n [VirtualCenter {{ .Values.vCenter.host | quote }}]\n datacenters = {{ .Values.vCenter.datacenters | quote }}';
230
+
231
+ configTemplateString = configTemplateString.replace('{{ required \".Values.vCenter.clusterId must be provided\" (default .Values.vCenter.clusterId .Values.global.cattle.clusterId) | quote }}', `"{{clusterId}}"`);
232
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.username | quote }}', `"${ username }"`);
233
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.password | quote }}', `"${ password }"`);
234
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.port | quote }}', `"${ port }"`);
235
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.insecureFlag | quote }}', `"${ insecureFlag }"`);
236
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.host | quote }}', `"${ host }"`);
237
+ configTemplateString = configTemplateString.replace('{{ .Values.vCenter.datacenters | quote }}', `"${ datacenters }"`);
238
+ // create secret as per https://github.com/rancher/vsphere-charts/blob/main/charts/rancher-vsphere-csi/templates/secret.yaml
239
+ const upstreamClusterName = value.metadata.name;
240
+ const upstreamNamespace = value.metadata.namespace;
241
+
242
+ const secret = await this.findOrCreateSecret(rke2Component, {
243
+ generateName,
244
+ upstreamClusterName,
245
+ upstreamNamespace,
246
+ downstreamName,
247
+ downstreamNamespace,
248
+ json: {
249
+ type: SECRET,
250
+ metadata: {
251
+ namespace: upstreamNamespace,
252
+ generateName,
253
+ annotations: {
254
+ 'provisioning.cattle.io/sync-target-namespace': downstreamNamespace,
255
+ 'provisioning.cattle.io/sync-target-name': downstreamName,
256
+ 'rke.cattle.io/object-authorized-for-clusters': upstreamClusterName,
257
+ 'provisioning.cattle.io/sync-bootstrap': 'true'
258
+ }
259
+ },
260
+ }
261
+ });
262
+
263
+ secret.setData(`csi-vsphere.conf`, configTemplateString);
264
+
265
+ await secret.save();
266
+
267
+ // reset csi chart values
268
+ if (!userValues.vCenter.configSecret) {
269
+ userValues.vCenter.configSecret = {};
270
+ }
271
+ userValues.vCenter.configSecret.generate = false;
272
+ userValues.vCenter.configSecret.name = downstreamName;
273
+ userValues.vCenter.username = '';
274
+ userValues.vCenter.password = '';
275
+ userValues.vCenter.host = '';
276
+ userValues.vCenter.datacenters = '';
277
+ }
278
+ }
279
+
280
+ const utils = new VSphereUtils();
281
+
282
+ export default utils;
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());
@@ -1,2 +0,0 @@
1
- // Auto-generated type definitions for shell
2
- // Do not modify this file as changes will get overwritten