autofocus>
<span class="invalid-feedback"
*ngIf="snapshotForm.showError('snapshotName', formDir, 'required')"
- i18n>This field is required.</span><br><br>
+ i18n>This field is required.</span>
<span *ngIf="((mirroring === 'snapshot') ? true : null) && (snapshotForm.getValue('mirrorImageSnapshot') === true) ? true: null"
i18n>Snapshot mode is enabled on image <b>{{ imageName }}</b>: snapshot names are auto generated</span>
</div>
</div>
- <div *ngIf="(mirroring === 'snapshot') ? true : null">
- <div class="form-group row">
+ <ng-container *ngIf="(mirroring === 'snapshot') ? true : null">
+ <div class="form-group row"
+ *ngIf="peerConfigured$ | async as peerConfigured">
<div class="cd-col-form-offset">
<div class="custom-control custom-checkbox">
<input type="checkbox"
formControlName="mirrorImageSnapshot"
name="mirrorImageSnapshot"
id="mirrorImageSnapshot"
+ [attr.disabled]="!(peerConfigured.length > 0) ? true : null"
(change)="onMirrorCheckBoxChange()">
<label for="mirrorImageSnapshot"
class="custom-control-label"
i18n>Mirror Image Snapshot</label>
+ <cd-helper i18n
+ *ngIf="!peerConfigured.length > 0">The peer must be registered to do this action.</cd-helper>
</div>
</div>
</div>
- </div>
+ </ng-container>
</div>
<div class="modal-footer">
<cd-form-button-panel (submitActionEvent)="submit()"
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { configureTestBed } from '~/testing/unit-test-helper';
import { RbdSnapshotFormModalComponent } from './rbd-snapshot-form-modal.component';
+import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
+import { of } from 'rxjs';
describe('RbdSnapshotFormModalComponent', () => {
let component: RbdSnapshotFormModalComponent;
let fixture: ComponentFixture<RbdSnapshotFormModalComponent>;
+ let rbdMirrorService: RbdMirroringService;
configureTestBed({
imports: [
beforeEach(() => {
fixture = TestBed.createComponent(RbdSnapshotFormModalComponent);
component = fixture.componentInstance;
+ rbdMirrorService = TestBed.inject(RbdMirroringService);
});
it('should create', () => {
const button = fixture.debugElement.nativeElement.querySelector('cd-submit-button');
expect(button.textContent).toBe('Rename RBD Snapshot');
});
+
+ it('should enable the mirror image snapshot creation when peer is configured', () => {
+ spyOn(rbdMirrorService, 'getPeerForPool').and.returnValue(of(['test_peer']));
+ component.mirroring = 'snapshot';
+ component.ngOnInit();
+ fixture.detectChanges();
+ const radio = fixture.debugElement.nativeElement.querySelector('#mirrorImageSnapshot');
+ expect(radio.disabled).toBe(false);
+ });
+
+ it('should disable the mirror image snapshot creation when peer is not configured', () => {
+ spyOn(rbdMirrorService, 'getPeerForPool').and.returnValue(of([]));
+ component.mirroring = 'snapshot';
+ component.ngOnInit();
+ fixture.detectChanges();
+ const radio = fixture.debugElement.nativeElement.querySelector('#mirrorImageSnapshot');
+ expect(radio.disabled).toBe(true);
+ });
});
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
-import { Subject } from 'rxjs';
+import { Observable, Subject } from 'rxjs';
+import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
import { RbdService } from '~/app/shared/api/rbd.service';
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
templateUrl: './rbd-snapshot-form-modal.component.html',
styleUrls: ['./rbd-snapshot-form-modal.component.scss']
})
-export class RbdSnapshotFormModalComponent {
+export class RbdSnapshotFormModalComponent implements OnInit {
poolName: string;
namespace: string;
imageName: string;
public onSubmit: Subject<string> = new Subject();
+ peerConfigured$: Observable<any>;
+
constructor(
public activeModal: NgbActiveModal,
private rbdService: RbdService,
private taskManagerService: TaskManagerService,
private notificationService: NotificationService,
- private actionLabels: ActionLabelsI18n
+ private actionLabels: ActionLabelsI18n,
+ private rbdMirrorService: RbdMirroringService
) {
this.action = this.actionLabels.CREATE;
this.resource = $localize`RBD Snapshot`;
});
}
+ ngOnInit(): void {
+ this.peerConfigured$ = this.rbdMirrorService.getPeerForPool(this.poolName);
+ }
+
setSnapName(snapName: string) {
this.snapName = snapName;
- if (this.mirroring !== 'snapshot') {
- this.snapshotForm.get('snapshotName').setValue(snapName);
- } else {
- this.snapshotForm.get('snapshotName').clearValidators();
- }
+ this.snapshotForm.get('snapshotName').setValue(snapName);
}
onMirrorCheckBoxChange() {
if (this.snapshotForm.getValue('mirrorImageSnapshot') === true) {
this.snapshotForm.get('snapshotName').setValue('');
+ this.snapshotForm.get('snapshotName').clearValidators();
+ } else {
+ this.snapshotForm.get('snapshotName').setValue(this.snapName);
+ this.snapshotForm.get('snapshotName').setValidators([Validators.required]);
}
}
permission: 'update',
icon: Icons.edit,
name: actionLabels.RENAME,
- disable: (selection: CdTableSelection) => this.disableForMirrorSnapshot(selection)
+ disable: (selection: CdTableSelection) =>
+ this.disableForMirrorSnapshot(selection) || !selection.hasSingleSelection
};
this.protect = {
permission: 'update',
permission: 'update',
icon: Icons.undo,
name: actionLabels.ROLLBACK,
- disable: (selection: CdTableSelection) => this.disableForMirrorSnapshot(selection)
+ disable: (selection: CdTableSelection) =>
+ this.disableForMirrorSnapshot(selection) || !selection.hasSingleSelection
};
this.deleteSnap = {
permission: 'delete',
import { MockComponent } from 'ng-mocks';
import { ToastrModule } from 'ngx-toastr';
import { Subject, throwError as observableThrowError } from 'rxjs';
-import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
import { RbdService } from '~/app/shared/api/rbd.service';
import { ComponentsModule } from '~/app/shared/components/components.module';
describe('api delete request', () => {
let called: boolean;
let rbdService: RbdService;
- let rbdMirroringService: RbdMirroringService;
let notificationService: NotificationService;
let authStorageService: AuthStorageService;
const modalService = TestBed.inject(ModalService);
const actionLabelsI18n = TestBed.inject(ActionLabelsI18n);
called = false;
- rbdMirroringService = new RbdMirroringService(null, null);
rbdService = new RbdService(null, null);
notificationService = new NotificationService(null, null, null);
authStorageService = new AuthStorageService();
null,
null,
rbdService,
- rbdMirroringService,
null,
notificationService,
null,
null,
null,
null,
- TestBed.inject(ActionLabelsI18n)
+ TestBed.inject(ActionLabelsI18n),
+ null
);
ref.componentInstance.onSubmit = new Subject();
return ref;
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import moment from 'moment';
import { of } from 'rxjs';
-import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
import { RbdService } from '~/app/shared/api/rbd.service';
import { CdHelperClass } from '~/app/shared/classes/cd-helper.class';
modalRef: NgbModalRef;
- peerConfigured = false;
-
builders = {
'rbd/snap/create': (metadata: any) => {
const model = new RbdSnapshotModel();
private dimlessBinaryPipe: DimlessBinaryPipe,
private cdDatePipe: CdDatePipe,
private rbdService: RbdService,
- private rbdMirrorService: RbdMirroringService,
private taskManagerService: TaskManagerService,
private notificationService: NotificationService,
private summaryService: SummaryService,
}
];
- this.rbdMirrorService.getPeerForPool(this.poolName).subscribe((resp: any) => {
- if (resp.length > 0) {
- this.peerConfigured = true;
- }
- });
-
this.imageSpec = new ImageSpec(this.poolName, this.namespace, this.rbdName);
this.rbdTableActions = new RbdSnapshotActionsModel(
this.actionLabels,
this.featuresName,
this.rbdService
);
- this.rbdTableActions.create.disable = () =>
- !this.primary || (!this.peerConfigured && this.mirroring === 'snapshot');
this.rbdTableActions.create.click = () => this.openCreateSnapshotModal();
this.rbdTableActions.rename.click = () => this.openEditSnapshotModal();
this.rbdTableActions.protect.click = () => this.toggleProtection();