@rancher/shell 0.3.5 → 0.3.7
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.
- package/assets/images/providers/outscale.svg +19 -0
- package/assets/styles/base/_basic.scss +18 -0
- package/assets/styles/base/_mixins.scss +0 -11
- package/assets/styles/base/_variables.scss +2 -4
- package/assets/styles/global/_button.scss +12 -2
- package/assets/translations/en-us.yaml +35 -1
- package/assets/translations/zh-hans.yaml +30 -10
- package/chart/gatekeeper.vue +3 -2
- package/chart/istio.vue +29 -3
- package/components/BrandImage.vue +1 -4
- package/components/Carousel.vue +85 -37
- package/components/EtcdInfoBanner.vue +7 -3
- package/components/ExplorerMembers.vue +100 -5
- package/components/ExplorerProjectsNamespaces.vue +32 -2
- package/components/GrafanaDashboard.vue +9 -2
- package/components/SortableTable/index.vue +23 -11
- package/components/SortableTable/selection.js +58 -50
- package/components/Wizard.vue +4 -2
- package/components/auth/AuthBanner.vue +6 -0
- package/components/auth/RoleDetailEdit.vue +2 -2
- package/components/form/HookOption.vue +14 -10
- package/components/form/Labels.vue +32 -27
- package/components/form/MatchExpressions.vue +2 -2
- package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +46 -21
- package/components/form/Tolerations.vue +4 -1
- package/components/form/ValueFromResource.vue +14 -9
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/form/__tests__/NameNsDescription.ts +27 -0
- package/components/formatter/WorkloadHealthScale.vue +8 -2
- package/components/nav/NamespaceFilter.vue +8 -0
- package/{nuxt/components → components/nuxt}/nuxt.js +1 -1
- package/{nuxt → config}/middleware.js +8 -8
- package/config/product/explorer.js +24 -3
- package/config/query-params.js +1 -0
- package/config/router.js +1 -1
- package/{nuxt → config}/store.js +82 -79
- package/config/table-headers.js +46 -12
- package/config/types.js +7 -0
- package/core/plugin.ts +4 -2
- package/core/types.ts +258 -1
- package/creators/app/files/tsconfig.json +0 -1
- package/creators/app/files/vue.config.js +0 -1
- package/creators/pkg/files/.github/workflows/build-extension.yml +3 -4
- package/creators/pkg/files/tsconfig.json +0 -1
- package/creators/pkg/pkg.package.json +3 -3
- package/detail/constraints.gatekeeper.sh.constraint.vue +14 -7
- package/detail/fleet.cattle.io.clustergroup.vue +7 -1
- package/edit/auth/ldap/config.vue +21 -1
- package/edit/auth/saml.vue +132 -37
- package/edit/fleet.cattle.io.gitrepo.vue +16 -1
- package/edit/logging.banzaicloud.io.output/index.vue +18 -5
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/namespace.vue +12 -8
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -4
- package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
- package/edit/provisioning.cattle.io.cluster/rke2.vue +96 -18
- package/edit/workload/mixins/workload.js +6 -7
- package/edit/workload/storage/Mount.vue +3 -3
- package/initialize/App.js +206 -0
- package/{nuxt → initialize}/client.js +406 -360
- package/{nuxt → initialize}/index.js +21 -22
- package/layouts/standalone.vue +13 -0
- package/list/catalog.cattle.io.clusterrepo.vue +1 -0
- package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
- package/list/workload.vue +6 -4
- package/mixins/chart.js +29 -1
- package/mixins/fetch.client.js +95 -0
- package/{nuxt/mixins → mixins}/fetch.server.js +30 -26
- package/mixins/labeled-form-element.ts +2 -2
- package/models/constraints.gatekeeper.sh.constraint.js +37 -0
- package/models/pod.js +4 -0
- package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
- package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
- package/package.json +9 -13
- package/pages/c/_cluster/apps/charts/install.vue +61 -39
- package/pages/diagnostic.vue +32 -25
- package/pages/rio/mesh.vue +1 -2
- package/pkg/tsconfig.json +0 -1
- package/plugins/clean-html-directive.js +3 -0
- package/plugins/dashboard-store/index.js +1 -1
- package/plugins/plugin.js +0 -14
- package/plugins/portal-vue.js +4 -0
- package/rancher-components/components/Banner/Banner.test.ts +3 -5
- package/rancher-components/components/Banner/Banner.vue +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
- package/scripts/extension/publish +42 -23
- package/scripts/serve-pkgs +6 -2
- package/store/type-map.js +1 -1
- package/tsconfig.json +0 -1
- package/types/rancher/index.d.ts +2 -0
- package/types/shell/index.d.ts +353 -284
- package/utils/__tests__/grafana.test.ts +44 -0
- package/utils/axios.js +190 -0
- package/{nuxt → utils}/cookie-universal-nuxt.js +7 -6
- package/utils/dom.js +15 -0
- package/utils/gc/gc.ts +1 -1
- package/utils/grafana.js +35 -16
- package/{nuxt/utils.js → utils/nuxt.js} +265 -236
- package/utils/router.scrollBehavior.js +1 -1
- package/vue.config.js +30 -19
- package/nuxt/App.js +0 -210
- package/nuxt/axios.js +0 -186
- package/nuxt/empty.js +0 -1
- package/nuxt/jsonp.js +0 -82
- package/nuxt/loading.html +0 -39
- package/nuxt/mixins/fetch.client.js +0 -90
- package/nuxt/portal-vue.js +0 -4
- package/nuxt/server.js +0 -312
- package/nuxt/views/app.template.html +0 -9
- package/nuxt/views/error.html +0 -23
- package/plugins/dashboard-store/extensions.js +0 -22
- /package/{nuxt/components → components/nuxt}/nuxt-build-indicator.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-child.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-error.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.client.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.server.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-loading.vue +0 -0
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
|
-
import Vuex from 'vuex';
|
|
3
2
|
import Meta from 'vue-meta';
|
|
4
3
|
import ClientOnly from 'vue-client-only';
|
|
5
4
|
import NoSsr from 'vue-no-ssr';
|
|
6
5
|
import { createRouter } from '../config/router.js';
|
|
7
|
-
import NuxtChild from '
|
|
6
|
+
import NuxtChild from '../components/nuxt/nuxt-child.js';
|
|
8
7
|
import NuxtError from '../layouts/error.vue';
|
|
9
|
-
import Nuxt from '
|
|
8
|
+
import Nuxt from '../components/nuxt/nuxt.js';
|
|
10
9
|
import App from './App.js';
|
|
11
|
-
import { setContext, getLocation, getRouteData, normalizeError } from '
|
|
12
|
-
import { createStore } from '
|
|
10
|
+
import { setContext, getLocation, getRouteData, normalizeError } from '../utils/nuxt';
|
|
11
|
+
import { createStore } from '../config/store.js';
|
|
13
12
|
|
|
14
13
|
/* Plugins */
|
|
15
14
|
|
|
16
|
-
import '
|
|
17
|
-
import cookieUniversalNuxt from '
|
|
18
|
-
import axios from '
|
|
15
|
+
import '../plugins/portal-vue.js';
|
|
16
|
+
import cookieUniversalNuxt from '../utils/cookie-universal-nuxt.js';
|
|
17
|
+
import axios from '../utils/axios.js';
|
|
19
18
|
import plugins from '../core/plugins.js';
|
|
20
19
|
import pluginsLoader from '../core/plugins-loader.js';
|
|
21
20
|
import axiosShell from '../plugins/axios';
|
|
@@ -42,7 +41,7 @@ import backButton from '../plugins/back-button';
|
|
|
42
41
|
import plugin from '../plugins/plugin';
|
|
43
42
|
import codeMirror from '../plugins/codemirror-loader';
|
|
44
43
|
import '../plugins/formatters';
|
|
45
|
-
import version from
|
|
44
|
+
import version from '../plugins/version';
|
|
46
45
|
import steveCreateWorker from '../plugins/steve-create-worker';
|
|
47
46
|
|
|
48
47
|
// Component: <ClientOnly>
|
|
@@ -55,7 +54,7 @@ Vue.component(NoSsr.name, {
|
|
|
55
54
|
if (process.client && !NoSsr._warned) {
|
|
56
55
|
NoSsr._warned = true;
|
|
57
56
|
|
|
58
|
-
console.warn('<no-ssr> has been deprecated and will be removed in Nuxt 3, please use <client-only> instead');
|
|
57
|
+
console.warn('<no-ssr> has been deprecated and will be removed in Nuxt 3, please use <client-only> instead'); // eslint-disable-line no-console
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
return NoSsr.render(h, ctx);
|
|
@@ -92,16 +91,6 @@ const defaultTransition = {
|
|
|
92
91
|
name: 'page', mode: 'out-in', appear: true, appearClass: 'appear', appearActiveClass: 'appear-active', appearToClass: 'appear-to'
|
|
93
92
|
};
|
|
94
93
|
|
|
95
|
-
const originalRegisterModule = Vuex.Store.prototype.registerModule;
|
|
96
|
-
|
|
97
|
-
function registerModule(path, rawModule, options = {}) {
|
|
98
|
-
const preserveState = process.client && (
|
|
99
|
-
Array.isArray(path) ? !!path.reduce((namespacedState, path) => namespacedState && namespacedState[path], this.state) : path in this.state
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
return originalRegisterModule.call(this, path, rawModule, { preserveState, ...options });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
94
|
async function createApp(ssrContext, config = {}) {
|
|
106
95
|
const router = await createRouter(ssrContext, config);
|
|
107
96
|
|
|
@@ -115,7 +104,17 @@ async function createApp(ssrContext, config = {}) {
|
|
|
115
104
|
// here we inject the router and store to all child components,
|
|
116
105
|
// making them available everywhere as `this.$router` and `this.$store`.
|
|
117
106
|
const app = {
|
|
118
|
-
head: {
|
|
107
|
+
head: {
|
|
108
|
+
title: 'dashboard',
|
|
109
|
+
meta: [{ charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, {
|
|
110
|
+
hid: 'description', name: 'description', content: 'Rancher Dashboard'
|
|
111
|
+
}],
|
|
112
|
+
link: [{
|
|
113
|
+
hid: 'icon', rel: 'icon', type: 'image\u002Fx-icon', href: '\u002Ffavicon.png'
|
|
114
|
+
}],
|
|
115
|
+
style: [],
|
|
116
|
+
script: []
|
|
117
|
+
},
|
|
119
118
|
|
|
120
119
|
store,
|
|
121
120
|
router,
|
|
@@ -318,7 +317,7 @@ async function createApp(ssrContext, config = {}) {
|
|
|
318
317
|
// Lock enablePreview in context
|
|
319
318
|
if (process.static && process.client) {
|
|
320
319
|
app.context.enablePreview = function() {
|
|
321
|
-
console.warn('You cannot call enablePreview() outside a plugin.');
|
|
320
|
+
console.warn('You cannot call enablePreview() outside a plugin.'); // eslint-disable-line no-console
|
|
322
321
|
};
|
|
323
322
|
}
|
|
324
323
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import ResourceTable from '@shell/components/ResourceTable';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
name: 'ListNamespace',
|
|
6
|
+
components: { ResourceTable },
|
|
7
|
+
props: {
|
|
8
|
+
resource: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
schema: {
|
|
13
|
+
type: Object,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
rows: {
|
|
17
|
+
type: Array,
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
loading: {
|
|
21
|
+
type: Boolean,
|
|
22
|
+
required: false,
|
|
23
|
+
},
|
|
24
|
+
useQueryParamsForSimpleFiltering: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
$loadingResources() {
|
|
31
|
+
return { loadIndeterminate: true };
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<div>
|
|
38
|
+
<ResourceTable
|
|
39
|
+
v-bind="$attrs"
|
|
40
|
+
:rows="rows"
|
|
41
|
+
:groupable="false"
|
|
42
|
+
:schema="schema"
|
|
43
|
+
:loading="loading"
|
|
44
|
+
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
45
|
+
v-on="$listeners"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
package/list/workload.vue
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import ResourceTable from '@shell/components/ResourceTable';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
WORKLOAD_TYPES, SCHEMA, NODE, POD, LIST_WORKLOAD_TYPES
|
|
5
|
+
} from '@shell/config/types';
|
|
4
6
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
5
7
|
|
|
6
8
|
const schema = {
|
|
@@ -16,7 +18,7 @@ const schema = {
|
|
|
16
18
|
const $loadingResources = ($route, $store) => {
|
|
17
19
|
const allowedResources = [];
|
|
18
20
|
|
|
19
|
-
Object.values(
|
|
21
|
+
Object.values(LIST_WORKLOAD_TYPES).forEach((type) => {
|
|
20
22
|
// You may not have RBAC to see some of the types
|
|
21
23
|
if ($store.getters['cluster/schemaFor'](type) ) {
|
|
22
24
|
allowedResources.push(type);
|
|
@@ -134,8 +136,8 @@ export default {
|
|
|
134
136
|
} else {
|
|
135
137
|
const type = this.$route.params.resource;
|
|
136
138
|
|
|
137
|
-
if (type === WORKLOAD_TYPES.JOB) {
|
|
138
|
-
// Ignore job (we're fetching this anyway, plus they contain their own state)
|
|
139
|
+
if (type === WORKLOAD_TYPES.JOB || type === POD) {
|
|
140
|
+
// Ignore job and pods (we're fetching this anyway, plus they contain their own state)
|
|
139
141
|
return;
|
|
140
142
|
}
|
|
141
143
|
|
package/mixins/chart.js
CHANGED
|
@@ -14,6 +14,8 @@ import { CAPI, CATALOG } from '@shell/config/types';
|
|
|
14
14
|
import { isPrerelease } from '@shell/utils/version';
|
|
15
15
|
import difference from 'lodash/difference';
|
|
16
16
|
import { LINUX } from '@shell/store/catalog';
|
|
17
|
+
import { clone } from 'utils/object';
|
|
18
|
+
import { merge } from 'lodash';
|
|
17
19
|
|
|
18
20
|
export default {
|
|
19
21
|
data() {
|
|
@@ -391,7 +393,6 @@ export default {
|
|
|
391
393
|
*/
|
|
392
394
|
|
|
393
395
|
if ( provider ) {
|
|
394
|
-
// more.push(provider);
|
|
395
396
|
try {
|
|
396
397
|
const crdVersionInfo = await this.$store.dispatch('catalog/getVersionInfo', {
|
|
397
398
|
repoType: provider.repoType,
|
|
@@ -399,6 +400,33 @@ export default {
|
|
|
399
400
|
chartName: provider.name,
|
|
400
401
|
versionName: provider.version
|
|
401
402
|
});
|
|
403
|
+
let existingCRDApp;
|
|
404
|
+
|
|
405
|
+
// search for an existing crd app to track any non-default values used on the previous install/upgrade
|
|
406
|
+
if (this.mode === _EDIT) {
|
|
407
|
+
const targetNamespace = crdVersionInfo?.chart?.annotations?.[CATALOG_ANNOTATIONS.NAMESPACE];
|
|
408
|
+
const targetName = crdVersionInfo?.chart?.annotations?.[CATALOG_ANNOTATIONS.RELEASE_NAME];
|
|
409
|
+
|
|
410
|
+
if (targetName && targetNamespace) {
|
|
411
|
+
existingCRDApp = await this.$store.dispatch('cluster/find', {
|
|
412
|
+
type: CATALOG.APP,
|
|
413
|
+
id: `${ targetNamespace }/${ targetName }`,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (existingCRDApp) {
|
|
418
|
+
// spec.values are any non-default values the user configured
|
|
419
|
+
// the installation form should show these, as well as any default values from the chart
|
|
420
|
+
const existingValues = clone(existingCRDApp.spec?.values || {});
|
|
421
|
+
const defaultValues = clone(existingCRDApp.spec?.chart?.values || {});
|
|
422
|
+
|
|
423
|
+
crdVersionInfo.existingValues = existingValues;
|
|
424
|
+
crdVersionInfo.allValues = merge(defaultValues, existingValues);
|
|
425
|
+
} else {
|
|
426
|
+
// allValues will potentially be updated in the UI - we want to track this separately from values to avoid mutating the chart object in the store
|
|
427
|
+
// this is similar to userValues for the main chart
|
|
428
|
+
crdVersionInfo.allValues = clone(crdVersionInfo.values);
|
|
429
|
+
}
|
|
402
430
|
|
|
403
431
|
out.push(crdVersionInfo);
|
|
404
432
|
} catch (e) {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
import { hasFetch, normalizeError, addLifecycleHook } from '../utils/nuxt';
|
|
3
|
+
|
|
4
|
+
const isSsrHydration = vm => vm.$vnode && vm.$vnode.elm && vm.$vnode.elm.dataset && vm.$vnode.elm.dataset.fetchKey;
|
|
5
|
+
const nuxtState = window.__NUXT__;
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
beforeCreate() {
|
|
9
|
+
if (!hasFetch(this)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this._fetchDelay = typeof this.$options.fetchDelay === 'number' ? this.$options.fetchDelay : 200;
|
|
14
|
+
|
|
15
|
+
Vue.util.defineReactive(this, '$fetchState', {
|
|
16
|
+
pending: false,
|
|
17
|
+
error: null,
|
|
18
|
+
timestamp: Date.now()
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
this.$fetch = $fetch.bind(this);
|
|
22
|
+
addLifecycleHook(this, 'created', created);
|
|
23
|
+
addLifecycleHook(this, 'beforeMount', beforeMount);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function beforeMount() {
|
|
28
|
+
if (!this._hydrated) {
|
|
29
|
+
return this.$fetch();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function created() {
|
|
34
|
+
if (!isSsrHydration(this)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Hydrate component
|
|
39
|
+
this._hydrated = true;
|
|
40
|
+
this._fetchKey = this.$vnode.elm.dataset.fetchKey;
|
|
41
|
+
const data = nuxtState.fetch[this._fetchKey];
|
|
42
|
+
|
|
43
|
+
// If fetch error
|
|
44
|
+
if (data && data._error) {
|
|
45
|
+
this.$fetchState.error = data._error;
|
|
46
|
+
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Merge data
|
|
51
|
+
for (const key in data) {
|
|
52
|
+
Vue.set(this.$data, key, data[key]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function $fetch() {
|
|
57
|
+
if (!this._fetchPromise) {
|
|
58
|
+
this._fetchPromise = $_fetch.call(this)
|
|
59
|
+
.then(() => {
|
|
60
|
+
delete this._fetchPromise;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return this._fetchPromise;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function $_fetch() { // eslint-disable-line camelcase
|
|
68
|
+
this.$nuxt.nbFetching++;
|
|
69
|
+
this.$fetchState.pending = true;
|
|
70
|
+
this.$fetchState.error = null;
|
|
71
|
+
this._hydrated = false;
|
|
72
|
+
let error = null;
|
|
73
|
+
const startTime = Date.now();
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await this.$options.fetch.call(this);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
if (process.dev) {
|
|
79
|
+
console.error('Error in fetch():', err); // eslint-disable-line no-console
|
|
80
|
+
}
|
|
81
|
+
error = normalizeError(err);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const delayLeft = this._fetchDelay - (Date.now() - startTime);
|
|
85
|
+
|
|
86
|
+
if (delayLeft > 0) {
|
|
87
|
+
await new Promise(resolve => setTimeout(resolve, delayLeft));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.$fetchState.error = error;
|
|
91
|
+
this.$fetchState.pending = false;
|
|
92
|
+
this.$fetchState.timestamp = Date.now();
|
|
93
|
+
|
|
94
|
+
this.$nextTick(() => this.$nuxt.nbFetching--);
|
|
95
|
+
}
|
|
@@ -1,69 +1,73 @@
|
|
|
1
|
-
import Vue from 'vue'
|
|
2
|
-
import {
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
import {
|
|
3
|
+
hasFetch, normalizeError, addLifecycleHook, purifyData, createGetCounter
|
|
4
|
+
} from '../../utils/nuxt';
|
|
3
5
|
|
|
4
6
|
async function serverPrefetch() {
|
|
5
7
|
if (!this._fetchOnServer) {
|
|
6
|
-
return
|
|
8
|
+
return;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
// Call and await on $fetch
|
|
10
12
|
try {
|
|
11
|
-
await this.$options.fetch.call(this)
|
|
13
|
+
await this.$options.fetch.call(this);
|
|
12
14
|
} catch (err) {
|
|
13
15
|
if (process.dev) {
|
|
14
|
-
console.error('Error in fetch():', err)
|
|
16
|
+
console.error('Error in fetch():', err); // eslint-disable-line no-console
|
|
15
17
|
}
|
|
16
|
-
this.$fetchState.error = normalizeError(err)
|
|
18
|
+
this.$fetchState.error = normalizeError(err);
|
|
17
19
|
}
|
|
18
|
-
this.$fetchState.pending = false
|
|
20
|
+
this.$fetchState.pending = false;
|
|
19
21
|
|
|
20
22
|
// Define an ssrKey for hydration
|
|
21
|
-
this._fetchKey = this._fetchKey || this.$ssrContext.fetchCounters['']
|
|
23
|
+
this._fetchKey = this._fetchKey || this.$ssrContext.fetchCounters['']++;
|
|
22
24
|
|
|
23
25
|
// Add data-fetch-key on parent element of Component
|
|
24
|
-
const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {}
|
|
25
|
-
|
|
26
|
+
const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {};
|
|
27
|
+
|
|
28
|
+
attrs['data-fetch-key'] = this._fetchKey;
|
|
26
29
|
|
|
27
30
|
// Add to ssrContext for window.__NUXT__.fetch
|
|
28
31
|
|
|
29
32
|
if (this.$ssrContext.nuxt.fetch[this._fetchKey] !== undefined) {
|
|
30
|
-
console.warn(`Duplicate fetch key detected (${this._fetchKey}). This may lead to unexpected results.`)
|
|
33
|
+
console.warn(`Duplicate fetch key detected (${ this._fetchKey }). This may lead to unexpected results.`); // eslint-disable-line no-console
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
this.$ssrContext.nuxt.fetch[this._fetchKey] =
|
|
34
|
-
this.$fetchState.error ? { _error: this.$fetchState.error } : purifyData(this._data)
|
|
37
|
+
this.$fetchState.error ? { _error: this.$fetchState.error } : purifyData(this._data);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
export default {
|
|
38
41
|
created() {
|
|
39
42
|
if (!hasFetch(this)) {
|
|
40
|
-
return
|
|
43
|
+
return;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
if (typeof this.$options.fetchOnServer === 'function') {
|
|
44
|
-
this._fetchOnServer = this.$options.fetchOnServer.call(this) !== false
|
|
47
|
+
this._fetchOnServer = this.$options.fetchOnServer.call(this) !== false;
|
|
45
48
|
} else {
|
|
46
|
-
this._fetchOnServer = this.$options.fetchOnServer !== false
|
|
49
|
+
this._fetchOnServer = this.$options.fetchOnServer !== false;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
const defaultKey = this.$options._scopeId || this.$options.name || ''
|
|
50
|
-
const getCounter = createGetCounter(this.$ssrContext.fetchCounters, defaultKey)
|
|
52
|
+
const defaultKey = this.$options._scopeId || this.$options.name || '';
|
|
53
|
+
const getCounter = createGetCounter(this.$ssrContext.fetchCounters, defaultKey);
|
|
51
54
|
|
|
52
55
|
if (typeof this.$options.fetchKey === 'function') {
|
|
53
|
-
this._fetchKey = this.$options.fetchKey.call(this, getCounter)
|
|
56
|
+
this._fetchKey = this.$options.fetchKey.call(this, getCounter);
|
|
54
57
|
} else {
|
|
55
|
-
const key =
|
|
56
|
-
|
|
58
|
+
const key = typeof this.$options.fetchKey === 'string' ? this.$options.fetchKey : defaultKey;
|
|
59
|
+
|
|
60
|
+
this._fetchKey = key ? `${ key }:${ getCounter(key) }` : String(getCounter(key));
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
// Added for remove vue undefined warning while ssr
|
|
60
|
-
this.$fetch = () => {} // issue #8043
|
|
64
|
+
this.$fetch = () => {}; // issue #8043
|
|
61
65
|
Vue.util.defineReactive(this, '$fetchState', {
|
|
62
|
-
pending:
|
|
63
|
-
error:
|
|
66
|
+
pending: true,
|
|
67
|
+
error: null,
|
|
64
68
|
timestamp: Date.now()
|
|
65
|
-
})
|
|
69
|
+
});
|
|
66
70
|
|
|
67
|
-
addLifecycleHook(this, 'serverPrefetch', serverPrefetch)
|
|
71
|
+
addLifecycleHook(this, 'serverPrefetch', serverPrefetch);
|
|
68
72
|
}
|
|
69
|
-
}
|
|
73
|
+
};
|
|
@@ -122,7 +122,7 @@ export default Vue.extend({
|
|
|
122
122
|
},
|
|
123
123
|
validationMessage(): string | undefined {
|
|
124
124
|
// we want to grab the required rule passed in if we can but if it's not there then we can just grab it from the formRulesGenerator
|
|
125
|
-
const requiredRule = this.rules.find((rule: any) => rule?.name === 'required');
|
|
125
|
+
const requiredRule = this.rules.find((rule: any) => rule?.name === 'required') as Function;
|
|
126
126
|
const ruleMessages = [];
|
|
127
127
|
const value = this?.value;
|
|
128
128
|
|
|
@@ -134,7 +134,7 @@ export default Vue.extend({
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
for (const rule of this.rules) {
|
|
137
|
+
for (const rule of this.rules as Function[]) {
|
|
138
138
|
const message = rule(value);
|
|
139
139
|
|
|
140
140
|
if (!!message && rule.name !== 'required') { // we're catching 'required' above so we can ignore it here
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import jsyaml from 'js-yaml';
|
|
2
2
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
3
|
+
import { downloadFile } from '@shell/utils/download';
|
|
3
4
|
|
|
4
5
|
export const ENFORCEMENT_ACTION_VALUES = {
|
|
5
6
|
DENY: 'deny',
|
|
@@ -7,6 +8,23 @@ export const ENFORCEMENT_ACTION_VALUES = {
|
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
export default class GateKeeperConstraint extends SteveModel {
|
|
11
|
+
get _availableActions() {
|
|
12
|
+
const out = super._availableActions;
|
|
13
|
+
|
|
14
|
+
const t = this.$rootGetters['i18n/t'];
|
|
15
|
+
|
|
16
|
+
const downloadViolations = {
|
|
17
|
+
action: 'downloadViolations',
|
|
18
|
+
icon: 'icon icon-fw icon-download',
|
|
19
|
+
label: t('gatekeeperConstraint.downloadViolations'),
|
|
20
|
+
total: 1,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
out.unshift(downloadViolations);
|
|
24
|
+
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
|
|
10
28
|
async save() {
|
|
11
29
|
let constraint;
|
|
12
30
|
let resourceVersion;
|
|
@@ -27,6 +45,25 @@ export default class GateKeeperConstraint extends SteveModel {
|
|
|
27
45
|
await constraint.save();
|
|
28
46
|
}
|
|
29
47
|
|
|
48
|
+
async downloadViolations() {
|
|
49
|
+
const Papa = await import(/* webpackChunkName: "csv" */'papaparse');
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const violations = (this.violations || []).map((violation) => {
|
|
53
|
+
delete violation.resourceLink;
|
|
54
|
+
delete violation.constraintLink;
|
|
55
|
+
|
|
56
|
+
return violation;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const csv = Papa.unparse(violations);
|
|
60
|
+
|
|
61
|
+
downloadFile(`violations-${ this.name }.csv`, csv, 'application/csv');
|
|
62
|
+
} catch (err) {
|
|
63
|
+
this.$dispatch('growl/fromError', { title: 'Error downloading file', err }, { root: true });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
30
67
|
cleanForNew() {
|
|
31
68
|
this.$dispatch(`cleanForNew`, this);
|
|
32
69
|
|
package/models/pod.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import HybridModel from '@shell/plugins/steve/hybrid-class';
|
|
2
|
+
import { GROUP, SERVICE_ACCOUNT, USER } from '@shell/config/types';
|
|
3
|
+
|
|
4
|
+
export default class ClusterRoleBinding extends HybridModel {
|
|
5
|
+
get users() {
|
|
6
|
+
return this.subjects?.filter(({ kind }) => kind?.toLowerCase() === USER);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get serviceAccounts() {
|
|
10
|
+
return this.subjects?.filter(({ kind }) => kind?.toLowerCase() === SERVICE_ACCOUNT);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get groups() {
|
|
14
|
+
return this.subjects?.filter(({ kind }) => kind?.toLowerCase() === GROUP);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import HybridModel from '@shell/plugins/steve/hybrid-class';
|
|
2
|
+
import { GROUP, SERVICE_ACCOUNT, USER } from '@shell/config/types';
|
|
3
|
+
|
|
4
|
+
export default class RoleBinding extends HybridModel {
|
|
5
|
+
get users() {
|
|
6
|
+
return this.subjects.filter(({ kind }) => kind?.toLowerCase() === USER);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get serviceAccounts() {
|
|
10
|
+
return this.subjects.filter(({ kind }) => kind?.toLowerCase() === SERVICE_ACCOUNT);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get groups() {
|
|
14
|
+
return this.subjects.filter(({ kind }) => kind?.toLowerCase() === GROUP);
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -36,21 +36,17 @@
|
|
|
36
36
|
"@babel/preset-typescript": "7.16.7",
|
|
37
37
|
"@innologica/vue-dropdown-menu": "0.1.3",
|
|
38
38
|
"@novnc/novnc": "1.2.0",
|
|
39
|
-
"@nuxt/types": "2.14.6",
|
|
40
39
|
"@nuxt/typescript-build": "2.1.0",
|
|
41
40
|
"@nuxtjs/axios": "5.12.0",
|
|
42
41
|
"@nuxtjs/eslint-config-typescript": "6.0.1",
|
|
43
|
-
"@nuxtjs/eslint-module": "1.2.0",
|
|
44
|
-
"@nuxtjs/proxy": "1.3.3",
|
|
45
|
-
"@nuxtjs/style-resources": "1.2.1",
|
|
46
42
|
"@nuxtjs/webpack-profile": "0.1.0",
|
|
47
43
|
"@popperjs/core": "2.4.4",
|
|
48
44
|
"@types/node": "16.4.3",
|
|
49
45
|
"@typescript-eslint/eslint-plugin": "4.33.0",
|
|
50
46
|
"@typescript-eslint/parser": "4.33.0",
|
|
51
|
-
"@vue/cli-plugin-babel": "4.5.
|
|
52
|
-
"@vue/cli-plugin-typescript": "4.5.
|
|
53
|
-
"@vue/cli-service": "4.5.
|
|
47
|
+
"@vue/cli-plugin-babel": "4.5.18",
|
|
48
|
+
"@vue/cli-plugin-typescript": "4.5.18",
|
|
49
|
+
"@vue/cli-service": "4.5.18",
|
|
54
50
|
"@vue/test-utils": "1.2.1",
|
|
55
51
|
"@vue/vue2-jest": "27.0.0",
|
|
56
52
|
"add": "2.0.6",
|
|
@@ -82,7 +78,7 @@
|
|
|
82
78
|
"eslint-plugin-import": "2.23.4",
|
|
83
79
|
"eslint-plugin-jest": "24.4.0",
|
|
84
80
|
"eslint-plugin-n": "15.2.0",
|
|
85
|
-
"eslint-plugin-vue": "
|
|
81
|
+
"eslint-plugin-vue": "9.10.0",
|
|
86
82
|
"event-target-shim": "5.0.1",
|
|
87
83
|
"express": "4.17.1",
|
|
88
84
|
"file-saver": "2.0.2",
|
|
@@ -109,7 +105,7 @@
|
|
|
109
105
|
"nyc": "15.1.0",
|
|
110
106
|
"papaparse": "5.3.0",
|
|
111
107
|
"portal-vue": "2.1.7",
|
|
112
|
-
"rancher-icons": "rancher/icons#v2.0.
|
|
108
|
+
"rancher-icons": "rancher/icons#v2.0.14",
|
|
113
109
|
"require-extension-hooks": "0.3.3",
|
|
114
110
|
"require-extension-hooks-babel": "1.0.0",
|
|
115
111
|
"require-extension-hooks-vue": "3.0.0",
|
|
@@ -125,15 +121,15 @@
|
|
|
125
121
|
"typescript": "4.1.6",
|
|
126
122
|
"url-parse": "1.5.10",
|
|
127
123
|
"v-tooltip": "2.0.3",
|
|
128
|
-
"vue": "2.
|
|
124
|
+
"vue": "2.7.14",
|
|
129
125
|
"vue-clipboard2": "0.3.1",
|
|
130
126
|
"vue-codemirror": "4.0.6",
|
|
131
127
|
"vue-js-modal": "1.3.35",
|
|
132
128
|
"vue-resize": "0.4.5",
|
|
133
129
|
"vue-select": "3.18.3",
|
|
134
|
-
"vue-server-renderer": "2.
|
|
130
|
+
"vue-server-renderer": "2.7.14",
|
|
135
131
|
"vue-shortkey": "3.1.7",
|
|
136
|
-
"vue-template-compiler": "2.
|
|
132
|
+
"vue-template-compiler": "2.7.14",
|
|
137
133
|
"vue-virtual-scroll-list": "^2.3.4",
|
|
138
134
|
"vue2-transitions": "0.3.0",
|
|
139
135
|
"vuedraggable": "2.24.3",
|