Skip to content

Commit b4dd802

Browse files
fix-kyverno-issues (#7656)
Co-authored-by: ahmadhamzh <[email protected]>
1 parent 79cc881 commit b4dd802

File tree

4 files changed

+67
-40
lines changed

4 files changed

+67
-40
lines changed

modules/web/src/app/dynamic/enterprise/kyverno-policies/cluster-policies/component.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {MatTableDataSource} from '@angular/material/table';
2626
import {KyvernoService} from '@app/core/services/kyverno';
2727
import {NotificationService} from '@app/core/services/notification';
2828
import {UserService} from '@app/core/services/user';
29-
import {PolicyTemplate} from '@app/shared/entity/kyverno';
29+
import {PolicyBinding, PolicyTemplate} from '@app/shared/entity/kyverno';
3030
import {Group} from '@app/shared/utils/member';
3131
import {filter, Subject, switchMap, take, takeUntil} from 'rxjs';
3232
import _ from 'lodash';
@@ -39,10 +39,6 @@ import {
3939
ConfirmationDialogConfig,
4040
} from '@app/shared/components/confirmation-dialog/component';
4141

42-
interface templatesBinding {
43-
bindingName: string;
44-
namespace: string;
45-
}
4642
@Component({
4743
selector: 'km-kyverno-cluster-policies-list',
4844
templateUrl: './template.html',
@@ -56,14 +52,13 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
5652
@ViewChild(MatSort, {static: true}) sort: MatSort;
5753
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
5854
private readonly _unsubscribe = new Subject<void>();
59-
dataSource = new MatTableDataSource<PolicyTemplate>();
55+
dataSource = new MatTableDataSource<PolicyBinding>();
6056
policyTemplates: PolicyTemplate[] = [];
61-
policiesWithBinding: PolicyTemplate[] = [];
57+
policyBindings: PolicyBinding[] = [];
6258
columns = ['name', 'category', 'namespace', 'view'];
6359
loadingTemplates = false;
6460
hasOwnerRole = false;
6561
nameSpaces: string[] = [];
66-
policyBindings: Record<string, templatesBinding> = {};
6762

6863
constructor(
6964
private readonly _kyvernoService: KyvernoService,
@@ -103,12 +98,13 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
10398
}
10499

105100
openAddPolicyDialog(): void {
106-
const noneBindingPolicies = this.policyTemplates.filter(template => !this.policyBindings[template.name]);
101+
const templatesToExclude = new Set(this.policyBindings.map(binding => binding.spec.policyTemplateRef.name));
102+
const templatesWithNoBinding = this.policyTemplates.filter(template => !templatesToExclude.has(template.name));
107103
const config: MatDialogConfig = {
108104
data: {
109105
projectID: this.projectID,
110106
clusterID: this.cluster.id,
111-
templates: noneBindingPolicies,
107+
templates: templatesWithNoBinding,
112108
namespaces: this.nameSpaces,
113109
} as AddPolicyDialogConfig,
114110
};
@@ -120,8 +116,7 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
120116
.subscribe(_ => this._getPolicyBindings());
121117
}
122118

123-
deletePolicyBinding(templateName: string): void {
124-
const bindingName = this.policyBindings[templateName].bindingName;
119+
deletePolicyBinding(bindingName: string): void {
125120
const config: MatDialogConfig = {
126121
data: {
127122
title: 'Delete Policy',
@@ -137,13 +132,26 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
137132
.pipe(switchMap(_ => this._kyvernoService.deletePolicyBinding(bindingName, this.projectID, this.cluster.id)))
138133
.subscribe(_ => {
139134
this._notificationService.success(`Deleting the ${bindingName} policy`);
140-
delete this.policyBindings[templateName];
141-
this.policiesWithBinding = this.policiesWithBinding.filter(template => template.name !== templateName);
142-
this.dataSource.data = this.policiesWithBinding;
135+
this.policyBindings = this.policyBindings.filter(binding => binding.name !== bindingName);
136+
this.dataSource.data = this.policyBindings;
143137
});
144138
}
145139

146-
viewTemplateSpec(template: PolicyTemplate): void {
140+
canDeletePolicy(templateName: string): boolean {
141+
const template = this.policyTemplates.find(template => template.name === templateName);
142+
143+
if (!template) {
144+
return this.hasOwnerRole && this.isClusterRunning;
145+
}
146+
return this.hasOwnerRole && !template?.spec.enforced && this.isClusterRunning;
147+
}
148+
149+
viewTemplateSpec(templateName: string): void {
150+
const template = this.policyTemplates.find(template => template.name === templateName);
151+
if (!template) {
152+
return;
153+
}
154+
147155
const config: MatDialogConfig = {
148156
data: {
149157
template: template,
@@ -152,21 +160,23 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
152160
this._matDialog.open(ViewTemplateDialogComponent, config);
153161
}
154162

155-
canDeletePolicy(enforced: boolean): boolean {
156-
return this.hasOwnerRole && !enforced && this.isClusterRunning;
163+
canViewTemplate(templateName: string): boolean {
164+
const template = this.policyTemplates.find(template => template.name === templateName);
165+
return !!template;
166+
}
167+
168+
getCategory(policyTemplateName: string): string {
169+
const template = this.policyTemplates.find(template => template.name === policyTemplateName);
170+
return template ? template.spec.category : '-';
157171
}
158172

159173
private _getPolicyBindings(): void {
160174
this._kyvernoService
161175
.listPolicyBindings(this.projectID, this.cluster.id)
162176
.pipe(takeUntil(this._unsubscribe))
163177
.subscribe(bindings => {
164-
bindings.forEach(binding => {
165-
this.policyBindings[binding.spec.policyTemplateRef.name] = {
166-
bindingName: binding?.name,
167-
namespace: binding?.spec?.kyvernoPolicyNamespace?.name,
168-
};
169-
});
178+
this.policyBindings = bindings;
179+
this.dataSource.data = bindings;
170180
this._getPolicyTemplates();
171181
});
172182
}
@@ -180,14 +190,15 @@ export class KyvernoClusterPoliciesListComponent implements OnInit, OnDestroy {
180190
if (_.isEmpty(template.spec?.target?.clusterSelector)) {
181191
return true;
182192
}
193+
if (this.policyBindings.some(binding => binding.spec.policyTemplateRef.name === template.name)) {
194+
return true;
195+
}
183196
const labelKeys: string[] = Object.keys(template.spec.target.clusterSelector.matchLabels);
184197
const hasMatchedLabels = !!labelKeys.find(key =>
185198
this._isMatchedLabel(key, template.spec.target.clusterSelector.matchLabels[key])
186199
);
187200
return hasMatchedLabels;
188201
});
189-
this.policiesWithBinding = this.policyTemplates.filter(template => !!this.policyBindings[template.name]);
190-
this.dataSource.data = this.policiesWithBinding;
191202
this.loadingTemplates = false;
192203
});
193204
}

modules/web/src/app/dynamic/enterprise/kyverno-policies/cluster-policies/template.html

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
class="km-header-cell">Category</th>
5151
<td mat-cell
5252
*matCellDef="let element">
53-
<span>{{element.spec.category}}</span>
53+
<span>{{getCategory(element.spec.policyTemplateRef.name)}}</span>
5454
</td>
5555
</ng-container>
5656
<ng-container matColumnDef="namespace">
@@ -66,8 +66,7 @@
6666
</div>
6767
<td mat-cell
6868
*matCellDef="let element">
69-
<span *ngIf="element.spec.namespacedPolicy">{{policyBindings[element.name]?.namespace}}</span>
70-
<span *ngIf="!element.spec.namespacedPolicy">Not Namespaced Policy</span>
69+
<span>{{element.spec.kyvernoPolicyNamespace?.name ?? 'Not Namespaced Policy'}}</span>
7170
</td>
7271
</ng-container>
7372
<ng-container matColumnDef="view">
@@ -78,13 +77,16 @@
7877
*matCellDef="let element">
7978
<div fxLayoutAlign="end"
8079
class="km-table-actions">
81-
<button mat-icon-button
82-
(click)="viewTemplateSpec(element)">
83-
<i class="km-icon-mask km-icon-show"></i>
84-
</button>
80+
<span [matTooltip]="canViewTemplate(element.spec.policyTemplateRef.name) ? 'View Template' : 'Template not available'">
81+
<button mat-icon-button
82+
(click)="viewTemplateSpec(element.spec.policyTemplateRef.name)"
83+
[disabled]="!canViewTemplate(element.spec.policyTemplateRef.name)">
84+
<i class="km-icon-mask km-icon-show"></i>
85+
</button>
86+
</span>
8587
<button mat-icon-button
8688
(click)="deletePolicyBinding(element.name)"
87-
[disabled]="!canDeletePolicy(element.spec.enforced)">
89+
[disabled]="!canDeletePolicy(element.spec.policyTemplateRef.name)">
8890
<i class="km-icon-mask km-icon-delete"></i>
8991
</button>
9092
</div>
@@ -96,10 +98,10 @@
9698
*matRowDef="let row; columns: columns;"></tr>
9799
</table>
98100
<div class="km-row km-empty-list-msg"
99-
*ngIf="!policiesWithBinding.length && !loadingTemplates">No policy templates are available</div>
101+
*ngIf="!policyBindings.length && !loadingTemplates">No policy templates are available</div>
100102

101103
<div class="km-row"
102-
*ngIf="loadingTemplates && policiesWithBinding.length">
104+
*ngIf="loadingTemplates && policyBindings.length">
103105
<mat-spinner color="accent"
104106
class="km-spinner km-with-spacing"
105107
[diameter]="25"></mat-spinner>

modules/web/src/app/dynamic/enterprise/kyverno-policies/policy-template/add-template/component.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
import {Project} from '@app/shared/entity/project';
3535
import {KUBERNETES_RESOURCE_NAME_PATTERN_VALIDATOR} from '@app/shared/validators/others';
3636
import * as y from 'js-yaml';
37-
import {Observable, Subject, take} from 'rxjs';
37+
import {Observable, Subject, take, takeUntil} from 'rxjs';
3838

3939
export interface AddPolicyTemplateDialogConfig {
4040
mode: PolicyTemplateDialogMode;
@@ -149,6 +149,18 @@ export class AddPolicyTemplateDialogComponent implements OnInit, OnDestroy {
149149
this.form.get(Controls.Project).disable();
150150
this.form.get(Controls.Scope).disable();
151151
}
152+
153+
this.form
154+
.get(Controls.Enforced)
155+
.valueChanges.pipe(takeUntil(this._unsubscribe))
156+
.subscribe(value => {
157+
if (value) {
158+
this.form.get(Controls.NamespacedPolicy).setValue(false);
159+
this.form.get(Controls.NamespacedPolicy).disable();
160+
} else {
161+
this.form.get(Controls.NamespacedPolicy).enable();
162+
}
163+
});
152164
}
153165

154166
ngOnDestroy(): void {

modules/web/src/app/dynamic/enterprise/kyverno-policies/policy-template/add-template/template.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@
9595
<i class="km-icon-info km-pointer"
9696
matTooltip="Enforced policies will be applied to all targeted clusters. Users can't delete them."></i>
9797
</mat-checkbox>
98-
<mat-checkbox [formControlName]="controls.NamespacedPolicy">
99-
Namespaced Policy
98+
<span>
99+
<mat-checkbox [formControlName]="controls.NamespacedPolicy">
100+
Namespaced Policy
101+
</mat-checkbox>
100102
<i class="km-icon-info km-pointer"
101103
matTooltip="Enable to scope the policy down to Namespace instead of the default i.e. Cluster scope."></i>
102-
</mat-checkbox>
104+
</span>
103105
</div>
104106
<km-label-form *ngIf="form.get(controls.Scope).value === scopes.Global"
105107
title="Projects Labels Selector"

0 commit comments

Comments
 (0)