Skip to content

Commit 3fc2600

Browse files
author
Wendy Gaultier
authored
Validate the volumes (#287)
* Validate the volumes * Fix linting
1 parent 62988bc commit 3fc2600

File tree

6 files changed

+117
-12
lines changed

6 files changed

+117
-12
lines changed

frontend/jupyter/i18n/fr/messages.fr.xlf

+18-2
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@
977977
<target>Nom est obligatoire</target>
978978
<context-group purpose="location">
979979
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
980-
<context context-type="linenumber">64</context>
980+
<context context-type="linenumber">77</context>
981981
</context-group>
982982
<context-group purpose="location">
983983
<context context-type="sourcefile">src/app/pages/form/form-new/volume/new/name/name.component.ts</context>
@@ -989,7 +989,23 @@
989989
<target>Est monté</target>
990990
<context-group purpose="location">
991991
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
992-
<context context-type="linenumber">67</context>
992+
<context context-type="linenumber">80</context>
993+
</context-group>
994+
</trans-unit>
995+
<trans-unit id="5493782202760870865" datatype="html">
996+
<source>Notebook is protected B but volume is unclassified</source>
997+
<target>Le bloc-note est protégé B mais le volume est non classifié</target>
998+
<context-group purpose="location">
999+
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
1000+
<context context-type="linenumber">83</context>
1001+
</context-group>
1002+
</trans-unit>
1003+
<trans-unit id="4388872362974019221" datatype="html">
1004+
<source>Notebook is unclassified but volume is protected B</source>
1005+
<target>Le bloc-note est non classifié mais le volume est protégé B</target>
1006+
<context-group purpose="location">
1007+
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
1008+
<context context-type="linenumber">86</context>
9931009
</context-group>
9941010
</trans-unit>
9951011
<trans-unit id="623533293782016444" datatype="html">

frontend/jupyter/i18n/messages.xlf

+16-2
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@
868868
<source>Name is required</source>
869869
<context-group purpose="location">
870870
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
871-
<context context-type="linenumber">64</context>
871+
<context context-type="linenumber">77</context>
872872
</context-group>
873873
<context-group purpose="location">
874874
<context context-type="sourcefile">src/app/pages/form/form-new/volume/new/name/name.component.ts</context>
@@ -879,7 +879,21 @@
879879
<source>Is mounted</source>
880880
<context-group purpose="location">
881881
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
882-
<context context-type="linenumber">67</context>
882+
<context context-type="linenumber">80</context>
883+
</context-group>
884+
</trans-unit>
885+
<trans-unit id="5493782202760870865" datatype="html">
886+
<source>Notebook is protected B but volume is unclassified</source>
887+
<context-group purpose="location">
888+
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
889+
<context context-type="linenumber">83</context>
890+
</context-group>
891+
</trans-unit>
892+
<trans-unit id="4388872362974019221" datatype="html">
893+
<source>Notebook is unclassified but volume is protected B</source>
894+
<context-group purpose="location">
895+
<context context-type="sourcefile">src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts</context>
896+
<context context-type="linenumber">86</context>
883897
</context-group>
884898
</trans-unit>
885899
<trans-unit id="623533293782016444" datatype="html">

frontend/jupyter/src/app/pages/form/form-new/form-protected-b/form-protected-b.component.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, OnInit, Input } from '@angular/core';
2-
import { FormGroup } from '@angular/forms';
2+
import { FormArray, FormGroup } from '@angular/forms';
33

44
import { MatIconRegistry } from '@angular/material/icon';
55

@@ -13,5 +13,17 @@ export class FormProtectedBComponent implements OnInit {
1313

1414
constructor() {}
1515

16-
ngOnInit() {}
16+
ngOnInit() {
17+
this.parentForm.get('prob').valueChanges.subscribe(val => {
18+
(this.parentForm.get('datavols') as FormArray).controls.forEach(
19+
element => {
20+
(element as FormGroup)
21+
.get('existingSource')
22+
.get('persistentVolumeClaim')
23+
.get('claimName')
24+
.updateValueAndValidity();
25+
},
26+
);
27+
});
28+
}
1729
}

frontend/jupyter/src/app/pages/form/form-new/volume/existing/pvc/pvc.component.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
>
1111
<mat-option *ngFor="let pvc of pvcs" [value]="pvc.name">
1212
<div class="flex">
13-
<div class="name truncate">{{ pvc.name }}</div>
13+
<div class="name truncate">
14+
{{ pvc.name }} {{ isProtectedLabel(pvc) }}
15+
</div>
1416
<ng-container *ngIf="select.panelOpen">
1517
<div class="size">{{ pvc.size }}</div>
1618
<div class="mode">{{ pvc.mode }}</div>

frontend/jupyter/src/app/pages/form/form-new/volume/existing/pvc/pvc.component.spec.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { CommonModule } from '@angular/common';
22
import { ComponentFixture, TestBed } from '@angular/core/testing';
3-
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
3+
import {
4+
FormArray,
5+
FormControl,
6+
FormGroup,
7+
ReactiveFormsModule,
8+
} from '@angular/forms';
49
import { MatCheckboxModule } from '@angular/material/checkbox';
510
import { MatFormFieldModule } from '@angular/material/form-field';
611
import { MatInputModule } from '@angular/material/input';
@@ -45,11 +50,25 @@ describe('ExistingPvcComponent', () => {
4550
beforeEach(() => {
4651
fixture = TestBed.createComponent(ExistingPvcComponent);
4752
component = fixture.componentInstance;
48-
component.pvcGroup = new FormGroup({
49-
readOnly: new FormControl(),
50-
claimName: new FormControl(),
53+
const fakeData = new FormGroup({
54+
prob: new FormControl(),
55+
datavols: new FormArray([
56+
new FormGroup({
57+
existingSource: new FormGroup({
58+
persistantVolumeClaim: new FormGroup({
59+
readOnly: new FormControl(),
60+
claimName: new FormControl(),
61+
}),
62+
}),
63+
}),
64+
]),
5165
});
5266

67+
component.pvcGroup = (fakeData.get('datavols') as FormArray)
68+
.at(0)
69+
.get('existingSource')
70+
.get('persistantVolumeClaim') as FormGroup;
71+
5372
fixture.detectChanges();
5473
});
5574

frontend/jupyter/src/app/pages/form/form-new/volume/existing/pvc/pvc.component.ts

+43-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export class ExistingPvcComponent implements OnInit {
2323
@Input() pvcGroup: FormGroup;
2424

2525
pvcs: PVCResponseObject[] = [];
26+
protectedBPvcs: Set<string> = new Set<string>();
27+
unclassifiedPvcs: Set<string> = new Set<string>();
2628
private mountedVolumes: Set<string> = new Set<string>(); //AAW
2729
matcher = new PvcErrorStateMatcher(); //AAW
2830
subscriptions = new Subscription(); //AAW
@@ -36,6 +38,13 @@ export class ExistingPvcComponent implements OnInit {
3638
this.ns.getSelectedNamespace().subscribe(ns => {
3739
this.backend.getPVCs(ns).subscribe(pvcs => {
3840
this.pvcs = pvcs;
41+
this.protectedBPvcs.clear();
42+
this.unclassifiedPvcs.clear();
43+
pvcs.forEach(pvc =>
44+
pvc.labels?.['data.statcan.gc.ca/classification'] === 'protected-b'
45+
? this.protectedBPvcs.add(pvc.name)
46+
: this.unclassifiedPvcs.add(pvc.name),
47+
);
3948
});
4049
});
4150
// Get the list of mounted volumes of the existing Notebooks in the selected Namespace, AAW
@@ -53,7 +62,11 @@ export class ExistingPvcComponent implements OnInit {
5362
);
5463
this.pvcGroup
5564
.get('claimName')
56-
.setValidators([Validators.required, this.isMountedValidator()]); //AAW
65+
.setValidators([
66+
Validators.required,
67+
this.isMountedValidator(),
68+
this.isProtectedBValidator(),
69+
]); //AAW
5770
}
5871

5972
// AAW
@@ -66,6 +79,12 @@ export class ExistingPvcComponent implements OnInit {
6679
if (volumeName.hasError('isMounted')) {
6780
return $localize`Is mounted`;
6881
}
82+
if (volumeName.hasError('isNotProb')) {
83+
return $localize`Notebook is protected B but volume is unclassified`;
84+
}
85+
if (volumeName.hasError('isNotUnclassified')) {
86+
return $localize`Notebook is unclassified but volume is protected B`;
87+
}
6988
}
7089

7190
//Method that disables selecting a mounted pvc, AAW
@@ -75,6 +94,29 @@ export class ExistingPvcComponent implements OnInit {
7594
return exists ? { isMounted: true } : null;
7695
};
7796
}
97+
98+
//Method that disables selecting a mounted pvc, AAW
99+
private isProtectedBValidator(): ValidatorFn {
100+
return (control: AbstractControl): { [key: string]: any } => {
101+
const protB =
102+
control.parent.parent.parent.parent.parent.get('prob').value;
103+
// Check for each volume if it's ok.
104+
if (protB && !this.protectedBPvcs.has(control.value)) {
105+
return { isNotProb: true };
106+
} else if (!protB && !this.unclassifiedPvcs.has(control.value)) {
107+
return { isNotUnclassified: true };
108+
}
109+
return null;
110+
};
111+
}
112+
113+
public isProtectedLabel(pvc): string {
114+
let status = '';
115+
if (pvc.labels?.['data.statcan.gc.ca/classification'] === 'protected-b') {
116+
status = '(protected-b)';
117+
}
118+
return status;
119+
}
78120
}
79121

80122
// Error when invalid control is dirty, touched, or submitted, AAW

0 commit comments

Comments
 (0)