mirror of https://github.com/rancher/dashboard.git
Merge pull request #10435 from richard-cox/optimise-branding-apps-fetch
Fetch only specific csp adapter helm apps... instead of all helm apps
This commit is contained in:
commit
fd92fbe93c
|
|
@ -0,0 +1,170 @@
|
||||||
|
import { mount } from '@vue/test-utils';
|
||||||
|
import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
||||||
|
import Brand from '@shell/mixins/brand';
|
||||||
|
|
||||||
|
describe('brandMixin', () => {
|
||||||
|
const createWrapper = (vaiOn = false) => {
|
||||||
|
const Component = {
|
||||||
|
template: '<div></div>',
|
||||||
|
mixins: [Brand],
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
apps: null, haveAppsAndSettings: null, canPaginate: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = {
|
||||||
|
dispatch: (action, ...args) => {
|
||||||
|
switch (action) {
|
||||||
|
case 'management/findAll':
|
||||||
|
if (args[0] === MANAGEMENT.SETTING) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (args[0] === CATALOG.APP) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
'auth/loggedIn': () => true,
|
||||||
|
'auth/fromHeader': () => false,
|
||||||
|
'management/byId': () => undefined,
|
||||||
|
'management/canList': () => () => true,
|
||||||
|
'management/schemaFor': (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case MANAGEMENT.SETTING:
|
||||||
|
return { linkFor: () => undefined };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'management/generation': () => undefined,
|
||||||
|
'management/paginationEnabled': () => vaiOn,
|
||||||
|
'management/all': (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case MANAGEMENT.SETTING:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = mount(
|
||||||
|
Component,
|
||||||
|
{
|
||||||
|
data: () => data,
|
||||||
|
global: { mocks: { $store: store } }
|
||||||
|
});
|
||||||
|
const spyManagementFindAll = jest.spyOn(store, 'dispatch');
|
||||||
|
|
||||||
|
return {
|
||||||
|
wrapper,
|
||||||
|
store,
|
||||||
|
spyManagementFindAll,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('should make correct requests', () => {
|
||||||
|
it('vai off', async() => {
|
||||||
|
const { wrapper, spyManagementFindAll } = createWrapper(false);
|
||||||
|
|
||||||
|
// NOTE - wrapper.vm.$options.fetch() doesn't work
|
||||||
|
await wrapper.vm.$options.fetch.apply(wrapper.vm);
|
||||||
|
|
||||||
|
// wrapper.vm.$nextTick();
|
||||||
|
expect(spyManagementFindAll).toHaveBeenNthCalledWith(1, 'management/findAll', {
|
||||||
|
type: MANAGEMENT.SETTING,
|
||||||
|
opt: {
|
||||||
|
load: 'multi', redirectUnauthorized: false, url: `/v1/${ MANAGEMENT.SETTING }s`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(spyManagementFindAll).toHaveBeenNthCalledWith(2, 'management/findAll', { type: CATALOG.APP });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('vai on', async() => {
|
||||||
|
const { wrapper, spyManagementFindAll } = createWrapper(true);
|
||||||
|
|
||||||
|
// NOTE - wrapper.vm.$options.fetch() doesn't work
|
||||||
|
await wrapper.vm.$options.fetch.apply(wrapper.vm);
|
||||||
|
|
||||||
|
expect(spyManagementFindAll).toHaveBeenNthCalledWith(1, 'management/findAll', {
|
||||||
|
type: MANAGEMENT.SETTING,
|
||||||
|
opt: {
|
||||||
|
load: 'multi', url: `/v1/${ MANAGEMENT.SETTING }s`, redirectUnauthorized: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(spyManagementFindAll).toHaveBeenNthCalledWith(2, 'management/findPage', {
|
||||||
|
type: CATALOG.APP,
|
||||||
|
opt: {
|
||||||
|
pagination: {
|
||||||
|
filters: [{
|
||||||
|
equals: true,
|
||||||
|
fields: [{
|
||||||
|
equals: true, exact: true, field: 'metadata.name', value: 'rancher-csp-adapter'
|
||||||
|
}, {
|
||||||
|
equals: true, exact: true, field: 'metadata.name', value: 'rancher-csp-billing-adapter'
|
||||||
|
}],
|
||||||
|
param: 'filter'
|
||||||
|
}],
|
||||||
|
labelSelector: undefined,
|
||||||
|
page: null,
|
||||||
|
pageSize: null,
|
||||||
|
projectsOrNamespaces: [],
|
||||||
|
sort: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('cspAdapter', () => {
|
||||||
|
it('should have correct csp values (off)', async() => {
|
||||||
|
const { wrapper, store } = createWrapper();
|
||||||
|
|
||||||
|
const spyManagementFindAll = jest.spyOn(store, 'dispatch').mockImplementation((_, options) => {
|
||||||
|
const { type } = options as any;
|
||||||
|
|
||||||
|
if (type === MANAGEMENT.SETTING) {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
if (type === CATALOG.APP) {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(new Error('reason'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// NOTE - wrapper.vm.$options.fetch() doesn't work
|
||||||
|
await wrapper.vm.$options.fetch.apply(wrapper.vm, []);
|
||||||
|
|
||||||
|
expect(spyManagementFindAll).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(wrapper.vm.canCalcCspAdapter).toBeTruthy();
|
||||||
|
expect(wrapper.vm.cspAdapter).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(['rancher-csp-adapter', 'rancher-csp-billing-adapter'])('should have correct csp values (on - %p )', async(chartName) => {
|
||||||
|
const { wrapper, store } = createWrapper();
|
||||||
|
|
||||||
|
const spyManagementFindAll = jest.spyOn(store, 'dispatch').mockImplementation((_, options) => {
|
||||||
|
const { type } = options as any;
|
||||||
|
|
||||||
|
if (type === MANAGEMENT.SETTING) {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
if (type === CATALOG.APP) {
|
||||||
|
return Promise.resolve([{ metadata: { name: chartName } }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(new Error('reason'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// NOTE - wrapper.vm.$options.fetch() doesn't work
|
||||||
|
await wrapper.vm.$options.fetch.apply(wrapper.vm, []);
|
||||||
|
|
||||||
|
expect(spyManagementFindAll).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(wrapper.vm.canCalcCspAdapter).toBeTruthy();
|
||||||
|
expect(wrapper.vm.cspAdapter).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,39 +1,38 @@
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
import { MANAGEMENT } from '@shell/config/types';
|
||||||
import { SETTING } from '@shell/config/settings';
|
import { SETTING } from '@shell/config/settings';
|
||||||
import { createCssVars } from '@shell/utils/color';
|
import { createCssVars } from '@shell/utils/color';
|
||||||
import { setTitle } from '@shell/config/private-label';
|
import { setTitle } from '@shell/config/private-label';
|
||||||
import { setFavIcon, haveSetFavIcon } from '@shell/utils/favicon';
|
import { setFavIcon, haveSetFavIcon } from '@shell/utils/favicon';
|
||||||
|
import { allHash } from '@shell/utils/promise';
|
||||||
const cspAdaptorApp = ['rancher-csp-adapter', 'rancher-csp-billing-adapter'];
|
import { fetchInitialSettings } from '@shell/utils/settings';
|
||||||
|
import CspAdapterUtils from '@shell/utils/cspAdaptor';
|
||||||
export const hasCspAdapter = (apps) => {
|
|
||||||
return apps?.find((a) => cspAdaptorApp.includes(a.metadata?.name));
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async fetch() {
|
async fetch() {
|
||||||
// For the login page, the schemas won't be loaded - we don't need the apps in this case
|
|
||||||
try {
|
try {
|
||||||
if (this.$store.getters['management/canList'](CATALOG.APP)) {
|
const res = await allHash({
|
||||||
this.apps = await this.$store.dispatch('management/findAll', { type: CATALOG.APP });
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
// Ensure we read the settings even when we are not authenticated
|
// Ensure we read the settings even when we are not authenticated
|
||||||
try {
|
globalSettings: fetchInitialSettings(this.$store),
|
||||||
|
apps: CspAdapterUtils.fetchCspAdaptorApp(this.$store),
|
||||||
|
});
|
||||||
|
|
||||||
// The favicon is implicitly dependent on the initial settings having already been fetched
|
// The favicon is implicitly dependent on the initial settings having already been fetched
|
||||||
if (!haveSetFavIcon()) {
|
if (!haveSetFavIcon()) {
|
||||||
setFavIcon(this.$store);
|
setFavIcon(this.$store);
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
|
||||||
|
this.apps = res.apps;
|
||||||
|
} catch (e) { }
|
||||||
|
|
||||||
// Setting this up front will remove `computed` churn, and we only care that we've initialised them
|
// Setting this up front will remove `computed` churn, and we only care that we've initialised them
|
||||||
this.haveAppsAndSettings = !!this.apps && !!this.globalSettings;
|
this.haveAppsAndSettings = !!this.apps && !!this.globalSettings;
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return { apps: null, haveAppsAndSettings: null };
|
return {
|
||||||
|
apps: null, haveAppsAndSettings: null, canPaginate: false
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -87,7 +86,7 @@ export default {
|
||||||
// Note! this used to be `findBy(this.app)` however for that case we lost reactivity on the collection
|
// Note! this used to be `findBy(this.app)` however for that case we lost reactivity on the collection
|
||||||
// (computed fires before fetch, fetch happens and update apps, computed would not fire again - even with vue.set)
|
// (computed fires before fetch, fetch happens and update apps, computed would not fire again - even with vue.set)
|
||||||
// So use `.find` in method instead
|
// So use `.find` in method instead
|
||||||
return hasCspAdapter(this.apps);
|
return CspAdapterUtils.hasCspAdapter({ $store: this.$store, apps: this.apps });
|
||||||
},
|
},
|
||||||
|
|
||||||
canCalcCspAdapter() {
|
canCalcCspAdapter() {
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
import BannerGraphic from '@shell/components/BannerGraphic';
|
import BannerGraphic from '@shell/components/BannerGraphic';
|
||||||
import IndentedPanel from '@shell/components/IndentedPanel';
|
import IndentedPanel from '@shell/components/IndentedPanel';
|
||||||
import CommunityLinks from '@shell/components/CommunityLinks';
|
import CommunityLinks from '@shell/components/CommunityLinks';
|
||||||
import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
import { MANAGEMENT } from '@shell/config/types';
|
||||||
import { getVendor } from '@shell/config/private-label';
|
import { getVendor } from '@shell/config/private-label';
|
||||||
import { SETTING } from '@shell/config/settings';
|
import { SETTING } from '@shell/config/settings';
|
||||||
import { addParam } from '@shell/utils/url';
|
import { addParam } from '@shell/utils/url';
|
||||||
import { isRancherPrime } from '@shell/config/version';
|
import { isRancherPrime } from '@shell/config/version';
|
||||||
import { hasCspAdapter } from '@shell/mixins/brand';
|
|
||||||
import TabTitle from '@shell/components/TabTitle';
|
import TabTitle from '@shell/components/TabTitle';
|
||||||
|
import CspAdapterUtils from '@shell/utils/cspAdaptor';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
|
|
@ -42,9 +42,7 @@ export default {
|
||||||
return setting;
|
return setting;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( this.$store.getters['management/canList'](CATALOG.APP) ) {
|
this.apps = await CspAdapterUtils.fetchCspAdaptorApp(this.$store);
|
||||||
this.apps = await this.$store.dispatch('management/findAll', { type: CATALOG.APP });
|
|
||||||
}
|
|
||||||
this.brandSetting = await fetchOrCreateSetting(SETTING.BRAND, '');
|
this.brandSetting = await fetchOrCreateSetting(SETTING.BRAND, '');
|
||||||
this.serverUrlSetting = await fetchOrCreateSetting(SETTING.SERVER_URL, '');
|
this.serverUrlSetting = await fetchOrCreateSetting(SETTING.SERVER_URL, '');
|
||||||
this.uiIssuesSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES });
|
this.uiIssuesSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES });
|
||||||
|
|
@ -75,7 +73,7 @@ export default {
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
cspAdapter() {
|
cspAdapter() {
|
||||||
return hasCspAdapter(this.apps);
|
return CspAdapterUtils.hasCspAdapter({ $store: this.$store, apps: this.apps });
|
||||||
},
|
},
|
||||||
|
|
||||||
hasSupport() {
|
hasSupport() {
|
||||||
|
|
|
||||||
|
|
@ -667,19 +667,19 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStore = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Disabled due to https://github.com/rancher/dashboard/issues/14493
|
management: {
|
||||||
// management: {
|
resources: {
|
||||||
// resources: {
|
enableAll: false,
|
||||||
// enableAll: false,
|
enableSome: {
|
||||||
// enableSome: {
|
enabled: [
|
||||||
// enabled: [
|
// { resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] }, // Disabled due to https://github.com/rancher/dashboard/issues/14493
|
||||||
// { resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] },
|
// { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] }, // Disabled due to https://github.com/rancher/dashboard/issues/14493
|
||||||
// { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
|
{ resource: CATALOG.APP, context: ['branding'] },
|
||||||
// ],
|
],
|
||||||
// generic: false,
|
generic: false,
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default new StevePaginationUtils();
|
export default new StevePaginationUtils();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// For testing these could be changed to something like...
|
||||||
|
|
||||||
|
import { CATALOG } from '@shell/config/types';
|
||||||
|
import { FilterArgs, PaginationFilterField, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
||||||
|
import { VuexStore } from '@shell/types/store/vuex';
|
||||||
|
|
||||||
|
const CSP_ADAPTER_APPS = ['rancher-csp-adapter', 'rancher-csp-billing-adapter'];
|
||||||
|
// For testing above line could be replaced with below line...
|
||||||
|
// const cspAdaptorApp = ['rancher-webhooka', 'rancher-webhook'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers in order to
|
||||||
|
*/
|
||||||
|
class CspAdapterUtils {
|
||||||
|
static canPagination($store: VuexStore): boolean {
|
||||||
|
return $store.getters[`management/paginationEnabled`]({ id: CATALOG.APP, context: 'branding' });
|
||||||
|
}
|
||||||
|
|
||||||
|
static fetchCspAdaptorApp($store: VuexStore): Promise<any> {
|
||||||
|
// For the login page, the schemas won't be loaded - we don't need the apps in this case
|
||||||
|
if ($store.getters['management/canList'](CATALOG.APP)) {
|
||||||
|
if (CspAdapterUtils.canPagination($store)) {
|
||||||
|
// Restrict the amount of apps we need to fetch
|
||||||
|
return $store.dispatch('management/findPage', {
|
||||||
|
type: CATALOG.APP,
|
||||||
|
opt: { // Of type ActionFindPageArgs
|
||||||
|
pagination: new FilterArgs({
|
||||||
|
filters: PaginationParamFilter.createMultipleFields(CSP_ADAPTER_APPS.map(
|
||||||
|
(t) => new PaginationFilterField({
|
||||||
|
field: 'metadata.name',
|
||||||
|
value: t,
|
||||||
|
})
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $store.dispatch('management/findAll', { type: CATALOG.APP });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static hasCspAdapter({ $store, apps }: { $store: VuexStore, apps: any[]}): Object {
|
||||||
|
// In theory this should contain the filtered apps when pagination is on, and all apps when off. Keep filtering though in both cases just in case
|
||||||
|
return apps?.find((a) => CSP_ADAPTER_APPS.includes(a.metadata?.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CspAdapterUtils;
|
||||||
Loading…
Reference in New Issue