diff --git a/etc/airshipui.json.example b/etc/airshipui.json.example index 20ad5ac..47d513f 100755 --- a/etc/airshipui.json.example +++ b/etc/airshipui.json.example @@ -1,4 +1,5 @@ { + "airshipConfigPath": "/home/ubuntu/.airship/config", "webservice": { "host": "", "port": , diff --git a/pkg/configs/configs.go b/pkg/configs/configs.go index 14c64cc..9e35ef5 100644 --- a/pkg/configs/configs.go +++ b/pkg/configs/configs.go @@ -38,10 +38,11 @@ var ( // Config basic structure to hold configuration params for Airship UI type Config struct { - WebService *WebService `json:"webservice,omitempty"` - AuthMethod *AuthMethod `json:"authMethod,omitempty"` - Dashboards []Dashboard `json:"dashboards,omitempty"` - Users map[string]string `json:"users,omitempty"` + WebService *WebService `json:"webservice,omitempty"` + AuthMethod *AuthMethod `json:"authMethod,omitempty"` + Dashboards []Dashboard `json:"dashboards,omitempty"` + Users map[string]string `json:"users,omitempty"` + AirshipConfigPath *string `json:"airshipConfigPath,omitempty"` } // AuthMethod structure to hold authentication parameters @@ -241,6 +242,28 @@ func SetUIConfig() error { return checkConfigs() } +// Persist saves the current UIConfig to the airshipui.json config file +func (c *Config) Persist() error { + bytes, err := json.Marshal(UIConfig) + if err != nil { + return err + } + + return ioutil.WriteFile(UIConfigFile, bytes, 0600) +} + +func createDefaultConfigPath() error { + home, err := os.UserHomeDir() + if err != nil { + return err + } + + path := filepath.Join(home, ".airship", "config") + UIConfig.AirshipConfigPath = &path + + return nil +} + // checkConfigs will work its way through the config file, if it exists, and creates defaults where needed func checkConfigs() error { writeFile := false @@ -279,6 +302,14 @@ func checkConfigs() error { } } + if UIConfig.AirshipConfigPath == nil { + writeFile = true + err := createDefaultConfigPath() + if err != nil { + return err + } + } + if writeFile { bytes, err := json.Marshal(UIConfig) if err != nil { diff --git a/pkg/ctl/airshipctl.go b/pkg/ctl/airshipctl.go index 879310c..6d780b0 100644 --- a/pkg/ctl/airshipctl.go +++ b/pkg/ctl/airshipctl.go @@ -26,14 +26,6 @@ import ( "opendev.org/airship/airshipui/pkg/webservice" ) -// AirshipConfigPath location of airship config (default $HOME/.airship.config) -// TODO(mfuller): are we going to retrieve these from the environment / cli options? -// leaving them both unset (nil) for now so that the default locations will be used -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.` @@ -111,7 +103,7 @@ func NewDefaultClient(airshipConfigPath *string) (*Client, error) { } // NewClient initializes the airshipctl client for external usage with the logging overridden. -func NewClient(airshipConfigPath, kubeConfigPath *string, request configs.WsMessage) (*Client, error) { +func NewClient(airshipConfigPath *string, request configs.WsMessage) (*Client, error) { client, err := NewDefaultClient(airshipConfigPath) if err != nil { return nil, err diff --git a/pkg/ctl/baremetal.go b/pkg/ctl/baremetal.go index 42fc030..4d8d1fb 100644 --- a/pkg/ctl/baremetal.go +++ b/pkg/ctl/baremetal.go @@ -111,7 +111,7 @@ func getBaremetalDefaults(request configs.WsMessage) (baremetalData, error) { // getNodeInfo gets and formats the default nodes as defined by the manifest(s) func getNodeInfo(request configs.WsMessage) ([]nodeInfo, error) { - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { log.Error(err) return nil, err @@ -198,7 +198,7 @@ func actionHelper(user *string, target string, phase string, request configs.WsM // create a transaction for this singular request transaction := statistics.NewTransaction(user, response) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, response) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, response) if err != nil { errorHelper(err, transaction, response) return diff --git a/pkg/ctl/config.go b/pkg/ctl/config.go index 94725d6..b1d88de 100644 --- a/pkg/ctl/config.go +++ b/pkg/ctl/config.go @@ -52,8 +52,8 @@ func newResponse(request configs.WsMessage) configs.WsMessage { } } -// 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 +// HandleConfigRequest will find the appropriate subcomponent function in the function map +// and wait for it to complete before returning the response message func HandleConfigRequest(user *string, request configs.WsMessage) configs.WsMessage { var response configs.WsMessage @@ -71,7 +71,12 @@ func HandleConfigRequest(user *string, request configs.WsMessage) configs.WsMess // GetAirshipConfigPath returns value stored in AirshipConfigPath func GetAirshipConfigPath(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - response.Message = AirshipConfigPath + + // leave message empty if the file doesn't exist + if configFileExists(configs.UIConfig.AirshipConfigPath) { + response.Message = configs.UIConfig.AirshipConfigPath + } + return response } @@ -80,9 +85,15 @@ func GetAirshipConfigPath(request configs.WsMessage) configs.WsMessage { func SetAirshipConfig(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - AirshipConfigPath = request.Message + configs.UIConfig.AirshipConfigPath = request.Message + err := configs.UIConfig.Persist() + if err != nil { + e := err.Error() + response.Error = &e + return response + } - msg := fmt.Sprintf("Config file set to '%s'", *AirshipConfigPath) + msg := fmt.Sprintf("Config file set to '%s'", *configs.UIConfig.AirshipConfigPath) response.Message = &msg return response @@ -92,7 +103,7 @@ func SetAirshipConfig(request configs.WsMessage) configs.WsMessage { func GetCurrentContext(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -128,9 +139,16 @@ func InitAirshipConfig(request configs.WsMessage) configs.WsMessage { return response } - AirshipConfigPath = &confPath + configs.UIConfig.AirshipConfigPath = &confPath + // save this location back to airshipui config file so we'll remember it for next time + err = configs.UIConfig.Persist() + if err != nil { + e := err.Error() + response.Error = &e + return response + } - msg := fmt.Sprintf("Config file set to '%s'", *AirshipConfigPath) + msg := fmt.Sprintf("Config file set to '%s'", *configs.UIConfig.AirshipConfigPath) response.Message = &msg @@ -148,7 +166,7 @@ type Context struct { func GetContexts(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -184,7 +202,7 @@ type Manifest struct { func GetManifests(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -216,7 +234,7 @@ type ManagementConfig struct { func GetManagementConfigs(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -254,7 +272,7 @@ type EncryptionConfig struct { func GetEncryptionConfigs(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -281,7 +299,7 @@ func GetEncryptionConfigs(request configs.WsMessage) configs.WsMessage { func SetContext(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -327,7 +345,7 @@ func SetContext(request configs.WsMessage) configs.WsMessage { func SetEncryptionConfig(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -376,7 +394,7 @@ func SetEncryptionConfig(request configs.WsMessage) configs.WsMessage { func SetManagementConfig(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -420,7 +438,7 @@ func SetManagementConfig(request configs.WsMessage) configs.WsMessage { func SetManifest(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -466,7 +484,7 @@ func SetManifest(request configs.WsMessage) configs.WsMessage { func UseContext(request configs.WsMessage) configs.WsMessage { response := newResponse(request) - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e diff --git a/pkg/ctl/document.go b/pkg/ctl/document.go index 6699ac1..ec2b27c 100644 --- a/pkg/ctl/document.go +++ b/pkg/ctl/document.go @@ -33,7 +33,7 @@ func HandleDocumentRequest(user *string, request configs.WsMessage) configs.WsMe var err error var message *string - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -62,7 +62,7 @@ func HandleDocumentRequest(user *string, request configs.WsMessage) configs.WsMe func (c *Client) docPull() (*string, error) { var message *string - cfgFactory := config.CreateFactory(AirshipConfigPath) + cfgFactory := config.CreateFactory(configs.UIConfig.AirshipConfigPath) // 2nd arg is noCheckout, I assume we want to checkout the repo, // so setting to false err := pull.Pull(cfgFactory, false) diff --git a/pkg/ctl/document_test.go b/pkg/ctl/document_test.go index 48de7f3..ac646e3 100644 --- a/pkg/ctl/document_test.go +++ b/pkg/ctl/document_test.go @@ -28,11 +28,8 @@ func TestHandleUnknownDocumentSubComponent(t *testing.T) { SubComponent: "fake_subcomponent", } - acp := "testdata/testairshipconfig" - kcp := "testdata/testkubeconfig" - - AirshipConfigPath = &acp - KubeConfigPath = &kcp + path := "testdata/testairshipconfig" + configs.UIConfig.AirshipConfigPath = &path user := "test" response := HandleDocumentRequest(&user, request) diff --git a/pkg/ctl/image.go b/pkg/ctl/image.go index c8d2b47..075a49b 100644 --- a/pkg/ctl/image.go +++ b/pkg/ctl/image.go @@ -34,7 +34,7 @@ func HandleImageRequest(user *string, request configs.WsMessage) configs.WsMessa var err error var message *string - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e @@ -66,7 +66,7 @@ func HandleImageRequest(user *string, request configs.WsMessage) configs.WsMessa // generate iso now just runs a phase and not an individual command func (c *Client) generateIso() (*string, error) { - cfgFactory := config.CreateFactory(AirshipConfigPath) + cfgFactory := config.CreateFactory(configs.UIConfig.AirshipConfigPath) p := &phase.RunCommand{ Factory: cfgFactory, } diff --git a/pkg/ctl/image_test.go b/pkg/ctl/image_test.go index 5a90724..0285040 100644 --- a/pkg/ctl/image_test.go +++ b/pkg/ctl/image_test.go @@ -28,11 +28,8 @@ func TestHandleUnknownBaremetalSubComponent(t *testing.T) { SubComponent: "fake_subcomponent", } - acp := "testdata/testairshipconfig" - kcp := "testdata/testkubeconfig" - - AirshipConfigPath = &acp - KubeConfigPath = &kcp + path := "testdata/testairshipconfig" + configs.UIConfig.AirshipConfigPath = &path user := "test" response := HandleBaremetalRequest(&user, request) diff --git a/pkg/ctl/phase.go b/pkg/ctl/phase.go index d712f02..d3356cf 100644 --- a/pkg/ctl/phase.go +++ b/pkg/ctl/phase.go @@ -56,7 +56,7 @@ func HandlePhaseRequest(user *string, request configs.WsMessage) configs.WsMessa var message *string var valid bool - client, err := NewClient(AirshipConfigPath, KubeConfigPath, request) + client, err := NewClient(configs.UIConfig.AirshipConfigPath, request) if err != nil { e := err.Error() response.Error = &e diff --git a/pkg/ctl/tree.go b/pkg/ctl/tree.go index 639f163..f97acb8 100644 --- a/pkg/ctl/tree.go +++ b/pkg/ctl/tree.go @@ -26,6 +26,7 @@ import ( "github.com/google/uuid" "opendev.org/airship/airshipctl/pkg/phase" "opendev.org/airship/airshipctl/pkg/phase/ifc" + "opendev.org/airship/airshipui/pkg/configs" "opendev.org/airship/airshipui/pkg/log" "sigs.k8s.io/kustomize/api/types" ) @@ -38,7 +39,7 @@ func getHelper() (ifc.Helper, error) { return helper, nil } - c, err := NewDefaultClient(AirshipConfigPath) + c, err := NewDefaultClient(configs.UIConfig.AirshipConfigPath) if err != nil { return nil, err }