Skip to content

Commit

Permalink
Show dialog for accepting certificate when adding project registry
Browse files Browse the repository at this point in the history
Show dialog for accepting certificate when adding project registry and
some small fixes.

- Add dialog for accepting certificate when adding a registry when the
certificate is not accepted. The dialog will be shown on add/edit. On
edit only in case the cert is missing for some reason
- Added initialization of the credentials on adding a registry. The
credentials were not loaded.
- Other minor fixes

Change-Id: Ia0357e4c13713d39d8360e5abb5b29c3f791c9db
Reviewed-on: https://bellevue-ci.eng.vmware.com:8080/31104
Reviewed-by: Iveta Ilieva <[email protected]>
Closures-Verified: jenkins <[email protected]>
Upgrade-Verified: jenkins <[email protected]>
Bellevue-Verified: jenkins <[email protected]>
CS-Verified: jenkins <[email protected]>
  • Loading branch information
gmuleshkov committed Apr 11, 2018
1 parent d95b28b commit b88fab4
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
import com.vmware.admiral.auth.util.SecurityContextUtil;
import com.vmware.admiral.closures.services.closure.ClosureService;
import com.vmware.admiral.closures.services.closuredescription.ClosureDescriptionService;
import com.vmware.admiral.common.ManagementUriParts;
import com.vmware.admiral.common.util.OperationUtil;
import com.vmware.admiral.compute.ContainerHostService.ContainerHostSpec;
import com.vmware.admiral.compute.RegistryHostConfigService;
import com.vmware.admiral.compute.RegistryHostConfigService.RegistryHostSpec;
import com.vmware.admiral.compute.cluster.ClusterService;
import com.vmware.admiral.compute.container.CompositeComponentService;
import com.vmware.admiral.compute.container.CompositeDescriptionService;
Expand Down Expand Up @@ -107,10 +109,32 @@ private static DeferredResult<Void> setProjectLinkAsTenantLink(Service service,
ContainerHostSpec hostSpec = extractContainerHostSpec(op);
if (hostSpec != null) {
handleContainerHostSpec(hostSpec, projectLink, op);
return DeferredResult.completed(null);
}

RegistryHostSpec registrySpec = extractRegistryHostSpec(op);
if (registrySpec != null) {
handleRegistryHostSpec(registrySpec, projectLink, op);
}

return DeferredResult.completed(null);
}

private static void handleRegistryHostSpec(RegistryHostSpec state, String projectLink,
Operation op) {
if (projectLink == null || projectLink.isEmpty() || state.hostState == null) {
return;
}
if (state.hostState.tenantLinks == null) {
state.hostState.tenantLinks = new ArrayList<>();
}
if (!state.hostState.tenantLinks.contains(projectLink)) {
state.hostState.tenantLinks.add(projectLink);
op.setBody(state);
}

}

private static void handleResourceState(ResourceState state, String projectLink, Operation op) {
if (projectLink == null || projectLink.isEmpty()) {
return;
Expand Down Expand Up @@ -179,13 +203,19 @@ private static MultiTenantDocument extractMultiTenantState(Service service, Oper
}

private static ContainerHostSpec extractContainerHostSpec(Operation o) {
if (!o.hasBody()) {
if (!o.hasBody() || o.getUri().getPath().equals(ManagementUriParts.REGISTRY_HOSTS)) {
return null;
}

return o.getBody(ContainerHostSpec.class);
}

private static RegistryHostSpec extractRegistryHostSpec(Operation o) {
if (!o.hasBody()) {
return null;
}
return o.getBody(RegistryHostSpec.class);
}

private static DeferredResult<Void> handleClusterServiceOp(Service service, Operation op) {
// In case of authn is not enabled do not check for authorization.
if (!service.getHost().isAuthorizationEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
~ conditions of the subcomponent's license, as noted in the LICENSE file.
-->

<clr-alert [clrAlertType]="'alert-danger'" [(clrAlertClosed)]="!alertMessage" (clrAlertClosedChange)="resetAlert()">
<clr-alert [clrAlertType]="alertType" [(clrAlertClosed)]="!alertMessage" (clrAlertClosedChange)="resetAlert()">
<div class="alert-item">
<span class="alert-text">{{ alertMessage }}</span>
</div>
Expand Down Expand Up @@ -54,19 +54,27 @@ <h3 *ngIf="!editMode" class="projects-details-header-title">{{"projects.projectR
</div>

<button *ngIf="!editMode" type="button" class="btn btn-primary"
[clrLoading]="isSavingRegistry || isTestingConnection || projectRegistryDetailsForm.invalid"
[clrLoading]="isSavingRegistry || projectRegistryDetailsForm.invalid"
(click)="save()">{{ "save" | i18n }}</button>
<button *ngIf="editMode" type="button" class="btn btn-primary"
[clrLoading]="isSavingRegistry || isTestingConnection || projectRegistryDetailsForm.invalid"
[clrLoading]="isSavingRegistry || projectRegistryDetailsForm.invalid"
(click)="update()">{{ "update" | i18n }}</button>
<button type="button" class="btn btn-secondary"
[clrLoading]="isTestingConnection"
[disabled]="isSavingRegistry || isTestingConnection"
(click)="testConnection()">{{ "verify" | i18n }}</button>
<button type="button" class="btn btn-secondary"
[disabled]="isSavingRegistry"
(click)="cancel()">{{ "cancel" | i18n }}</button>
</section>
</form>
<!-- Untrusted certificate prompt -->
<verify-certificate [visible]="showCertificateWarning"
[hostAddress]="projectRegistryDetailsForm.value.address"
[certificate]="certificate"
(onAccept)="acceptCertificate()"
(onDecline)="declineCertificate()">
</verify-certificate>
</clr-tab-content>
</clr-tab>
</clr-tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { FormControl, FormGroup } from "@angular/forms";
import { Utils } from "../../../utils/utils";
import { formatUtils } from 'admiral-ui-common';
import * as I18n from 'i18next';
import { Constants } from '../../../utils/constants';

@Component({
selector: 'app-project-registry-details',
Expand All @@ -35,9 +36,12 @@ export class ProjectRegistryDetailsComponent extends BaseDetailsComponent implem
credentials: any[];
projectLink: string;
registryLink: string;

showCertificateWarning: boolean;
certificate: any;

alertType: string;

private sub: any;
isSaving: boolean;

Expand All @@ -63,24 +67,18 @@ export class ProjectRegistryDetailsComponent extends BaseDetailsComponent implem
}

ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let projectId = params['projectId'];
if (projectId) {
this.projectLink = Links.PROJECTS + '/' + projectId;
}
});
}

ngOnDestroy() {
this.sub.unsubscribe();
super.ngOnInit();
this.populateCredentials(null);
}

populateCredentials(authCredentialsLink) {
this.service.list(Links.CREDENTIALS, {}).then(credentials => {
this.credentials = credentials.documents
.filter(c => !Utils.areSystemScopedCredentials(c))
.map(this.toCredentialViewModel);
this.preselectCredential(authCredentialsLink);
if (authCredentialsLink) {
this.preselectCredential(authCredentialsLink);
}
}).catch((e) => {
console.log('Credentials retrieval failed', e);
});
Expand All @@ -89,7 +87,7 @@ export class ProjectRegistryDetailsComponent extends BaseDetailsComponent implem
preselectCredential(authCredentialsLink) {
if (authCredentialsLink) {
var credItem = this.credentials
.filter((c) => c.documentSelfLink === authCredentialsLink);
.filter((c) => c.documentSelfLink === authCredentialsLink);
if (credItem.length > 0) {
this.projectRegistryDetailsForm.get('credentials').setValue(credItem[0]);
}
Expand Down Expand Up @@ -126,51 +124,44 @@ export class ProjectRegistryDetailsComponent extends BaseDetailsComponent implem
this.alertMessage = null;
}

private save() {
private save(acceptCert: boolean = false) {
this.isSavingRegistry = true;
let formInput = this.projectRegistryDetailsForm.value;
let registryName = formInput.name && formatUtils.escapeHtml(formInput.name);
let registryState = {
'address': formInput.address,
'name': registryName,
'endpointType': 'container.docker.registry',
'authCredentialsLink': formInput.credentials.documentSelfLink
};

let registrySpec = {
'hostState': registryState,
'acceptCertificate': true
};
let registrySpec = this.getRegistrySpec(acceptCert);

this.service.put(Links.REGISTRY_SPEC, registrySpec, this.projectLink).then((response) => {
this.isSavingRegistry = false;
this.router.navigate(['..'], { relativeTo: this.route });
if (!this.isCertificateResponse(response)) {
this.isSavingRegistry = false;
this.router.navigate(['..'], { relativeTo: this.route });
}
}).catch(error => {
this.isSavingRegistry = false;
this.alertMessage = Utils.getErrorMessage(error)._generic;
this.showErrorMessage(error);
});
}

private update() {
private update(acceptCert: boolean = false) {
this.isSavingRegistry = true;
let formInput = this.projectRegistryDetailsForm.value;
let registryName = formInput.name && formatUtils.escapeHtml(formInput.name);

this.entity.name = formInput.name && formatUtils.escapeHtml(formInput.name);
this.entity.address = formInput.address;
this.entity.endpointType = 'container.docker.registry';
this.entity.authCredentialsLink = formInput.documentSelfLink;
this.entity.authCredentialsLink = formInput.credentials.documentSelfLink;

let registrySpec = {
'hostState': this.entity,
'acceptCertificate': acceptCert
};

this.service.put(Links.REGISTRY_SPEC, registrySpec, this.projectLink).then((response) => {
this.isSavingRegistry = false;
this.router.navigate(['../../'], { relativeTo: this.route });
if (!this.isCertificateResponse(response)) {
this.isSavingRegistry = false;
this.router.navigate(['../../'], { relativeTo: this.route });
}
}).catch(error => {
this.isSavingRegistry = false;
this.alertMessage = Utils.getErrorMessage(error)._generic;
this.showErrorMessage(error);
});
}

Expand All @@ -181,4 +172,69 @@ export class ProjectRegistryDetailsComponent extends BaseDetailsComponent implem
this.router.navigate(['..'], { relativeTo: this.route });
}
}

private testConnection(acceptCert: boolean = false) {
this.isTestingConnection = true;
let registrySpec = this.getRegistrySpec(acceptCert);

this.service.put(Links.REGISTRY_SPEC + '?validate=true', registrySpec).then((response) => {
if (!this.isCertificateResponse(response)) {
this.isTestingConnection = false;
this.alertType = Constants.alert.type.SUCCESS;
this.alertMessage = I18n.t('hosts.verified');
}
}).catch(error => {
this.isTestingConnection = false;
this.showErrorMessage(error);
});
}

private getRegistrySpec(acceptCert: boolean) {
let formInput = this.projectRegistryDetailsForm.value;
let registryName = formInput.name && formatUtils.escapeHtml(formInput.name);
let registryState = {
'address': formInput.address,
'name': registryName,
'endpointType': 'container.docker.registry',
'authCredentialsLink': formInput.credentials.documentSelfLink
};
registryState.authCredentialsLink = formInput.credentials.documentSelfLink;
let registrySpec = {
'hostState': registryState,
'acceptCertificate': acceptCert
};
return registrySpec;
}

private showErrorMessage(error) {
this.alertType = Constants.alert.type.DANGER;
this.alertMessage = Utils.getErrorMessage(error)._generic;
}

declineCertificate() {
this.showCertificateWarning = false;
this.isSavingRegistry = false;
this.isTestingConnection = false;
}

acceptCertificate() {
this.showCertificateWarning = false;
if (this.editMode && this.isSavingRegistry) {
this.update(true);
} else if (this.isTestingConnection) {
this.testConnection(true);
} else if (this.isSavingRegistry) {
this.save(true);
}
}

isCertificateResponse(response: any) {
if (response && response.certificate) {
this.certificate = response;
this.showCertificateWarning = true;
return true;
} else {
return false;
}
}
}

0 comments on commit b88fab4

Please sign in to comment.