Add create new config item
Allows users to create a new config type (i.e. manifest, context, encryption config, etc.) from the UI and save changes to airship config. Known issues: - Still no validation on frontend forms yet - Validation on backend is still hit or miss. It's still possible to make changes that render the config file invalid, and they must be fixed with text editor - Some config keys are deprecated since the airshipctl version hasn't been uplifted in some time. That's a big todo... Change-Id: Ifeefe26933966d0a434d1346ea677c213d976b78
This commit is contained in:
parent
c004a202dc
commit
b20f7feba4
@ -1,7 +1,7 @@
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="title">
|
||||
<h4>{{config.name}}</h4>
|
||||
<h4>{{config.Name}}</h4>
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<p>
|
||||
|
@ -42,7 +42,7 @@ export class ConfigManagementComponent implements OnInit {
|
||||
constructor(private websocketService: WsService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.name.setValue(this.config.name);
|
||||
this.name.setValue(this.config.Name);
|
||||
this.insecure.setValue(this.config.insecure);
|
||||
this.systemActionRetries.setValue(this.config.systemActionRetries);
|
||||
this.systemRebootDelay.setValue(this.config.systemRebootDelay);
|
||||
@ -67,7 +67,7 @@ export class ConfigManagementComponent implements OnInit {
|
||||
msg.name = this.name.value;
|
||||
|
||||
const cfg: ManagementConfig = {
|
||||
name: this.name.value,
|
||||
Name: this.name.value,
|
||||
insecure: this.insecure.value,
|
||||
// TODO(mfuller): need to validate these are numerical values in the form
|
||||
systemActionRetries: +this.systemActionRetries.value,
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
.form-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.text-input {
|
||||
width: 80%;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<h1 mat-dialog-title>New {{data.formName}} configuration</h1>
|
||||
<div mat-dialog-content class="form-content">
|
||||
<form [formGroup]="group">
|
||||
<div *ngFor="let key of keys">
|
||||
<mat-form-field *ngIf="!isBool(dataObj[key])" appearance="fill">
|
||||
<mat-label>{{key}}</mat-label>
|
||||
<input class="text-input" formControlName="{{key}}" matInput>
|
||||
</mat-form-field>
|
||||
<p *ngIf="isBool(dataObj[key])">
|
||||
<mat-checkbox formControlName="{{key}}" labelPosition="before">{{key}} </mat-checkbox>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-raised-button (click)="closeDialog()">Cancel</button>
|
||||
<button mat-raised-button color="primary" (click)="setConfig(data.formName)">Save</button>
|
||||
</div>
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDialogModule, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { ConfigNewComponent } from './config-new.component';
|
||||
|
||||
describe('ConfigNewComponent', () => {
|
||||
let component: ConfigNewComponent;
|
||||
let fixture: ComponentFixture<ConfigNewComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatButtonModule,
|
||||
MatInputModule,
|
||||
MatDialogModule,
|
||||
MatCheckboxModule,
|
||||
ToastrModule.forRoot(),
|
||||
],
|
||||
declarations: [ ConfigNewComponent ],
|
||||
providers: [
|
||||
{provide: MAT_DIALOG_DATA, useValue: {formType: 'context'}},
|
||||
{provide: MatDialogRef, useValue: {}}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ConfigNewComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
component.data.formName = 'context';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
103
client/src/app/ctl/config/config-new/config-new.component.ts
Normal file
103
client/src/app/ctl/config/config-new/config-new.component.ts
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ContextOptions, EncryptionConfigOptions, ManagementConfig, ManifestOptions } from '../config.models';
|
||||
import { WsConstants, WsMessage } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-config-new',
|
||||
templateUrl: './config-new.component.html',
|
||||
styleUrls: ['./config-new.component.css']
|
||||
})
|
||||
export class ConfigNewComponent implements OnInit {
|
||||
group: FormGroup;
|
||||
|
||||
dataObj: any;
|
||||
keys: string[] = [];
|
||||
|
||||
dataObjs = {
|
||||
context: new ContextOptions(),
|
||||
manifest: new ManifestOptions(),
|
||||
encryption: new EncryptionConfigOptions(),
|
||||
management: new ManagementConfig()
|
||||
};
|
||||
|
||||
constructor(private websocketService: WsService,
|
||||
private fb: FormBuilder,
|
||||
@Inject(MAT_DIALOG_DATA) public data: {formName: string},
|
||||
public dialogRef: MatDialogRef<ConfigNewComponent>) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
const grp = {};
|
||||
this.dataObj = this.dataObjs[this.data.formName];
|
||||
|
||||
for (const [key, val] of Object.entries(this.dataObj)) {
|
||||
this.keys.push(key);
|
||||
grp[key] = new FormControl(val);
|
||||
}
|
||||
|
||||
this.group = new FormGroup(grp);
|
||||
}
|
||||
|
||||
setConfig(type: string): void {
|
||||
let subComponent = '';
|
||||
|
||||
switch (type) {
|
||||
case 'context':
|
||||
subComponent = WsConstants.SET_CONTEXT;
|
||||
break;
|
||||
case 'manifest':
|
||||
subComponent = WsConstants.SET_MANIFEST;
|
||||
break;
|
||||
case 'encryption':
|
||||
subComponent = WsConstants.SET_ENCRYPTION_CONFIG;
|
||||
break;
|
||||
case 'management':
|
||||
subComponent = WsConstants.SET_MANAGEMENT_CONFIG;
|
||||
break;
|
||||
}
|
||||
|
||||
for (const [key, control] of Object.entries(this.group.controls)) {
|
||||
// TODO(mfuller): need to validate this within the form
|
||||
if (typeof this.dataObj[key] === 'number') {
|
||||
this.dataObj[key] = +control.value;
|
||||
} else {
|
||||
this.dataObj[key] = control.value;
|
||||
}
|
||||
}
|
||||
|
||||
const msg = new WsMessage(WsConstants.CTL, WsConstants.CONFIG, subComponent);
|
||||
msg.data = JSON.parse(JSON.stringify(this.dataObj));
|
||||
msg.name = this.dataObj.Name;
|
||||
|
||||
this.websocketService.sendMessage(msg);
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
// annoying helper method because apparently I can't just test this natively
|
||||
// inside an *ngIf
|
||||
isBool(val: any): boolean {
|
||||
return typeof val === 'boolean';
|
||||
}
|
||||
|
||||
}
|
43
client/src/app/ctl/config/config-new/config-new.module.ts
Normal file
43
client/src/app/ctl/config/config-new/config-new.module.ts
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { ContextOptions, EncryptionConfigOptions, ManagementConfig, ManifestOptions } from '../config.models';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
ReactiveFormsModule,
|
||||
MatCheckboxModule,
|
||||
MatDialogModule,
|
||||
ContextOptions,
|
||||
ManifestOptions,
|
||||
ManagementConfig,
|
||||
EncryptionConfigOptions
|
||||
],
|
||||
declarations: [
|
||||
],
|
||||
providers: []
|
||||
})
|
||||
export class ConfigNewModule { }
|
@ -14,7 +14,11 @@
|
||||
<mat-accordion *ngFor="let context of contexts">
|
||||
<app-config-context [context]="context"></app-config-context>
|
||||
</mat-accordion>
|
||||
<button mat-icon-button (click)="newConfig('context')">
|
||||
<mat-icon class="grey-icon" svgIcon="add"></mat-icon>New Context
|
||||
</button>
|
||||
</mat-expansion-panel>
|
||||
<br />
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="title">
|
||||
@ -24,7 +28,11 @@
|
||||
<mat-accordion *ngFor="let manifest of manifests">
|
||||
<app-config-manifest [manifest]="manifest"></app-config-manifest>
|
||||
</mat-accordion>
|
||||
<button mat-icon-button (click)="newConfig('manifest')">
|
||||
<mat-icon class="grey-icon" svgIcon="add"></mat-icon>New Manifest
|
||||
</button>
|
||||
</mat-expansion-panel>
|
||||
<br />
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="title">
|
||||
@ -34,7 +42,11 @@
|
||||
<mat-accordion *ngFor="let config of encryptionConfigs">
|
||||
<app-config-encryption [config]="config"></app-config-encryption>
|
||||
</mat-accordion>
|
||||
<button mat-icon-button (click)="newConfig('encryption')">
|
||||
<mat-icon class="grey-icon" svgIcon="add"></mat-icon>New Encryption Config
|
||||
</button>
|
||||
</mat-expansion-panel>
|
||||
<br />
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="title">
|
||||
@ -44,6 +56,9 @@
|
||||
<mat-accordion *ngFor="let config of managementConfigs">
|
||||
<app-config-management [config]="config"></app-config-management>
|
||||
</mat-accordion>
|
||||
<button mat-icon-button (click)="newConfig('management')">
|
||||
<mat-icon class="grey-icon" svgIcon="add"></mat-icon>New Management Config
|
||||
</button>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
<ng-template #initblock>
|
||||
|
@ -30,6 +30,7 @@ import { ConfigEncryptionComponent } from './config-encryption/config-encryption
|
||||
import { ConfigContextComponent } from './config-context/config-context.component';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
|
||||
describe('ConfigComponent', () => {
|
||||
let component: ConfigComponent;
|
||||
@ -49,7 +50,8 @@ describe('ConfigComponent', () => {
|
||||
ConfigEncryptionModule,
|
||||
ReactiveFormsModule,
|
||||
MatExpansionModule,
|
||||
BrowserAnimationsModule
|
||||
BrowserAnimationsModule,
|
||||
MatDialogModule
|
||||
],
|
||||
declarations: [
|
||||
ConfigComponent,
|
||||
|
@ -18,6 +18,8 @@ import { LogMessage } from 'src/services/log/log-message';
|
||||
import { Context, ManagementConfig, Manifest, EncryptionConfig } from './config.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ConfigNewComponent } from './config-new/config-new.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bare-metal',
|
||||
@ -37,7 +39,8 @@ export class ConfigComponent implements WsReceiver, OnInit {
|
||||
managementConfigs: ManagementConfig[] = [];
|
||||
encryptionConfigs: EncryptionConfig[] = [];
|
||||
|
||||
constructor(private websocketService: WsService) {
|
||||
constructor(private websocketService: WsService,
|
||||
public dialog: MatDialog) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
@ -81,15 +84,19 @@ export class ConfigComponent implements WsReceiver, OnInit {
|
||||
break;
|
||||
case WsConstants.SET_CONTEXT:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getContexts();
|
||||
break;
|
||||
case WsConstants.SET_ENCRYPTION_CONFIG:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getEncryptionConfigs();
|
||||
break;
|
||||
case WsConstants.SET_MANIFEST:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getManifests();
|
||||
break;
|
||||
case WsConstants.SET_MANAGEMENT_CONFIG:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getManagementConfigs();
|
||||
break;
|
||||
default:
|
||||
Log.Error(new LogMessage('Config message sub component not handled', this.className, message));
|
||||
@ -109,7 +116,7 @@ export class ConfigComponent implements WsReceiver, OnInit {
|
||||
|
||||
getAirshipConfigPath(): void {
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, 'getAirshipConfigPath')
|
||||
this.type, this.component, WsConstants.GET_AIRSHIP_CONFIG_PATH)
|
||||
);
|
||||
}
|
||||
|
||||
@ -142,4 +149,12 @@ export class ConfigComponent implements WsReceiver, OnInit {
|
||||
this.type, this.component, WsConstants.GET_MANAGEMENT_CONFIGS)
|
||||
);
|
||||
}
|
||||
|
||||
newConfig(configType: string): void {
|
||||
const dialogRef = this.dialog.open(ConfigNewComponent, {
|
||||
width: '550px',
|
||||
height: '650px',
|
||||
data: { formName: configType}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -29,19 +29,23 @@ export class Context {
|
||||
}
|
||||
|
||||
export class ContextOptions {
|
||||
Name: string;
|
||||
Manifest: string;
|
||||
ManagementConfiguration: string;
|
||||
EncryptionConfig: string;
|
||||
Name = '';
|
||||
Manifest = '';
|
||||
ManagementConfiguration = '';
|
||||
EncryptionConfig = '';
|
||||
}
|
||||
|
||||
// There's no corresponding ManagementConfigOptions in CTL, so the
|
||||
// Name property has been deliberately capitalized to make it consistent
|
||||
// with the other ConfigOptions structs and we can retrieve it without
|
||||
// special handling
|
||||
export class ManagementConfig {
|
||||
name: string;
|
||||
insecure: boolean;
|
||||
systemActionRetries: number;
|
||||
systemRebootDelay: number;
|
||||
type: string;
|
||||
useproxy: boolean;
|
||||
Name = '';
|
||||
insecure = false;
|
||||
systemActionRetries = 0;
|
||||
systemRebootDelay = 0;
|
||||
type = '';
|
||||
useproxy = false;
|
||||
}
|
||||
|
||||
export class Manifest {
|
||||
@ -88,24 +92,24 @@ export class Permissions {
|
||||
}
|
||||
|
||||
export class ManifestOptions {
|
||||
Name: string;
|
||||
RepoName: string;
|
||||
URL: string;
|
||||
Branch: string;
|
||||
CommitHash: string;
|
||||
Tag: string;
|
||||
RemoteRef: string;
|
||||
Force: boolean;
|
||||
IsPhase: boolean;
|
||||
SubPath: string;
|
||||
TargetPath: string;
|
||||
MetadataPath: string;
|
||||
Name = '';
|
||||
RepoName = '';
|
||||
URL = '';
|
||||
Branch = '';
|
||||
CommitHash = '';
|
||||
Tag = '';
|
||||
RemoteRef = '';
|
||||
Force = false;
|
||||
IsPhase = false;
|
||||
SubPath = '';
|
||||
TargetPath = '';
|
||||
MetadataPath = '';
|
||||
}
|
||||
|
||||
export class EncryptionConfigOptions {
|
||||
Name: string;
|
||||
EncryptionKeyPath: string;
|
||||
DecryptionKeyPath: string;
|
||||
KeySecretName: string;
|
||||
KeySecretNamespace: string;
|
||||
Name = '';
|
||||
EncryptionKeyPath = '';
|
||||
DecryptionKeyPath = '';
|
||||
KeySecretName = '';
|
||||
KeySecretNamespace = '';
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import { ConfigManifestComponent } from './config-manifest/config-manifest.compo
|
||||
import { ConfigInitComponent } from './config-init/config-init.component';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { ConfigNewComponent } from './config-new/config-new.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -48,7 +49,8 @@ import { MatExpansionModule } from '@angular/material/expansion';
|
||||
ConfigEncryptionComponent,
|
||||
ConfigManagementComponent,
|
||||
ConfigManifestComponent,
|
||||
ConfigInitComponent
|
||||
ConfigInitComponent,
|
||||
ConfigNewComponent
|
||||
],
|
||||
providers: [],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
|
1
client/src/assets/icons/add.svg
Normal file
1
client/src/assets/icons/add.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
|
After Width: | Height: | Size: 173 B |
@ -34,5 +34,6 @@ export enum Icons {
|
||||
close = 'close',
|
||||
lock = 'lock',
|
||||
lock_open = 'lock_open',
|
||||
history = 'history'
|
||||
history = 'history',
|
||||
add = 'add'
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
AirshipConfigNotFoundErr = `No airship config file found.
|
||||
Please visit the Config section to specify or initialize a config file.`
|
||||
// AirshipConfigNotFoundErr generic error for missing airship config file
|
||||
AirshipConfigNotFoundErr = "No airship config file found."
|
||||
)
|
||||
|
||||
// CTLFunctionMap is a function map for the CTL functions that is referenced in the webservice
|
||||
|
@ -226,7 +226,7 @@ func GetManifests(request configs.WsMessage) configs.WsMessage {
|
||||
// ManagementConfig wrapper struct for CTL's ManagementConfiguration that
|
||||
// includes a name
|
||||
type ManagementConfig struct {
|
||||
Name string `json:"name"`
|
||||
Name string `json:"Name"`
|
||||
ctlconfig.ManagementConfiguration
|
||||
}
|
||||
|
||||
@ -408,22 +408,20 @@ func SetManagementConfig(request configs.WsMessage) configs.WsMessage {
|
||||
return response
|
||||
}
|
||||
|
||||
if mCfg, found := client.Config.ManagementConfiguration[request.Name]; found {
|
||||
err = json.Unmarshal(bytes, mCfg)
|
||||
if err != nil {
|
||||
e := err.Error()
|
||||
response.Error = &e
|
||||
return response
|
||||
}
|
||||
var mCfg ctlconfig.ManagementConfiguration
|
||||
|
||||
err = client.Config.PersistConfig()
|
||||
if err != nil {
|
||||
e := err.Error()
|
||||
response.Error = &e
|
||||
return response
|
||||
}
|
||||
} else {
|
||||
e := fmt.Sprintf("Management configuration '%s' not found", request.Name)
|
||||
err = json.Unmarshal(bytes, &mCfg)
|
||||
if err != nil {
|
||||
e := err.Error()
|
||||
response.Error = &e
|
||||
return response
|
||||
}
|
||||
|
||||
client.Config.ManagementConfiguration[request.Name] = &mCfg
|
||||
|
||||
err = client.Config.PersistConfig()
|
||||
if err != nil {
|
||||
e := err.Error()
|
||||
response.Error = &e
|
||||
return response
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user