Skip to content
Closed
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
48 changes: 28 additions & 20 deletions pkg/kubewarden/chart/kubewarden/admission/General.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script>
import isEmpty from 'lodash/isEmpty';

import { _CREATE } from '@shell/config/query-params';
import { set } from '@shell/utils/object';

Expand All @@ -11,8 +9,9 @@ import { Banner } from '@components/Banner';
import { LabeledInput } from '@components/Form/LabeledInput';
import { RadioGroup } from '@components/Form/Radio';

import { KUBEWARDEN, KUBEWARDEN_APPS } from '@kubewarden/types';
import { KUBEWARDEN } from '@kubewarden/types';
import { buildModuleString } from '@kubewarden/modules/policyChart';
import { applyCreatePolicyDefaults } from '@kubewarden/modules/policyDefaults';

export default {
name: 'General',
Expand Down Expand Up @@ -56,16 +55,8 @@ export default {
await this.$store.dispatch('cluster/findAll', { type: KUBEWARDEN.POLICY_SERVER });
}

if (this.isCreate && !isEmpty(this.policy.spec)) {
set(this.policy.spec, 'mode', 'protect');
}

if (this.isCreate && !isEmpty(this.policyServers)) {
const defaultPolicyServer = this.policyServers.find((ps) => {
return ps.metadata.annotations?.['meta.helm.sh/release-name'] === KUBEWARDEN_APPS.RANCHER_DEFAULTS;
});

this.policy.spec.policyServer = defaultPolicyServer?.id;
if (this.isCreate) {
applyCreatePolicyDefaults(this.policy, this.policyServers);
}
},

Expand All @@ -79,8 +70,12 @@ export default {
}

// fix for https://github.com/rancher/kubewarden-ui/issues/672
// enforce `default` as namespace for creation of AP's
if (this.mode === _CREATE && this.chartType === KUBEWARDEN.ADMISSION_POLICY) {
// default namespace for AP create only when not already preselected
if (
this.mode === _CREATE &&
this.chartType === KUBEWARDEN.ADMISSION_POLICY &&
!policy?.metadata?.namespace
) {
set(policy.metadata, 'namespace', 'default');
}

Expand Down Expand Up @@ -121,6 +116,12 @@ export default {
policyTag() {
this.syncModule();
},

hasValuesModule(neu) {
if (!neu) {
this.$emit('module-validation', false);
}
},
},

created() {
Expand Down Expand Up @@ -204,19 +205,23 @@ export default {

methods: {
syncModule() {
if (!this.hasValuesModule || !this.policy?.spec) {
if (!this.policy?.spec) {
return;
}

const registry = this.policyRegistry?.trim() || '';
const repository = this.policyRepository?.trim() || '';
const tag = this.policyTag?.trim() || '';
if (!this.hasValuesModule) {
this.$emit('module-validation', false);

if (!repository || !tag) {
return;
}

const registry = this.policyRegistry?.trim() || '';
const repository = this.policyRepository?.trim() || '';
const tag = this.policyTag?.trim() || '';

this.policy.spec.module = buildModuleString(registry, repository, tag);

this.$emit('module-validation', !registry || !repository || !tag);
}
}
};
Expand Down Expand Up @@ -274,6 +279,7 @@ export default {
:mode="mode"
:label="t('kubewarden.policies.module.registry')"
:placeholder="t('kubewarden.policies.module.registryPlaceholder')"
:required="true"
/>
</div>
<div class="col span-5">
Expand All @@ -282,6 +288,7 @@ export default {
data-testid="kw-policy-general-repository-input"
:mode="mode"
:label="t('kubewarden.policies.module.repository')"
:required="true"
/>
</div>
<div class="col span-3">
Expand All @@ -290,6 +297,7 @@ export default {
data-testid="kw-policy-general-tag-input"
:mode="mode"
:label="t('kubewarden.policies.module.tag')"
:required="true"
/>
</div>
</template>
Expand Down
8 changes: 2 additions & 6 deletions pkg/kubewarden/chart/kubewarden/admission/Rules/Rule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,8 @@ export default {
components: { LabeledSelect },

fetch() {
if (this.isCreate && isEmpty(this.value?.apiGroups)) {
if (!Array.isArray(this.value.apiGroups)) {
this.value.apiGroups = [];
}

this.value.apiGroups.push('*');
if (this.isCreate && this.value?.apiGroups === undefined) {
this.value.apiGroups = ['*'];
}
},

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { shallowMount } from '@vue/test-utils';

import { KUBEWARDEN } from '@kubewarden/types';
import Rule from '@kubewarden/chart/kubewarden/admission/Rules/Rule.vue';

describe('component: Rule fetch defaults', () => {
function mountRule(value: any) {
return shallowMount(Rule, {
propsData: {
value,
disabled: true,
mode: 'create',
},
global: { provide: { chartType: KUBEWARDEN.CLUSTER_ADMISSION_POLICY } },
});
}

it('does not overwrite an explicitly empty apiGroups array', async() => {
const value = { apiGroups: [] };
const wrapper = mountRule(value);

await wrapper.vm.$options.fetch.call(wrapper.vm);

expect(value.apiGroups).toStrictEqual([]);
});

it('applies wildcard apiGroups only when apiGroups is unset', async() => {
const value = {};
const wrapper = mountRule(value);

await wrapper.vm.$options.fetch.call(wrapper.vm);

expect(value.apiGroups).toStrictEqual(['*']);
});
});
13 changes: 10 additions & 3 deletions pkg/kubewarden/chart/kubewarden/admission/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ export default {

data() {
return {
activeTab: null,
chartValues: null
activeTab: null,
chartValues: null,
moduleFieldsMissing: false
};
},

Expand All @@ -82,7 +83,7 @@ export default {
},

generalTabError() {
return !this.chartValues?.policy?.metadata?.name || !this.chartValues?.policy?.spec?.module;
return !this.chartValues?.policy?.metadata?.name || !this.chartValues?.policy?.spec?.module || this.moduleFieldsMissing;
},

rulesTabError() {
Expand Down Expand Up @@ -161,6 +162,11 @@ export default {
},

methods: {
onModuleValidation(missing) {
this.moduleFieldsMissing = missing;
this.$emit('module-validation', missing);
},

settingsChanged(event) {
this.chartValues.policy.spec.settings = jsyaml.load(event);
},
Expand Down Expand Up @@ -190,6 +196,7 @@ export default {
:target-namespace="targetNamespace"
:is-custom="isCustom"
:module-info="moduleInfo"
@module-validation="onModuleValidation"
/>
</Tab>

Expand Down
61 changes: 40 additions & 21 deletions pkg/kubewarden/components/Policies/Create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ export default ({
},
yamlValues: '',

hasCustomPolicy: false,
yamlOption: VALUES_STATE.FORM,
finishAttempts: 0,
hasCustomPolicy: false,
yamlOption: VALUES_STATE.FORM,
finishAttempts: 0,
moduleFieldsMissing: false,

// Steps
stepPolicies: {
Expand Down Expand Up @@ -164,11 +165,11 @@ export default ({

/** Allow create if either editing in yaml view or module and required rules/settings have been met */
canFinish() {
if (this.yamlOption === VALUES_STATE.YAML) {
if (this.yamlOption === VALUES_STATE.YAML || this.yamlOption === VALUES_STATE.DIFF) {
return true;
}

return !!this.chartValues?.policy?.spec?.module && this.hasRequired;
return !!this.chartValues?.policy?.spec?.module && this.hasRequired && !this.moduleFieldsMissing;
},

systemDefaultRegistry() {
Expand Down Expand Up @@ -279,7 +280,13 @@ export default ({

watch: {
yamlOption(neu, old) {
if (neu === VALUES_STATE.FORM && old === VALUES_STATE.YAML && !this.customPolicy && this.selectedPolicyDetails) {
const shouldSyncModuleFromYaml =
neu === VALUES_STATE.FORM &&
old !== VALUES_STATE.FORM &&
!this.customPolicy &&
this.selectedPolicyDetails;

if (shouldSyncModuleFromYaml) {
// Sync chartValues.policy.spec.module from any YAML edits the user made
if (this.yamlValues) {
try {
Expand Down Expand Up @@ -338,23 +345,34 @@ export default ({
return;
}

// Repository or tag was also changed — split on last ':' (tag) and first '/' (registry)
// Repository or tag was also changed. Be tolerant of partial values
// (e.g. empty tag: "repo:") so form fields are preserved on YAML -> form.
const lastColon = savedModule.lastIndexOf(':');
const repoWithRegistry = lastColon >= 0 ? savedModule.slice(0, lastColon) : savedModule;
const tag = lastColon >= 0 ? savedModule.slice(lastColon + 1) : '';

let registry = '';
let repository = repoWithRegistry;

// Prefer chart repository as an anchor to avoid hostname heuristics.
if (repoWithRegistry === chartInfo.repository) {
repository = chartInfo.repository;
} else if (repoWithRegistry.endsWith(`/${ chartInfo.repository }`)) {
registry = repoWithRegistry.slice(0, -(chartInfo.repository.length + 1));
repository = chartInfo.repository;
} else {
const firstSlash = repoWithRegistry.indexOf('/');

if (lastColon > 0 && lastColon < savedModule.length - 1) {
const repoWithRegistry = savedModule.slice(0, lastColon);
const tag = savedModule.slice(lastColon + 1);
const firstSlash = repoWithRegistry.indexOf('/');
const registry = firstSlash >= 0 ? repoWithRegistry.slice(0, firstSlash) : '';
const repository = firstSlash >= 0 ? repoWithRegistry.slice(firstSlash + 1) : repoWithRegistry;

this.policyModuleInfo = {
registry,
repository,
tag,
source: chartInfo.source,
};
registry = firstSlash >= 0 ? repoWithRegistry.slice(0, firstSlash) : '';
repository = firstSlash >= 0 ? repoWithRegistry.slice(firstSlash + 1) : repoWithRegistry;
}

this.policyModuleInfo = {
registry,
repository,
tag,
source: chartInfo.source,
};
},

async addRepository(btnCb) {
Expand Down Expand Up @@ -468,7 +486,7 @@ export default ({
try {
let out;

if (this.yamlOption === VALUES_STATE.YAML) {
if (this.yamlOption === VALUES_STATE.YAML || this.yamlOption === VALUES_STATE.DIFF) {
out = jsyaml.load(this.yamlValues);
} else {
out = this.chartValues?.policy ? this.chartValues.policy : jsyaml.load(this.yamlValues);
Expand Down Expand Up @@ -765,6 +783,7 @@ export default ({
:module-info="policyModuleInfo"
@editor="$event => yamlOption = $event"
@updateYamlValues="$event => yamlValues = $event"
@module-validation="$event => moduleFieldsMissing = $event"
/>
</template>

Expand Down
Loading