Skip to content

Commit

Permalink
Add isEditable checkbox in preset dialog and enable editable fields…
Browse files Browse the repository at this point in the history
… in cluster creation wizard
  • Loading branch information
Waseem826 committed Sep 4, 2024
1 parent 00c816f commit 2fee594
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {distinctUntilChanged, filter, map, switchMap, takeUntil} from 'rxjs/oper
enum Controls {
Settings = 'settings',
Datacenter = 'datacenter',
IsEditable = 'isEditable',
}

@Component({
Expand Down Expand Up @@ -72,13 +73,15 @@ export class PresetSettingsStepComponent extends BaseFormValidator implements On
this.form = this._builder.group({
[Controls.Settings]: this._builder.control(''),
[Controls.Datacenter]: this._builder.control(''),
[Controls.IsEditable]: this._builder.control(false),
});

this._presetDialogService.providerChanges.pipe(takeUntil(this._unsubscribe)).subscribe(provider => {
this.provider = provider;
this.form.removeControl(Controls.Settings);
this.form.addControl(Controls.Settings, this._builder.control(''));
this.form.get(Controls.Datacenter).setValue(AutocompleteInitialState);
this.form.get(Controls.IsEditable).setValue(false);
this.form.updateValueAndValidity();
});

Expand All @@ -102,18 +105,31 @@ export class PresetSettingsStepComponent extends BaseFormValidator implements On
.pipe(filter(form => !!form))
.pipe(map(form => form[AutocompleteControls.Main]))
.pipe(takeUntil(this._unsubscribe))
.subscribe(datacenter => this._update(datacenter));
.subscribe(datacenter => this._updateDatacenter(datacenter));

this.form
.get(Controls.IsEditable)
.valueChanges.pipe(takeUntil(this._unsubscribe))
.subscribe(value => this._updateIsEditable(value));
}

isExternal(): boolean {
return EXTERNAL_NODE_PROVIDERS.includes(this.provider);
}

isProvider(...provider: NodeProvider[]): boolean {
return provider.includes(this.provider);
}

private _filterByProvider(datacenters: Datacenter[]): string[] {
return datacenters.filter(dc => dc.spec.provider === this.provider).map(dc => dc.metadata.name);
}

private _update(datacenter: string): void {
private _updateDatacenter(datacenter: string): void {
this._presetDialogService.preset.spec[this._presetDialogService.provider].datacenter = datacenter;
}

isExternal(): boolean {
return EXTERNAL_NODE_PROVIDERS.includes(this.provider);
private _updateIsEditable(value: boolean): void {
this._presetDialogService.preset.spec[this._presetDialogService.provider].isEditable = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@

<ng-container *ngIf="!isExternal()">
<div class="optional-section">Optional Restrictions</div>
<mat-checkbox *ngIf="isProvider(Providers.OPENSTACK)"
[formControlName]="Controls.IsEditable">
Is Editable
<i class="km-icon-info km-pointer"
matTooltip="Allow editing empty settings during cluster creation."></i>
</mat-checkbox>
<km-autocomplete label="Restrict to Datacenter"
[formControlName]="Controls.Datacenter"
[isLoading]="isLoadingDatacenters"
Expand Down
11 changes: 11 additions & 0 deletions modules/web/src/app/shared/entity/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,21 @@ export class Preset {
export class PresetProvider {
name: NodeProvider;
enabled: boolean;
isEditable: boolean;

// Provider specific fields
openstack?: OpenstackAPIPreset;
vmwareCloudDirector?: VMwareCloudDirectorAPIPreset;
}

export class OpenstackAPIPreset {
network?: string;
securityGroups?: string;
floatingIPPool?: string;
routerID?: string;
subnetID?: string;
}

export class VMwareCloudDirectorAPIPreset {
ovdcNetwork?: string;
ovdcNetworks?: string[];
Expand Down Expand Up @@ -103,6 +113,7 @@ export class CreatePresetSpec {
export class PresetProviderSpec {
enabled?: boolean;
datacenter?: string;
isEditable?: boolean;
}

export class AlibabaPresetSpec extends PresetProviderSpec {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,28 @@ export class OpenstackProviderBasicComponent extends BaseFormValidator implement

this._init();

this._presets.presetChanges.pipe(takeUntil(this._unsubscribe)).subscribe(preset =>
Object.values(Controls).forEach(control => {
this.isPresetSelected = !!preset;
this._enable(!this.isPresetSelected, control);
})
);
this._presets.presetDetailedChanges.pipe(takeUntil(this._unsubscribe)).subscribe(preset => {
this.isPresetSelected = !!preset;
this._enable(!this.isPresetSelected, Controls.Domain);
this._enable(!this.isPresetSelected, Controls.Credentials);
if (!this.isPresetSelected) {
this._enable(!this.isPresetSelected, Controls.FloatingIPPool);
} else {
const providerSettings = preset?.providers.find(provider => provider.name === NodeProvider.OPENSTACK);
// check if floatingIPPool key exists and is empty
const enableFloatingIPPool =
(providerSettings.isEditable && providerSettings.openstack?.floatingIPPool === null) ||
providerSettings.openstack?.floatingIPPool === '';
this._enable(enableFloatingIPPool, Controls.FloatingIPPool);
if (enableFloatingIPPool) {
this.onCredentialsChange(null, preset.name);
}
}
});

this.form.valueChanges
.pipe(filter(_ => this._clusterSpecService.provider === NodeProvider.OPENSTACK))
.pipe(filter(_ => !this._presets.preset))
.pipe(takeUntil(this._unsubscribe))
.subscribe(_ =>
this._presets.enablePresets(OpenstackCloudSpec.isEmpty(this._clusterSpecService.cluster.spec.cloud.openstack))
Expand Down Expand Up @@ -153,9 +166,9 @@ export class OpenstackProviderBasicComponent extends BaseFormValidator implement
return '';
}

onCredentialsChange(credentials: OpenstackCredentials): void {
onCredentialsChange(credentials?: OpenstackCredentials, preset?: string): void {
this._clearFloatingIPPool();
this._floatingIPPoolListObservable(credentials)
this._floatingIPPoolListObservable(credentials, preset)
.pipe(take(1))
.subscribe((floatingIPPools: OpenstackFloatingIPPool[]) => {
this.floatingIPPools = floatingIPPools;
Expand All @@ -171,13 +184,18 @@ export class OpenstackProviderBasicComponent extends BaseFormValidator implement
(!!this._clusterSpecService.cluster.spec.cloud.openstack?.applicationCredentialID &&
!!this._clusterSpecService.cluster.spec.cloud.openstack?.applicationCredentialSecret) ||
(!!this._clusterSpecService.cluster.spec.cloud.openstack?.username &&
!!this._clusterSpecService.cluster.spec.cloud.openstack?.password)
!!this._clusterSpecService.cluster.spec.cloud.openstack?.password) ||
this.isPresetSelected
);
}

private _floatingIPPoolListObservable(credentials: OpenstackCredentials): Observable<OpenstackFloatingIPPool[]> {
private _floatingIPPoolListObservable(
credentials?: OpenstackCredentials,
preset?: string
): Observable<OpenstackFloatingIPPool[]> {
return this._presets
.provider(NodeProvider.OPENSTACK)
.credential(preset)
.domain(this._clusterSpecService.cluster.spec.cloud.openstack.domain)
.applicationCredentialID(credentials?.applicationCredentialID)
.applicationCredentialPassword(credentials?.applicationCredentialSecret)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class OpenstackProviderExtendedAppCredentialsComponent

private _applicationCredentialID = '';
private _applicationCredentialSecret = '';
private _preset = '';

constructor(
private readonly _builder: FormBuilder,
Expand All @@ -124,12 +125,23 @@ export class OpenstackProviderExtendedAppCredentialsComponent
[Controls.IPv6SubnetPool]: this._builder.control(''),
});

this._presets.presetChanges.pipe(takeUntil(this._unsubscribe)).subscribe(preset =>
Object.values(Controls).forEach(control => {
this.isPresetSelected = !!preset;
this._enable(!this.isPresetSelected, control);
})
);
this._presets.presetDetailedChanges.pipe(takeUntil(this._unsubscribe)).subscribe(preset => {
this.isPresetSelected = !!preset;
const providerSettings = preset?.providers.find(provider => provider.name === NodeProvider.OPENSTACK);
if (providerSettings.isEditable && providerSettings.openstack) {
const openstack = providerSettings.openstack;
// enable if preset is editable and values are defined but empty
this._enable(openstack.securityGroups === null || openstack.securityGroups === '', Controls.SecurityGroup);
this._enable(openstack.network === null || openstack.network === '', Controls.Network);
this._enable(openstack.subnetID === null || openstack.subnetID === '', Controls.IPv4SubnetID);
this._enable(true, Controls.IPv6SubnetID);
this._enable(true, Controls.IPv6SubnetPool);
} else {
Object.values(Controls).forEach(control => {
this._enable(!this.isPresetSelected, control);
});
}
});

this._credentialsTypeService.credentialsTypeChanges
.pipe(takeUntil(this._unsubscribe))
Expand Down Expand Up @@ -163,7 +175,11 @@ export class OpenstackProviderExtendedAppCredentialsComponent
)
.subscribe(null);

merge(this._clusterSpecService.clusterChanges, this._credentialsTypeService.credentialsTypeChanges)
merge(
this._clusterSpecService.clusterChanges,
this._credentialsTypeService.credentialsTypeChanges,
this._presets.presetChanges
)
.pipe(filter(_ => this._clusterSpecService.provider === NodeProvider.OPENSTACK))
.pipe(debounceTime(this._debounceTime))
.pipe(
Expand All @@ -175,13 +191,26 @@ export class OpenstackProviderExtendedAppCredentialsComponent
}
})
)
.pipe(filter(_ => this._hasApplicationCredentials()))
.pipe(filter(_ => this._hasApplicationCredentials() || this.isPresetSelected))
.pipe(filter(_ => this._areCredentialsChanged()))
.pipe(tap(_ => this._securityGroupListObservable().subscribe(this._loadSecurityGroups.bind(this))))
.pipe(tap(_ => this._networkListObservable().subscribe(this._loadNetworks.bind(this))))
.pipe(
tap(
_ =>
this.form.get(Controls.SecurityGroup).enabled &&
this._securityGroupListObservable().subscribe(this._loadSecurityGroups.bind(this))
)
)
.pipe(
tap(
_ =>
this.form.get(Controls.Network).enabled &&
this._networkListObservable().subscribe(this._loadNetworks.bind(this))
)
)
.pipe(
tap(_ =>
Cluster.isDualStackNetworkSelected(this._clusterSpecService.cluster)
Cluster.isDualStackNetworkSelected(this._clusterSpecService.cluster) &&
this.form.get(Controls.IPv6SubnetPool).enabled
? this._subnetPoolListObservable().subscribe(this._loadSubnetPools.bind(this))
: null
)
Expand Down Expand Up @@ -225,7 +254,7 @@ export class OpenstackProviderExtendedAppCredentialsComponent
case Controls.SecurityGroup:
case Controls.Network:
case Controls.IPv6SubnetPool:
return this._hasApplicationCredentials() ? '' : 'Please enter your credentials first.';
return this._hasApplicationCredentials() || this.isPresetSelected ? '' : 'Please enter your credentials first.';
case Controls.IPv4SubnetID:
case Controls.IPv6SubnetID:
return this._canLoadSubnet() ? '' : 'Please enter your credentials and network first.';
Expand Down Expand Up @@ -302,6 +331,11 @@ export class OpenstackProviderExtendedAppCredentialsComponent
credentialsChanged = true;
}

if (this._preset !== this._presets.preset) {
this._preset = this._presets.preset;
credentialsChanged = true;
}

return credentialsChanged;
}

Expand All @@ -311,12 +345,16 @@ export class OpenstackProviderExtendedAppCredentialsComponent
}

private _canLoadSubnet(): boolean {
return this._hasApplicationCredentials() && !!this._clusterSpecService.cluster.spec.cloud.openstack.network;
return (
(this._hasApplicationCredentials() || this.isPresetSelected) &&
!!this._clusterSpecService.cluster.spec.cloud.openstack.network
);
}

private _securityGroupListObservable(): Observable<OpenstackSecurityGroup[]> {
return this._presets
.provider(NodeProvider.OPENSTACK)
.credential(this._presets.preset)
.applicationCredentialID(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialID)
.applicationCredentialPassword(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialSecret)
.datacenter(this._clusterSpecService.cluster.spec.cloud.dc)
Expand Down Expand Up @@ -346,6 +384,7 @@ export class OpenstackProviderExtendedAppCredentialsComponent
private _networkListObservable(): Observable<OpenstackNetwork[]> {
return this._presets
.provider(NodeProvider.OPENSTACK)
.credential(this._presets.preset)
.applicationCredentialID(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialID)
.applicationCredentialPassword(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialSecret)
.datacenter(this._clusterSpecService.cluster.spec.cloud.dc)
Expand Down Expand Up @@ -375,6 +414,7 @@ export class OpenstackProviderExtendedAppCredentialsComponent
private _subnetIDListObservable(): Observable<OpenstackSubnet[]> {
return this._presets
.provider(NodeProvider.OPENSTACK)
.credential(this._presets.preset)
.applicationCredentialID(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialID)
.applicationCredentialPassword(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialSecret)
.datacenter(this._clusterSpecService.cluster.spec.cloud.dc)
Expand Down Expand Up @@ -408,6 +448,7 @@ export class OpenstackProviderExtendedAppCredentialsComponent
private _subnetPoolListObservable(): Observable<OpenstackSubnetPool[]> {
return this._presets
.provider(NodeProvider.OPENSTACK)
.credential(this._presets.preset)
.applicationCredentialID(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialID)
.applicationCredentialPassword(this._clusterSpecService.cluster.spec.cloud.openstack.applicationCredentialSecret)
.datacenter(this._clusterSpecService.cluster.spec.cloud.dc)
Expand Down
Loading

0 comments on commit 2fee594

Please sign in to comment.