1 import { Component, OnInit } from '@angular/core';
2 import { Location } from '@angular/common';
3 import { UntypedFormControl, Validators } from '@angular/forms';
4 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
5 import { Subscription, forkJoin } from 'rxjs';
6 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
7 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
8 import { WizardStepModel } from '~/app/shared/models/wizard-steps';
9 import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
10 import { RgwDaemonService } from '~/app/shared/api/rgw-daemon.service';
11 import { RgwDaemon } from '../models/rgw-daemon';
12 import { MultiClusterService } from '~/app/shared/api/multi-cluster.service';
13 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
14 import { Icons } from '~/app/shared/enum/icons.enum';
15 import { SelectOption } from '~/app/shared/components/select/select-option.model';
16 import _ from 'lodash';
17 import { SelectMessages } from '~/app/shared/components/select/select-messages.model';
18 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
19 import { NotificationService } from '~/app/shared/services/notification.service';
20 import { ActivatedRoute } from '@angular/router';
21 import { map, switchMap } from 'rxjs/operators';
22 import { BaseModal, Step } from 'carbon-components-angular';
23 import { SummaryService } from '~/app/shared/services/summary.service';
24 import { ExecutingTask } from '~/app/shared/models/executing-task';
26 STEP_TITLES_MULTI_CLUSTER_CONFIGURED,
27 STEP_TITLES_SINGLE_CLUSTER
28 } from './multisite-wizard-steps.enum';
31 selector: 'cd-rgw-multisite-wizard',
32 templateUrl: './rgw-multisite-wizard.component.html',
33 styleUrls: ['./rgw-multisite-wizard.component.scss']
35 export class RgwMultisiteWizardComponent extends BaseModal implements OnInit {
36 multisiteSetupForm: CdFormGroup;
37 currentStep: WizardStepModel;
38 currentStepSub: Subscription;
39 permissions: Permissions;
40 stepTitles: Step[] = STEP_TITLES_MULTI_CLUSTER_CONFIGURED.map((title) => ({
43 stepsToSkip: { [steps: string]: boolean } = {};
44 daemons: RgwDaemon[] = [];
46 clusterDetailsArray: any;
47 isMultiClusterConfigured = false;
48 exportTokenForm: CdFormGroup;
53 rgwEndpoints: { value: any[]; options: any[]; messages: any };
54 executingTask: ExecutingTask;
55 setupCompleted = false;
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 route: ActivatedRoute,
66 private summaryService: SummaryService,
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['url'] !== clusters['current_url']);
122 this.isMultiClusterConfigured = this.clusterDetailsArray.length > 0;
123 if (!this.isMultiClusterConfigured) {
124 this.stepTitles = STEP_TITLES_SINGLE_CLUSTER.map((title) => ({
127 this.stepTitles.forEach((steps, index) => {
128 steps.onClick = () => (this.currentStep.stepIndex = index);
131 this.selectedCluster = this.clusterDetailsArray[0]['name'];
133 this.wizardStepsService.setTotalSteps(this.stepTitles.length);
136 this.summaryService.subscribe((summary) => {
137 this.executingTask = summary.executing_tasks.filter((tasks) =>
138 tasks.name.includes('progress/Multisite-Setup')
142 this.stepTitles.forEach((stepTitle) => {
143 this.stepsToSkip[stepTitle.label] = false;
148 this.multisiteSetupForm = new CdFormGroup({
149 realmName: new UntypedFormControl('default_realm', {
150 validators: [Validators.required]
152 zonegroupName: new UntypedFormControl('default_zonegroup', {
153 validators: [Validators.required]
155 zonegroup_endpoints: new UntypedFormControl(null, [Validators.required]),
156 zoneName: new UntypedFormControl('default_zone', {
157 validators: [Validators.required]
159 zone_endpoints: new UntypedFormControl(null, {
160 validators: [Validators.required]
162 username: new UntypedFormControl('default_system_user', {
163 validators: [Validators.required]
165 cluster: new UntypedFormControl(null, {
166 validators: [Validators.required]
168 replicationZoneName: new UntypedFormControl('new_replicated_zone', {
169 validators: [Validators.required]
173 if (!this.isMultiClusterConfigured) {
174 this.exportTokenForm = new CdFormGroup({});
178 showSubmitButtonLabel() {
179 if (this.wizardStepsService.isLastStep()) {
180 if (!this.setupCompleted) {
181 if (this.isMultiClusterConfigured) {
182 return $localize`Configure Multi-Site`;
184 return $localize`Export Multi-Site token`;
187 return $localize`Close`;
190 return $localize`Next`;
194 showCancelButtonLabel() {
195 return !this.wizardStepsService.isFirstStep()
196 ? this.actionLabels.BACK
197 : this.actionLabels.CANCEL;
201 if (!this.wizardStepsService.isLastStep()) {
202 this.wizardStepsService.moveToNextStep();
204 if (this.setupCompleted) {
210 this.wizardStepsService.getCurrentStep().subscribe((step: WizardStepModel) => {
211 this.currentStep = step;
212 if (this.currentStep.stepIndex === 2 && this.isMultiClusterConfigured) {
213 this.stepsToSkip['Select Cluster'] = false;
220 const values = this.multisiteSetupForm.getRawValue();
221 const realmName = values['realmName'];
222 const zonegroupName = values['zonegroupName'];
223 const zonegroupEndpoints = this.rgwEndpoints.value.join(',');
224 const zoneName = values['zoneName'];
225 const zoneEndpoints = this.rgwEndpoints.value.join(',');
226 const username = values['username'];
227 if (!this.isMultiClusterConfigured || this.stepsToSkip['Select Cluster']) {
228 this.rgwMultisiteService
229 .setUpMultisiteReplication(
237 .subscribe((data: object[]) => {
238 this.setupCompleted = true;
239 this.rgwMultisiteService.setRestartGatewayMessage(false);
240 this.loading = false;
242 this.showSuccessNotification();
245 const cluster = values['cluster'];
246 const replicationZoneName = values['replicationZoneName'];
247 this.rgwMultisiteService
248 .setUpMultisiteReplication(
257 this.clusterDetailsArray
261 this.setupCompleted = true;
262 this.rgwMultisiteService.setRestartGatewayMessage(false);
263 this.loading = false;
264 this.showSuccessNotification();
267 this.multisiteSetupForm.setErrors({ cdSubmitButton: true });
273 showSuccessNotification() {
274 this.notificationService.show(
275 NotificationType.success,
276 $localize`Multi-site setup completed successfully.`
281 if (!this.wizardStepsService.isFirstStep()) {
282 this.wizardStepsService.moveToPreviousStep();
284 this.location.back();
289 const stepTitle = this.stepTitles[this.currentStep.stepIndex];
290 this.stepsToSkip[stepTitle.label] = true;
295 this.location.back();