+
@@ -45,3 +46,8 @@
+
+
+
diff --git a/client/src/app/ctl/config/config.component.ts b/client/src/app/ctl/config/config.component.ts
index 3dbc12d..43c3c3e 100755
--- a/client/src/app/ctl/config/config.component.ts
+++ b/client/src/app/ctl/config/config.component.ts
@@ -30,6 +30,8 @@ export class ConfigComponent implements WSReceiver, OnInit {
type = 'ctl';
component = 'config';
+ airshipConfigPath: string;
+
currentContext: string;
contexts: Context[] = [];
manifests: Manifest[] = [];
@@ -49,6 +51,17 @@ export class ConfigComponent implements WSReceiver, OnInit {
this.websocketService.printIfToast(message);
} else {
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':
this.currentContext = message.message;
break;
@@ -87,6 +100,7 @@ export class ConfigComponent implements WSReceiver, OnInit {
}
getConfig(): void {
+ this.getAirshipConfigPath();
this.getCurrentContext();
this.getContexts();
this.getManifests();
@@ -94,6 +108,12 @@ export class ConfigComponent implements WSReceiver, OnInit {
this.getEncryptionConfigs();
}
+ getAirshipConfigPath(): void {
+ this.websocketService.sendMessage(new WebsocketMessage(
+ this.type, this.component, 'getAirshipConfigPath')
+ );
+ }
+
getCurrentContext(): void {
this.websocketService.sendMessage(new WebsocketMessage(
this.type, this.component, 'getCurrentContext')
diff --git a/client/src/app/ctl/config/config.module.ts b/client/src/app/ctl/config/config.module.ts
index 03b0d4e..3db3792 100755
--- a/client/src/app/ctl/config/config.module.ts
+++ b/client/src/app/ctl/config/config.module.ts
@@ -25,6 +25,7 @@ import { ConfigContextComponent } from './config-context/config-context.componen
import { ConfigEncryptionComponent } from './config-encryption/config-encryption.component';
import { ConfigManagementComponent } from './config-management/config-management.component';
import { ConfigManifestComponent } from './config-manifest/config-manifest.component';
+import { ConfigInitComponent } from './config-init/config-init.component';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatExpansionModule } from '@angular/material/expansion';
@@ -46,7 +47,8 @@ import { MatExpansionModule } from '@angular/material/expansion';
ConfigContextComponent,
ConfigEncryptionComponent,
ConfigManagementComponent,
- ConfigManifestComponent
+ ConfigManifestComponent,
+ ConfigInitComponent
],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
diff --git a/client/src/app/ctl/ctl.module.ts b/client/src/app/ctl/ctl.module.ts
index 287dfb4..7723625 100644
--- a/client/src/app/ctl/ctl.module.ts
+++ b/client/src/app/ctl/ctl.module.ts
@@ -22,9 +22,11 @@ import { CtlRoutingModule } from './ctl-routing.module';
import { PhaseModule } from './phase/phase.module';
import { SecretModule } from './secret/secret.module';
import { ConfigModule } from './config/config.module';
+import { CommonModule } from '@angular/common';
@NgModule({
imports: [
+ CommonModule,
CtlRoutingModule,
ClusterModule,
ConfigModule,
diff --git a/go.sum b/go.sum
index 356d120..cb10933 100644
--- a/go.sum
+++ b/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-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.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
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-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=
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/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.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=
diff --git a/pkg/configs/configs.go b/pkg/configs/configs.go
index 2f75e37..14c64cc 100644
--- a/pkg/configs/configs.go
+++ b/pkg/configs/configs.go
@@ -137,6 +137,8 @@ const (
Status WsSubComponentType = "status"
// ctl config subcomponets
+ SetAirshipConfig WsSubComponentType = "setAirshipConfig"
+ GetAirshipConfigPath WsSubComponentType = "getAirshipConfigPath"
GetContexts WsSubComponentType = "getContexts"
GetCurrentContext WsSubComponentType = "getCurrentContext"
GetEncryptionConfigs WsSubComponentType = "getEncryptionConfigs"
diff --git a/pkg/ctl/airshipctl.go b/pkg/ctl/airshipctl.go
index 560b2b5..879310c 100644
--- a/pkg/ctl/airshipctl.go
+++ b/pkg/ctl/airshipctl.go
@@ -15,6 +15,9 @@
package ctl
import (
+ "fmt"
+ "os"
+
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipui/pkg/configs"
@@ -31,6 +34,11 @@ var AirshipConfigPath *string
// KubeConfigPath location of kubeconfig used by airshipctl (default $HOME/.airship/kubeconfig)
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
var CTLFunctionMap = map[configs.WsComponentType]func(*string, configs.WsMessage) configs.WsMessage{
configs.Baremetal: HandleBaremetalRequest,
@@ -63,8 +71,25 @@ func Init() {
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.
func NewDefaultClient(airshipConfigPath *string) (*Client, error) {
+ if !configFileExists(airshipConfigPath) {
+ return nil, fmt.Errorf(AirshipConfigNotFoundErr)
+ }
+
cfgFactory := config.CreateFactory(airshipConfigPath)
// TODO(mfuller): Factory doesn't throw an error if there's no
diff --git a/pkg/ctl/config.go b/pkg/ctl/config.go
index c7b9a7d..94725d6 100644
--- a/pkg/ctl/config.go
+++ b/pkg/ctl/config.go
@@ -17,82 +17,124 @@ package ctl
import (
"encoding/json"
"fmt"
+ "os"
+ "path/filepath"
ctlconfig "opendev.org/airship/airshipctl/pkg/config"
"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
-// 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 {
- response := configs.WsMessage{
+// ConfigFunctionMap is being used to call the appropriate function based on the SubComponentType,
+// since the linter seems to think there are too many cases for a switch / case
+var ConfigFunctionMap = map[configs.WsSubComponentType]func(configs.WsMessage) 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,
Component: configs.CTLConfig,
SubComponent: request.SubComponent,
Name: request.Name,
}
+}
- var err error
- var message *string
+// HandleConfigRequest will flop between requests so we don't have to have them all mapped as function calls
+// 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
- client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
- if err != nil {
- e := fmt.Sprintf("Error initializing airshipctl client: %s", err)
- response.Error = &e
- return response
- }
-
- subComponent := request.SubComponent
- 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
+ if handler, ok := ConfigFunctionMap[request.SubComponent]; ok {
+ response = handler(request)
} else {
- response.Message = message
+ 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)
+ if err != nil {
+ e := err.Error()
+ response.Error = &e
+ return response
+ }
+
+ response.Message = &client.Config.CurrentContext
+
+ return response
+}
+
// InitAirshipConfig wrapper function for CTL's CreateConfig using the specified path
-func InitAirshipConfig(path *string) error {
- return ctlconfig.CreateConfig(*path)
+// TODO(mfuller): we'll need to persist this info in airshipui.json so that we can
+// 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
@@ -103,7 +145,16 @@ type Context struct {
// GetContexts returns a slice of wrapper Context structs so we know the name of each
// 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{}
for name, context := range client.Config.Contexts {
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
@@ -128,7 +181,16 @@ type Manifest struct {
// GetManifests returns a slice of wrapper Manifest structs so we know the name of each
// 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{}
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
@@ -149,7 +213,16 @@ type ManagementConfig struct {
}
// 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{}
for name, conf := range client.Config.ManagementConfiguration {
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
@@ -175,7 +251,16 @@ type EncryptionConfig struct {
// GetEncryptionConfigs returns a slice of wrapper EncryptionConfig structs so we
// 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{}
for name, config := range client.Config.EncryptionConfigs {
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
-func SetContext(client *Client, message configs.WsMessage) (bool, error) {
- bytes, err := json.Marshal(message.Data)
+func SetContext(request configs.WsMessage) configs.WsMessage {
+ response := newResponse(request)
+
+ client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
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
err = json.Unmarshal(bytes, &opts)
if err != nil {
- return false, err
+ e := err.Error()
+ response.Error = &e
+ return response
}
err = opts.Validate()
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
-func SetEncryptionConfig(client *Client, message configs.WsMessage) (bool, error) {
- bytes, err := json.Marshal(message.Data)
+func SetEncryptionConfig(request configs.WsMessage) configs.WsMessage {
+ response := newResponse(request)
+
+ client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
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
err = json.Unmarshal(bytes, &opts)
if err != nil {
- return false, err
+ e := err.Error()
+ response.Error = &e
+ return response
}
err = opts.Validate()
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
// received from the frontend client
// 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
-func SetManagementConfig(client *Client, message configs.WsMessage) error {
- bytes, err := json.Marshal(message.Data)
+func SetManagementConfig(request configs.WsMessage) configs.WsMessage {
+ response := newResponse(request)
+
+ client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
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)
if err != nil {
- return err
+ e := err.Error()
+ response.Error = &e
+ return response
}
err = client.Config.PersistConfig()
if err != nil {
- return err
+ e := err.Error()
+ response.Error = &e
+ return response
}
} 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
-func SetManifest(client *Client, message configs.WsMessage) (bool, error) {
- bytes, err := json.Marshal(message.Data)
+func SetManifest(request configs.WsMessage) configs.WsMessage {
+ response := newResponse(request)
+
+ client, err := NewClient(AirshipConfigPath, KubeConfigPath, request)
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
err = json.Unmarshal(bytes, &opts)
if err != nil {
- return false, err
+ e := err.Error()
+ response.Error = &e
+ return response
}
- log.Infof("Unmarshaled options: %+v", opts)
err = opts.Validate()
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
-func UseContext(client *Client, message configs.WsMessage) error {
- return ctlconfig.RunUseContext(message.Name, client.Config)
+func UseContext(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
+ }
+
+ 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
}