@rancher/shell 0.1.4 → 0.1.21

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 (152) hide show
  1. package/assets/brand/suse/favicon.png +0 -0
  2. package/assets/images/generic-plugin.svg +1 -7
  3. package/assets/translations/en-us.yaml +81 -47
  4. package/components/CommunityLinks.vue +40 -49
  5. package/components/ExplorerProjectsNamespaces.vue +20 -3
  6. package/components/LazyImage.vue +21 -8
  7. package/components/PromptRemove.vue +2 -2
  8. package/components/ResourceList/Masthead.vue +21 -1
  9. package/components/ResourceList/ResourceLoadingIndicator.vue +0 -8
  10. package/components/ResourceList/index.vue +9 -23
  11. package/components/SortableTable/index.vue +13 -10
  12. package/components/Tabbed/index.vue +25 -7
  13. package/components/TypeDescription.vue +10 -1
  14. package/components/fleet/FleetClusters.vue +6 -0
  15. package/components/fleet/FleetRepos.vue +7 -1
  16. package/components/form/Command.vue +5 -0
  17. package/components/form/EnvVars.vue +5 -0
  18. package/components/form/NameNsDescription.vue +3 -1
  19. package/components/form/NodeScheduling.vue +6 -1
  20. package/components/form/PodAffinity.vue +5 -0
  21. package/components/form/ServiceNameSelect.vue +5 -0
  22. package/components/form/ValueFromResource.vue +7 -1
  23. package/components/nav/TopLevelMenu.vue +2 -1
  24. package/config/home-links.js +155 -0
  25. package/config/private-label.js +1 -1
  26. package/config/product/manager.js +0 -2
  27. package/config/product/uiplugins.js +1 -1
  28. package/config/settings.js +3 -1
  29. package/config/uiplugins.js +63 -6
  30. package/config/version.js +17 -0
  31. package/core/plugin.ts +12 -0
  32. package/core/plugins.js +29 -5
  33. package/core/types.ts +6 -0
  34. package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
  35. package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
  36. package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
  37. package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
  38. package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
  39. package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
  40. package/creators/app/init +16 -17
  41. package/creators/app/package.json +6 -0
  42. package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
  43. package/creators/pkg/{index.ts → files/index.ts} +0 -0
  44. package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
  45. package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
  46. package/creators/pkg/init +1 -1
  47. package/creators/update/init +54 -0
  48. package/creators/update/package.json +20 -0
  49. package/creators/update/upgrade +56 -0
  50. package/creators/update/yarn-error.log +54 -0
  51. package/detail/workload/index.vue +1 -0
  52. package/edit/persistentvolume/index.vue +48 -13
  53. package/edit/persistentvolumeclaim.vue +31 -13
  54. package/edit/provisioning.cattle.io.cluster/rke2.vue +27 -19
  55. package/edit/workload/index.vue +19 -9
  56. package/edit/workload/mixins/workload.js +109 -114
  57. package/edit/workload/storage/index.vue +11 -17
  58. package/edit/workload/storage/persistentVolumeClaim/index.vue +5 -0
  59. package/edit/workload/storage/secret.vue +6 -1
  60. package/list/catalog.cattle.io.app.vue +10 -9
  61. package/list/catalog.cattle.io.clusterrepo.vue +6 -61
  62. package/list/cis.cattle.io.clusterscan.vue +12 -12
  63. package/list/fleet.cattle.io.bundle.vue +33 -28
  64. package/list/fleet.cattle.io.cluster.vue +26 -22
  65. package/list/fleet.cattle.io.clustergroup.vue +6 -0
  66. package/list/fleet.cattle.io.clusterregistrationtoken.vue +28 -24
  67. package/list/fleet.cattle.io.gitrepo.vue +25 -14
  68. package/list/helm.cattle.io.projecthelmchart.vue +52 -33
  69. package/list/logging.banzaicloud.io.clusterflow.vue +7 -12
  70. package/list/logging.banzaicloud.io.flow.vue +7 -14
  71. package/list/management.cattle.io.cluster.vue +26 -15
  72. package/list/management.cattle.io.feature.vue +13 -8
  73. package/list/management.cattle.io.user.vue +38 -19
  74. package/list/monitoring.coreos.com.alertmanagerconfig.vue +8 -15
  75. package/list/namespace.vue +14 -1
  76. package/list/node.vue +13 -16
  77. package/list/persistentvolume.vue +16 -9
  78. package/list/persistentvolumeclaim.vue +5 -8
  79. package/list/provisioning.cattle.io.cluster.vue +34 -8
  80. package/list/service.vue +24 -12
  81. package/list/ui.cattle.io.navlink.vue +6 -0
  82. package/list/workload.vue +2 -2
  83. package/middleware/authenticated.js +6 -0
  84. package/mixins/resource-fetch.js +12 -18
  85. package/mixins/resource-manager.js +126 -0
  86. package/models/catalog.cattle.io.uiplugin.js +4 -0
  87. package/models/pod.js +15 -5
  88. package/models/provisioning.cattle.io.cluster.js +4 -0
  89. package/models/workload.service.js +10 -0
  90. package/nuxt.config.js +2 -1
  91. package/package.json +1 -1
  92. package/pages/auth/login.vue +10 -0
  93. package/pages/auth/verify.vue +9 -0
  94. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +108 -0
  95. package/pages/c/_cluster/settings/links.vue +53 -101
  96. package/pages/c/_cluster/settings/performance.vue +90 -7
  97. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +3 -3
  98. package/pages/c/_cluster/uiplugins/InstallDialog.vue +71 -20
  99. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +21 -5
  100. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -7
  101. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +23 -15
  102. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +11 -4
  103. package/pages/c/_cluster/uiplugins/index.vue +179 -65
  104. package/pages/support/index.vue +31 -142
  105. package/plugins/dashboard-store/actions.js +19 -0
  106. package/plugins/dashboard-store/getters.js +20 -3
  107. package/plugins/dashboard-store/mutations.js +13 -7
  108. package/plugins/plugin.js +18 -15
  109. package/plugins/steve/getters.js +12 -0
  110. package/plugins/version.js +21 -0
  111. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -7
  112. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  113. package/rancher-components/components/BadgeState/BadgeState.vue +107 -0
  114. package/rancher-components/components/BadgeState/index.ts +1 -0
  115. package/rancher-components/components/Banner/Banner.test.ts +13 -0
  116. package/rancher-components/components/Banner/Banner.vue +163 -0
  117. package/rancher-components/components/Banner/index.ts +1 -0
  118. package/rancher-components/components/Card/Card.vue +150 -0
  119. package/rancher-components/components/Card/index.ts +1 -0
  120. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
  121. package/rancher-components/components/Form/Checkbox/Checkbox.vue +395 -0
  122. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  123. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +29 -0
  124. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +343 -0
  125. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  126. package/rancher-components/components/Form/Radio/RadioButton.vue +270 -0
  127. package/rancher-components/components/Form/Radio/RadioGroup.vue +235 -0
  128. package/rancher-components/components/Form/Radio/index.ts +2 -0
  129. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +168 -0
  130. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  131. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  132. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +137 -0
  133. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  134. package/rancher-components/components/Form/index.ts +5 -0
  135. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +137 -0
  136. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  137. package/scripts/publish-shell.sh +39 -6
  138. package/scripts/record-deps.js +37 -0
  139. package/scripts/test-plugins-build.sh +8 -5
  140. package/scripts/typegen.sh +84 -0
  141. package/store/auth.js +3 -0
  142. package/store/index.js +12 -3
  143. package/types/shell/index.d.ts +3046 -0
  144. package/utils/favicon.js +8 -2
  145. package/utils/gc/gc-interval.ts +40 -0
  146. package/utils/gc/gc-root-store.js +76 -0
  147. package/utils/gc/gc-route-changed.ts +44 -0
  148. package/utils/gc/gc-types.ts +21 -0
  149. package/utils/gc/gc.ts +282 -0
  150. package/config/footer.js +0 -18
  151. package/creators/pkg/nuxt.config.js +0 -6
  152. package/yarn-error.log +0 -195
@@ -1222,32 +1222,40 @@ export default {
1222
1222
  return;
1223
1223
  }
1224
1224
 
1225
- const clusterId = get(this.credential, 'decodedData.clusterId') || '';
1225
+ try {
1226
+ const clusterId = get(this.credential, 'decodedData.clusterId') || '';
1226
1227
 
1227
- this.applyChartValues(this.value.spec.rkeConfig);
1228
+ this.applyChartValues(this.value.spec.rkeConfig);
1228
1229
 
1229
- const isUpgrade = this.isEdit && this.liveValue?.spec?.kubernetesVersion !== this.value?.spec?.kubernetesVersion;
1230
+ const isUpgrade = this.isEdit && this.liveValue?.spec?.kubernetesVersion !== this.value?.spec?.kubernetesVersion;
1230
1231
 
1231
- if (this.agentConfig['cloud-provider-name'] === HARVESTER && clusterId && (this.isCreate || isUpgrade)) {
1232
- const namespace = this.machinePools?.[0]?.config?.vmNamespace;
1232
+ if (this.agentConfig['cloud-provider-name'] === HARVESTER && clusterId && (this.isCreate || isUpgrade)) {
1233
+ const namespace = this.machinePools?.[0]?.config?.vmNamespace;
1233
1234
 
1234
- const res = await this.$store.dispatch('management/request', {
1235
- url: `/k8s/clusters/${ clusterId }/v1/harvester/kubeconfig`,
1236
- method: 'POST',
1237
- data: {
1238
- clusterRoleName: 'harvesterhci.io:cloudprovider',
1239
- namespace,
1240
- serviceAccountName: this.value.metadata.name,
1241
- },
1242
- });
1235
+ const res = await this.$store.dispatch('management/request', {
1236
+ url: `/k8s/clusters/${ clusterId }/v1/harvester/kubeconfig`,
1237
+ method: 'POST',
1238
+ data: {
1239
+ clusterRoleName: 'harvesterhci.io:cloudprovider',
1240
+ namespace,
1241
+ serviceAccountName: this.value.metadata.name,
1242
+ },
1243
+ });
1244
+
1245
+ const kubeconfig = res.data;
1243
1246
 
1244
- const kubeconfig = res.data;
1247
+ const harvesterKubeconfigSecret = await this.createKubeconfigSecret(kubeconfig);
1245
1248
 
1246
- const harvesterKubeconfigSecret = await this.createKubeconfigSecret(kubeconfig);
1249
+ set(this.agentConfig, 'cloud-provider-config', `secret://fleet-default:${ harvesterKubeconfigSecret?.metadata?.name }`);
1250
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.clusterName`, this.value.metadata.name);
1251
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`, '/var/lib/rancher/rke2/etc/config-files/cloud-provider-config');
1252
+ }
1253
+ } catch (err) {
1254
+ this.errors.push(err);
1255
+
1256
+ btnCb(false);
1247
1257
 
1248
- set(this.agentConfig, 'cloud-provider-config', `secret://fleet-default:${ harvesterKubeconfigSecret?.metadata?.name }`);
1249
- set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.clusterName`, this.value.metadata.name);
1250
- set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`, '/var/lib/rancher/rke2/etc/config-files/cloud-provider-config');
1258
+ return;
1251
1259
  }
1252
1260
 
1253
1261
  await this.save(btnCb);
@@ -4,7 +4,7 @@ import FormValidation from '@shell/mixins/form-validation';
4
4
  import WorkLoadMixin from '@shell/edit/workload/mixins/workload';
5
5
 
6
6
  export default {
7
- name: 'WorkloadDeployments',
7
+ name: 'Workload',
8
8
  mixins: [CreateEditView, FormValidation, WorkLoadMixin], // The order here is important since WorkLoadMixin contains some FormValidation configuration
9
9
  props: {
10
10
  value: {
@@ -56,6 +56,7 @@ export default {
56
56
  :mode="mode"
57
57
  :rules="{name: fvGetAndReportPathRules('metadata.name'), namespace: fvGetAndReportPathRules('metadata.namespace'), description: []}"
58
58
  @change="name=value.metadata.name"
59
+ @isNamespaceNew="isNamespaceNew = $event"
59
60
  />
60
61
  <div v-if="isCronJob || isReplicable || isStatefulSet || containerOptions.length > 1" class="row mb-20">
61
62
  <div v-if="isCronJob" class="col span-3">
@@ -91,10 +92,10 @@ export default {
91
92
  />
92
93
  </div>
93
94
  </div>
94
- <Tabbed class="deployment-tabs" :show-tabs-add-remove="true" :default-tab="defaultTab" @changed="changed">
95
+ <Tabbed class="deployment-tabs" :show-tabs-add-remove="true" :default-tab="defaultTab" :flat="true" @changed="changed">
95
96
  <Tab
96
97
  v-for="(tab, i) in allContainers"
97
- :key="i+tab.name"
98
+ :key="i"
98
99
  :label="tab.name"
99
100
  :name="tab.name"
100
101
  :weight="tab.weight"
@@ -110,7 +111,7 @@ export default {
110
111
  <div>
111
112
  <div :style="{'align-items':'center'}" class="row mb-20">
112
113
  <div class="col span-6">
113
- <LabeledInput v-model="container.name" :mode="mode" :label="t('workload.container.containerName')" />
114
+ <LabeledInput v-model="allContainers[i].name" :mode="mode" :label="t('workload.container.containerName')" />
114
115
  </div>
115
116
  <div class="col span-6">
116
117
  <RadioGroup
@@ -127,7 +128,7 @@ export default {
127
128
  <div class="row mb-20">
128
129
  <div class="col span-6">
129
130
  <LabeledInput
130
- v-model.trim="container.image"
131
+ v-model.trim="allContainers[i].image"
131
132
  :mode="mode"
132
133
  :label="t('workload.container.image')"
133
134
  :placeholder="t('generic.placeholder', {text: 'nginx:latest'}, true)"
@@ -136,7 +137,7 @@ export default {
136
137
  </div>
137
138
  <div class="col span-6">
138
139
  <LabeledSelect
139
- v-model="container.imagePullPolicy"
140
+ v-model="allContainers[i].imagePullPolicy"
140
141
  :label="t('workload.container.imagePullPolicy')"
141
142
  :options="pullPolicyOptions"
142
143
  :mode="mode"
@@ -169,7 +170,13 @@ export default {
169
170
  <div class="spacer" />
170
171
  <div>
171
172
  <h3>{{ t('workload.container.titles.command') }}</h3>
172
- <Command v-model="allContainers[i]" :secrets="namespacedSecrets" :config-maps="namespacedConfigMaps" :mode="mode" />
173
+ <Command
174
+ v-model="allContainers[i]"
175
+ :secrets="namespacedSecrets"
176
+ :config-maps="namespacedConfigMaps"
177
+ :mode="mode"
178
+ :loading="isLoadingSecondaryResources"
179
+ />
173
180
  </div>
174
181
  <ServiceNameSelect
175
182
  :value="podTemplateSpec.serviceAccountName"
@@ -178,6 +185,7 @@ export default {
178
185
  :select-placeholder="t('workload.serviceAccountName.label')"
179
186
  :options="namespacedServiceNames"
180
187
  option-label="metadata.name"
188
+ :loading="isLoadingSecondaryResources"
181
189
  @input="updateServiceAccount"
182
190
  />
183
191
  <div class="spacer" />
@@ -234,6 +242,8 @@ export default {
234
242
  :secrets="namespacedSecrets"
235
243
  :config-maps="namespacedConfigMaps"
236
244
  :save-pvc-hook-name="savePvcHookName"
245
+ :loading="isLoadingSecondaryResources"
246
+ :namespaced-pvcs="pvcs"
237
247
  @removePvcForm="clearPvcFormState"
238
248
  />
239
249
  </Tab>
@@ -265,10 +275,10 @@ export default {
265
275
  </template>
266
276
  </Tab>
267
277
  <Tab :label="t('workload.container.titles.podScheduling')" name="podScheduling" :weight="tabWeightMap['podScheduling']">
268
- <PodAffinity :mode="mode" :value="podTemplateSpec" :nodes="allNodeObjects" />
278
+ <PodAffinity :mode="mode" :value="podTemplateSpec" :nodes="allNodeObjects" :loading="isLoadingSecondaryResources" />
269
279
  </Tab>
270
280
  <Tab :label="t('workload.container.titles.nodeScheduling')" name="nodeScheduling" :weight="tabWeightMap['nodeScheduling']">
271
- <NodeScheduling :mode="mode" :value="podTemplateSpec" :nodes="allNodes" />
281
+ <NodeScheduling :mode="mode" :value="podTemplateSpec" :nodes="allNodes" :loading="isLoadingSecondaryResources" />
272
282
  </Tab>
273
283
  <Tab :label="t('workload.container.titles.upgrading')" name="upgrading" :weight="tabWeightMap['upgrading']">
274
284
  <Job v-if="isJob || isCronJob" v-model="spec" :mode="mode" :type="type" />
@@ -1,3 +1,4 @@
1
+ import { mapGetters } from 'vuex';
1
2
  import omitBy from 'lodash/omitBy';
2
3
  import { cleanUp } from '@shell/utils/object';
3
4
  import {
@@ -13,7 +14,7 @@ import {
13
14
  } from '@shell/config/types';
14
15
  import Tab from '@shell/components/Tabbed/Tab';
15
16
  import CreateEditView from '@shell/mixins/create-edit-view';
16
- import { allHash } from '@shell/utils/promise';
17
+ import ResourceManager from '@shell/mixins/resource-manager';
17
18
  import LabeledSelect from '@shell/components/form/LabeledSelect';
18
19
  import { LabeledInput } from '@components/Form/LabeledInput';
19
20
  import ServiceNameSelect from '@shell/components/form/ServiceNameSelect';
@@ -29,7 +30,7 @@ import WorkloadPorts from '@shell/components/form/WorkloadPorts';
29
30
  import ContainerResourceLimit from '@shell/components/ContainerResourceLimit';
30
31
  import KeyValue from '@shell/components/form/KeyValue';
31
32
  import Tabbed from '@shell/components/Tabbed';
32
- import { mapGetters } from 'vuex';
33
+
33
34
  import NodeScheduling from '@shell/components/form/NodeScheduling';
34
35
  import PodAffinity from '@shell/components/form/PodAffinity';
35
36
  import Tolerations from '@shell/components/form/Tolerations';
@@ -94,7 +95,7 @@ export default {
94
95
  ContainerMountPaths
95
96
  },
96
97
 
97
- mixins: [CreateEditView],
98
+ mixins: [CreateEditView, ResourceManager],
98
99
 
99
100
  props: {
100
101
  value: {
@@ -118,36 +119,11 @@ export default {
118
119
  },
119
120
 
120
121
  async fetch() {
121
- const requests = { rancherClusters: this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER }) };
122
- const needed = {
123
- configMaps: CONFIG_MAP,
124
- nodes: NODE,
125
- services: SERVICE,
126
- pvcs: PVC,
127
- sas: SERVICE_ACCOUNT,
128
- secrets: SECRET,
129
- };
130
-
131
- // Only fetch types if the user can see them
132
- Object.keys(needed).forEach((key) => {
133
- const type = needed[key];
134
-
135
- if (this.$store.getters['cluster/schemaFor'](type)) {
136
- requests[key] = this.$store.dispatch('cluster/findAll', { type });
137
- }
138
- });
139
-
140
- const hash = await allHash(requests);
122
+ await this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
141
123
 
142
- this.servicesOwned = hash.services ? await this.value.getServicesOwned() : [];
143
-
144
- this.allSecrets = hash.secrets || [];
145
- this.allConfigMaps = hash.configMaps || [];
146
- this.allNodeObjects = hash.nodes || [];
147
- this.allNodes = this.allNodeObjects.map(node => node.id);
148
- this.allServices = hash.services || [];
149
- this.pvcs = hash.pvcs || [];
150
- this.sas = hash.sas || [];
124
+ // don't block UI for these resources
125
+ this.resourceManagerFetchSecondaryResources(this.secondaryResourceData);
126
+ this.servicesOwned = await this.value.getServicesOwned();
151
127
  },
152
128
 
153
129
  data() {
@@ -167,16 +143,21 @@ export default {
167
143
  name: `container-0`,
168
144
  }];
169
145
 
170
- const podSpec = { template: { spec: { containers: podContainers, initContainers: [] } } };
146
+ const metadata = { ...this.value.metadata };
147
+
148
+ const podSpec = { template: { spec: { containers: podContainers, initContainers: [] }, metadata } };
171
149
 
172
150
  this.$set(this.value, 'spec', podSpec);
173
151
  }
174
152
  }
175
153
 
154
+ // EDIT view for POD
155
+ // Transform it from POD world to workload
176
156
  if ((this.mode === _EDIT || this.mode === _VIEW ) && this.value.type === 'pod' ) {
177
157
  const podSpec = { ...this.value.spec };
158
+ const metadata = { ...this.value.metadata };
178
159
 
179
- this.$set(this.value.spec, 'template', { spec: podSpec });
160
+ this.$set(this.value.spec, 'template', { spec: podSpec, metadata });
180
161
  }
181
162
 
182
163
  const spec = this.value.spec;
@@ -228,37 +209,81 @@ export default {
228
209
  this.selectContainer(container);
229
210
 
230
211
  return {
231
- allConfigMaps: [],
232
- allNodes: null,
233
- allNodeObjects: [],
234
- allSecrets: [],
235
- allServices: [],
236
- name: this.value?.metadata?.name || null,
237
- pvcs: [],
238
- sas: [],
239
- showTabs: false,
240
- pullPolicyOptions: ['Always', 'IfNotPresent', 'Never'],
212
+ secondaryResourceData: {
213
+ namespace: this.value?.metadata?.namespace || null,
214
+ data: {
215
+ [CONFIG_MAP]: { applyTo: [{ var: 'namespacedConfigMaps' }] },
216
+ [PVC]: { applyTo: [{ var: 'pvcs' }] },
217
+ [SERVICE_ACCOUNT]: { applyTo: [{ var: 'namespacedServiceNames' }] },
218
+ [SECRET]: {
219
+ applyTo: [
220
+ { var: 'namespacedSecrets' },
221
+ {
222
+ var: 'imagePullNamespacedSecrets',
223
+ parsingFunc: (data) => {
224
+ return data.filter(secret => (secret._type === SECRET_TYPES.DOCKER || secret._type === SECRET_TYPES.DOCKER_JSON));
225
+ }
226
+ }
227
+ ]
228
+ },
229
+ [NODE]: {
230
+ applyTo: [
231
+ { var: 'allNodeObjects' },
232
+ {
233
+ var: 'allNodes',
234
+ parsingFunc: (data) => {
235
+ return data.map(node => node.id);
236
+ }
237
+ }
238
+ ]
239
+ },
240
+ [SERVICE]: {
241
+ applyTo: [
242
+ { var: 'allServices' },
243
+ {
244
+ var: 'headlessServices',
245
+ parsingFunc: (data) => {
246
+ return data.filter(service => service.spec.clusterIP === 'None');
247
+ }
248
+ }
249
+ ]
250
+ },
251
+ }
252
+ },
253
+ namespacedConfigMaps: [],
254
+ allNodes: null,
255
+ allNodeObjects: [],
256
+ namespacedSecrets: [],
257
+ imagePullNamespacedSecrets: [],
258
+ allServices: [],
259
+ headlessServices: [],
260
+ name: this.value?.metadata?.name || null,
261
+ pvcs: [],
262
+ namespacedServiceNames: [],
263
+ showTabs: false,
264
+ pullPolicyOptions: ['Always', 'IfNotPresent', 'Never'],
241
265
  spec,
242
266
  type,
243
- servicesOwned: [],
244
- servicesToRemove: [],
245
- portsForServices: [],
267
+ servicesOwned: [],
268
+ servicesToRemove: [],
269
+ portsForServices: [],
246
270
  isInitContainer,
247
271
  container,
248
- containerChange: 0,
249
- tabChange: 0,
250
- podFsGroup: podTemplateSpec.securityContext?.fsGroup,
251
- savePvcHookName: 'savePvcHook',
252
- tabWeightMap: TAB_WEIGHT_MAP,
253
- fvFormRuleSets: [{
272
+ containerChange: 0,
273
+ tabChange: 0,
274
+ podFsGroup: podTemplateSpec.securityContext?.fsGroup,
275
+ savePvcHookName: 'savePvcHook',
276
+ tabWeightMap: TAB_WEIGHT_MAP,
277
+ fvFormRuleSets: [{
254
278
  path: 'image', rootObject: this.container, rules: ['required'], translationKey: 'workload.container.image'
255
279
  }],
256
280
  fvReportedValidationPaths: ['spec'],
257
-
281
+ isNamespaceNew: false,
258
282
  };
259
283
  },
260
284
 
261
285
  computed: {
286
+ ...mapGetters(['currentCluster']),
262
287
  tabErrors() {
263
288
  return { general: this.fvGetPathErrors(['image'])?.length > 0 };
264
289
  },
@@ -326,13 +351,13 @@ export default {
326
351
  }
327
352
 
328
353
  return this.spec.jobTemplate.metadata.labels;
329
- } else {
330
- if (!this.spec.template.metadata) {
331
- this.$set(this.spec.template, 'metadata', { labels: {} });
332
- }
354
+ }
333
355
 
334
- return this.spec.template.metadata.labels;
356
+ if (!this.spec.template.metadata) {
357
+ this.$set(this.spec.template, 'metadata', { labels: {} });
335
358
  }
359
+
360
+ return this.spec.template.metadata.labels;
336
361
  },
337
362
  set(neu) {
338
363
  if (this.isCronJob) {
@@ -351,13 +376,12 @@ export default {
351
376
  }
352
377
 
353
378
  return this.spec.jobTemplate.metadata.annotations;
354
- } else {
355
- if (!this.spec.template.metadata) {
356
- this.$set(this.spec.template, 'metadata', { annotations: {} });
357
- }
358
-
359
- return this.spec.template.metadata.annotations;
360
379
  }
380
+ if (!this.spec.template.metadata) {
381
+ this.$set(this.spec.template, 'metadata', { annotations: {} });
382
+ }
383
+
384
+ return this.spec.template.metadata.annotations;
361
385
  },
362
386
  set(neu) {
363
387
  if (this.isCronJob) {
@@ -467,55 +491,6 @@ export default {
467
491
  return this.$store.getters['cluster/schemaFor'](this.type);
468
492
  },
469
493
 
470
- namespacedSecrets() {
471
- const namespace = this.value?.metadata?.namespace;
472
-
473
- if (namespace) {
474
- return this.allSecrets.filter(
475
- secret => secret.metadata.namespace === namespace
476
- );
477
- } else {
478
- return this.allSecrets;
479
- }
480
- },
481
-
482
- imagePullNamespacedSecrets() {
483
- const namespace = this.value?.metadata?.namespace;
484
-
485
- return this.allSecrets.filter(secret => secret.metadata.namespace === namespace && (secret._type === SECRET_TYPES.DOCKER || secret._type === SECRET_TYPES.DOCKER_JSON));
486
- },
487
-
488
- namespacedConfigMaps() {
489
- const namespace = this.value?.metadata?.namespace;
490
-
491
- if (namespace) {
492
- return this.allConfigMaps.filter(
493
- configMap => configMap.metadata.namespace === namespace
494
- );
495
- } else {
496
- return this.allConfigMaps;
497
- }
498
- },
499
-
500
- namespacedServiceNames() {
501
- const { namespace } = this.value?.metadata;
502
-
503
- if (namespace) {
504
- return this.sas.filter(
505
- serviceName => serviceName.metadata.namespace === namespace
506
- );
507
- } else {
508
- return this.sas;
509
- }
510
- },
511
-
512
- headlessServices() {
513
- return this.allServices.filter(
514
- service => service.spec.clusterIP === 'None' &&
515
- service.metadata.namespace === this.value.metadata.namespace
516
- );
517
- },
518
-
519
494
  workloadTypes() {
520
495
  return omitBy(WORKLOAD_TYPES, (type) => {
521
496
  return (
@@ -558,6 +533,25 @@ export default {
558
533
  },
559
534
 
560
535
  watch: {
536
+ async 'value.metadata.namespace'(neu) {
537
+ if (this.isNamespaceNew) {
538
+ // we don't need to re-fetch namespace specific (or non-namespace specific) resources when the namespace hasn't been created yet
539
+ return;
540
+ }
541
+ this.secondaryResourceData.namespace = neu;
542
+ // Fetch resources that are namespace specific, we don't need to re-fetch non-namespaced resources on namespace change
543
+ this.resourceManagerFetchSecondaryResources(this.secondaryResourceData, true);
544
+
545
+ this.servicesOwned = await this.value.getServicesOwned();
546
+ },
547
+
548
+ isNamespaceNew(neu, old) {
549
+ if (!old && neu) {
550
+ // As the namespace is new any resource that's been fetched with a namespace is now invalid
551
+ this.resourceManagerClearSecondaryResources(this.secondaryResourceData, true);
552
+ }
553
+ },
554
+
561
555
  type(neu, old) {
562
556
  const template =
563
557
  old === WORKLOAD_TYPES.CRON_JOB ? this.spec?.jobTemplate?.spec?.template : this.spec?.template;
@@ -689,6 +683,7 @@ export default {
689
683
  template = this.spec.template;
690
684
  }
691
685
 
686
+ // WORKLOADS
692
687
  if (
693
688
  this.type !== WORKLOAD_TYPES.JOB &&
694
689
  this.type !== WORKLOAD_TYPES.CRON_JOB &&
@@ -1,5 +1,4 @@
1
1
  <script>
2
- import { PVC } from '@shell/config/types';
3
2
  import ButtonDropdown from '@shell/components/ButtonDropdown';
4
3
  import Mount from '@shell/edit/workload/storage/Mount';
5
4
  import { _VIEW } from '@shell/config/query-params';
@@ -47,25 +46,25 @@ export default {
47
46
  type: Array,
48
47
  default: () => [],
49
48
  },
49
+ namespacedPvcs: {
50
+ type: Array,
51
+ default: () => [],
52
+ },
50
53
 
51
54
  registerBeforeHook: {
52
55
  type: Function,
53
56
  default: null,
54
57
  },
55
- },
56
-
57
- async fetch() {
58
- if ( this.$store.getters['cluster/schemaFor'](PVC) ) {
59
- this.pvcs = await this.$store.dispatch('cluster/findAll', { type: PVC });
60
- } else {
61
- this.pvcs = [];
62
- }
58
+ loading: {
59
+ default: false,
60
+ type: Boolean
61
+ },
63
62
  },
64
63
 
65
64
  data() {
66
65
  this.initializeStorage();
67
66
 
68
- return { pvcs: [] };
67
+ return {};
69
68
  },
70
69
 
71
70
  computed: {
@@ -73,12 +72,6 @@ export default {
73
72
  return this.mode === _VIEW;
74
73
  },
75
74
 
76
- namespacedPVCs() {
77
- const namespace = this.namespace || this.$store.getters['defaultNamespace'];
78
-
79
- return this.pvcs.filter(pvc => pvc.metadata.namespace === namespace);
80
- },
81
-
82
75
  /**
83
76
  * Generated list of volumes
84
77
  */
@@ -110,7 +103,7 @@ export default {
110
103
  },
111
104
 
112
105
  pvcNames() {
113
- return this.namespacedPVCs.map(pvc => pvc.metadata.name);
106
+ return this.namespacedPvcs.map(pvc => pvc.metadata.name);
114
107
  },
115
108
  },
116
109
 
@@ -270,6 +263,7 @@ export default {
270
263
  :pvcs="pvcNames"
271
264
  :register-before-hook="registerBeforeHook"
272
265
  :save-pvc-hook-name="savePvcHookName"
266
+ :loading="loading"
273
267
  @removePvcForm="removePvcForm"
274
268
  />
275
269
  <div v-else-if="isView">
@@ -53,6 +53,10 @@ export default {
53
53
  type: String,
54
54
  required: true
55
55
  },
56
+ loading: {
57
+ default: false,
58
+ type: Boolean
59
+ },
56
60
  },
57
61
 
58
62
  async fetch() {
@@ -129,6 +133,7 @@ export default {
129
133
  :mode="mode"
130
134
  :label="t('workload.storage.subtypes.persistentVolumeClaim')"
131
135
  :options="pvcs"
136
+ :loading="loading"
132
137
  />
133
138
  </div>
134
139
  </div>
@@ -43,7 +43,10 @@ export default {
43
43
  return {};
44
44
  }
45
45
  },
46
-
46
+ loading: {
47
+ default: false,
48
+ type: Boolean
49
+ },
47
50
  },
48
51
 
49
52
  computed: {
@@ -154,6 +157,7 @@ export default {
154
157
  :mode="mode"
155
158
  :required="true"
156
159
  :label="t('workload.storage.subtypes.secret')"
160
+ :loading="loading"
157
161
  />
158
162
  <LabeledSelect
159
163
  v-else-if="type==='configMap'"
@@ -162,6 +166,7 @@ export default {
162
166
  :required="true"
163
167
  :mode="mode"
164
168
  :label="t('workload.storage.subtypes.configMap')"
169
+ :loading="loading"
165
170
  />
166
171
  </div>
167
172
  <div class="col span-6">
@@ -1,10 +1,11 @@
1
1
  <script>
2
2
  import ResourceTable from '@shell/components/ResourceTable';
3
- import Loading from '@shell/components/Loading';
3
+ import ResourceFetch from '@shell/mixins/resource-fetch';
4
4
 
5
5
  export default {
6
6
  name: 'ListApps',
7
- components: { Loading, ResourceTable },
7
+ components: { ResourceTable },
8
+ mixins: [ResourceFetch],
8
9
 
9
10
  props: {
10
11
  resource: {
@@ -21,18 +22,18 @@ export default {
21
22
  async fetch() {
22
23
  await this.$store.dispatch('catalog/load');
23
24
 
24
- this.rows = await this.$store.dispatch('cluster/findAll', { type: this.resource });
25
- },
26
-
27
- data() {
28
- return { rows: null };
25
+ await this.$fetchType(this.resource);
29
26
  },
30
27
  };
31
28
  </script>
32
29
 
33
30
  <template>
34
- <Loading v-if="$fetchState.pending" />
35
- <ResourceTable v-else class="apps" :schema="schema" :rows="rows">
31
+ <ResourceTable
32
+ class="apps"
33
+ :schema="schema"
34
+ :rows="rows"
35
+ :loading="loading"
36
+ >
36
37
  <template #cell:upgrade="{row}">
37
38
  <span v-if="row.upgradeAvailable" class="badge-state bg-warning hand" @click="row.goToUpgrade(row.upgradeAvailable)">
38
39
  {{ row.upgradeAvailable }}