1 import { Component, OnInit } from '@angular/core';
2 import { FormArray, FormBuilder, FormControl, NgForm, Validators } from '@angular/forms';
3 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 import _ from 'lodash';
5 import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
6 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
7 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
8 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
9 import { CdValidators } from '~/app/shared/forms/cd-validators';
10 import { NotificationService } from '~/app/shared/services/notification.service';
11 import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite';
12 import { Icons } from '~/app/shared/enum/icons.enum';
13 import { SelectOption } from '~/app/shared/components/select/select-option.model';
16 selector: 'cd-rgw-multisite-zonegroup-form',
17 templateUrl: './rgw-multisite-zonegroup-form.component.html',
18 styleUrls: ['./rgw-multisite-zonegroup-form.component.scss']
20 export class RgwMultisiteZonegroupFormComponent implements OnInit {
21 readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/;
22 readonly ipv4Rgx = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
23 readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
26 multisiteZonegroupForm: CdFormGroup;
30 zonegroup: RgwZonegroup;
32 defaultsInfo: string[] = [];
33 multisiteInfo: object[] = [];
34 realmList: RgwRealm[] = [];
35 zonegroupList: RgwZonegroup[] = [];
36 zonegroupNames: string[];
38 placementTargets: FormArray;
39 newZonegroupName: string;
40 zonegroupZoneNames: string[];
41 labelsOption: Array<SelectOption> = [];
42 zoneList: RgwZone[] = [];
43 allZoneNames: string[];
44 zgZoneNames: string[];
46 removedZones: string[];
47 isRemoveMasterZone = false;
49 disableDefault = false;
50 disableMaster = false;
53 public activeModal: NgbActiveModal,
54 public actionLabels: ActionLabelsI18n,
55 public rgwZonegroupService: RgwZonegroupService,
56 public notificationService: NotificationService,
57 private formBuilder: FormBuilder
59 this.action = this.editing
60 ? this.actionLabels.EDIT + this.resource
61 : this.actionLabels.CREATE + this.resource;
66 this.multisiteZonegroupForm = new CdFormGroup({
67 default_zonegroup: new FormControl(false),
68 zonegroupName: new FormControl(null, {
71 CdValidators.custom('uniqueName', (zonegroupName: string) => {
73 this.action === 'create' &&
74 this.zonegroupNames &&
75 this.zonegroupNames.indexOf(zonegroupName) !== -1
80 master_zonegroup: new FormControl(false),
81 selectedRealm: new FormControl(null),
82 zonegroup_endpoints: new FormControl(null, [
83 CdValidators.custom('endpoint', (value: string) => {
84 if (_.isEmpty(value)) {
87 if (value.includes(',')) {
88 value.split(',').forEach((url: string) => {
90 !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url)
95 !this.endpoints.test(value) &&
96 !this.ipv4Rgx.test(value) &&
97 !this.ipv6Rgx.test(value)
105 placementTargets: this.formBuilder.array([])
110 _.forEach(this.multisiteZonegroupForm.get('placementTargets'), (placementTarget) => {
111 const fg = this.addPlacementTarget();
112 fg.patchValue(placementTarget);
114 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as FormArray;
116 this.multisiteInfo[0] !== undefined && this.multisiteInfo[0].hasOwnProperty('realms')
117 ? this.multisiteInfo[0]['realms']
120 this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
121 ? this.multisiteInfo[1]['zonegroups']
123 this.zonegroupList.forEach((zgp: any) => {
124 if (zgp.is_master === true && !_.isEmpty(zgp.realm_id)) {
125 this.isMaster = true;
126 this.disableMaster = true;
129 if (!this.isMaster) {
130 this.multisiteZonegroupForm.get('master_zonegroup').setValue(true);
131 this.multisiteZonegroupForm.get('master_zonegroup').disable();
134 this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
135 ? this.multisiteInfo[2]['zones']
137 this.zonegroupNames = this.zonegroupList.map((zonegroup) => {
138 return zonegroup['name'];
140 let allZonegroupZonesList = this.zonegroupList.map((zonegroup: RgwZonegroup) => {
141 return zonegroup['zones'];
143 const allZonegroupZonesInfo = allZonegroupZonesList.reduce(
144 (accumulator, value) => accumulator.concat(value),
147 const allZonegroupZonesNames = allZonegroupZonesInfo.map((zone) => {
150 this.allZoneNames = this.zoneList.map((zone: RgwZone) => {
153 this.allZoneNames = _.difference(this.allZoneNames, allZonegroupZonesNames);
154 if (this.action === 'create' && this.defaultsInfo['defaultRealmName'] !== null) {
155 this.multisiteZonegroupForm
156 .get('selectedRealm')
157 .setValue(this.defaultsInfo['defaultRealmName']);
158 if (this.disableMaster) {
159 this.multisiteZonegroupForm.get('master_zonegroup').disable();
162 if (this.action === 'edit') {
163 this.multisiteZonegroupForm.get('zonegroupName').setValue(this.info.data.name);
164 this.multisiteZonegroupForm.get('selectedRealm').setValue(this.info.data.parent);
165 this.multisiteZonegroupForm.get('default_zonegroup').setValue(this.info.data.is_default);
166 this.multisiteZonegroupForm.get('master_zonegroup').setValue(this.info.data.is_master);
167 this.multisiteZonegroupForm.get('zonegroup_endpoints').setValue(this.info.data.endpoints);
169 if (this.info.data.is_default) {
170 this.multisiteZonegroupForm.get('default_zonegroup').disable();
173 !this.info.data.is_default &&
174 this.multisiteZonegroupForm.getValue('selectedRealm') !==
175 this.defaultsInfo['defaultRealmName']
177 this.multisiteZonegroupForm.get('default_zonegroup').disable();
178 this.disableDefault = true;
180 if (this.info.data.is_master || this.disableMaster) {
181 this.multisiteZonegroupForm.get('master_zonegroup').disable();
184 this.zonegroupZoneNames = this.info.data.zones.map((zone: { [x: string]: any }) => {
187 this.zgZoneNames = this.info.data.zones.map((zone: { [x: string]: any }) => {
190 this.zgZoneIds = this.info.data.zones.map((zone: { [x: string]: any }) => {
193 const uniqueZones = new Set(this.allZoneNames);
194 this.labelsOption = Array.from(uniqueZones).map((zone) => {
195 return { enabled: true, name: zone, selected: false, description: null };
198 this.info.data.placement_targets.forEach((target: object) => {
199 const fg = this.addPlacementTarget();
201 placement_id: target['name'],
202 tags: target['tags'].join(','),
204 typeof target['storage_classes'] === 'string'
205 ? target['storage_classes']
206 : target['storage_classes'].join(',')
214 const values = this.multisiteZonegroupForm.getRawValue();
215 if (this.action === 'create') {
216 this.realm = new RgwRealm();
217 this.realm.name = values['selectedRealm'];
218 this.zonegroup = new RgwZonegroup();
219 this.zonegroup.name = values['zonegroupName'];
220 this.zonegroup.endpoints = values['zonegroup_endpoints'];
221 this.rgwZonegroupService
222 .create(this.realm, this.zonegroup, values['default_zonegroup'], values['master_zonegroup'])
225 this.notificationService.show(
226 NotificationType.success,
227 $localize`Zonegroup: '${values['zonegroupName']}' created successfully`
229 this.activeModal.close();
232 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
235 } else if (this.action === 'edit') {
236 this.removedZones = _.difference(this.zgZoneNames, this.zonegroupZoneNames);
237 const masterZoneName = this.info.data.zones.filter(
238 (zone: any) => zone.id === this.info.data.master_zone
240 this.isRemoveMasterZone = this.removedZones.includes(masterZoneName[0].name);
241 if (this.isRemoveMasterZone) {
242 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
245 this.addedZones = _.difference(this.zonegroupZoneNames, this.zgZoneNames);
246 this.realm = new RgwRealm();
247 this.realm.name = values['selectedRealm'];
248 this.zonegroup = new RgwZonegroup();
249 this.zonegroup.name = this.info.data.name;
250 this.newZonegroupName = values['zonegroupName'];
251 this.zonegroup.endpoints = values['zonegroup_endpoints'].toString();
252 this.zonegroup.placement_targets = values['placementTargets'];
253 this.rgwZonegroupService
257 this.newZonegroupName,
258 values['default_zonegroup'],
259 values['master_zonegroup'],
265 this.notificationService.show(
266 NotificationType.success,
267 $localize`Zonegroup: '${values['zonegroupName']}' updated successfully`
269 this.activeModal.close();
272 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
278 addPlacementTarget() {
279 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as FormArray;
280 const fg = new CdFormGroup({
281 placement_id: new FormControl('', {
282 validators: [Validators.required]
284 tags: new FormControl(''),
285 storage_class: new FormControl([])
287 this.placementTargets.push(fg);
291 trackByFn(index: number) {
295 removePlacementTarget(index: number) {
296 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as FormArray;
297 this.placementTargets.removeAt(index);
300 showError(index: number, control: string, formDir: NgForm, x: string) {
301 return (<any>this.multisiteZonegroupForm.controls.placementTargets).controls[index].showError(