Add init to config component
This change allows users to init a new airship config file or specify an existing one if it hasn't been found in the default location. Known Issues: - Initializing or specifying a config file should persist those changes back to the airshipui.json config file, so that the chosen location can be read on app launch. It currently doesn't - Once initialized or specified, the location of the config file cannot be changed from within the UI Change-Id: If2be1054c06ce0896179f3c43676a4e7cadcbe3a
This commit is contained in:
parent
5f26bb7c8e
commit
e05b2efed0
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
# 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.grey-icon {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-action-row {
|
||||||
|
place-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #3f51b5;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-form-field {
|
||||||
|
width: 80%;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<div class="config-init-form">
|
||||||
|
<h4>Initialize new Airship configuration file</h4>
|
||||||
|
<mat-form-field class="init-form-field">
|
||||||
|
<mat-label>Path</mat-label>
|
||||||
|
<input matInput type="text" placeholder="Leave blank for default $HOME/.airship/config" [formControl]="initValue">
|
||||||
|
<button mat-button *ngIf="initValue" matSuffix mat-icon-button aria-label="Clear" (click)="initValue=''">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-raised-button color="primary" (click)="initAirshipConfig()">Initialize</button>
|
||||||
|
</div>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<div class="config-specify-form">
|
||||||
|
<h4>Specify existing Airship configuration file</h4>
|
||||||
|
<mat-form-field class="specify-form-field">
|
||||||
|
<mat-label>Path</mat-label>
|
||||||
|
<input matInput type="text" [formControl]="specifyValue">
|
||||||
|
<button mat-button *ngIf="specifyValue" matSuffix mat-icon-button aria-label="Clear" (click)="specifyValue=''">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-raised-button color="primary" (click)="setAirshipConfig()">Set Path</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 { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { ToastrModule } from 'ngx-toastr';
|
||||||
|
|
||||||
|
import { ConfigInitComponent } from './config-init.component';
|
||||||
|
|
||||||
|
describe('ConfigEncryptionComponent', () => {
|
||||||
|
let component: ConfigInitComponent;
|
||||||
|
let fixture: ComponentFixture<ConfigInitComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ConfigInitComponent ],
|
||||||
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
FormsModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatButtonModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
ToastrModule.forRoot(),
|
||||||
|
MatExpansionModule,
|
||||||
|
MatDividerModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ConfigInitComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
# 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 } from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { WebsocketService } from '../../../../services/websocket/websocket.service';
|
||||||
|
import { WebsocketMessage } from '../../../../services/websocket/websocket.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-config-init',
|
||||||
|
templateUrl: './config-init.component.html',
|
||||||
|
styleUrls: ['./config-init.component.css']
|
||||||
|
})
|
||||||
|
export class ConfigInitComponent {
|
||||||
|
type = 'ctl';
|
||||||
|
component = 'config';
|
||||||
|
|
||||||
|
initValue = new FormControl('');
|
||||||
|
specifyValue = new FormControl('');
|
||||||
|
|
||||||
|
constructor(private websocketService: WebsocketService) {}
|
||||||
|
|
||||||
|
initAirshipConfig(): void {
|
||||||
|
const msg = new WebsocketMessage(this.type, this.component, 'init');
|
||||||
|
msg.message = this.initValue.value;
|
||||||
|
this.websocketService.sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAirshipConfig(): void {
|
||||||
|
const msg = new WebsocketMessage(this.type, this.component, 'setAirshipConfig');
|
||||||
|
msg.message = this.specifyValue.value;
|
||||||
|
this.websocketService.sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
client/src/app/ctl/config/config-init/config-init.module.ts
Normal file
35
client/src/app/ctl/config/config-init/config-init.module.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
# 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 { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatButtonModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class ConfigInitModule { }
|
@ -1,6 +1,7 @@
|
|||||||
<h1>Airship Configuration Options</h1>
|
<h1>Airship Configuration Options</h1>
|
||||||
|
<h5>Airship Config File: {{airshipConfigPath}}</h5>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<div class="config-container">
|
<div *ngIf="airshipConfigPath !== '' && airshipConfigPath !== undefined; else initblock" class="config-container">
|
||||||
<mat-expansion-panel>
|
<mat-expansion-panel>
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title class="title">
|
<mat-panel-title class="title">
|
||||||
@ -45,3 +46,8 @@
|
|||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
|
<ng-template #initblock>
|
||||||
|
<div class="config-init-container">
|
||||||
|
<app-config-init></app-config-init>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
@ -30,6 +30,8 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
|||||||
type = 'ctl';
|
type = 'ctl';
|
||||||
component = 'config';
|
component = 'config';
|
||||||
|
|
||||||
|
airshipConfigPath: string;
|
||||||
|
|
||||||
currentContext: string;
|
currentContext: string;
|
||||||
contexts: Context[] = [];
|
contexts: Context[] = [];
|
||||||
manifests: Manifest[] = [];
|
manifests: Manifest[] = [];
|
||||||
@ -49,6 +51,17 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
|||||||
this.websocketService.printIfToast(message);
|
this.websocketService.printIfToast(message);
|
||||||
} else {
|
} else {
|
||||||
switch (message.subComponent) {
|
switch (message.subComponent) {
|
||||||
|
case 'init':
|
||||||
|
this.websocketService.printIfToast(message);
|
||||||
|
this.getConfig();
|
||||||
|
break;
|
||||||
|
case 'setAirshipConfig':
|
||||||
|
this.websocketService.printIfToast(message);
|
||||||
|
this.getConfig();
|
||||||
|
break;
|
||||||
|
case 'getAirshipConfigPath':
|
||||||
|
this.airshipConfigPath = message.message;
|
||||||
|
break;
|
||||||
case 'getCurrentContext':
|
case 'getCurrentContext':
|
||||||
this.currentContext = message.message;
|
this.currentContext = message.message;
|
||||||
break;
|
break;
|
||||||
@ -87,6 +100,7 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getConfig(): void {
|
getConfig(): void {
|
||||||
|
this.getAirshipConfigPath();
|
||||||
this.getCurrentContext();
|
this.getCurrentContext();
|
||||||
this.getContexts();
|
this.getContexts();
|
||||||
this.getManifests();
|
this.getManifests();
|
||||||
@ -94,6 +108,12 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
|||||||
this.getEncryptionConfigs();
|
this.getEncryptionConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAirshipConfigPath(): void {
|
||||||
|
this.websocketService.sendMessage(new WebsocketMessage(
|
||||||
|
this.type, this.component, 'getAirshipConfigPath')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getCurrentContext(): void {
|
getCurrentContext(): void {
|
||||||
this.websocketService.sendMessage(new WebsocketMessage(
|
this.websocketService.sendMessage(new WebsocketMessage(
|
||||||
this.type, this.component, 'getCurrentContext')
|
this.type, this.component, 'getCurrentContext')
|
||||||
|
@ -25,6 +25,7 @@ import { ConfigContextComponent } from './config-context/config-context.componen
|
|||||||
import { ConfigEncryptionComponent } from './config-encryption/config-encryption.component';
|
import { ConfigEncryptionComponent } from './config-encryption/config-encryption.component';
|
||||||
import { ConfigManagementComponent } from './config-management/config-management.component';
|
import { ConfigManagementComponent } from './config-management/config-management.component';
|
||||||
import { ConfigManifestComponent } from './config-manifest/config-manifest.component';
|
import { ConfigManifestComponent } from './config-manifest/config-manifest.component';
|
||||||
|
import { ConfigInitComponent } from './config-init/config-init.component';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
|
||||||
@ -46,7 +47,8 @@ import { MatExpansionModule } from '@angular/material/expansion';
|
|||||||
ConfigContextComponent,
|
ConfigContextComponent,
|
||||||
ConfigEncryptionComponent,
|
ConfigEncryptionComponent,
|
||||||
ConfigManagementComponent,
|
ConfigManagementComponent,
|
||||||
ConfigManifestComponent
|
ConfigManifestComponent,
|
||||||
|
ConfigInitComponent
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
@ -22,9 +22,11 @@ import { CtlRoutingModule } from './ctl-routing.module';
|
|||||||
import { PhaseModule } from './phase/phase.module';
|
import { PhaseModule } from './phase/phase.module';
|
||||||
import { SecretModule } from './secret/secret.module';
|
import { SecretModule } from './secret/secret.module';
|
||||||
import { ConfigModule } from './config/config.module';
|
import { ConfigModule } from './config/config.module';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
CommonModule,
|
||||||
CtlRoutingModule,
|
CtlRoutingModule,
|
||||||
ClusterModule,
|
ClusterModule,
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
|
2
go.sum
2
go.sum
@ -125,6 +125,7 @@ github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
|||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
@ -702,6 +703,7 @@ github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7
|
|||||||
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
|
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
|
||||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||||
|
@ -137,6 +137,8 @@ const (
|
|||||||
Status WsSubComponentType = "status"
|
Status WsSubComponentType = "status"
|
||||||
|
|
||||||
// ctl config subcomponets
|
// ctl config subcomponets
|
||||||
|
SetAirshipConfig WsSubComponentType = "setAirshipConfig"
|
||||||
|
GetAirshipConfigPath WsSubComponentType = "getAirshipConfigPath"
|
||||||
GetContexts WsSubComponentType = "getContexts"
|
GetContexts WsSubComponentType = "getContexts"
|
||||||
GetCurrentContext WsSubComponentType = "getCurrentContext"
|
GetCurrentContext WsSubComponentType = "getCurrentContext"
|
||||||
GetEncryptionConfigs WsSubComponentType = "getEncryptionConfigs"
|
GetEncryptionConfigs WsSubComponentType = "getEncryptionConfigs"
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
package ctl
|
package ctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
"opendev.org/airship/airshipctl/pkg/log"
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
"opendev.org/airship/airshipui/pkg/configs"
|
"opendev.org/airship/airshipui/pkg/configs"
|
||||||
@ -31,6 +34,11 @@ var AirshipConfigPath *string
|
|||||||
// KubeConfigPath location of kubeconfig used by airshipctl (default $HOME/.airship/kubeconfig)
|
// KubeConfigPath location of kubeconfig used by airshipctl (default $HOME/.airship/kubeconfig)
|
||||||
var KubeConfigPath *string
|
var KubeConfigPath *string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AirshipConfigNotFoundErr = `No airship config file found.
|
||||||
|
Please visit the Config section to specify or initialize a config file.`
|
||||||
|
)
|
||||||
|
|
||||||
// CTLFunctionMap is a function map for the CTL functions that is referenced in the webservice
|
// CTLFunctionMap is a function map for the CTL functions that is referenced in the webservice
|
||||||
var CTLFunctionMap = map[configs.WsComponentType]func(*string, configs.WsMessage) configs.WsMessage{
|
var CTLFunctionMap = map[configs.WsComponentType]func(*string, configs.WsMessage) configs.WsMessage{
|
||||||
configs.Baremetal: HandleBaremetalRequest,
|
configs.Baremetal: HandleBaremetalRequest,
|
||||||
@ -63,8 +71,25 @@ func Init() {
|
|||||||
webservice.AppendToFunctionMap(configs.CTL, CTLFunctionMap)
|
webservice.AppendToFunctionMap(configs.CTL, CTLFunctionMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func configFileExists(airshipConfigPath *string) bool {
|
||||||
|
if airshipConfigPath == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := os.Stat(*airshipConfigPath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !info.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
// NewDefaultClient initializes the airshipctl client for external usage with default logging.
|
// NewDefaultClient initializes the airshipctl client for external usage with default logging.
|
||||||
func NewDefaultClient(airshipConfigPath *string) (*Client, error) {
|
func NewDefaultClient(airshipConfigPath *string) (*Client, error) {
|
||||||
|
if !configFileExists(airshipConfigPath) {
|
||||||
|
return nil, fmt.Errorf(AirshipConfigNotFoundErr)
|
||||||
|
}
|
||||||
|
|
||||||
cfgFactory := config.CreateFactory(airshipConfigPath)
|
cfgFactory := config.CreateFactory(airshipConfigPath)
|
||||||
|
|
||||||
// TODO(mfuller): Factory doesn't throw an error if there's no
|
// TODO(mfuller): Factory doesn't throw an error if there's no
|
||||||
|
@ -17,82 +17,124 @@ package ctl
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
ctlconfig "opendev.org/airship/airshipctl/pkg/config"
|
ctlconfig "opendev.org/airship/airshipctl/pkg/config"
|
||||||
"opendev.org/airship/airshipui/pkg/configs"
|
"opendev.org/airship/airshipui/pkg/configs"
|
||||||
"opendev.org/airship/airshipui/pkg/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleConfigRequest will flop between requests so we don't have to have them all mapped as function calls
|
// ConfigFunctionMap is being used to call the appropriate function based on the SubComponentType,
|
||||||
// This will wait for the sub component to complete before responding. The assumption is this is an async request
|
// since the linter seems to think there are too many cases for a switch / case
|
||||||
func HandleConfigRequest(user *string, request configs.WsMessage) configs.WsMessage {
|
var ConfigFunctionMap = map[configs.WsSubComponentType]func(configs.WsMessage) configs.WsMessage{
|
||||||
response := configs.WsMessage{
|
configs.SetAirshipConfig: SetAirshipConfig,
|
||||||
|
configs.GetAirshipConfigPath: GetAirshipConfigPath,
|
||||||
|
configs.GetCurrentContext: GetCurrentContext,
|
||||||
|
configs.GetContexts: GetContexts,
|
||||||
|
configs.GetEncryptionConfigs: GetEncryptionConfigs,
|
||||||
|
configs.GetManagementConfigs: GetManagementConfigs,
|
||||||
|
configs.GetManifests: GetManifests,
|
||||||
|
configs.Init: InitAirshipConfig,
|
||||||
|
configs.SetContext: SetContext,
|
||||||
|
configs.SetEncryptionConfig: SetEncryptionConfig,
|
||||||
|
configs.SetManagementConfig: SetManagementConfig,
|
||||||
|
configs.SetManifest: SetManifest,
|
||||||
|
configs.UseContext: UseContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create most of the relevant bits of the response message
|
||||||
|
func newResponse(request configs.WsMessage) configs.WsMessage {
|
||||||
|
return configs.WsMessage{
|
||||||
Type: configs.CTL,
|
Type: configs.CTL,
|
||||||
Component: configs.CTLConfig,
|
Component: configs.CTLConfig,
|
||||||
SubComponent: request.SubComponent,
|
SubComponent: request.SubComponent,
|
||||||
Name: request.Name,
|
Name: request.Name,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
// HandleConfigRequest will flop between requests so we don't have to have them all mapped as function calls
|
||||||
var message *string
|
// This will wait for the sub component to complete before responding. The assumption is this is an async request
|
||||||
|
func HandleConfigRequest(user *string, request configs.WsMessage) configs.WsMessage {
|
||||||
|
var response configs.WsMessage
|
||||||
|
|
||||||
|
if handler, ok := ConfigFunctionMap[request.SubComponent]; ok {
|
||||||
|
response = handler(request)
|
||||||
|
} else {
|
||||||
|
response = newResponse(request)
|
||||||
|
err := fmt.Sprintf("Subcomponent %s not found", request.SubComponent)
|
||||||
|
response.Error = &err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAirshipConfigPath returns value stored in AirshipConfigPath
|
||||||
|
func GetAirshipConfigPath(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
response.Message = AirshipConfigPath
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAirshipConfig sets the AirshipConfigPath to the value specified by
|
||||||
|
// UI client
|
||||||
|
func SetAirshipConfig(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
AirshipConfigPath = request.Message
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Config file set to '%s'", *AirshipConfigPath)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentContext returns the name of the currently configured context
|
||||||
|
func GetCurrentContext(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error initializing airshipctl client: %s", err)
|
e := err.Error()
|
||||||
response.Error = &e
|
response.Error = &e
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
subComponent := request.SubComponent
|
response.Message = &client.Config.CurrentContext
|
||||||
switch subComponent {
|
|
||||||
case configs.GetCurrentContext:
|
|
||||||
context := client.Config.CurrentContext
|
|
||||||
message = &context
|
|
||||||
case configs.GetContexts:
|
|
||||||
response.Data = GetContexts(client)
|
|
||||||
case configs.GetEncryptionConfigs:
|
|
||||||
response.Data = GetEncryptionConfigs(client)
|
|
||||||
case configs.GetManagementConfigs:
|
|
||||||
response.Data = GetManagementConfigs(client)
|
|
||||||
case configs.GetManifests:
|
|
||||||
response.Data = GetManifests(client)
|
|
||||||
case configs.Init:
|
|
||||||
err = InitAirshipConfig(AirshipConfigPath)
|
|
||||||
case configs.SetContext:
|
|
||||||
response.Data, err = SetContext(client, request)
|
|
||||||
str := fmt.Sprintf("Context '%s' has been modified", request.Name)
|
|
||||||
message = &str
|
|
||||||
case configs.SetEncryptionConfig:
|
|
||||||
response.Data, err = SetEncryptionConfig(client, request)
|
|
||||||
str := fmt.Sprintf("Encryption configuration '%s' has been modified", request.Name)
|
|
||||||
message = &str
|
|
||||||
case configs.SetManagementConfig:
|
|
||||||
err = SetManagementConfig(client, request)
|
|
||||||
str := fmt.Sprintf("Management configuration '%s' has been modified", request.Name)
|
|
||||||
message = &str
|
|
||||||
case configs.SetManifest:
|
|
||||||
response.Data, err = SetManifest(client, request)
|
|
||||||
str := fmt.Sprintf("Manifest '%s' has been modified", request.Name)
|
|
||||||
message = &str
|
|
||||||
case configs.UseContext:
|
|
||||||
err = UseContext(client, request)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("Subcomponent %s not found", request.SubComponent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
e := err.Error()
|
|
||||||
response.Error = &e
|
|
||||||
} else {
|
|
||||||
response.Message = message
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitAirshipConfig wrapper function for CTL's CreateConfig using the specified path
|
// InitAirshipConfig wrapper function for CTL's CreateConfig using the specified path
|
||||||
func InitAirshipConfig(path *string) error {
|
// TODO(mfuller): we'll need to persist this info in airshipui.json so that we can
|
||||||
return ctlconfig.CreateConfig(*path)
|
// set AirshipConfigPath at app launch
|
||||||
|
func InitAirshipConfig(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
confPath := *request.Message
|
||||||
|
if confPath == "" {
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
confPath = filepath.Join(home, ".airship", "config")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ctlconfig.CreateConfig(confPath)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
AirshipConfigPath = &confPath
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Config file set to '%s'", *AirshipConfigPath)
|
||||||
|
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context wrapper struct to include context name with CTL's Context
|
// Context wrapper struct to include context name with CTL's Context
|
||||||
@ -103,7 +145,16 @@ type Context struct {
|
|||||||
|
|
||||||
// GetContexts returns a slice of wrapper Context structs so we know the name of each
|
// GetContexts returns a slice of wrapper Context structs so we know the name of each
|
||||||
// for display in the UI
|
// for display in the UI
|
||||||
func GetContexts(client *Client) []Context {
|
func GetContexts(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
contexts := []Context{}
|
contexts := []Context{}
|
||||||
for name, context := range client.Config.Contexts {
|
for name, context := range client.Config.Contexts {
|
||||||
contexts = append(contexts, Context{
|
contexts = append(contexts, Context{
|
||||||
@ -117,7 +168,9 @@ func GetContexts(client *Client) []Context {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return contexts
|
response.Data = contexts
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest wraps CTL's Manifest to include the manifest name
|
// Manifest wraps CTL's Manifest to include the manifest name
|
||||||
@ -128,7 +181,16 @@ type Manifest struct {
|
|||||||
|
|
||||||
// GetManifests returns a slice of wrapper Manifest structs so we know the name of each
|
// GetManifests returns a slice of wrapper Manifest structs so we know the name of each
|
||||||
// for display in the UI
|
// for display in the UI
|
||||||
func GetManifests(client *Client) []Manifest {
|
func GetManifests(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
manifests := []Manifest{}
|
manifests := []Manifest{}
|
||||||
|
|
||||||
for name, manifest := range client.Config.Manifests {
|
for name, manifest := range client.Config.Manifests {
|
||||||
@ -138,7 +200,9 @@ func GetManifests(client *Client) []Manifest {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return manifests
|
response.Data = manifests
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManagementConfig wrapper struct for CTL's ManagementConfiguration that
|
// ManagementConfig wrapper struct for CTL's ManagementConfiguration that
|
||||||
@ -149,7 +213,16 @@ type ManagementConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetManagementConfigs function to retrieve all management configs
|
// GetManagementConfigs function to retrieve all management configs
|
||||||
func GetManagementConfigs(client *Client) []ManagementConfig {
|
func GetManagementConfigs(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
configs := []ManagementConfig{}
|
configs := []ManagementConfig{}
|
||||||
for name, conf := range client.Config.ManagementConfiguration {
|
for name, conf := range client.Config.ManagementConfiguration {
|
||||||
configs = append(configs, ManagementConfig{
|
configs = append(configs, ManagementConfig{
|
||||||
@ -163,7 +236,10 @@ func GetManagementConfigs(client *Client) []ManagementConfig {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return configs
|
|
||||||
|
response.Data = configs
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptionConfig wrapper struct for CTL's EncryptionConfiguration that
|
// EncryptionConfig wrapper struct for CTL's EncryptionConfiguration that
|
||||||
@ -175,7 +251,16 @@ type EncryptionConfig struct {
|
|||||||
|
|
||||||
// GetEncryptionConfigs returns a slice of wrapper EncryptionConfig structs so we
|
// GetEncryptionConfigs returns a slice of wrapper EncryptionConfig structs so we
|
||||||
// know the name of each for display in the UI
|
// know the name of each for display in the UI
|
||||||
func GetEncryptionConfigs(client *Client) []EncryptionConfig {
|
func GetEncryptionConfigs(request configs.WsMessage) configs.WsMessage {
|
||||||
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
configs := []EncryptionConfig{}
|
configs := []EncryptionConfig{}
|
||||||
for name, config := range client.Config.EncryptionConfigs {
|
for name, config := range client.Config.EncryptionConfigs {
|
||||||
configs = append(configs, EncryptionConfig{
|
configs = append(configs, EncryptionConfig{
|
||||||
@ -187,101 +272,216 @@ func GetEncryptionConfigs(client *Client) []EncryptionConfig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return configs
|
response.Data = configs
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetContext wrapper function for CTL's RunSetContext, using a UI client
|
// SetContext wrapper function for CTL's RunSetContext, using a UI client
|
||||||
func SetContext(client *Client, message configs.WsMessage) (bool, error) {
|
func SetContext(request configs.WsMessage) configs.WsMessage {
|
||||||
bytes, err := json.Marshal(message.Data)
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(request.Data)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts ctlconfig.ContextOptions
|
var opts ctlconfig.ContextOptions
|
||||||
err = json.Unmarshal(bytes, &opts)
|
err = json.Unmarshal(bytes, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
err = opts.Validate()
|
err = opts.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctlconfig.RunSetContext(&opts, client.Config, true)
|
_, err = ctlconfig.RunSetContext(&opts, client.Config, true)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Context '%s' has been modified", request.Name)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEncryptionConfig wrapper function for CTL's RunSetEncryptionConfig, using a UI client
|
// SetEncryptionConfig wrapper function for CTL's RunSetEncryptionConfig, using a UI client
|
||||||
func SetEncryptionConfig(client *Client, message configs.WsMessage) (bool, error) {
|
func SetEncryptionConfig(request configs.WsMessage) configs.WsMessage {
|
||||||
bytes, err := json.Marshal(message.Data)
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(request.Data)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts ctlconfig.EncryptionConfigOptions
|
var opts ctlconfig.EncryptionConfigOptions
|
||||||
err = json.Unmarshal(bytes, &opts)
|
err = json.Unmarshal(bytes, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
err = opts.Validate()
|
err = opts.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctlconfig.RunSetEncryptionConfig(&opts, client.Config, true)
|
_, err = ctlconfig.RunSetEncryptionConfig(&opts, client.Config, true)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Encryption configuration '%s' has been modified", request.Name)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetManagementConfig sets the specified management configuration with values
|
// SetManagementConfig sets the specified management configuration with values
|
||||||
// received from the frontend client
|
// received from the frontend client
|
||||||
// TODO(mfuller): there's currently no setter for this in the CTL config pkg
|
// TODO(mfuller): there's currently no setter for this in the CTL config pkg
|
||||||
// so we'll set the values manually and then persist the config
|
// so we'll set the values manually and then persist the config
|
||||||
func SetManagementConfig(client *Client, message configs.WsMessage) error {
|
func SetManagementConfig(request configs.WsMessage) configs.WsMessage {
|
||||||
bytes, err := json.Marshal(message.Data)
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
if mCfg, found := client.Config.ManagementConfiguration[message.Name]; found {
|
bytes, err := json.Marshal(request.Data)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
if mCfg, found := client.Config.ManagementConfiguration[request.Name]; found {
|
||||||
err = json.Unmarshal(bytes, mCfg)
|
err = json.Unmarshal(bytes, mCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.Config.PersistConfig()
|
err = client.Config.PersistConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Management configuration '%s' not found", message.Name)
|
e := fmt.Sprintf("Management configuration '%s' not found", request.Name)
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
msg := fmt.Sprintf("Management configuration '%s' has been modified", request.Name)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetManifest wrapper function for CTL's RunSetManifest, using a UI client
|
// SetManifest wrapper function for CTL's RunSetManifest, using a UI client
|
||||||
func SetManifest(client *Client, message configs.WsMessage) (bool, error) {
|
func SetManifest(request configs.WsMessage) configs.WsMessage {
|
||||||
bytes, err := json.Marshal(message.Data)
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(request.Data)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts ctlconfig.ManifestOptions
|
var opts ctlconfig.ManifestOptions
|
||||||
err = json.Unmarshal(bytes, &opts)
|
err = json.Unmarshal(bytes, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Unmarshaled options: %+v", opts)
|
|
||||||
err = opts.Validate()
|
err = opts.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctlconfig.RunSetManifest(&opts, client.Config, true)
|
_, err = ctlconfig.RunSetManifest(&opts, client.Config, true)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Manifest '%s' has been modified", request.Name)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseContext wrapper function for CTL's RunUseConfig, using a UI client
|
// UseContext wrapper function for CTL's RunUseConfig, using a UI client
|
||||||
func UseContext(client *Client, message configs.WsMessage) error {
|
func UseContext(request configs.WsMessage) configs.WsMessage {
|
||||||
return ctlconfig.RunUseContext(message.Name, client.Config)
|
response := newResponse(request)
|
||||||
|
|
||||||
|
client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctlconfig.RunUseContext(request.Name, client.Config)
|
||||||
|
if err != nil {
|
||||||
|
e := err.Error()
|
||||||
|
response.Error = &e
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Using context '%s'", request.Name)
|
||||||
|
response.Message = &msg
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user