Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cypress/e2e/tests/priority/no-vai-setup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FeatureFlagsPagePo } from '@/cypress/e2e/po/pages/global-settings/featu

// Vai ('ui-sql-cache') is now on by default. This sets up the `noVai` test suite by disabling it

const featureFlagsPage = new FeatureFlagsPagePo('_');
const featureFlagsPage = new FeatureFlagsPagePo('local');

describe('Disable Vai', { testIsolation: 'off', tags: ['@noVai', '@adminUser'] }, () => {
before(() => {
Expand Down
2 changes: 2 additions & 0 deletions docs/developer/api-resources-and-schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ In a production setup these are all handled natively by Rancher. For developmen
| `/k8s/clusters/<id>` | Proxy straight to the native k8s API for the given downstream cluster |
| `/k8s/clusters/<id>/v1` | Steve API for given downstream cluster via the server proxy |

> `/` redirects to `/k8s/clusters/local`, which means steve upstream requests using `/v1` are just shortcuts for `/k8s/clusters/local/v1`

The older Norman API is served on `/v3`. The newer Steve API (see [here](https://github.com/rancher/api-spec/blob/master/specification.md) for spec) is served on `/v1` .

In both cases the schemas returned dictate
Expand Down
3 changes: 1 addition & 2 deletions shell/components/nav/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export default {
'isSingleProduct',
'isRancherInHarvester',
'showTopLevelMenu',
'isMultiCluster',
'showWorkspaceSwitcher'
]),

Expand Down Expand Up @@ -424,7 +423,7 @@ export default {
data-testid="header"
>
<div>
<TopLevelMenu v-if="isRancherInHarvester || isMultiCluster || !isSingleProduct" />
<TopLevelMenu v-if="showTopLevelMenu" />
</div>

<div
Expand Down
45 changes: 32 additions & 13 deletions shell/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export const state = () => {
$route: markRaw({}),
$plugin: markRaw({}),
showWorkspaceSwitcher: true,

localCluster: null,
};
};

Expand All @@ -272,10 +272,20 @@ export const getters = {
return state.clusterReady === true;
},

/**
* Cache of the mgmt cluster fetched at start up
*
* We cannot rely on the store to cache this as the store may contain a page without the local cluster
*/
localCluster(state) {
return state.localCluster;
},

isMultiCluster(state, getters) {
const clusters = getters['management/all'](MANAGEMENT.CLUSTER);
const clusterCount = getters['management/all'](COUNT)?.[0]?.counts?.[MANAGEMENT.CLUSTER]?.summary?.count || 0;
const localCluster = getters['localCluster'];

if (clusters.length === 1 && clusters[0].metadata?.name === 'local') {
if (clusterCount === 1 && !!localCluster) {
return false;
} else {
return true;
Expand Down Expand Up @@ -592,10 +602,9 @@ export const getters = {
},

isStandaloneHarvester(state, getters) {
const clusters = getters['management/all'](MANAGEMENT.CLUSTER);
const cluster = clusters.find((c) => c.id === 'local') || {};
const localCluster = getters['localCluster'];

return getters['isSingleProduct'] && cluster.isHarvester && !getters['isRancherInHarvester'];
return getters['isSingleProduct'] && localCluster?.isHarvester && !getters['isRancherInHarvester'];
},

showTopLevelMenu(getters) {
Expand Down Expand Up @@ -640,9 +649,10 @@ export const mutations = {
clearPageActionHandler(state) {
state.pageActionHandler = null;
},
managementChanged(state, { ready, isRancher }) {
managementChanged(state, { ready, isRancher, localCluster }) {
state.managementReady = ready;
state.isRancher = isRancher;
state.localCluster = localCluster;
},
clusterReady(state, ready) {
state.clusterReady = ready;
Expand Down Expand Up @@ -846,23 +856,29 @@ export const actions = {

res = await allHash(promises);

let localCluster = null;

if (!res[MANAGEMENT.SETTING] || !paginateClusters({ rootGetters, state })) {
// This introduces a synchronous request, however we need settings to determine if SSP is enabled
// Eventually it will be removed when SSP is always on
res[MANAGEMENT.CLUSTER] = await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } });
await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } });
toWatch.push(MANAGEMENT.CLUSTER);

localCluster = getters['management/byId'](MANAGEMENT.CLUSTER, 'local');
} else {
try {
localCluster = await dispatch('management/find', {
type: MANAGEMENT.CLUSTER, id: 'local', opt: { watch: false }
});
} catch (e) { // we don't care about errors, specifically 404s
}
}

// See comment above. Now that we have feature flags we can watch resources
toWatch.forEach((type) => {
dispatch('management/watch', { type });
});

const isMultiCluster = getters['isMultiCluster'];

// If the local cluster is a Harvester cluster and 'rancher-manager-support' is true, it means that the embedded Rancher is being used.
const localCluster = res[MANAGEMENT.CLUSTER]?.find((c) => c.id === 'local');

if (localCluster?.isHarvester) {
const harvesterSetting = await dispatch('cluster/findAll', { type: HCI.SETTING, opt: { url: `/v1/harvester/${ HCI.SETTING }s` } });
const rancherManagerSupport = harvesterSetting.find((setting) => setting.id === 'rancher-manager-support');
Expand Down Expand Up @@ -904,6 +920,7 @@ export const actions = {
commit('managementChanged', {
ready: true,
isRancher,
localCluster
});

if ( res[FLEET.WORKSPACE] ) {
Expand All @@ -914,6 +931,8 @@ export const actions = {
});
}

const isMultiCluster = getters['isMultiCluster'];

console.log(`Done loading management; isRancher=${ isRancher }; isMultiCluster=${ isMultiCluster }`); // eslint-disable-line no-console
},

Expand Down
6 changes: 3 additions & 3 deletions shell/store/type-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,7 @@ function ifHave(getters, option) {
case IF_HAVE.NOT_V1_ISTIO: {
return !isV1Istio(getters);
}
case IF_HAVE.MULTI_CLUSTER: {
case IF_HAVE.MULTI_CLUSTER: { // Used by harvester extension
return getters.isMultiCluster;
}
case IF_HAVE.NEUVECTOR_NAMESPACE: {
Expand All @@ -1904,10 +1904,10 @@ function ifHave(getters, option) {
case IF_HAVE.ADMIN: {
return isAdminUser(getters);
}
case IF_HAVE.MCM_DISABLED: {
case IF_HAVE.MCM_DISABLED: { // There's a general MCM ff, this is conflating it with a harvester concept
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo ff -> off.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, i should have expanded that. ff here means Feature Flag.

I'll sneak an update in another PR

return !getters['isRancherInHarvester'];
}
case IF_HAVE.NOT_STANDALONE_HARVESTER: {
case IF_HAVE.NOT_STANDALONE_HARVESTER: { // Not used by harvester extension...
return !getters['isStandaloneHarvester'];
}
default:
Expand Down
24 changes: 15 additions & 9 deletions shell/utils/dynamic-content/__tests__/info.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ describe('systemInfoProvider', () => {
return undefined;
}),
'management/schemaFor': jest.fn(),
localCluster: mockClusters.find((c) => c.id === 'local') || null,
};

(version.getVersionData as jest.Mock).mockReturnValue({
Expand Down Expand Up @@ -159,6 +160,7 @@ describe('systemInfoProvider', () => {

mockGetters['uiplugins/plugins'] = null; // No plugins
mockGetters['auth/principalId'] = null; // No user
mockGetters['localCluster'] = null; // No clusters

const infoProvider = new SystemInfoProvider(mockGetters, {});
const qs = infoProvider.buildQueryString();
Expand Down Expand Up @@ -191,6 +193,7 @@ describe('systemInfoProvider', () => {

mockGetters['auth/principalId'] = 'user-456';
mockGetters['uiplugins/plugins'] = []; // No plugins
mockGetters['localCluster'] = null; // No clusters

const infoProvider = new SystemInfoProvider(mockGetters, {});
const qs = infoProvider.buildQueryString();
Expand All @@ -199,7 +202,6 @@ describe('systemInfoProvider', () => {
expect(mockGetters['management/byId']).toHaveBeenCalledWith(MANAGEMENT.SETTING, 'install-uuid');
expect(mockGetters['management/byId']).toHaveBeenCalledWith(MANAGEMENT.SETTING, 'server-version-type');
expect(mockGetters['management/typeRegistered']).toHaveBeenCalledWith(COUNT);
expect(mockGetters['management/typeRegistered']).toHaveBeenCalledWith(MANAGEMENT.CLUSTER);
expect(mockGetters['management/all']).not.toHaveBeenCalled();

// Verify the query string is built with fallback or empty values
Expand All @@ -225,6 +227,16 @@ describe('systemInfoProvider', () => {
return { id, value: '' }; // Empty values for all settings
}
});

// local cluster with missing properties
const localCluster = {
id: 'local',
isLocal: true,
status: { nodeCount: 1 },
// kubernetesVersionBase is missing
// provisioner is missing
};

mockGetters['management/all'].mockImplementation((type: string) => {
if (type === MANAGEMENT.SETTING) {
// Return settings, but with empty values
Expand All @@ -237,20 +249,14 @@ describe('systemInfoProvider', () => {
return [{ counts: { [MANAGEMENT.CLUSTER]: { summary: { count: 1 } } } }];
}
if (type === MANAGEMENT.CLUSTER) {
// local cluster with missing properties
return [{
id: 'local',
isLocal: true,
status: { nodeCount: 1 },
// kubernetesVersionBase is missing
// provisioner is missing
}];
return [localCluster];
}

return [];
});

mockGetters['auth/principalId'] = null; // No user
mockGetters['localCluster'] = localCluster;

const infoProvider = new SystemInfoProvider(mockGetters, {});
const qs = infoProvider.buildQueryString();
Expand Down
3 changes: 1 addition & 2 deletions shell/utils/dynamic-content/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ export class SystemInfoProvider {
// High-level information from clusters
const counts = this.getAll(getters, COUNT)?.[0]?.counts || {};
const clusterCount = counts[MANAGEMENT.CLUSTER] || {};
const all = this.getAll(getters, MANAGEMENT.CLUSTER);
const localCluster = all ? all.find((c: any) => c.isLocal) : undefined;
const localCluster = getters['localCluster'];

// Stats for installed extensions
const uiExtensionList = getters['uiplugins/plugins'];
Expand Down
Loading