@rancher/shell 0.3.4 → 0.3.6

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 (289) hide show
  1. package/assets/images/providers/outscale.svg +19 -0
  2. package/assets/styles/app.scss +1 -1
  3. package/assets/styles/base/_basic.scss +18 -0
  4. package/assets/styles/base/_mixins.scss +0 -11
  5. package/assets/styles/base/_variables.scss +2 -4
  6. package/assets/styles/fonts/_fontstack.scss +11 -11
  7. package/assets/styles/global/_button.scss +12 -2
  8. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  9. package/assets/translations/en-us.yaml +113 -22
  10. package/assets/translations/zh-hans.yaml +113 -24
  11. package/babel.config.js +13 -0
  12. package/chart/gatekeeper.vue +78 -0
  13. package/chart/istio.vue +135 -112
  14. package/chart/logging/index.vue +13 -4
  15. package/chart/monitoring/index.vue +15 -5
  16. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  17. package/chart/rancher-backup/index.vue +10 -3
  18. package/cloud-credential/aws.vue +1 -1
  19. package/cloud-credential/digitalocean.vue +1 -1
  20. package/cloud-credential/gcp.vue +1 -1
  21. package/cloud-credential/generic.vue +2 -2
  22. package/cloud-credential/linode.vue +1 -1
  23. package/cloud-credential/pnap.vue +1 -1
  24. package/components/ActionMenu.vue +3 -4
  25. package/components/AssignTo.vue +1 -1
  26. package/components/AsyncButton.vue +1 -1
  27. package/components/BannerGraphic.vue +1 -1
  28. package/components/BrandImage.vue +1 -4
  29. package/components/ButtonDropdown.vue +2 -3
  30. package/components/Carousel.vue +85 -37
  31. package/components/ChartPsp.vue +76 -0
  32. package/components/CruResource.vue +6 -2
  33. package/components/DashboardMetrics.vue +12 -10
  34. package/components/DetailText.vue +1 -1
  35. package/components/DisableAuthProviderModal.vue +1 -1
  36. package/components/EmberPage.vue +1 -1
  37. package/components/EtcdInfoBanner.vue +12 -7
  38. package/components/ExplorerMembers.vue +101 -6
  39. package/components/ExplorerProjectsNamespaces.vue +46 -3
  40. package/components/FileDiff.vue +6 -7
  41. package/components/GrafanaDashboard.vue +27 -23
  42. package/components/LazyImage.vue +10 -12
  43. package/components/LogItem.vue +1 -1
  44. package/components/Markdown.vue +1 -1
  45. package/components/PromptRemove.vue +2 -2
  46. package/components/PromptRestore.vue +1 -1
  47. package/components/ResourceDetail/Masthead.vue +16 -0
  48. package/components/ResourceDetail/index.vue +21 -4
  49. package/components/ResourceList/index.vue +1 -1
  50. package/components/ResourceTable.vue +4 -1
  51. package/components/SingleClusterInfo.vue +2 -2
  52. package/components/SortableTable/THead.vue +1 -1
  53. package/components/SortableTable/index.vue +28 -13
  54. package/components/SortableTable/selection.js +58 -50
  55. package/components/Wizard.vue +4 -2
  56. package/components/__tests__/AsyncButton.test.ts +3 -1
  57. package/components/__tests__/ChartPsp.test.ts +75 -0
  58. package/components/__tests__/CruResource.test.ts +3 -1
  59. package/components/auth/Principal.vue +1 -1
  60. package/components/auth/RoleDetailEdit.vue +2 -2
  61. package/components/fleet/FleetBundles.vue +3 -1
  62. package/components/fleet/FleetClusters.vue +1 -2
  63. package/components/fleet/FleetIntro.vue +9 -1
  64. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  65. package/components/fleet/FleetSummary.vue +7 -1
  66. package/components/form/HookOption.vue +14 -10
  67. package/components/form/LabeledSelect.vue +14 -11
  68. package/components/form/Labels.vue +32 -27
  69. package/components/form/MatchExpressions.vue +19 -4
  70. package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
  71. package/components/form/NameNsDescription.vue +32 -46
  72. package/components/form/ProjectMemberEditor.vue +46 -21
  73. package/components/form/ResourceSelector.vue +1 -1
  74. package/components/form/SecretSelector.vue +5 -1
  75. package/components/form/ServiceNameSelect.vue +1 -1
  76. package/components/form/SimpleSecretSelector.vue +9 -9
  77. package/components/form/Tolerations.vue +4 -1
  78. package/components/form/ValueFromResource.vue +14 -9
  79. package/components/form/WorkloadPorts.vue +2 -2
  80. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  81. package/components/form/__tests__/NameNsDescription.ts +59 -0
  82. package/components/formatter/InternalExternalIP.vue +6 -0
  83. package/components/formatter/InvolvedObjectLink.vue +54 -0
  84. package/components/formatter/Link.vue +20 -4
  85. package/components/formatter/LinkName.vue +6 -1
  86. package/components/formatter/ServiceTargets.vue +1 -1
  87. package/components/formatter/WorkloadHealthScale.vue +8 -2
  88. package/components/nav/Group.vue +2 -2
  89. package/components/nav/NamespaceFilter.vue +23 -11
  90. package/components/nav/TopLevelMenu.vue +2 -4
  91. package/components/nav/Type.vue +1 -1
  92. package/components/nav/WorkspaceSwitcher.vue +46 -5
  93. package/components/nuxt/nuxt-build-indicator.vue +143 -0
  94. package/components/nuxt/nuxt-child.js +122 -0
  95. package/components/nuxt/nuxt-error.vue +98 -0
  96. package/components/nuxt/nuxt-link.client.js +98 -0
  97. package/components/nuxt/nuxt-link.server.js +16 -0
  98. package/components/nuxt/nuxt-loading.vue +154 -0
  99. package/components/nuxt/nuxt.js +101 -0
  100. package/config/labels-annotations.js +17 -0
  101. package/config/middleware.js +12 -0
  102. package/config/product/auth.js +3 -2
  103. package/config/product/explorer.js +34 -6
  104. package/config/product/fleet.js +2 -0
  105. package/config/query-params.js +1 -0
  106. package/config/router.js +414 -0
  107. package/config/store.js +181 -0
  108. package/config/table-headers.js +54 -12
  109. package/config/types.js +18 -8
  110. package/config/uiplugins.js +30 -0
  111. package/content/docs/en-us/whats-new.md +10 -0
  112. package/content/docs/zh-hans/whats-new.md +11 -1
  113. package/core/plugin-routes.ts +23 -0
  114. package/core/plugin.ts +4 -2
  115. package/core/types.ts +258 -1
  116. package/creators/app/app.package.json +2 -1
  117. package/creators/app/files/.eslintrc.js +1 -1
  118. package/creators/app/files/babel.config.js +1 -18
  119. package/creators/app/files/tsconfig.json +0 -1
  120. package/creators/app/files/vue.config.js +6 -0
  121. package/creators/app/init +5 -5
  122. package/creators/pkg/files/.github/workflows/build-extension.yml +110 -0
  123. package/creators/pkg/files/tsconfig.json +0 -1
  124. package/creators/pkg/init +35 -4
  125. package/creators/pkg/pkg.package.json +3 -3
  126. package/creators/update/init +1 -1
  127. package/detail/constraints.gatekeeper.sh.constraint.vue +34 -17
  128. package/detail/fleet.cattle.io.clustergroup.vue +7 -1
  129. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  130. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  131. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  132. package/detail/workload/index.vue +3 -3
  133. package/dialog/AddClusterMemberDialog.vue +1 -1
  134. package/dialog/AddProjectMemberDialog.vue +2 -2
  135. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  136. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  137. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  138. package/dialog/GenericPrompt.vue +18 -6
  139. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  140. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  141. package/dialog/ScaleMachineDownDialog.vue +1 -1
  142. package/edit/auth/github.vue +8 -8
  143. package/edit/auth/googleoauth.vue +5 -5
  144. package/edit/auth/ldap/index.vue +1 -1
  145. package/edit/auth/oidc.vue +1 -1
  146. package/edit/auth/saml.vue +1 -1
  147. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  148. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  149. package/edit/fleet.cattle.io.gitrepo.vue +32 -4
  150. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  151. package/edit/logging.banzaicloud.io.output/index.vue +18 -5
  152. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
  153. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  154. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  155. package/edit/management.cattle.io.setting.vue +1 -1
  156. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  157. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  158. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  159. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  160. package/edit/namespace.vue +14 -10
  161. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  162. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +21 -4
  164. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  165. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  166. package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
  167. package/edit/provisioning.cattle.io.cluster/rke2.vue +344 -102
  168. package/edit/resources.cattle.io.backup.vue +1 -1
  169. package/edit/service.vue +1 -1
  170. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  171. package/edit/workload/__tests__/Job.test.ts +3 -1
  172. package/edit/workload/index.vue +8 -3
  173. package/edit/workload/mixins/workload.js +22 -7
  174. package/edit/workload/storage/Mount.vue +3 -3
  175. package/initialize/App.js +206 -0
  176. package/initialize/client.js +863 -0
  177. package/initialize/index.js +364 -0
  178. package/layouts/default.vue +7 -3
  179. package/layouts/standalone.vue +13 -0
  180. package/list/catalog.cattle.io.clusterrepo.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +6 -3
  182. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  183. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  184. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  185. package/list/node.vue +69 -16
  186. package/list/provisioning.cattle.io.cluster.vue +30 -1
  187. package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
  188. package/list/workload.vue +6 -4
  189. package/machine-config/azure.vue +97 -38
  190. package/middleware/authenticated.js +34 -0
  191. package/mixins/chart.js +101 -2
  192. package/mixins/fetch.client.js +95 -0
  193. package/mixins/fetch.server.js +73 -0
  194. package/mixins/labeled-form-element.ts +2 -2
  195. package/mixins/resource-fetch.js +2 -2
  196. package/models/apps.statefulset.js +28 -0
  197. package/models/cluster/node.js +23 -2
  198. package/models/cluster.x-k8s.io.machine.js +4 -2
  199. package/models/clusterroletemplatebinding.js +7 -0
  200. package/models/constraints.gatekeeper.sh.constraint.js +46 -0
  201. package/models/fleet.cattle.io.cluster.js +19 -10
  202. package/models/fleet.cattle.io.gitrepo.js +7 -2
  203. package/models/management.cattle.io.cluster.js +1 -1
  204. package/models/management.cattle.io.fleetworkspace.js +12 -0
  205. package/models/management.cattle.io.gitreporestriction.js +5 -0
  206. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  207. package/models/pod.js +4 -0
  208. package/models/provisioning.cattle.io.cluster.js +7 -5
  209. package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
  210. package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
  211. package/package.json +13 -21
  212. package/pages/auth/setup.vue +2 -2
  213. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  214. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  215. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  216. package/pages/c/_cluster/apps/charts/install.vue +98 -102
  217. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  218. package/pages/c/_cluster/explorer/index.vue +29 -25
  219. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  220. package/pages/c/_cluster/fleet/index.vue +95 -34
  221. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  222. package/pages/c/_cluster/istio/index.vue +5 -5
  223. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  224. package/pages/c/_cluster/monitoring/index.vue +7 -0
  225. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  226. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  227. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  228. package/pages/diagnostic.vue +32 -25
  229. package/pages/home.vue +9 -4
  230. package/pages/index.vue +10 -1
  231. package/pages/rio/mesh.vue +1 -2
  232. package/pkg/tsconfig.json +0 -1
  233. package/plugins/clean-html-directive.js +34 -0
  234. package/plugins/dashboard-store/actions.js +32 -9
  235. package/plugins/dashboard-store/index.js +1 -1
  236. package/plugins/dashboard-store/mutations.js +5 -2
  237. package/plugins/dashboard-store/resource-class.js +8 -1
  238. package/plugins/plugin.js +0 -14
  239. package/plugins/portal-vue.js +4 -0
  240. package/plugins/steve/mutations.js +3 -2
  241. package/plugins/steve/steve-description-class.js +5 -1
  242. package/plugins/steve/subscribe.js +63 -54
  243. package/plugins/steve-create-worker.js +14 -0
  244. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  245. package/promptRemove/management.cattle.io.project.vue +2 -2
  246. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  247. package/promptRemove/pod.vue +1 -1
  248. package/public/index.html +65 -0
  249. package/rancher-components/components/Banner/Banner.test.ts +7 -1
  250. package/rancher-components/components/Banner/Banner.vue +2 -1
  251. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  252. package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
  253. package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
  254. package/scripts/build-pkg.sh +1 -0
  255. package/scripts/clean +6 -0
  256. package/scripts/extension/bundle +58 -0
  257. package/scripts/extension/helmpatch +89 -0
  258. package/scripts/extension/publish +333 -0
  259. package/scripts/serve-pkgs +6 -2
  260. package/scripts/test-plugins-build.sh +4 -0
  261. package/store/__tests__/index.test.ts +110 -0
  262. package/store/index.js +145 -58
  263. package/store/type-map.js +6 -2
  264. package/tsconfig.default.json +36 -0
  265. package/tsconfig.json +23 -0
  266. package/types/rancher/index.d.ts +2 -0
  267. package/types/shell/index.d.ts +466 -320
  268. package/utils/__tests__/grafana.test.ts +44 -0
  269. package/utils/__tests__/string.test.ts +12 -0
  270. package/utils/auth.js +65 -0
  271. package/utils/axios.js +190 -0
  272. package/utils/cookie-universal-nuxt.js +10 -0
  273. package/utils/dom.js +15 -0
  274. package/utils/grafana.js +35 -16
  275. package/utils/monitoring.js +2 -1
  276. package/utils/nuxt.js +659 -0
  277. package/utils/position.js +5 -8
  278. package/utils/router.scrollBehavior.js +80 -0
  279. package/utils/select.js +1 -3
  280. package/utils/socket.js +1 -0
  281. package/utils/string.js +13 -0
  282. package/utils/time.js +9 -0
  283. package/vue.config.js +690 -0
  284. package/chart/rancher-alerting-drivers.vue +0 -53
  285. package/chart/rancher-gatekeeper.vue +0 -37
  286. package/creators/app/files/nuxt.config.js +0 -6
  287. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  288. package/nuxt.config.js +0 -798
  289. package/plugins/dashboard-store/extensions.js +0 -22
@@ -0,0 +1,44 @@
1
+ import { getClusterPrefix } from '@shell/utils/grafana';
2
+
3
+ describe('fx: getClusterPrefix', () => {
4
+ it('old monitoring version, downstream cluster', () => {
5
+ const prefix = getClusterPrefix('101.0.0+up19.0.3', 'c-abcd');
6
+
7
+ expect(prefix).toStrictEqual('/k8s/clusters/c-abcd');
8
+ });
9
+ it('old monitoring version, local cluster', () => {
10
+ const prefix = getClusterPrefix('101.0.0+up19.0.3', 'local');
11
+
12
+ expect(prefix).toStrictEqual('');
13
+ });
14
+ it('new monitoring version, downstream cluster', () => {
15
+ const prefix = getClusterPrefix('102.0.0+up40.1.2', 'c-abcd');
16
+
17
+ expect(prefix).toStrictEqual('/k8s/clusters/c-abcd');
18
+ });
19
+ it('new monitoring version, local cluster', () => {
20
+ const prefix = getClusterPrefix('102.0.0+up40.1.2', 'local');
21
+
22
+ expect(prefix).toStrictEqual('/k8s/clusters/local');
23
+ });
24
+ it('future monitoring version, downstream cluster', () => {
25
+ const prefix = getClusterPrefix('103.0.0+up41.0.0', 'c-abcd');
26
+
27
+ expect(prefix).toStrictEqual('/k8s/clusters/c-abcd');
28
+ });
29
+ it('future monitoring version, local cluster', () => {
30
+ const prefix = getClusterPrefix('103.0.0+up41.0.0', 'local');
31
+
32
+ expect(prefix).toStrictEqual('/k8s/clusters/local');
33
+ });
34
+ it('empty monitoring version, downstream cluster', () => {
35
+ const prefix = getClusterPrefix('', 'c-abcd');
36
+
37
+ expect(prefix).toStrictEqual('/k8s/clusters/c-abcd');
38
+ });
39
+ it('empty monitoring version, local cluster', () => {
40
+ const prefix = getClusterPrefix('', 'local');
41
+
42
+ expect(prefix).toStrictEqual('/k8s/clusters/local');
43
+ });
44
+ });
@@ -0,0 +1,12 @@
1
+ import { decodeHtml } from '@shell/utils/string';
2
+
3
+ describe('fx: decodeHtml', () => {
4
+ it('should decode HTML values from escaped string into valid markup', () => {
5
+ const text = '<i>whatever</i>';
6
+ const expectation = `<i>whatever</i>`;
7
+
8
+ const result = decodeHtml(text);
9
+
10
+ expect(result).toStrictEqual(expectation);
11
+ });
12
+ });
package/utils/auth.js CHANGED
@@ -2,6 +2,7 @@ import { Popup, popupWindowOptions } from '@shell/utils/window';
2
2
  import { parse as parseUrl, addParam } from '@shell/utils/url';
3
3
  import { BACK_TO, SPA, _EDIT, _FLAGGED } from '@shell/config/query-params';
4
4
  import { MANAGEMENT } from '@shell/config/types';
5
+ import { allHash } from '@shell/utils/promise';
5
6
 
6
7
  export function openAuthPopup(url, provider) {
7
8
  const popup = new Popup(() => {
@@ -79,3 +80,67 @@ export const authProvidersInfo = async(store) => {
79
80
  enabled
80
81
  };
81
82
  };
83
+
84
+ export const checkSchemasForFindAllHash = (types, store) => {
85
+ const hash = {};
86
+
87
+ for (const [key, value] of Object.entries(types)) {
88
+ const schema = store.getters[`${ value.inStoreType }/schemaFor`](value.type);
89
+
90
+ // It could be that user has permissions for GET but not list
91
+ // e.g. Standard user with GitRepo permissions try to fetch list of fleetworkspaces
92
+ // user has ability to GET but not fleet workspaces
93
+ // so optionally define a function that require it to pass before /findAll
94
+ const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema;
95
+
96
+ if (validSchema) {
97
+ hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type } );
98
+ }
99
+ }
100
+
101
+ return allHash(hash);
102
+ };
103
+
104
+ export const checkPermissions = (types, getters) => {
105
+ const hash = {};
106
+
107
+ for (const [key, value] of Object.entries(types)) {
108
+ const schema = getters['management/schemaFor'](value.type);
109
+
110
+ if (!schema) {
111
+ hash[key] = false;
112
+
113
+ continue;
114
+ }
115
+
116
+ // It could be that user has permissions for GET but not list
117
+ // e.g. Standard user with GitRepo permissions try to fetch list of fleetworkspaces
118
+ // user has ability to GET but not fleet workspaces
119
+ // so optionally define a function that require it to pass before /findAll
120
+ if (value.schemaValidator) {
121
+ hash[key] = value.schemaValidator(schema);
122
+
123
+ continue;
124
+ }
125
+
126
+ if (value.resourceMethods && schema) {
127
+ hash[key] = value.resourceMethods.every((method) => {
128
+ return (schema.resourceMethods || []).includes(method);
129
+ });
130
+
131
+ continue;
132
+ }
133
+
134
+ if (value.collectionMethods && schema) {
135
+ hash[key] = value.collectionMethods.every((method) => {
136
+ return (schema.collectionMethods || []).includes(method);
137
+ });
138
+
139
+ continue;
140
+ }
141
+
142
+ hash[key] = !!schema;
143
+ }
144
+
145
+ return allHash(hash);
146
+ };
package/utils/axios.js ADDED
@@ -0,0 +1,190 @@
1
+ import Axios from 'axios';
2
+ import defu from 'defu';
3
+ import axiosRetry from 'axios-retry';
4
+
5
+ // Axios.prototype cannot be modified
6
+ const axiosExtra = {
7
+ setBaseURL(baseURL) {
8
+ this.defaults.baseURL = baseURL;
9
+ },
10
+ setHeader(name, value, scopes = 'common') {
11
+ for (const scope of Array.isArray(scopes) ? scopes : [scopes]) {
12
+ if (!value) {
13
+ delete this.defaults.headers[scope][name];
14
+
15
+ return;
16
+ }
17
+ this.defaults.headers[scope][name] = value;
18
+ }
19
+ },
20
+ setToken(token, type, scopes = 'common') {
21
+ const value = !token ? null : (type ? `${ type } ` : '') + token;
22
+
23
+ this.setHeader('Authorization', value, scopes);
24
+ },
25
+ onRequest(fn) {
26
+ this.interceptors.request.use(config => fn(config) || config);
27
+ },
28
+ onResponse(fn) {
29
+ this.interceptors.response.use(response => fn(response) || response);
30
+ },
31
+ onRequestError(fn) {
32
+ this.interceptors.request.use(undefined, error => fn(error) || Promise.reject(error));
33
+ },
34
+ onResponseError(fn) {
35
+ this.interceptors.response.use(undefined, error => fn(error) || Promise.reject(error));
36
+ },
37
+ onError(fn) {
38
+ this.onRequestError(fn);
39
+ this.onResponseError(fn);
40
+ },
41
+ create(options) {
42
+ return createAxiosInstance(defu(options, this.defaults));
43
+ }
44
+ };
45
+
46
+ // Request helpers ($get, $post, ...)
47
+ for (const method of ['request', 'delete', 'get', 'head', 'options', 'post', 'put', 'patch']) {
48
+ axiosExtra[`$${ method }`] = function() {
49
+ return this[method].apply(this, arguments).then(res => res && res.data);
50
+ };
51
+ }
52
+
53
+ const extendAxiosInstance = (axios) => {
54
+ for (const key in axiosExtra) {
55
+ axios[key] = axiosExtra[key].bind(axios);
56
+ }
57
+ };
58
+
59
+ const createAxiosInstance = (axiosOptions) => {
60
+ // Create new axios instance
61
+ const axios = Axios.create(axiosOptions);
62
+
63
+ axios.CancelToken = Axios.CancelToken;
64
+ axios.isCancel = Axios.isCancel;
65
+
66
+ // Extend axios proto
67
+ extendAxiosInstance(axios);
68
+
69
+ // Setup interceptors
70
+
71
+ setupProgress(axios);
72
+ axiosRetry(axios, { retries: 0 });
73
+
74
+ return axios;
75
+ };
76
+
77
+ const setupProgress = (axios) => {
78
+ if (process.server) {
79
+ return;
80
+ }
81
+
82
+ // A noop loading inteterface for when $nuxt is not yet ready
83
+ const noopLoading = {
84
+ finish: () => { },
85
+ start: () => { },
86
+ fail: () => { },
87
+ set: () => { }
88
+ };
89
+
90
+ const $loading = () => {
91
+ const $nuxt = typeof window !== 'undefined' && window['$nuxt'];
92
+
93
+ return ($nuxt && $nuxt.$loading && $nuxt.$loading.set) ? $nuxt.$loading : noopLoading;
94
+ };
95
+
96
+ let currentRequests = 0;
97
+
98
+ axios.onRequest((config) => {
99
+ if (config && config.progress === false) {
100
+ return;
101
+ }
102
+
103
+ currentRequests++;
104
+ });
105
+
106
+ axios.onResponse((response) => {
107
+ if (response && response.config && response.config.progress === false) {
108
+ return;
109
+ }
110
+
111
+ currentRequests--;
112
+ if (currentRequests <= 0) {
113
+ currentRequests = 0;
114
+ $loading().finish();
115
+ }
116
+ });
117
+
118
+ axios.onError((error) => {
119
+ if (error && error.config && error.config.progress === false) {
120
+ return;
121
+ }
122
+
123
+ currentRequests--;
124
+
125
+ if (Axios.isCancel(error)) {
126
+ return;
127
+ }
128
+
129
+ $loading().fail();
130
+ $loading().finish();
131
+ });
132
+
133
+ const onProgress = (e) => {
134
+ if (!currentRequests) {
135
+ return;
136
+ }
137
+ const progress = ((e.loaded * 100) / (e.total * currentRequests));
138
+
139
+ $loading().set(Math.min(100, progress));
140
+ };
141
+
142
+ axios.defaults.onUploadProgress = onProgress;
143
+ axios.defaults.onDownloadProgress = onProgress;
144
+ };
145
+
146
+ export default (ctx, inject) => {
147
+ // runtimeConfig
148
+ const runtimeConfig = (ctx.$config && ctx.$config.axios) || {};
149
+ // baseURL
150
+ const baseURL = process.browser ? (runtimeConfig.browserBaseURL || runtimeConfig.baseURL || '/') : (runtimeConfig.baseURL || process.env._AXIOS_BASE_URL_ || 'https://localhost:8005/');
151
+
152
+ // Create fresh objects for all default header scopes
153
+ // Axios creates only one which is shared across SSR requests!
154
+ // https://github.com/mzabriskie/axios/blob/master/lib/defaults.js
155
+ const headers = {
156
+ common: { Accept: 'application/json, text/plain, */*' },
157
+ delete: {},
158
+ get: {},
159
+ head: {},
160
+ post: {},
161
+ put: {},
162
+ patch: {}
163
+ };
164
+
165
+ const axiosOptions = {
166
+ baseURL,
167
+ headers
168
+ };
169
+
170
+ // Proxy SSR request headers headers
171
+ if (process.server && ctx.req && ctx.req.headers) {
172
+ const reqHeaders = { ...ctx.req.headers };
173
+
174
+ for (const h of ['accept', 'host', 'cf-ray', 'cf-connecting-ip', 'content-length', 'content-md5', 'content-type']) {
175
+ delete reqHeaders[h];
176
+ }
177
+ axiosOptions.headers.common = { ...reqHeaders, ...axiosOptions.headers.common };
178
+ }
179
+
180
+ if (process.server) {
181
+ // Don't accept brotli encoding because Node can't parse it
182
+ axiosOptions.headers.common['accept-encoding'] = 'gzip, deflate';
183
+ }
184
+
185
+ const axios = createAxiosInstance(axiosOptions);
186
+
187
+ // Inject axios to the context as $axios
188
+ ctx.$axios = axios;
189
+ inject('axios', axios);
190
+ };
@@ -0,0 +1,10 @@
1
+ import cookieUniversal from 'cookie-universal';
2
+
3
+ export default ({ req, res }, inject) => {
4
+ const options = {
5
+ alias: 'cookies',
6
+ parseJSON: true
7
+ };
8
+
9
+ inject(options.alias, cookieUniversal(req, res, options.parseJSON));
10
+ };
package/utils/dom.js ADDED
@@ -0,0 +1,15 @@
1
+ export function getParent(el, parentSelector) {
2
+ el = el?.parentElement;
3
+
4
+ if (!el) {
5
+ return null;
6
+ }
7
+
8
+ const matchFn = el.matches || el.matchesSelector;
9
+
10
+ if (!matchFn.call(el, parentSelector)) {
11
+ return getParent(el, parentSelector);
12
+ }
13
+
14
+ return el;
15
+ }
package/utils/grafana.js CHANGED
@@ -1,11 +1,22 @@
1
1
  import { haveV2Monitoring } from '@shell/utils/monitoring';
2
2
  import { parse as parseUrl, addParam } from '@shell/utils/url';
3
+ import { compare } from '@shell/utils/version';
4
+ import { CATALOG } from '@shell/config/types';
3
5
 
4
- export function computeDashboardUrl(embedUrl, clusterId, params) {
6
+ const MONITORING_VERSION_NEW_URL_PATTERN = '102.0.0+up40.1.2';
7
+
8
+ export function getClusterPrefix(monitoringVersion, clusterId) {
9
+ if (compare(monitoringVersion, MONITORING_VERSION_NEW_URL_PATTERN) >= 0) {
10
+ return `/k8s/clusters/${ clusterId }`;
11
+ }
12
+
13
+ return clusterId === 'local' ? '' : `/k8s/clusters/${ clusterId }`;
14
+ }
15
+
16
+ export function computeDashboardUrl(monitoringVersion, embedUrl, clusterId, params) {
5
17
  const url = parseUrl(embedUrl);
6
- const clusterPrefix = clusterId === 'local' ? '' : `/k8s/clusters/${ clusterId }`;
7
18
 
8
- let newUrl = `${ clusterPrefix }${ url.path }`;
19
+ let newUrl = `${ getClusterPrefix(monitoringVersion, clusterId) }${ url.path }`;
9
20
 
10
21
  if (url.query.viewPanel) {
11
22
  newUrl = addParam(newUrl, 'viewPanel', url.query.viewPanel);
@@ -20,14 +31,13 @@ export function computeDashboardUrl(embedUrl, clusterId, params) {
20
31
  return newUrl;
21
32
  }
22
33
 
23
- export async function dashboardExists(store, clusterId, embedUrl, storeName = 'cluster') {
34
+ export async function dashboardExists(monitoringVersion, store, clusterId, embedUrl, storeName = 'cluster') {
24
35
  if ( !haveV2Monitoring(store.getters) ) {
25
36
  return false;
26
37
  }
27
38
 
28
39
  const url = parseUrl(embedUrl);
29
- const clusterPrefix = clusterId === 'local' ? '' : `/k8s/clusters/${ clusterId }`;
30
- const prefix = `${ clusterPrefix }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/`;
40
+ const prefix = `${ getClusterPrefix(monitoringVersion, clusterId) }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/`;
31
41
  const delimiter = 'http:rancher-monitoring-grafana:80/proxy/';
32
42
  const path = url.path.split(delimiter)[1];
33
43
  const uid = path.split('/')[1];
@@ -43,41 +53,50 @@ export async function dashboardExists(store, clusterId, embedUrl, storeName = 'c
43
53
  }
44
54
 
45
55
  export async function allDashboardsExist(store, clusterId, embeddedUrls, storeName = 'cluster') {
46
- const existPromises = embeddedUrls.map(url => dashboardExists(store, clusterId, url, storeName));
56
+ let res;
57
+
58
+ try {
59
+ res = await store.dispatch(`${ storeName }/find`, { type: CATALOG.APP, id: 'cattle-monitoring-system/rancher-monitoring' });
60
+ } catch (err) {
61
+ return false;
62
+ }
63
+
64
+ const monitoringVersion = res?.currentVersion;
65
+
66
+ const existPromises = embeddedUrls.map(url => dashboardExists(monitoringVersion, store, clusterId, url, storeName));
47
67
 
48
68
  return (await Promise.all(existPromises)).every(exists => exists);
49
69
  }
50
70
 
51
- export function queryGrafana(dispatch, clusterId, query, range, step) {
52
- const clusterPrefix = clusterId === 'local' ? '' : `/k8s/clusters/${ clusterId }`;
53
- const url = `${ clusterPrefix }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/api/datasources/proxy/1/api/v1/query_range?query=${ query }&start=${ range.start }&end=${ range.end }&step=${ step }`;
71
+ export function queryGrafana(monitoringVersion, dispatch, clusterId, query, range, step) {
72
+ const url = `${ getClusterPrefix(monitoringVersion, clusterId) }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/api/datasources/proxy/1/api/v1/query_range?query=${ query }&start=${ range.start }&end=${ range.end }&step=${ step }`;
54
73
 
55
74
  return dispatch('cluster/request', { url, redirectUnauthorized: false });
56
75
  }
57
76
 
58
- export async function hasLeader(dispatch, clusterId) {
77
+ export async function hasLeader(monitoringVersion, dispatch, clusterId) {
59
78
  const end = Date.now() / 1000;
60
79
  const start = end - (5 * 60);
61
80
 
62
- const response = await queryGrafana(dispatch, clusterId, 'max(etcd_server_has_leader)', { start, end }, 30);
81
+ const response = await queryGrafana(monitoringVersion, dispatch, clusterId, 'max(etcd_server_has_leader)', { start, end }, 30);
63
82
 
64
83
  return response.data.result[0]?.values?.[0]?.[1] === '1';
65
84
  }
66
85
 
67
- export async function leaderChanges(dispatch, clusterId) {
86
+ export async function leaderChanges(monitoringVersion, dispatch, clusterId) {
68
87
  const end = Date.now() / 1000;
69
88
  const start = end - (60 * 60);
70
89
 
71
- const response = await queryGrafana(dispatch, clusterId, 'max(etcd_server_leader_changes_seen_total)', { start, end }, 30);
90
+ const response = await queryGrafana(monitoringVersion, dispatch, clusterId, 'max(etcd_server_leader_changes_seen_total)', { start, end }, 30);
72
91
 
73
92
  return response.data.result[0]?.values?.[0]?.[1] || 0;
74
93
  }
75
94
 
76
- export async function failedProposals(dispatch, clusterId) {
95
+ export async function failedProposals(monitoringVersion, dispatch, clusterId) {
77
96
  const end = Date.now() / 1000;
78
97
  const start = end - (60 * 60);
79
98
 
80
- const response = await queryGrafana(dispatch, clusterId, 'sum(etcd_server_proposals_failed_total)', { start, end }, 30);
99
+ const response = await queryGrafana(monitoringVersion, dispatch, clusterId, 'sum(etcd_server_proposals_failed_total)', { start, end }, 30);
81
100
 
82
101
  return response.data.result[0]?.values?.[0]?.[1] || 0;
83
102
  }
@@ -26,9 +26,10 @@ export function haveV2Monitoring(getters) {
26
26
  if (haveV1Monitoring(getters)) {
27
27
  return false;
28
28
  }
29
+ const inStore = getters['getStoreNameByProductId'];
29
30
 
30
31
  // Just check for the pod monitors CRD
31
- const schemas = getters[`cluster/all`](SCHEMA);
32
+ const schemas = getters[`${ inStore }/all`](SCHEMA);
32
33
  const exists = findBy(schemas, 'id', normalizeType(MONITORING.PODMONITOR));
33
34
 
34
35
  return !!exists;