@rancher/shell 0.3.16 → 0.3.17
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/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +69 -14
- package/assets/translations/zh-hans.yaml +87 -7
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/components/CommunityLinks.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/ResourceDetail/index.vue +4 -12
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/YamlEditor.vue +1 -0
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +2 -2
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/nav/Header.vue +2 -2
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +5 -1
- package/config/router.js +0 -4
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +20 -12
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +17 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/node.vue +6 -6
- package/detail/pod.vue +2 -6
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +9 -9
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +52 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +330 -150
- package/edit/ui.cattle.io.navlink.vue +2 -1
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +93 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/package.json +2 -2
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +1 -1
- package/pages/auth/logout.vue +11 -3
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- package/pages/c/_cluster/explorer/index.vue +1 -10
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +155 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +5 -5
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/resource-class.js +35 -2
- package/plugins/plugin.js +9 -1
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +44 -26
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +1 -0
- package/server/server-middleware.js +4 -12
- package/store/index.js +13 -0
- package/store/prefs.js +0 -3
- package/store/type-map.js +17 -29
- package/types/shell/index.d.ts +236 -83
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/settings.ts +2 -2
- package/vue.config.js +3 -2
- package/components/.DS_Store +0 -0
- package/components/__tests__/.DS_Store +0 -0
- package/creators/pkg/package-lock.json +0 -37
- package/pages/safeMode.vue +0 -17
- package/rancher-components/components/BadgeState/BadgeState.spec.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -63
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -420
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -23
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -355
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -287
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -254
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -170
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -149
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -151
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -484
- package/rancher-components/components/StringList/StringList.vue +0 -611
- package/rancher-components/components/StringList/index.ts +0 -1
- package/yarn-error.log +0 -196
- /package/rancher-components/{components/Card → Card}/Card.test.ts +0 -0
- /package/rancher-components/{components/Form → Form}/Radio/RadioButton.test.ts +0 -0
package/initialize/App.js
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
getMatchedComponentsInstances, getChildrenComponentInstancesUsingFetch, promisify, globalHandleError, sanitizeComponent
|
|
5
|
-
} from '../utils/nuxt';
|
|
3
|
+
import { getMatchedComponentsInstances, getChildrenComponentInstancesUsingFetch, promisify, globalHandleError } from '../utils/nuxt';
|
|
6
4
|
import NuxtError from '../layouts/error.vue';
|
|
7
5
|
import NuxtLoading from '../components/nav/GlobalLoading.vue';
|
|
8
6
|
|
|
9
7
|
import '../assets/styles/app.scss';
|
|
8
|
+
import { getLayouts } from './layouts';
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
import defaultLayout from '../layouts/default.vue';
|
|
13
|
-
import home from '../layouts/home.vue';
|
|
14
|
-
import plain from '../layouts/plain.vue';
|
|
15
|
-
import unauthenticated from '../layouts/unauthenticated.vue';
|
|
16
|
-
import standalone from '../layouts/standalone.vue';
|
|
17
|
-
|
|
18
|
-
const layouts = {
|
|
19
|
-
_blank: sanitizeComponent(blank), _default: sanitizeComponent(defaultLayout), _home: sanitizeComponent(home), _plain: sanitizeComponent(plain), _unauthenticated: sanitizeComponent(unauthenticated), _standalone: sanitizeComponent(standalone)
|
|
20
|
-
};
|
|
10
|
+
const layouts = getLayouts();
|
|
21
11
|
|
|
22
12
|
export default {
|
|
23
13
|
render(h) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { sanitizeComponent } from '@shell/utils/nuxt';
|
|
2
|
+
import blank from '@shell/layouts/blank.vue';
|
|
3
|
+
import defaultLayout from '@shell/layouts/default.vue';
|
|
4
|
+
import home from '@shell/layouts/home.vue';
|
|
5
|
+
import plain from '@shell/layouts/plain.vue';
|
|
6
|
+
import unauthenticated from '@shell/layouts/unauthenticated.vue';
|
|
7
|
+
import standalone from '@shell/layouts/standalone.vue';
|
|
8
|
+
|
|
9
|
+
export type Component = { [key: string]: any };
|
|
10
|
+
export type Layouts = { [key: string]: Component };
|
|
11
|
+
const layouts: Layouts = { };
|
|
12
|
+
|
|
13
|
+
export function getLayouts(): Layouts {
|
|
14
|
+
return layouts;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function registerLayout(name: string, component: Component): void {
|
|
18
|
+
layouts[`_${ name }`] = sanitizeComponent(component);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
registerLayout('blank', blank) ;
|
|
22
|
+
registerLayout('default', defaultLayout) ;
|
|
23
|
+
registerLayout('home', home) ;
|
|
24
|
+
registerLayout('plain', plain) ;
|
|
25
|
+
registerLayout('unauthenticated', unauthenticated) ;
|
|
26
|
+
registerLayout('standalone', standalone);
|
|
@@ -135,6 +135,13 @@ export default {
|
|
|
135
135
|
},
|
|
136
136
|
|
|
137
137
|
harvesterEnabled: mapFeature(HARVESTER_FEATURE),
|
|
138
|
+
|
|
139
|
+
nonStandardNamespaces() {
|
|
140
|
+
// Show the namespace grouping option if there's clusters with namespaces other than 'fleet-default' or 'fleet-local'
|
|
141
|
+
// This will be used when there's clusters from extension based provisioners
|
|
142
|
+
// We should re-visit this for scaling reasons
|
|
143
|
+
return this.filteredRows.some((c) => c.metadata.namespace !== 'fleet-local' && c.metadata.namespace !== 'fleet-default');
|
|
144
|
+
}
|
|
138
145
|
},
|
|
139
146
|
|
|
140
147
|
$loadingResources() {
|
|
@@ -182,7 +189,7 @@ export default {
|
|
|
182
189
|
<ResourceTable
|
|
183
190
|
:schema="schema"
|
|
184
191
|
:rows="filteredRows"
|
|
185
|
-
:namespaced="
|
|
192
|
+
:namespaced="nonStandardNamespaces"
|
|
186
193
|
:loading="loading"
|
|
187
194
|
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
188
195
|
:data-testid="'cluster-list'"
|
|
@@ -26,6 +26,16 @@ const getPackageFromRoute = (route) => {
|
|
|
26
26
|
return arraySafe.find((m) => !!m.pkg)?.pkg;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const getResourceFromRoute = (to) => {
|
|
30
|
+
let resource = to.params?.resource;
|
|
31
|
+
|
|
32
|
+
if (!resource) {
|
|
33
|
+
resource = findMeta(to, 'resource');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return resource;
|
|
37
|
+
};
|
|
38
|
+
|
|
29
39
|
let beforeEachSetup = false;
|
|
30
40
|
|
|
31
41
|
function findMeta(route, key) {
|
|
@@ -71,9 +81,18 @@ export function getProductFromRoute(to) {
|
|
|
71
81
|
return product;
|
|
72
82
|
}
|
|
73
83
|
|
|
74
|
-
function setProduct(store, to) {
|
|
84
|
+
function setProduct(store, to, redirect) {
|
|
75
85
|
let product = getProductFromRoute(to);
|
|
76
86
|
|
|
87
|
+
// since all products are hardcoded as routes (ex: c-local-explorer), if we match the wildcard route it means that the product does not exist
|
|
88
|
+
if ((product && (!to.matched.length || (to.matched.length && to.matched[0].path === '/c/:cluster/:product'))) ||
|
|
89
|
+
// if the product grabbed from the route is not registered, then we don't have it!
|
|
90
|
+
(product && !store.getters['type-map/isProductRegistered'](product))) {
|
|
91
|
+
store.dispatch('loadingError', new Error(store.getters['i18n/t']('nav.failWhale.productNotFound', { productNotFound: product }, true)));
|
|
92
|
+
|
|
93
|
+
return () => redirect(302, '/fail-whale');
|
|
94
|
+
}
|
|
95
|
+
|
|
77
96
|
if ( !product ) {
|
|
78
97
|
product = EXPLORER;
|
|
79
98
|
}
|
|
@@ -92,6 +111,42 @@ function setProduct(store, to) {
|
|
|
92
111
|
// There might be management catalog items in it vs cluster.
|
|
93
112
|
store.commit('catalog/reset');
|
|
94
113
|
}
|
|
114
|
+
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Check that the resource is valid, if not redirect to fail whale
|
|
120
|
+
*
|
|
121
|
+
* This requires that
|
|
122
|
+
* - product is set
|
|
123
|
+
* - product's store is set and setup (so we can check schema's within it)
|
|
124
|
+
* - product's store has the schemaFor getter (extension stores might not have it)
|
|
125
|
+
* - there's a resource associated with route (meta or param)
|
|
126
|
+
*/
|
|
127
|
+
function invalidResource(store, to, redirect) {
|
|
128
|
+
const product = store.getters['currentProduct'];
|
|
129
|
+
const inStore = product?.inStore;
|
|
130
|
+
const schemaFor = store.getters[`${ inStore }/schemaFor`]; // There's a chance we're in an extension's product who's store could be anything
|
|
131
|
+
const resource = getResourceFromRoute(to);
|
|
132
|
+
|
|
133
|
+
// In order to check a resource is valid we need all of these
|
|
134
|
+
if (!product || !inStore || !schemaFor || !resource) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Resource is valid if a schema exists for it (standard resource, spoofed resource) or it's a virtual resource
|
|
139
|
+
const validResource = schemaFor(resource) || store.getters['type-map/isVirtual'](resource);
|
|
140
|
+
|
|
141
|
+
if (validResource) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Unknown resource, redirect to fail whale
|
|
146
|
+
|
|
147
|
+
store.dispatch('loadingError', new Error(store.getters['i18n/t']('nav.failWhale.resourceNotFound', { resource }, true)));
|
|
148
|
+
|
|
149
|
+
return () => redirect(302, '/fail-whale');
|
|
95
150
|
}
|
|
96
151
|
|
|
97
152
|
export default async function({
|
|
@@ -281,19 +336,39 @@ export default async function({
|
|
|
281
336
|
store.dispatch('gcRouteChanged', route);
|
|
282
337
|
|
|
283
338
|
// Load stuff
|
|
339
|
+
let localCheckResource = false;
|
|
340
|
+
|
|
284
341
|
await applyProducts(store, $plugin);
|
|
342
|
+
|
|
285
343
|
// Setup a beforeEach hook once to keep track of the current product
|
|
286
344
|
if ( !beforeEachSetup ) {
|
|
287
345
|
beforeEachSetup = true;
|
|
346
|
+
// This only needs to happen when beforeEach hook hasn't run (the initial load)
|
|
347
|
+
localCheckResource = true;
|
|
288
348
|
|
|
289
349
|
store.app.router.beforeEach((to, from, next) => {
|
|
290
350
|
// NOTE - This beforeEach runs AFTER this middleware. So anything in this middleware that requires it must set it manually
|
|
291
|
-
setProduct(store, to);
|
|
351
|
+
let redirected = setProduct(store, to, redirect);
|
|
352
|
+
|
|
353
|
+
if (redirected) {
|
|
354
|
+
return redirected();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
redirected = invalidResource(store, to, redirect);
|
|
358
|
+
|
|
359
|
+
if (redirected) {
|
|
360
|
+
return redirected();
|
|
361
|
+
}
|
|
362
|
+
|
|
292
363
|
next();
|
|
293
364
|
});
|
|
294
365
|
|
|
295
366
|
// Call it for the initial pageload
|
|
296
|
-
setProduct(store, route);
|
|
367
|
+
const redirected = setProduct(store, route, redirect);
|
|
368
|
+
|
|
369
|
+
if (redirected) {
|
|
370
|
+
return redirected();
|
|
371
|
+
}
|
|
297
372
|
|
|
298
373
|
if (process.client) {
|
|
299
374
|
store.app.router.afterEach((to, from) => {
|
|
@@ -376,7 +451,12 @@ export default async function({
|
|
|
376
451
|
// When fleet moves to it's own package this should be moved to pkg onEnter/onLeave
|
|
377
452
|
if ((oldProduct === FLEET_NAME || product === FLEET_NAME) && oldProduct !== product) {
|
|
378
453
|
// See note above for store.app.router.beforeEach, need to setProduct manually, for the moment do this in a targeted way
|
|
379
|
-
setProduct(store, route);
|
|
454
|
+
const redirected = setProduct(store, route, redirect);
|
|
455
|
+
|
|
456
|
+
if (redirected) {
|
|
457
|
+
return redirected();
|
|
458
|
+
}
|
|
459
|
+
|
|
380
460
|
store.commit('updateWorkspace', {
|
|
381
461
|
value: store.getters['prefs/get'](WORKSPACE) || DEFAULT_WORKSPACE,
|
|
382
462
|
getters: store.getters
|
|
@@ -397,6 +477,14 @@ export default async function({
|
|
|
397
477
|
})
|
|
398
478
|
]);
|
|
399
479
|
|
|
480
|
+
if (localCheckResource) {
|
|
481
|
+
const redirected = invalidResource(store, route, redirect);
|
|
482
|
+
|
|
483
|
+
if (redirected) {
|
|
484
|
+
return redirected();
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
400
488
|
if (!clusterId) {
|
|
401
489
|
clusterId = store.getters['defaultClusterId']; // This needs the cluster list, so no parallel
|
|
402
490
|
const isSingleProduct = store.getters['isSingleProduct'];
|
|
@@ -422,7 +510,7 @@ export default async function({
|
|
|
422
510
|
return redirect(302, '/home');
|
|
423
511
|
} else {
|
|
424
512
|
// Sets error 500 if lost connection to API
|
|
425
|
-
store.commit('setError', { error: e, locationError: new Error('
|
|
513
|
+
store.commit('setError', { error: e, locationError: new Error(store.getters['i18n/t']('nav.failWhale.authMiddleware')) });
|
|
426
514
|
|
|
427
515
|
return redirect(302, '/fail-whale');
|
|
428
516
|
}
|
package/mixins/brand.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mapGetters } from 'vuex';
|
|
1
2
|
import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
|
2
3
|
import { getVendor } from '@shell/config/private-label';
|
|
3
4
|
import { SETTING } from '@shell/config/settings';
|
|
@@ -5,6 +6,12 @@ import { findBy } from '@shell/utils/array';
|
|
|
5
6
|
import { createCssVars } from '@shell/utils/color';
|
|
6
7
|
import { _ALL_IF_AUTHED } from '@shell/plugins/dashboard-store/actions';
|
|
7
8
|
|
|
9
|
+
const cspAdaptorApp = ['rancher-csp-adapter', 'rancher-csp-billing-adapter'];
|
|
10
|
+
|
|
11
|
+
export const hasCspAdapter = (apps) => {
|
|
12
|
+
return apps?.find((a) => cspAdaptorApp.includes(a.metadata?.name));
|
|
13
|
+
};
|
|
14
|
+
|
|
8
15
|
export default {
|
|
9
16
|
async fetch() {
|
|
10
17
|
// For the login page, the schemas won't be loaded - we don't need the apps in this case
|
|
@@ -23,13 +30,19 @@ export default {
|
|
|
23
30
|
}
|
|
24
31
|
});
|
|
25
32
|
} catch (e) {}
|
|
33
|
+
|
|
34
|
+
// Setting this up front will remove `computed` churn, and we only care that we've initialised them
|
|
35
|
+
this.haveAppsAndSettings = !!this.apps && !!this.globalSettings;
|
|
26
36
|
},
|
|
27
37
|
|
|
28
38
|
data() {
|
|
29
|
-
return {
|
|
39
|
+
return {
|
|
40
|
+
apps: null, globalSettings: null, haveAppsAndSettings: null
|
|
41
|
+
};
|
|
30
42
|
},
|
|
31
43
|
|
|
32
44
|
computed: {
|
|
45
|
+
...mapGetters({ loggedIn: 'auth/loggedIn' }),
|
|
33
46
|
|
|
34
47
|
brand() {
|
|
35
48
|
const setting = findBy(this.globalSettings, 'id', SETTING.BRAND);
|
|
@@ -61,7 +74,23 @@ export default {
|
|
|
61
74
|
},
|
|
62
75
|
|
|
63
76
|
cspAdapter() {
|
|
64
|
-
|
|
77
|
+
if (!this.canCalcCspAdapter) {
|
|
78
|
+
// We only have a watch on cspAdapter to kick off persisting the brand setting.
|
|
79
|
+
// So we need to ensure we don't return an undefined here... which would match the undefined gave if no csp app was found...
|
|
80
|
+
// .. and wouldn't kick off the watcher
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Note! this used to be `findBy(this.app)` however for that case we lost reactivity on the collection
|
|
85
|
+
// (computed fires before fetch, fetch happens and update apps, computed would not fire again - even with vue.set)
|
|
86
|
+
// So use `.find` in method instead
|
|
87
|
+
return hasCspAdapter(this.apps);
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
canCalcCspAdapter() {
|
|
91
|
+
// We need to take consider the loggedIn state, as the brand mixin is used in the logout page where we can be in a mixed state
|
|
92
|
+
// (things in store but user has no auth to make changes)
|
|
93
|
+
return this.loggedIn && this.haveAppsAndSettings;
|
|
65
94
|
}
|
|
66
95
|
},
|
|
67
96
|
|
|
@@ -90,7 +119,13 @@ export default {
|
|
|
90
119
|
},
|
|
91
120
|
|
|
92
121
|
cspAdapter(neu) {
|
|
122
|
+
if (!this.canCalcCspAdapter) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// The brand setting will only get updated if...
|
|
93
127
|
if (neu && !this.brand) {
|
|
128
|
+
// 1) There should be a brand... but there's no brand setting
|
|
94
129
|
const brandSetting = findBy(this.globalSettings, 'id', SETTING.BRAND);
|
|
95
130
|
|
|
96
131
|
if (brandSetting) {
|
|
@@ -109,7 +144,8 @@ export default {
|
|
|
109
144
|
} else if (!neu) {
|
|
110
145
|
const brandSetting = findBy(this.globalSettings, 'id', SETTING.BRAND);
|
|
111
146
|
|
|
112
|
-
if (brandSetting) {
|
|
147
|
+
if (brandSetting && brandSetting.value !== '') {
|
|
148
|
+
// 2) There should not be a brand... but there is a brand setting
|
|
113
149
|
brandSetting.value = '';
|
|
114
150
|
brandSetting.save();
|
|
115
151
|
}
|
package/mixins/child-hook.js
CHANGED
|
@@ -20,8 +20,8 @@ export default {
|
|
|
20
20
|
});
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
registerAfterHook(boundFn, name, priority) {
|
|
24
|
-
this._registerHook(AFTER_SAVE_HOOKS, boundFn, name, priority);
|
|
23
|
+
registerAfterHook(boundFn, name, priority = 99, boundFnContext) {
|
|
24
|
+
this._registerHook(AFTER_SAVE_HOOKS, boundFn, name, priority, boundFnContext);
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
async applyHooks(key, ...args) {
|
|
@@ -124,7 +124,7 @@ export default {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
try {
|
|
127
|
-
await this.applyHooks(BEFORE_SAVE_HOOKS);
|
|
127
|
+
await this.applyHooks(BEFORE_SAVE_HOOKS, this.value);
|
|
128
128
|
|
|
129
129
|
// Remove the labels map if it's empty
|
|
130
130
|
if ( this.value?.metadata?.labels && Object.keys(this.value.metadata.labels || {}).length === 0 ) {
|
|
@@ -152,7 +152,7 @@ export default {
|
|
|
152
152
|
await this.$store.dispatch('cluster/findAll', { type: this.value.type, opt: { force: true } }, { root: true });
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
await this.applyHooks(AFTER_SAVE_HOOKS);
|
|
155
|
+
await this.applyHooks(AFTER_SAVE_HOOKS, this.value);
|
|
156
156
|
buttonDone && buttonDone(true);
|
|
157
157
|
|
|
158
158
|
this.done();
|
|
@@ -9,10 +9,11 @@ import { ucFirst } from '@shell/utils/string';
|
|
|
9
9
|
import { compare } from '@shell/utils/version';
|
|
10
10
|
import { AS, MODE, _VIEW, _YAML } from '@shell/config/query-params';
|
|
11
11
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
12
|
+
import { CAPI as CAPI_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Class representing Cluster resource.
|
|
15
|
-
* @extends
|
|
16
|
+
* @extends SteveModel
|
|
16
17
|
*/
|
|
17
18
|
export default class ProvCluster extends SteveModel {
|
|
18
19
|
get details() {
|
|
@@ -381,6 +382,13 @@ export default class ProvCluster extends SteveModel {
|
|
|
381
382
|
}
|
|
382
383
|
|
|
383
384
|
get machineProvider() {
|
|
385
|
+
// First check annotation - useful for clusters created by extension providers
|
|
386
|
+
const fromAnnotation = this.annotations?.[CAPI_ANNOTATIONS.UI_CUSTOM_PROVIDER];
|
|
387
|
+
|
|
388
|
+
if (fromAnnotation) {
|
|
389
|
+
return fromAnnotation;
|
|
390
|
+
}
|
|
391
|
+
|
|
384
392
|
if (this.isHarvester) {
|
|
385
393
|
return HARVESTER;
|
|
386
394
|
} else if ( this.isImported ) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.17",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"d3-selection": "1.4.1",
|
|
70
70
|
"dagre-d3": "0.6.4",
|
|
71
71
|
"dayjs": "1.8.29",
|
|
72
|
-
"diff2html": "
|
|
72
|
+
"diff2html": "3.4.24",
|
|
73
73
|
"dompurify": "2.4.5",
|
|
74
74
|
"eslint": "7.32.0",
|
|
75
75
|
"eslint-config-standard": "16.0.3",
|
package/pages/about.vue
CHANGED
|
@@ -6,6 +6,7 @@ import { MANAGEMENT } from '@shell/config/types';
|
|
|
6
6
|
import { SETTING } from '@shell/config/settings';
|
|
7
7
|
import { getVendor } from '@shell/config/private-label';
|
|
8
8
|
import { downloadFile } from '@shell/utils/download';
|
|
9
|
+
import { mapGetters } from 'vuex';
|
|
9
10
|
|
|
10
11
|
export default {
|
|
11
12
|
layout: 'plain',
|
|
@@ -22,6 +23,7 @@ export default {
|
|
|
22
23
|
};
|
|
23
24
|
},
|
|
24
25
|
computed: {
|
|
26
|
+
...mapGetters(['releaseNotesUrl']),
|
|
25
27
|
rancherVersion() {
|
|
26
28
|
return this.settings.find((s) => s.id === SETTING.VERSION_RANCHER);
|
|
27
29
|
},
|
|
@@ -168,9 +170,13 @@ export default {
|
|
|
168
170
|
</tr>
|
|
169
171
|
</table>
|
|
170
172
|
<p class="pt-20">
|
|
171
|
-
<
|
|
173
|
+
<a
|
|
174
|
+
:href="releaseNotesUrl"
|
|
175
|
+
target="_blank"
|
|
176
|
+
rel="nofollow noopener noreferrer"
|
|
177
|
+
>
|
|
172
178
|
{{ t('about.versions.releaseNotes') }}
|
|
173
|
-
</
|
|
179
|
+
</a>
|
|
174
180
|
</p>
|
|
175
181
|
<template v-if="downloadImageList.length">
|
|
176
182
|
<h3 class="pt-40">
|
package/pages/auth/login.vue
CHANGED
package/pages/auth/logout.vue
CHANGED
|
@@ -11,8 +11,16 @@ export default {
|
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
13
|
<main class="main-layout">
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
</
|
|
14
|
+
<div>
|
|
15
|
+
<h1 v-t="'logout.message'" />
|
|
16
|
+
</div>
|
|
17
17
|
</main>
|
|
18
18
|
</template>
|
|
19
|
+
<style lang="scss" scoped>
|
|
20
|
+
main > div {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
height: 100vh;
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
@@ -242,7 +242,7 @@ export default {
|
|
|
242
242
|
},
|
|
243
243
|
|
|
244
244
|
created() {
|
|
245
|
-
const release = this.currentCluster?.status?.version
|
|
245
|
+
const release = this.currentCluster?.status?.version?.gitVersion || '';
|
|
246
246
|
const isRKE2 = release.includes('rke2');
|
|
247
247
|
const version = release.match(/\d+/g);
|
|
248
248
|
|
|
@@ -352,7 +352,10 @@ export default {
|
|
|
352
352
|
<div v-else>
|
|
353
353
|
<header>
|
|
354
354
|
<div class="title">
|
|
355
|
-
<h1
|
|
355
|
+
<h1
|
|
356
|
+
data-testid="charts-header-title"
|
|
357
|
+
class="m-0"
|
|
358
|
+
>
|
|
356
359
|
{{ t('catalog.charts.header') }}
|
|
357
360
|
</h1>
|
|
358
361
|
</div>
|
|
@@ -1251,6 +1251,10 @@ export default {
|
|
|
1251
1251
|
this.steps[0].ready = okRequires && okChart;
|
|
1252
1252
|
},
|
|
1253
1253
|
|
|
1254
|
+
updateStepTwoReady(update) {
|
|
1255
|
+
this.updateStep('helmValues', { ready: update });
|
|
1256
|
+
},
|
|
1257
|
+
|
|
1254
1258
|
getOptionLabel(opt) {
|
|
1255
1259
|
return opt?.chartNameDisplay;
|
|
1256
1260
|
},
|
|
@@ -1567,6 +1571,7 @@ export default {
|
|
|
1567
1571
|
@warn="e=>errors.push(e)"
|
|
1568
1572
|
@register-before-hook="registerBeforeHook"
|
|
1569
1573
|
@register-after-hook="registerAfterHook"
|
|
1574
|
+
@valid="updateStepTwoReady($event)"
|
|
1570
1575
|
/>
|
|
1571
1576
|
</Tabbed>
|
|
1572
1577
|
<template v-else>
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
STATE,
|
|
28
28
|
} from '@shell/config/table-headers';
|
|
29
29
|
|
|
30
|
-
import { mapPref,
|
|
30
|
+
import { mapPref, PSP_DEPRECATION_BANNER } from '@shell/store/prefs';
|
|
31
31
|
import { haveV1Monitoring, monitoringStatus } from '@shell/utils/monitoring';
|
|
32
32
|
import Tabbed from '@shell/components/Tabbed';
|
|
33
33
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
@@ -173,7 +173,6 @@ export default {
|
|
|
173
173
|
return this.$store.getters['management/all'](MANAGEMENT.CLUSTER);
|
|
174
174
|
},
|
|
175
175
|
|
|
176
|
-
hideClusterToolsTip: mapPref(CLUSTER_TOOLS_TIP),
|
|
177
176
|
hidePspDeprecationBanner: mapPref(PSP_DEPRECATION_BANNER),
|
|
178
177
|
|
|
179
178
|
hasV1Monitoring() {
|
|
@@ -441,14 +440,6 @@ export default {
|
|
|
441
440
|
:raw="true"
|
|
442
441
|
/>
|
|
443
442
|
</Banner>
|
|
444
|
-
<Banner
|
|
445
|
-
v-if="!hideClusterToolsTip"
|
|
446
|
-
:closable="true"
|
|
447
|
-
class="cluster-tools-tip"
|
|
448
|
-
color="info"
|
|
449
|
-
label-key="cluster.toolsTip"
|
|
450
|
-
@close="hideClusterToolsTip = true"
|
|
451
|
-
/>
|
|
452
443
|
<div
|
|
453
444
|
class="cluster-dashboard-glance"
|
|
454
445
|
>
|