@rancher/shell 0.3.10 → 0.3.12

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 (96) hide show
  1. package/assets/translations/en-us.yaml +51 -5
  2. package/chart/monitoring/StorageClassSelector.vue +1 -0
  3. package/chart/monitoring/index.vue +4 -0
  4. package/chart/monitoring/prometheus/index.vue +6 -3
  5. package/components/ActionMenu.vue +1 -1
  6. package/components/DetailText.vue +1 -0
  7. package/components/DetailTop.vue +0 -2
  8. package/components/ExplorerMembers.vue +22 -10
  9. package/components/ExplorerProjectsNamespaces.vue +1 -0
  10. package/components/GrafanaDashboard.vue +2 -2
  11. package/components/Inactivity.vue +1 -0
  12. package/components/ModalWithCard.vue +1 -0
  13. package/components/ResourceList/index.vue +1 -1
  14. package/components/SortableTable/THead.vue +1 -0
  15. package/components/Tabbed/index.vue +2 -0
  16. package/components/Wizard.vue +4 -3
  17. package/components/form/ChangePassword.vue +3 -0
  18. package/components/form/KeyValue.vue +12 -7
  19. package/components/form/NodeAffinity.vue +29 -7
  20. package/components/form/PodAffinity.vue +27 -7
  21. package/components/form/Taints.vue +6 -0
  22. package/components/formatter/ExtensionCache.vue +74 -0
  23. package/components/nav/Header.vue +1 -0
  24. package/components/nav/WindowManager/ContainerShell.vue +10 -0
  25. package/components/nav/WindowManager/index.vue +1 -0
  26. package/config/product/explorer.js +1 -10
  27. package/config/product/monitoring.js +2 -1
  28. package/config/router.js +3 -3
  29. package/config/table-headers.js +32 -24
  30. package/config/uiplugins.js +11 -0
  31. package/config/workload.ts +1 -0
  32. package/core/types.ts +25 -7
  33. package/creators/pkg/files/.github/workflows/build-container.yml +64 -0
  34. package/creators/pkg/init +13 -6
  35. package/detail/helm.cattle.io.projecthelmchart.vue +2 -2
  36. package/detail/node.vue +2 -2
  37. package/detail/workload/index.vue +1 -1
  38. package/edit/__tests__/management.cattle.io.setting.test.ts +1 -1
  39. package/edit/autoscaling.horizontalpodautoscaler/metric-target.vue +0 -2
  40. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +43 -0
  41. package/edit/logging.banzaicloud.io.output/index.vue +8 -5
  42. package/edit/logging.banzaicloud.io.output/providers/__tests__/loki.test.ts +13 -0
  43. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
  44. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +0 -2
  45. package/edit/monitoring.coreos.com.receiver/index.vue +32 -1
  46. package/edit/monitoring.coreos.com.receiver/types/email.vue +12 -4
  47. package/edit/namespace.vue +1 -0
  48. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +36 -6
  49. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +2 -2
  50. package/edit/provisioning.cattle.io.cluster/rke2.vue +58 -13
  51. package/edit/token.vue +1 -0
  52. package/middleware/authenticated.js +1 -0
  53. package/models/__tests__/batch.cronjob.test.ts +88 -0
  54. package/models/cluster/node.js +8 -0
  55. package/models/management.cattle.io.clusterroletemplatebinding.js +5 -1
  56. package/models/projectroletemplatebinding.js +9 -1
  57. package/models/workload.js +1 -1
  58. package/package.json +1 -1
  59. package/pages/__tests__/prefs.test.ts +96 -0
  60. package/pages/account/index.vue +3 -0
  61. package/pages/auth/setup.vue +13 -13
  62. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  63. package/pages/c/_cluster/apps/charts/install.vue +5 -2
  64. package/pages/c/_cluster/monitoring/index.vue +10 -5
  65. package/pages/c/_cluster/settings/performance.vue +2 -0
  66. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +601 -0
  67. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +183 -0
  68. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +50 -9
  69. package/pages/c/_cluster/uiplugins/index.vue +329 -224
  70. package/pages/fail-whale.vue +1 -1
  71. package/pages/home.vue +11 -0
  72. package/pages/prefs.vue +20 -1
  73. package/plugins/plugin.js +1 -1
  74. package/plugins/steve/subscribe.js +34 -7
  75. package/plugins/steve/worker/index.js +4 -3
  76. package/public/index.html +6 -1
  77. package/rancher-components/components/Card/Card.vue +1 -0
  78. package/rancher-components/components/Form/Radio/RadioGroup.vue +1 -0
  79. package/scripts/extension/bundle +20 -4
  80. package/scripts/extension/helm/charts/ui-plugin-server/.helmignore +23 -0
  81. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +20 -0
  82. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +52 -0
  83. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +12 -0
  84. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +6 -0
  85. package/scripts/extension/helm/package/Dockerfile +27 -0
  86. package/scripts/extension/helm/package/nginx.conf +17 -0
  87. package/scripts/extension/helm/scripts/package +23 -0
  88. package/scripts/extension/helm/scripts/patch +101 -0
  89. package/scripts/extension/helm/scripts/version +31 -0
  90. package/scripts/extension/helmpatch +3 -25
  91. package/scripts/extension/publish +47 -32
  92. package/types/shell/index.d.ts +30 -24
  93. package/utils/__tests__/grafana.test.ts +2 -2
  94. package/utils/error.js +11 -0
  95. package/utils/grafana.js +5 -4
  96. package/vue.config.js +3 -17
@@ -0,0 +1,183 @@
1
+ <script>
2
+ import { mapGetters } from 'vuex';
3
+ import isEmpty from 'lodash/isEmpty';
4
+
5
+ import ResourceManager from '@shell/mixins/resource-manager';
6
+ import { SERVICE, WORKLOAD_TYPES } from '@shell/config/types';
7
+ import { UI_PLUGIN_LABELS, UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
8
+ import { UI_PLUGIN_CATALOG } from '@shell/config/table-headers';
9
+
10
+ import ActionMenu from '@shell/components/ActionMenu';
11
+ import ResourceTable from '@shell/components/ResourceTable';
12
+
13
+ export default {
14
+ name: 'CatalogList',
15
+
16
+ props: {
17
+ plugins: {
18
+ type: Array,
19
+ required: true
20
+ }
21
+ },
22
+
23
+ components: { ActionMenu, ResourceTable },
24
+
25
+ mixins: [ResourceManager],
26
+
27
+ data() {
28
+ const actions = [
29
+ {
30
+ action: 'uninstall',
31
+ label: this.t('plugins.uninstall.label'),
32
+ icon: 'icon icon-trash',
33
+ enabled: true,
34
+ }
35
+ ];
36
+
37
+ return {
38
+ actions,
39
+ catalogHeaders: UI_PLUGIN_CATALOG,
40
+ menuTargetElement: null,
41
+ menuTargetEvent: null,
42
+ menuOpen: false,
43
+ };
44
+ },
45
+
46
+ computed: {
47
+ ...mapGetters({ allRepos: 'catalog/repos' }),
48
+
49
+ namespacedDeployments() {
50
+ return this.$store.getters['management/all'](WORKLOAD_TYPES.DEPLOYMENT).filter(dep => dep.metadata.namespace === UI_PLUGIN_NAMESPACE);
51
+ },
52
+
53
+ namespacedServices() {
54
+ return this.$store.getters['management/all'](SERVICE).filter(svc => svc.metadata.namespace === UI_PLUGIN_NAMESPACE);
55
+ },
56
+
57
+ catalogRows() {
58
+ const rows = [];
59
+
60
+ if (this.plugins.length) {
61
+ // Find the resources associated with the image by the CATALOG_IMAGE label
62
+ this.plugins.forEach((plugin) => {
63
+ const resources = [this.namespacedDeployments, this.namespacedServices, this.allRepos];
64
+ const pluginName = plugin.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE];
65
+
66
+ if (pluginName) {
67
+ const out = {
68
+ uiplugin: plugin,
69
+ catalog: true,
70
+ name: pluginName,
71
+ state: plugin.metadata?.state?.name,
72
+ cacheState: plugin.status?.cacheState,
73
+ version: plugin.spec?.plugin?.version,
74
+ deployment: null,
75
+ deploymentImage: null,
76
+ service: null,
77
+ repo: null
78
+ };
79
+ const keys = ['deployment', 'service', 'repo'];
80
+
81
+ resources.forEach((resource, i) => {
82
+ out[keys[i]] = resource?.filter(item => item.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE] === pluginName)[0];
83
+ });
84
+
85
+ if (!isEmpty(out?.deployment)) {
86
+ out.deploymentImage = out.deployment.spec?.template?.spec?.containers[0]?.image;
87
+
88
+ rows.push(out);
89
+ }
90
+ }
91
+ });
92
+ }
93
+
94
+ return rows;
95
+ }
96
+ },
97
+
98
+ methods: {
99
+ setMenu(event) {
100
+ this.menuOpen = !!event;
101
+
102
+ if (event) {
103
+ this.menuTargetElement = this.$refs.catalogActions;
104
+ this.menuTargetEvent = event;
105
+ } else {
106
+ this.menuTargetElement = undefined;
107
+ this.menuTargetEvent = undefined;
108
+ }
109
+ }
110
+ }
111
+ };
112
+ </script>
113
+
114
+ <template>
115
+ <div class="row mt-20">
116
+ <div class="col span-12">
117
+ <ResourceTable
118
+ :headers="catalogHeaders"
119
+ :rows="catalogRows"
120
+ :paging="true"
121
+ :rows-per-page="10"
122
+ :table-actions="false"
123
+ key-field="name"
124
+ >
125
+ <template #header-left>
126
+ <div>
127
+ <button
128
+ class="btn bg-primary mr-10"
129
+ type="button"
130
+ aria-haspopup="dialog"
131
+ data-testid="extensions-catalog-load-dialog"
132
+ @click="$emit('showCatalogLoadDialog')"
133
+ >
134
+ {{ t('plugins.manageCatalog.imageLoad.load') }}
135
+ </button>
136
+ </div>
137
+ </template>
138
+ <template #row-actions="{row}">
139
+ <button
140
+ ref="catalogActions"
141
+ aria-haspopup="true"
142
+ type="button"
143
+ class="btn btn-sm role-multi-action actions"
144
+ data-testid="extensions-page-catalog-row-menu"
145
+ @click="setMenu"
146
+ >
147
+ <i class="icon icon-actions" />
148
+ </button>
149
+ <ActionMenu
150
+ :custom-actions="actions"
151
+ :open="menuOpen"
152
+ :use-custom-target-element="true"
153
+ :custom-target-element="menuTargetElement"
154
+ :custom-target-event="menuTargetEvent"
155
+ @close="setMenu(false)"
156
+ @uninstall="e => $emit('showUninstallDialog', row, e.event)"
157
+ />
158
+ </template>
159
+ </ResourceTable>
160
+ </div>
161
+ </div>
162
+ </template>
163
+
164
+ <style lang="scss" scoped>
165
+ .sub-row {
166
+ border-bottom: 1px solid var(--sortable-table-top-divider);
167
+ padding-left: 1rem;
168
+ padding-right: 1rem;
169
+ }
170
+
171
+ .col {
172
+ display: flex;
173
+ flex-direction: column;
174
+
175
+ section {
176
+ margin-bottom: 1.5rem;
177
+ }
178
+
179
+ .title {
180
+ margin-bottom: 0.5rem;
181
+ }
182
+ }
183
+ </style>
@@ -1,8 +1,10 @@
1
1
  <script>
2
- import AsyncButton from '@shell/components/AsyncButton';
3
- import { CATALOG } from '@shell/config/types';
2
+ import { mapGetters } from 'vuex';
4
3
 
5
- import { UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
4
+ import AsyncButton from '@shell/components/AsyncButton';
5
+ import { CATALOG, SERVICE, WORKLOAD_TYPES } from '@shell/config/types';
6
+ import { UI_PLUGIN_LABELS, UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
7
+ import { allHash } from '@shell/utils/promise';
6
8
 
7
9
  export default {
8
10
  components: { AsyncButton },
@@ -11,6 +13,8 @@ export default {
11
13
  return { plugin: undefined, busy: false };
12
14
  },
13
15
 
16
+ computed: { ...mapGetters({ allCharts: 'catalog/charts' }) },
17
+
14
18
  methods: {
15
19
  showDialog(plugin) {
16
20
  this.plugin = plugin;
@@ -29,7 +33,7 @@ export default {
29
33
  this.$emit('update', plugin.name, 'uninstall');
30
34
 
31
35
  // Delete the CR if this is a developer plugin (there is no Helm App, so need to remove the CRD ourselves)
32
- if (plugin.uiplugin?.isDeveloper) {
36
+ if (plugin.uiplugin?.isDeveloper || (plugin.catalog && plugin.uiplugin)) {
33
37
  // Delete the custom resource
34
38
  await plugin.uiplugin.remove();
35
39
  }
@@ -37,13 +41,28 @@ export default {
37
41
  // Find the app for this plugin
38
42
  const apps = await this.$store.dispatch('management/findAll', { type: CATALOG.APP });
39
43
 
40
- const pluginApp = apps.find((app) => {
41
- return app.namespace === UI_PLUGIN_NAMESPACE && app.name === plugin.name;
44
+ const pluginApps = apps.filter((app) => {
45
+ if (plugin.catalog && app.namespace === UI_PLUGIN_NAMESPACE) {
46
+ // Find the related apps from the deployed helm repository
47
+ const charts = this.allCharts.filter(chart => chart.repoName === plugin.repo?.metadata?.name);
48
+
49
+ return charts.some(chart => chart.chartName === app.metadata.name);
50
+ }
51
+
52
+ if (app.namespace === UI_PLUGIN_NAMESPACE && app.name === plugin.name) {
53
+ return app;
54
+ }
55
+
56
+ return false;
42
57
  });
43
58
 
44
- if (pluginApp) {
59
+ if (plugin.catalog) {
60
+ await this.removePluginImageResources(plugin.uiplugin);
61
+ }
62
+
63
+ if (pluginApps.length) {
45
64
  try {
46
- await pluginApp.remove();
65
+ pluginApps.forEach(app => app.remove());
47
66
  } catch (e) {
48
67
  this.$store.dispatch('growl/error', {
49
68
  title: this.t('plugins.error.generic'),
@@ -56,6 +75,28 @@ export default {
56
75
  }
57
76
 
58
77
  this.closeDialog(plugin);
78
+ },
79
+ async removePluginImageResources(plugin) {
80
+ const selector = `${ UI_PLUGIN_LABELS.CATALOG_IMAGE }=${ plugin.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE] }`;
81
+ const namespace = UI_PLUGIN_NAMESPACE;
82
+
83
+ if (selector) {
84
+ const hash = await allHash({
85
+ deployment: this.$store.dispatch('management/findMatching', {
86
+ type: WORKLOAD_TYPES.DEPLOYMENT, selector, namespace
87
+ }),
88
+ service: this.$store.dispatch('management/findMatching', {
89
+ type: SERVICE, selector, namespace
90
+ }),
91
+ repo: this.$store.dispatch('management/findMatching', { type: CATALOG.CLUSTER_REPO, selector })
92
+ });
93
+
94
+ for (const resource of Object.keys(hash)) {
95
+ if (hash[resource]) {
96
+ hash[resource].forEach(r => r.remove());
97
+ }
98
+ }
99
+ }
59
100
  }
60
101
  }
61
102
  };
@@ -77,7 +118,7 @@ export default {
77
118
  <div class="mt-10 dialog-panel">
78
119
  <div class="dialog-info">
79
120
  <p>
80
- {{ t('plugins.uninstall.prompt') }}
121
+ {{ plugin.catalog ? t('plugins.uninstall.custom') : t('plugins.uninstall.prompt') }}
81
122
  </p>
82
123
  </div>
83
124
  <div class="dialog-buttons">