1 import { Component, OnInit } from '@angular/core';
2 import { UntypedFormControl, Validators } from '@angular/forms';
3 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 import { Subscription, forkJoin } from 'rxjs';
5 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
6 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
7 import { WizardStepModel } from '~/app/shared/models/wizard-steps';
8 import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
9 import { RgwDaemonService } from '~/app/shared/api/rgw-daemon.service';
10 import { RgwDaemon } from '../models/rgw-daemon';
11 import { MultiClusterService } from '~/app/shared/api/multi-cluster.service';
12 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
13 import { Icons } from '~/app/shared/enum/icons.enum';
14 import { SelectOption } from '~/app/shared/components/select/select-option.model';
15 import _ from 'lodash';
16 import { SelectMessages } from '~/app/shared/components/select/select-messages.model';
17 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
18 import { NotificationService } from '~/app/shared/services/notification.service';
19 import { ActivatedRoute, Router } from '@angular/router';
20 import { map, switchMap } from 'rxjs/operators';
21 import { BaseModal, Step } from 'carbon-components-angular';
22 import { Location } from '@angular/common';
25 selector: 'cd-rgw-multisite-wizard',
26 templateUrl: './rgw-multisite-wizard.component.html',
27 styleUrls: ['./rgw-multisite-wizard.component.scss']
29 export class RgwMultisiteWizardComponent extends BaseModal implements OnInit {
30 multisiteSetupForm: CdFormGroup;
31 currentStep: WizardStepModel;
32 currentStepSub: Subscription;
33 permissions: Permissions;
34 stepTitles: Step[] = [
36 label: 'Create Realm & Zonegroup'
42 label: 'Select Cluster'
45 stepsToSkip: { [steps: string]: boolean } = {};
46 daemons: RgwDaemon[] = [];
48 clusterDetailsArray: any;
49 isMultiClusterConfigured = false;
50 exportTokenForm: CdFormGroup;
55 rgwEndpoints: { value: any[]; options: any[]; messages: any };
58 private wizardStepsService: WizardStepsService,
59 public activeModal: NgbActiveModal,
60 public actionLabels: ActionLabelsI18n,
61 private rgwDaemonService: RgwDaemonService,
62 private multiClusterService: MultiClusterService,
63 private rgwMultisiteService: RgwMultisiteService,
64 public notificationService: NotificationService,
65 private router: Router,
66 private route: ActivatedRoute,
67 private location: Location
70 this.pageURL = 'rgw/multisite/configuration';
71 this.currentStepSub = this.wizardStepsService
73 .subscribe((step: WizardStepModel) => {
74 this.currentStep = step;
76 this.currentStep.stepIndex = 0;
81 messages: new SelectMessages({
82 empty: $localize`There are no endpoints.`,
83 filter: $localize`Select endpoints`
89 this.open = this.route.outlet === 'modal';
93 switchMap((daemons) => {
94 this.daemons = daemons;
95 const daemonStatsObservables = daemons.map((daemon) =>
96 this.rgwDaemonService.get(daemon.id).pipe(
97 map((daemonStats) => ({
98 hostname: daemon.server_hostname,
100 frontendConfig: daemonStats['rgw_metadata']['frontend_config#0']
104 return forkJoin(daemonStatsObservables);
107 .subscribe((daemonStatsArray) => {
108 this.rgwEndpoints.value = daemonStatsArray.map((daemonStats) => {
109 const protocol = daemonStats.frontendConfig.includes('ssl_port') ? 'https' : 'http';
110 return `${protocol}://${daemonStats.hostname}:${daemonStats.port}`;
112 const options: SelectOption[] = this.rgwEndpoints.value.map(
113 (endpoint: string) => new SelectOption(false, endpoint, '')
115 this.rgwEndpoints.options = [...options];
118 this.multiClusterService.getCluster().subscribe((clusters) => {
119 this.clusterDetailsArray = Object.values(clusters['config'])
121 .filter((cluster) => cluster['cluster_alias'] !== 'local-cluster');
122 this.isMultiClusterConfigured = this.clusterDetailsArray.length > 0;
123 if (!this.isMultiClusterConfigured) {
126 label: 'Create Realm & Zonegroup'
132 label: 'Export Multi-site token'
135 this.stepTitles.forEach((steps, index) => {
136 steps.onClick = () => (this.currentStep.stepIndex = index);
139 this.selectedCluster = this.clusterDetailsArray[0]['name'];
145 this.multisiteSetupForm = new CdFormGroup({
146 realmName: new UntypedFormControl('default_realm', {
147 validators: [Validators.required]
149 zonegroupName: new UntypedFormControl('default_zonegroup', {
150 validators: [Validators.required]
152 zonegroup_endpoints: new UntypedFormControl(null, [Validators.required]),
153 zoneName: new UntypedFormControl('default_zone', {
154 validators: [Validators.required]
156 zone_endpoints: new UntypedFormControl(null, {
157 validators: [Validators.required]
159 username: new UntypedFormControl('default_system_user', {
160 validators: [Validators.required]
162 cluster: new UntypedFormControl(null, {
163 validators: [Validators.required]
167 if (!this.isMultiClusterConfigured) {
168 this.exportTokenForm = new CdFormGroup({});
172 showSubmitButtonLabel() {
173 if (this.isMultiClusterConfigured) {
174 return !this.wizardStepsService.isLastStep()
175 ? this.actionLabels.NEXT
176 : $localize`Configure Multi-site`;
178 return !this.wizardStepsService.isLastStep() ? this.actionLabels.NEXT : $localize`Close`;
182 showCancelButtonLabel() {
183 return !this.wizardStepsService.isFirstStep()
184 ? this.actionLabels.BACK
185 : this.actionLabels.CANCEL;
189 if (!this.wizardStepsService.isLastStep()) {
190 this.wizardStepsService.getCurrentStep().subscribe((step: WizardStepModel) => {
191 this.currentStep = step;
193 if (this.currentStep.stepIndex === 2 && !this.isMultiClusterConfigured) {
196 this.wizardStepsService.moveToNextStep();
205 const values = this.multisiteSetupForm.value;
206 const realmName = values['realmName'];
207 const zonegroupName = values['zonegroupName'];
208 const zonegroupEndpoints = this.rgwEndpoints.value.join(',');
209 const zoneName = values['zoneName'];
210 const zoneEndpoints = this.rgwEndpoints.value.join(',');
211 const username = values['username'];
212 if (!this.isMultiClusterConfigured) {
213 if (this.wizardStepsService.isLastStep()) {
214 this.activeModal.close();
215 this.refreshMultisitePage();
217 this.rgwMultisiteService
218 .setUpMultisiteReplication(
226 .subscribe((data: object[]) => {
227 this.loading = false;
229 this.wizardStepsService.moveToNextStep();
230 this.showSuccessNotification();
234 const cluster = values['cluster'];
235 this.rgwMultisiteService
236 .setUpMultisiteReplication(
247 this.showSuccessNotification();
248 this.activeModal.close();
249 this.refreshMultisitePage();
252 this.multisiteSetupForm.setErrors({ cdSubmitButton: true });
258 showSuccessNotification() {
259 this.notificationService.show(
260 NotificationType.success,
261 $localize`Multi-site setup completed successfully.`
265 refreshMultisitePage() {
266 const currentRoute = this.router.url.split('?')[0];
267 const navigateTo = currentRoute.includes('multisite') ? '/pool' : '/';
268 this.router.navigateByUrl(navigateTo, { skipLocationChange: true }).then(() => {
269 this.router.navigate([currentRoute]);
274 if (!this.wizardStepsService.isFirstStep()) {
275 this.wizardStepsService.moveToPreviousStep();
277 this.location.back();
282 const stepTitle = this.stepTitles[this.currentStep.stepIndex];
283 this.stepsToSkip[stepTitle.label] = true;