Skip to content

Commit

Permalink
prevent fetch of policy reports if controller app version is not 1.11 (
Browse files Browse the repository at this point in the history
…#650)

Co-authored-by: Alexandre Alves <[email protected]>
  • Loading branch information
aalves08 and Alexandre Alves authored Mar 19, 2024
1 parent b2e265f commit 32500dc
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 14 deletions.
22 changes: 22 additions & 0 deletions pkg/kubewarden/modules/kubewardenController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Store } from 'vuex';

import { CATALOG } from '@shell/config/types';
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';

import { KUBEWARDEN_APPS, CatalogApp } from '../types';

export const fetchControllerApp = async(store: Store<any>): Promise<CatalogApp | undefined> => {
if ( store.getters['cluster/schemaFor'](CATALOG.APP) ) {
const allApps: CatalogApp[] = await store.dispatch('cluster/findAll', { type: CATALOG.APP });

const controllerApp = allApps?.find(app => (
app.spec?.chart?.metadata?.annotations?.[CATALOG_ANNOTATIONS.RELEASE_NAME] === KUBEWARDEN_APPS.RANCHER_CONTROLLER
));

if ( controllerApp ) {
store.dispatch('kubewarden/updateControllerApp', controllerApp);

return controllerApp;
}
}
};
38 changes: 24 additions & 14 deletions pkg/kubewarden/modules/policyReporter.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import { Store } from 'vuex';
import isEmpty from 'lodash/isEmpty';
import semver from 'semver';
import { randomStr } from '@shell/utils/string';
import {
KUBEWARDEN, Severity, Result, PolicyReport, PolicyReportResult, PolicyReportSummary, WG_POLICY_K8S
KUBEWARDEN, CatalogApp, Severity, Result, PolicyReport, PolicyReportResult, PolicyReportSummary, WG_POLICY_K8S
} from '../types';
import * as coreTypes from '../core/core-resources';
import { createKubewardenRoute } from '../utils/custom-routing';
import { splitGroupKind } from './core';
import { fetchControllerApp } from './kubewardenController';

/**
* Attempts to fetch PolicyReports by dispatching a findAll against `wgpolicyk8s.io.policyreport`
* @param store
* @returns `PolicyReport[] | void` - Scaffolded value of a PolicyReport accomplished by scaffoldPolicyReport()
*/
export async function getPolicyReports(store: any): Promise<PolicyReport[] | void> {
export async function getPolicyReports(store: Store<any>): Promise<PolicyReport[] | void> {
const schema = store.getters['cluster/schemaFor'](WG_POLICY_K8S.POLICY_REPORT.TYPE);
let controllerApp: CatalogApp | undefined = store.getters['kubewarden/controllerApp'];

if ( schema ) {
try {
const reports = await fetchPolicyReports(store);
if ( !controllerApp ) {
controllerApp = await fetchControllerApp(store);
}

if ( !isEmpty(reports) ) {
reports?.forEach((report: PolicyReport) => store.dispatch('kubewarden/updatePolicyReports', report));
if ( schema && controllerApp && controllerApp?.spec?.chart?.metadata?.appVersion ) {
// only fetch reports if app version is compatible with new data structure
if ( semver.gte(controllerApp.spec.chart.metadata.appVersion, '1.10.100') ) {
try {
const reports = await fetchPolicyReports(store);

return reports;
if ( !isEmpty(reports) ) {
reports?.forEach((report: PolicyReport) => store.dispatch('kubewarden/updatePolicyReports', report));

return reports;
}
} catch (e) {
console.warn(`Error fetching PolicyReports: ${ e }`); // eslint-disable-line no-console
}
} catch (e) {
console.warn(`Error fetching PolicyReports: ${ e }`); // eslint-disable-line no-console
}
}
}
Expand All @@ -36,7 +46,7 @@ export async function getPolicyReports(store: any): Promise<PolicyReport[] | voi
* @param store
* @returns `PolicyReport[] | void`
*/
export async function fetchPolicyReports(store: any): Promise<Array<PolicyReport>> {
export async function fetchPolicyReports(store: Store<any>): Promise<Array<PolicyReport>> {
return await store.dispatch('cluster/findAll', { type: WG_POLICY_K8S.POLICY_REPORT.TYPE }, { root: true });
}

Expand All @@ -46,7 +56,7 @@ export async function fetchPolicyReports(store: any): Promise<Array<PolicyReport
* @param resource
* @returns `PolicyReportSummary | null | void`
*/
export function getFilteredSummary(store: any, resource: any): PolicyReportSummary | null | void {
export function getFilteredSummary(store: Store<any>, resource: any): PolicyReportSummary | null | void {
const schema = store.getters['cluster/schemaFor'](resource.type);

if ( schema ) {
Expand Down Expand Up @@ -93,7 +103,7 @@ export function getFilteredSummary(store: any, resource: any): PolicyReportSumma
* @param resource
* @returns `PolicyReport | PolicyReportResult[] | null | void`
*/
export async function getFilteredReports(store: any, resource: any): Promise<PolicyReport[] | PolicyReportResult[] | null | void> {
export async function getFilteredReports(store: Store<any>, resource: any): Promise<PolicyReport[] | PolicyReportResult[] | null | void> {
const schema = store.getters['cluster/schemaFor'](resource?.type);

if ( schema ) {
Expand Down Expand Up @@ -161,7 +171,7 @@ export async function getFilteredReports(store: any, resource: any): Promise<Pol
* @param report: `PolicyReportResult`
* @returns `createKubewardenRoute` | Will return a route to either a ClusterAdmissionPolicy or AdmissionPolicy
*/
export function getLinkForPolicy(store: any, report: PolicyReportResult): Object | void {
export function getLinkForPolicy(store: Store<any>, report: PolicyReportResult): Object | void {
if ( report?.policy ) {
const apSchema = store.getters['cluster/schemaFor'](KUBEWARDEN.ADMISSION_POLICY);
const capSchema = store.getters['cluster/schemaFor'](KUBEWARDEN.CLUSTER_ADMISSION_POLICY);
Expand Down
49 changes: 49 additions & 0 deletions tests/unit/_templates_/controllerApp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { CatalogApp } from '@kubewarden/types';

export const mockControllerApp: CatalogApp = {
id: 'cattle-kubewarden-system/rancher-kubewarden-controller',
type: 'app',
apiVersion: 'catalog.cattle.io/v1',
kind: 'App',
metadata: {
annotations: {},
labels: {},
name: 'rancher-kubewarden-controller',
namespace: 'cattle-kubewarden-system'
},
spec: {
chart: {
metadata: {
annotations: {
'catalog.cattle.io/auto-install': 'kubewarden-crds=1.4.5',
'catalog.cattle.io/certified': 'rancher',
'catalog.cattle.io/display-name': 'Kubewarden',
'catalog.cattle.io/namespace': 'cattle-kubewarden-system',
'catalog.cattle.io/os': 'linux',
'catalog.cattle.io/provides-gvr': 'policyservers.policies.kubewarden.io/v1',
'catalog.cattle.io/rancher-version': '>= 2.6.0-0 <= 2.8.100-0',
'catalog.cattle.io/release-name': 'rancher-kubewarden-controller',
'catalog.cattle.io/requests-cpu': '250m',
'catalog.cattle.io/requests-memory': '50Mi',
'catalog.cattle.io/type': 'cluster-tool',
'catalog.cattle.io/ui-component': 'kubewarden',
'catalog.cattle.io/ui-source-repo': 'kubewarden-charts',
'catalog.cattle.io/ui-source-repo-type': 'cluster',
'catalog.cattle.io/upstream-version': '2.0.9'
},
apiVersion: 'v2',
appVersion: 'v1.11.0',
name: 'kubewarden-controller',
type: 'application',
version: '2.0.9'
},
values: {}
},
info: { status: 'deployed' },
name: 'rancher-kubewarden-controller',
namespace: 'cattle-kubewarden-system',
resources: [],
values: {}
},
status: { summary: { state: 'deployed' } }
};
45 changes: 45 additions & 0 deletions tests/unit/modules/kubewardenController.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { CATALOG } from '@shell/config/labels-annotations';
import { KUBEWARDEN_APPS } from '@kubewarden/types';
import { fetchControllerApp } from '@kubewarden/modules/kubewardenController';

const mockStore = {
getters: { 'cluster/schemaFor': jest.fn() },
dispatch: jest.fn(),
};

beforeEach(() => { //
jest.clearAllMocks();
});

describe('fetchControllerApp', () => {
it('should fetch and return the controller app when found', async() => {
const expectedControllerApp = { spec: { chart: { metadata: { annotations: { [CATALOG.RELEASE_NAME]: KUBEWARDEN_APPS.RANCHER_CONTROLLER } } } } };

mockStore.getters['cluster/schemaFor'].mockReturnValue(true);
mockStore.dispatch.mockResolvedValue([expectedControllerApp]);

const result = await fetchControllerApp(mockStore);

expect(result).toEqual(expectedControllerApp);
expect(mockStore.dispatch).toHaveBeenCalledWith('kubewarden/updateControllerApp', expectedControllerApp);
});

it('should return undefined if the controller app is not found', async() => {
mockStore.getters['cluster/schemaFor'].mockReturnValue(true);
mockStore.dispatch.mockResolvedValue([]);

const result = await fetchControllerApp(mockStore);

expect(result).toBeUndefined();
expect(mockStore.dispatch).not.toHaveBeenCalledWith('kubewarden/updateControllerApp', expect.anything());
});

it('should not proceed if the schema for CATALOG.APP is not found', async() => {
mockStore.getters['cluster/schemaFor'].mockReturnValue(false);

const result = await fetchControllerApp(mockStore);

expect(result).toBeUndefined();
expect(mockStore.dispatch).not.toHaveBeenCalled();
});
});
21 changes: 21 additions & 0 deletions tests/unit/modules/policyReporter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as policyReporterModule from '@kubewarden/modules/policyReporter.ts';
import { KUBEWARDEN } from '@kubewarden/types';
import { mockPolicyReport } from '../_templates_/policyReports';
import { mockControllerApp } from '../_templates_/controllerApp';

// Mocking lodash's isEmpty function//
jest.mock('lodash/isEmpty', () => ({
Expand All @@ -15,6 +16,7 @@ const mockStore = {
getters: {
'cluster/schemaFor': jest.fn(),
'kubewarden/policyReports': [mockPolicyReport],
'kubewarden/controllerApp': mockControllerApp
},
dispatch: jest.fn(),
};
Expand Down Expand Up @@ -76,4 +78,23 @@ describe('getLinkForPolicy', () => {
})
});
});
});

describe('newPolicyReportCompatible', () => {
it('should be incompatible with OLD data structure for a controller app version >= 1.10.0 && UI plugin version >= 1.4.0', () => {
const result = policyReporterModule.newPolicyReportCompatible('1.10.0', '1.4.0');

expect(result).toStrictEqual({
oldPolicyReports: false,
newPolicyReports: true
});
});
it('should be incompatible with NEW data structure for a controller app version >= 1.11.0 && UI plugin version >= 1.3.6', () => {
const result = policyReporterModule.newPolicyReportCompatible('1.11.0', '1.3.6');

expect(result).toStrictEqual({
oldPolicyReports: true,
newPolicyReports: false
});
});
});

0 comments on commit 32500dc

Please sign in to comment.