@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
package/vue.config.js ADDED
@@ -0,0 +1,690 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const serveStatic = require('serve-static');
4
+ const webpack = require('webpack');
5
+ const { generateDynamicTypeImport } = require('./pkg/auto-import');
6
+ const CopyWebpackPlugin = require('copy-webpack-plugin');
7
+
8
+ // Suppress info level logging messages from http-proxy-middleware
9
+ // This hides all of the "[HPM Proxy created] ..." messages
10
+ const oldInfoLogger = console.info; // eslint-disable-line no-console
11
+
12
+ console.info = () => {}; // eslint-disable-line no-console
13
+
14
+ const { createProxyMiddleware } = require('http-proxy-middleware');
15
+
16
+ console.info = oldInfoLogger; // eslint-disable-line no-console
17
+
18
+ // This is currently hardcoded to avoid importing the TS
19
+ // const { STANDARD } = require('./config/private-label');
20
+ const STANDARD = 1;
21
+
22
+ const dev = (process.env.NODE_ENV !== 'production');
23
+ const devPorts = dev || process.env.DEV_PORTS === 'true';
24
+
25
+ // human readable version used on rancher dashboard about page
26
+ const dashboardVersion = process.env.DASHBOARD_VERSION;
27
+
28
+ const prime = process.env.PRIME;
29
+
30
+ const pl = process.env.PL || STANDARD;
31
+ const commit = process.env.COMMIT || 'head';
32
+ const perfTest = (process.env.PERF_TEST === 'true'); // Enable performance testing when in dev
33
+ const instrumentCode = (process.env.TEST_INSTRUMENT === 'true'); // Instrument code for code coverage in e2e tests
34
+
35
+ let api = process.env.API || 'http://localhost:8989';
36
+
37
+ if ( !api.startsWith('http') ) {
38
+ api = `https://${ api }`;
39
+ }
40
+ // ===============================================================================================
41
+ // Nuxt configuration
42
+ // ===============================================================================================
43
+
44
+ // Expose a function that can be used by an app to provide a nuxt configuration for building an application
45
+ // This takes the directory of the application as tehfirst argument so that we can derive folder locations
46
+ // from it, rather than from the location of this file
47
+ module.exports = function(dir, _appConfig) {
48
+ // Paths to the shell folder when it is included as a node dependency
49
+ let SHELL = 'node_modules/@rancher/shell';
50
+ let SHELL_ABS = path.join(dir, 'node_modules/@rancher/shell');
51
+ let COMPONENTS_DIR = path.join(SHELL_ABS, 'rancher-components');
52
+
53
+ if (fs.existsSync(SHELL_ABS)) {
54
+ const stat = fs.lstatSync(SHELL_ABS);
55
+
56
+ // If @rancher/shell is a symlink, then use the components folder for it
57
+ if (stat.isSymbolicLink()) {
58
+ const REAL_SHELL_ABS = fs.realpathSync(SHELL_ABS); // In case the shell is being linked via 'yarn link'
59
+
60
+ COMPONENTS_DIR = path.join(REAL_SHELL_ABS, '..', 'pkg', 'rancher-components', 'src', 'components');
61
+ }
62
+ }
63
+
64
+ // If we have a local folder named 'shell' then use that rather than the one in node_modules
65
+ // This will be the case in the main dashboard repository.
66
+ if (fs.existsSync(path.join(dir, 'shell'))) {
67
+ SHELL = './shell';
68
+ SHELL_ABS = path.join(dir, 'shell');
69
+ COMPONENTS_DIR = path.join(dir, 'pkg', 'rancher-components', 'src', 'components');
70
+ }
71
+
72
+ const babelPlugins = [
73
+ // TODO: Browser support
74
+ // ['@babel/plugin-transform-modules-commonjs'],
75
+ ['@babel/plugin-proposal-private-property-in-object', { loose: true }]
76
+ ];
77
+
78
+ if (instrumentCode) {
79
+ babelPlugins.push('babel-plugin-istanbul');
80
+
81
+ console.warn('Instrumenting code for coverage'); // eslint-disable-line no-console
82
+ }
83
+
84
+ // ===============================================================================================
85
+ // Functions for the UI Pluginas
86
+ // ===============================================================================================
87
+
88
+ const appConfig = _appConfig || {};
89
+ const excludes = appConfig.excludes || [];
90
+
91
+ const serverMiddleware = [];
92
+ const watcherIgnores = [
93
+ /.shell/,
94
+ /dist-pkg/,
95
+ /scripts\/standalone/
96
+ ];
97
+
98
+ // Find any UI packages in node_modules
99
+ const NM = path.join(dir, 'node_modules');
100
+ const pkg = require(path.join(dir, 'package.json'));
101
+ const nmPackages = {};
102
+
103
+ if (pkg && pkg.dependencies) {
104
+ Object.keys(pkg.dependencies).forEach((pkg) => {
105
+ const f = require(path.join(NM, pkg, 'package.json'));
106
+
107
+ // The package.json must have the 'rancher' property to mark it as a UI package
108
+ if (f.rancher) {
109
+ const id = `${ f.name }-${ f.version }`;
110
+
111
+ nmPackages[id] = f.main;
112
+
113
+ // Add server middleware to serve up the files for this UI package
114
+ serverMiddleware.push({
115
+ path: `/pkg/${ id }`,
116
+ handler: serveStatic(path.join(NM, pkg))
117
+ });
118
+ }
119
+ });
120
+ }
121
+
122
+ serverMiddleware.push({
123
+ path: '/uiplugins-catalog',
124
+ handler: (req, res, next) => {
125
+ const p = req.url.split('?');
126
+
127
+ try {
128
+ const proxy = createProxyMiddleware({
129
+ target: p[1],
130
+ pathRewrite: { '^.*': p[0] }
131
+ });
132
+
133
+ return proxy(req, res, next);
134
+ } catch (e) {
135
+ console.error(e); // eslint-disable-line no-console
136
+ }
137
+ }
138
+ });
139
+
140
+ function includePkg(name) {
141
+ if (name.startsWith('.') || name === 'node_modules') {
142
+ return false;
143
+ }
144
+
145
+ return !excludes || (excludes && !excludes.includes(name));
146
+ }
147
+
148
+ excludes.forEach((e) => {
149
+ watcherIgnores.push(new RegExp(`/pkg.${ e }`));
150
+ });
151
+
152
+ // For each package in the pkg folder that is being compiled into the application,
153
+ // Add in the code to automatically import the types from that package
154
+ // This imports models, edit, detail, list etc
155
+ // When built as a UI package, shell/pkg/vue.config.js does the same thing
156
+ const autoImportTypes = {};
157
+ const VirtualModulesPlugin = require('webpack-virtual-modules');
158
+ let reqs = '';
159
+ const pkgFolder = path.relative(dir, './pkg');
160
+
161
+ if (fs.existsSync(pkgFolder)) {
162
+ const items = fs.readdirSync(path.relative(dir, './pkg'));
163
+
164
+ // Ignore hidden folders
165
+ items.filter(name => !name.startsWith('.')).forEach((name) => {
166
+ const f = require(path.join(dir, 'pkg', name, 'package.json'));
167
+
168
+ // Package file must have rancher field to be a plugin
169
+ if (includePkg(name) && f.rancher) {
170
+ reqs += `$plugin.initPlugin('${ name }', require(\'~/pkg/${ name }\')); `;
171
+ }
172
+
173
+ // // Serve the code for the UI package in case its used for dynamic loading (but not if the same package was provided in node_modules)
174
+ // if (!nmPackages[name]) {
175
+ // const pkgPackageFile = require(path.join(dir, 'pkg', name, 'package.json'));
176
+ // const pkgRef = `${ name }-${ pkgPackageFile.version }`;
177
+
178
+ // serverMiddleware.push({ path: `/pkg/${ pkgRef }`, handler: serveStatic(`${ dir }/dist-pkg/${ pkgRef }`) });
179
+ // }
180
+ autoImportTypes[`node_modules/@rancher/auto-import/${ name }`] = generateDynamicTypeImport(`@pkg/${ name }`, path.join(dir, `pkg/${ name }`));
181
+ });
182
+ }
183
+
184
+ Object.keys(nmPackages).forEach((m) => {
185
+ reqs += `$plugin.loadAsync('${ m }', '/pkg/${ m }/${ nmPackages[m] }');`;
186
+ });
187
+
188
+ // Generate a virtual module '@rancher/dyanmic.js` which imports all of the packages that should be built into the application
189
+ // This is imported in 'shell/extensions/extension-loader.js` which ensures the all code for plugins to be included is imported in the application
190
+ const virtualModules = new VirtualModulesPlugin({ 'node_modules/@rancher/dynamic.js': `export default function ($plugin) { ${ reqs } };` });
191
+ const autoImport = new webpack.NormalModuleReplacementPlugin(/^@rancher\/auto-import$/, (resource) => {
192
+ const ctx = resource.context.split('/');
193
+ const pkg = ctx[ctx.length - 1];
194
+
195
+ resource.request = `@rancher/auto-import/${ pkg }`;
196
+ });
197
+
198
+ // @pkg imports must be resolved to the package that it importing them - this allows a package to use @pkg as an alis
199
+ // to the root of that particular package
200
+ const pkgImport = new webpack.NormalModuleReplacementPlugin(/^@pkg/, (resource) => {
201
+ const ctx = resource.context.split('/');
202
+ // Find 'pkg' folder in the contxt
203
+ const index = ctx.findIndex(s => s === 'pkg');
204
+
205
+ if (index !== -1 && (index + 1) < ctx.length) {
206
+ const pkg = ctx[index + 1];
207
+ let p = path.resolve(dir, 'pkg', pkg, resource.request.substr(5));
208
+
209
+ if (resource.request.startsWith(`@pkg/${ pkg }`)) {
210
+ p = path.resolve(dir, 'pkg', resource.request.substr(5));
211
+ }
212
+
213
+ resource.request = p;
214
+ }
215
+ });
216
+
217
+ // Serve up the dist-pkg folder under /pkg
218
+ serverMiddleware.push({ path: `/pkg/`, handler: serveStatic(`${ dir }/dist-pkg/`) });
219
+ // Endpoint to download and unpack a tgz from the local verdaccio rgistry (dev)
220
+ serverMiddleware.push(path.resolve(dir, SHELL, 'server', 'verdaccio-middleware'));
221
+ // Add the standard dashboard server middleware after the middleware added to serve up UI packages
222
+ serverMiddleware.push(path.resolve(dir, SHELL, 'server', 'server-middleware'));
223
+
224
+ // ===============================================================================================
225
+ // Dashboard nuxt configuration
226
+ // ===============================================================================================
227
+
228
+ require('events').EventEmitter.defaultMaxListeners = 20;
229
+ require('dotenv').config();
230
+
231
+ let routerBasePath = '/';
232
+ let resourceBase = '';
233
+ let outputDir = 'dist';
234
+
235
+ if ( typeof process.env.ROUTER_BASE !== 'undefined' ) {
236
+ routerBasePath = process.env.ROUTER_BASE;
237
+ }
238
+
239
+ if ( typeof process.env.RESOURCE_BASE !== 'undefined' ) {
240
+ resourceBase = process.env.RESOURCE_BASE;
241
+ }
242
+
243
+ if ( typeof process.env.OUTPUT_DIR !== 'undefined' ) {
244
+ outputDir = process.env.OUTPUT_DIR;
245
+ }
246
+
247
+ if ( resourceBase && !resourceBase.endsWith('/') ) {
248
+ resourceBase += '/';
249
+ }
250
+
251
+ // Store the Router Base as env variable that we can use in `nuxt/router.js`
252
+ process.env.VUE_APP_ROUTER_BASE = routerBasePath;
253
+
254
+ console.log(`Build: ${ dev ? 'Development' : 'Production' }`); // eslint-disable-line no-console
255
+
256
+ if ( !dev ) {
257
+ console.log(`Version: ${ dashboardVersion }`); // eslint-disable-line no-console
258
+ }
259
+
260
+ if ( !dev ) {
261
+ console.log(`Version: ${ dashboardVersion }`); // eslint-disable-line no-console
262
+ }
263
+
264
+ if ( resourceBase ) {
265
+ console.log(`Resource Base URL: ${ resourceBase }`); // eslint-disable-line no-console
266
+ }
267
+
268
+ if ( routerBasePath !== '/' ) {
269
+ console.log(`Router Base Path: ${ routerBasePath }`); // eslint-disable-line no-console
270
+ }
271
+
272
+ if ( pl !== STANDARD ) {
273
+ console.log(`PL: ${ pl }`); // eslint-disable-line no-console
274
+ }
275
+ const rancherEnv = process.env.RANCHER_ENV || 'web';
276
+
277
+ console.log(`API: '${ api }'. Env: '${ rancherEnv }'`); // eslint-disable-line no-console
278
+ const proxy = {
279
+ ...appConfig.proxies,
280
+ '/k8s': proxyWsOpts(api), // Straight to a remote cluster (/k8s/clusters/<id>/)
281
+ '/pp': proxyWsOpts(api), // For (epinio) standalone API
282
+ '/api': proxyWsOpts(api), // Management k8s API
283
+ '/apis': proxyWsOpts(api), // Management k8s API
284
+ '/v1': proxyWsOpts(api), // Management Steve API
285
+ '/v3': proxyWsOpts(api), // Rancher API
286
+ '/v3-public': proxyOpts(api), // Rancher Unauthed API
287
+ '/api-ui': proxyOpts(api), // Browser API UI
288
+ '/meta': proxyMetaOpts(api), // Browser API UI
289
+ '/v1-*': proxyOpts(api), // SAML, KDM, etc
290
+ '/rancherversion': proxyPrimeOpts(api), // Rancher version endpoint
291
+ // These are for Ember embedding
292
+ '/c/*/edit': proxyOpts('https://127.0.0.1:8000'), // Can't proxy all of /c because that's used by Vue too
293
+ '/k/': proxyOpts('https://127.0.0.1:8000'),
294
+ '/g/': proxyOpts('https://127.0.0.1:8000'),
295
+ '/n/': proxyOpts('https://127.0.0.1:8000'),
296
+ '/p/': proxyOpts('https://127.0.0.1:8000'),
297
+ '/assets': proxyOpts('https://127.0.0.1:8000'),
298
+ '/translations': proxyOpts('https://127.0.0.1:8000'),
299
+ '/engines-dist': proxyOpts('https://127.0.0.1:8000'),
300
+ };
301
+
302
+ const config = {
303
+ // Vue server
304
+ devServer: {
305
+ https: (devPorts ? {
306
+ key: fs.readFileSync(path.resolve(__dirname, 'server/server.key')),
307
+ cert: fs.readFileSync(path.resolve(__dirname, 'server/server.crt'))
308
+ } : null),
309
+ port: (devPorts ? 8005 : 80),
310
+ host: '0.0.0.0',
311
+ public: `https://0.0.0.0:${ devPorts ? 8005 : 80 }`,
312
+ before(app, server) {
313
+ const socketProxies = {};
314
+
315
+ // Close down quickly in response to CTRL + C
316
+ process.once('SIGINT', () => {
317
+ server.close();
318
+ console.log('\n'); // eslint-disable-line no-console
319
+ process.exit(1);
320
+ });
321
+
322
+ Object.keys(proxy).forEach((p) => {
323
+ const px = createProxyMiddleware({
324
+ ...proxy[p],
325
+ ws: false // We will handle the web socket upgrade
326
+ });
327
+
328
+ if (proxy[p].ws) {
329
+ socketProxies[p] = px;
330
+ }
331
+ app.use(p, px);
332
+ });
333
+
334
+ server.websocketProxies.push({
335
+ upgrade(req, socket, head) {
336
+ const path = Object.keys(socketProxies).find(path => req.url.startsWith(path));
337
+
338
+ if (path) {
339
+ const proxy = socketProxies[path];
340
+
341
+ if (proxy.upgrade) {
342
+ proxy.upgrade(req, socket, head);
343
+ } else {
344
+ console.log(`Upgrade for Proxy is not defined. Cannot upgrade Web socket for ${ req.url }`); // eslint-disable-line no-console
345
+ }
346
+ } else {
347
+ console.log(`Unknown Web socket upgrade request for ${ req.url }`); // eslint-disable-line no-console
348
+ }
349
+ }
350
+ });
351
+ },
352
+ },
353
+ publicPath: resourceBase || undefined,
354
+ css: {
355
+ loaderOptions: {
356
+ sass: {
357
+ // This is effectively added to the beginning of each style that's imported or included in a vue file. We may want to look into including these in app.scss
358
+ additionalData: `
359
+ @use 'sass:math';
360
+ @import "~shell/assets/styles/base/_variables.scss";
361
+ @import "~shell/assets/styles/base/_functions.scss";
362
+ @import "~shell/assets/styles/base/_mixins.scss";
363
+ `
364
+ }
365
+ }
366
+ },
367
+
368
+ outputDir,
369
+
370
+ pages: {
371
+ index: {
372
+ entry: path.join(SHELL_ABS, '/initialize/client.js'),
373
+ template: path.join(SHELL_ABS, '/public/index.html')
374
+ }
375
+ },
376
+
377
+ configureWebpack(config) {
378
+ config.resolve.alias['~'] = dir;
379
+ config.resolve.alias['@'] = dir;
380
+ config.resolve.alias['~assets'] = path.join(__dirname, 'assets');
381
+ config.resolve.alias['~shell'] = SHELL_ABS;
382
+ config.resolve.alias['@shell'] = SHELL_ABS;
383
+ config.resolve.alias['@pkg'] = path.join(dir, 'pkg');
384
+ config.resolve.alias['./node_modules'] = path.join(dir, 'node_modules');
385
+ config.resolve.alias['@components'] = COMPONENTS_DIR;
386
+ config.resolve.modules.push(__dirname);
387
+ config.plugins.push(virtualModules);
388
+ config.plugins.push(autoImport);
389
+ config.plugins.push(new VirtualModulesPlugin(autoImportTypes));
390
+ config.plugins.push(pkgImport);
391
+ // DefinePlugin does string replacement within our code. We may want to consider replacing it with something else. In code we'll see something like
392
+ // process.env.commit even though process and env aren't even defined objects. This could cause people to be mislead.
393
+ config.plugins.push(new webpack.DefinePlugin({
394
+ 'process.client': JSON.stringify(true),
395
+ 'process.env.commit': JSON.stringify(commit),
396
+ 'process.env.version': JSON.stringify(dashboardVersion),
397
+ 'process.env.dev': JSON.stringify(dev),
398
+ 'process.env.pl': JSON.stringify(pl),
399
+ 'process.env.perfTest': JSON.stringify(perfTest),
400
+ 'process.env.rancherEnv': JSON.stringify(rancherEnv),
401
+ 'process.env.harvesterPkgUrl': JSON.stringify(process.env.HARVESTER_PKG_URL),
402
+ 'process.env.api': JSON.stringify(api),
403
+
404
+ // This is a replacement of the nuxt publicRuntimeConfig
405
+ 'nuxt.publicRuntimeConfig': JSON.stringify({
406
+ rancherEnv,
407
+ dashboardVersion
408
+ }),
409
+ }));
410
+
411
+ // The static assets need to be in the built public folder in order to get served (primarily the favicon for now)
412
+ config.plugins.push(new CopyWebpackPlugin([{ from: path.join(SHELL_ABS, 'static'), to: 'public' }]));
413
+
414
+ config.resolve.extensions.push(...['.tsx', '.ts', '.js', '.vue', '.scss']);
415
+ config.watchOptions = config.watchOptions || {};
416
+ config.watchOptions.ignored = watcherIgnores;
417
+
418
+ if (dev) {
419
+ config.devtool = 'cheap-module-source-map';
420
+ } else {
421
+ config.devtool = 'source-map';
422
+ }
423
+
424
+ config.resolve.symlinks = false;
425
+
426
+ // Ensure we process files in the @rancher/shell folder
427
+ config.module.rules.forEach((r) => {
428
+ if ('test.js'.match(r.test)) {
429
+ if (r.exclude) {
430
+ const orig = r.exclude;
431
+
432
+ r.exclude = function(modulePath) {
433
+ if (modulePath.indexOf(SHELL_ABS) === 0 || typeof orig !== 'function') {
434
+ return false;
435
+ }
436
+
437
+ return orig(modulePath);
438
+ };
439
+ }
440
+ }
441
+ });
442
+
443
+ // Instrument code for tests
444
+ const babelPlugins = [
445
+ // TODO: Browser support
446
+ // ['@babel/plugin-transform-modules-commonjs'],
447
+ ['@babel/plugin-proposal-private-property-in-object', { loose: true }],
448
+ ['@babel/plugin-proposal-class-properties', { loose: true }]
449
+ ];
450
+
451
+ if (instrumentCode) {
452
+ babelPlugins.push('babel-plugin-istanbul');
453
+
454
+ console.warn('Instrumenting code for coverage'); // eslint-disable-line no-console
455
+ }
456
+
457
+ const loaders = [
458
+ // Ensure there is a fallback for browsers that don't support web workers
459
+ {
460
+ test: /web-worker.[a-z-]+.js/i,
461
+ loader: 'worker-loader',
462
+ options: { inline: 'fallback' },
463
+ },
464
+ // Handler for csv files (e.g. ec2 instance data)
465
+ {
466
+ test: /\.csv$/i,
467
+ loader: 'csv-loader',
468
+ options: {
469
+ dynamicTyping: true,
470
+ header: true,
471
+ skipEmptyLines: true
472
+ },
473
+ },
474
+ // Handler for yaml files (used for i18n files, for example)
475
+ {
476
+ test: /\.ya?ml$/i,
477
+ loader: 'js-yaml-loader',
478
+ options: { name: '[path][name].[ext]' },
479
+ },
480
+ {
481
+ test: /\.m?[tj]sx?$/,
482
+ // This excludes no modules except for node_modules/@rancher/... so that plugins can properly compile
483
+ // when referencing @rancher/shell
484
+ exclude: /node_modules\/(?!(@rancher)\/).*/,
485
+ use: [
486
+ {
487
+ loader: 'cache-loader',
488
+ options: {
489
+ cacheDirectory: 'node_modules/.cache/babel-loader',
490
+ cacheIdentifier: 'e93f32da'
491
+ }
492
+ },
493
+ {
494
+ loader: 'babel-loader',
495
+ options: {
496
+ presets: [
497
+ [
498
+ require.resolve('@nuxt/babel-preset-app'),
499
+ {
500
+ corejs: { version: 3 },
501
+ targets: { browsers: ['last 2 versions'] },
502
+ modern: true
503
+ }
504
+ ],
505
+ '@babel/preset-typescript',
506
+ ],
507
+ plugins: babelPlugins
508
+ }
509
+ }
510
+ ]
511
+ },
512
+ {
513
+ test: /\.tsx?$/,
514
+ use: [
515
+ {
516
+ loader: 'cache-loader',
517
+ options: {
518
+ cacheDirectory: 'node_modules/.cache/ts-loader',
519
+ cacheIdentifier: '3596741e'
520
+ }
521
+ },
522
+ {
523
+ loader: 'ts-loader',
524
+ options: {
525
+ transpileOnly: true,
526
+ happyPackMode: false,
527
+ appendTsxSuffixTo: [
528
+ '\\.vue$'
529
+ ],
530
+ configFile: path.join(SHELL_ABS, 'tsconfig.json')
531
+ }
532
+ }
533
+ ]
534
+ },
535
+ // Prevent warning in log with the md files in the content folder
536
+ {
537
+ test: /\.md$/,
538
+ use: [
539
+ {
540
+ loader: 'url-loader',
541
+ options: {
542
+ name: '[path][name].[ext]',
543
+ limit: 1,
544
+ esModule: false
545
+ },
546
+ }
547
+ ]
548
+ },
549
+ // Prevent warning in log with the md files in the content folder
550
+ {
551
+ test: /\.md$/,
552
+ use: [
553
+ {
554
+ loader: 'frontmatter-markdown-loader',
555
+ options: { mode: ['body'] }
556
+ }
557
+ ]
558
+ }
559
+ ];
560
+
561
+ config.module.rules.push(...loaders);
562
+
563
+ // Update vue-loader to set whitespace to 'preserve'
564
+ // This was the setting with nuxt, but is not the default with vue cli
565
+ // Need to find the vue loader in the webpack config and update the setting
566
+ config.module.rules.forEach((loader) => {
567
+ if (loader.use) {
568
+ loader.use.forEach((use) => {
569
+ if (use.loader.includes('vue-loader')) {
570
+ use.options.compilerOptions.whitespace = 'preserve';
571
+ }
572
+ });
573
+ }
574
+ });
575
+ },
576
+ };
577
+
578
+ return config;
579
+ };
580
+
581
+ // ===============================================================================================
582
+ // Functions for the request proxying used in dev
583
+ // ===============================================================================================
584
+
585
+ function proxyMetaOpts(target) {
586
+ return {
587
+ target,
588
+ followRedirects: true,
589
+ secure: !dev,
590
+ changeOrigin: true,
591
+ onProxyReq,
592
+ onProxyReqWs,
593
+ onError,
594
+ onProxyRes,
595
+ };
596
+ }
597
+
598
+ function proxyOpts(target) {
599
+ return {
600
+ target,
601
+ secure: !devPorts,
602
+ changeOrigin: true,
603
+ onProxyReq,
604
+ onProxyReqWs,
605
+ onError,
606
+ onProxyRes
607
+ };
608
+ }
609
+
610
+ // Intercept the /rancherversion API call wnad modify the 'RancherPrime' value
611
+ // if configured to do so by the environment variable PRIME
612
+ function proxyPrimeOpts(target) {
613
+ const opts = proxyOpts(target);
614
+
615
+ // Don't intercept if the PRIME environment variable is not set
616
+ if (!prime?.length) {
617
+ return opts;
618
+ }
619
+
620
+ opts.onProxyRes = (proxyRes, req, res) => {
621
+ const _end = res.end;
622
+ let body = '';
623
+
624
+ proxyRes.on( 'data', (data) => {
625
+ data = data.toString('utf-8');
626
+ body += data;
627
+ });
628
+
629
+ res.write = () => {};
630
+
631
+ res.end = () => {
632
+ let output = body;
633
+
634
+ try {
635
+ const out = JSON.parse(body);
636
+
637
+ out.RancherPrime = prime;
638
+ output = JSON.stringify(out);
639
+ } catch (err) {}
640
+
641
+ res.setHeader('content-length', output.length );
642
+ res.setHeader('content-type', 'application/json' );
643
+ res.setHeader('transfer-encoding', '');
644
+ res.setHeader('cache-control', 'no-cache');
645
+ res.writeHead(proxyRes.statusCode);
646
+ _end.apply(res, [output]);
647
+ };
648
+ };
649
+
650
+ return opts;
651
+ }
652
+
653
+ function onProxyRes(proxyRes, req, res) {
654
+ if (devPorts) {
655
+ proxyRes.headers['X-Frame-Options'] = 'ALLOWALL';
656
+ }
657
+ }
658
+
659
+ function proxyWsOpts(target) {
660
+ return {
661
+ ...proxyOpts(target),
662
+ ws: true,
663
+ changeOrigin: true,
664
+ };
665
+ }
666
+
667
+ function onProxyReq(proxyReq, req) {
668
+ if (!(proxyReq._currentRequest && proxyReq._currentRequest._headerSent)) {
669
+ proxyReq.setHeader('x-api-host', req.headers['host']);
670
+ proxyReq.setHeader('x-forwarded-proto', 'https');
671
+ }
672
+ }
673
+
674
+ function onProxyReqWs(proxyReq, req, socket, options, head) {
675
+ req.headers.origin = options.target.href;
676
+ proxyReq.setHeader('origin', options.target.href);
677
+ proxyReq.setHeader('x-api-host', req.headers['host']);
678
+ proxyReq.setHeader('x-forwarded-proto', 'https');
679
+ // console.log(proxyReq.getHeaders());
680
+
681
+ socket.on('error', (err) => {
682
+ console.error('Proxy WS Error:', err); // eslint-disable-line no-console
683
+ });
684
+ }
685
+
686
+ function onError(err, req, res) {
687
+ res.statusCode = 598;
688
+ console.error('Proxy Error:', err); // eslint-disable-line no-console
689
+ res.write(JSON.stringify(err));
690
+ }