From 29bff23684a29483a781f226398a865a6ff6bdb6 Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 1 Jun 2017 14:39:55 +0530 Subject: [PATCH] Setting configuration at ~/.datacol/config --- api/models/extra.go | 5 +- client/client.go | 23 +------- cmd/logs.go | 4 +- cmd/main.go | 6 -- cmd/provider/gcp/gcp.go | 2 +- cmd/stack.go | 44 +++++++------- cmd/stdcli/apprc.go | 127 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 160 insertions(+), 51 deletions(-) create mode 100644 cmd/stdcli/apprc.go diff --git a/api/models/extra.go b/api/models/extra.go index 2ed146a4..90212e9e 100644 --- a/api/models/extra.go +++ b/api/models/extra.go @@ -8,8 +8,8 @@ import ( ) var ( - ConfigPath string - SvaFilename = "sva.json" + ConfigPath, ApprcPath string + SvaFilename = "sva.json" ) func init() { @@ -18,6 +18,7 @@ func init() { log.Fatal(err) } ConfigPath = filepath.Join(home, ".datacol") + ApprcPath = filepath.Join(ConfigPath, "config.json") } type Environment map[string]string diff --git a/client/client.go b/client/client.go index 64205895..b4a5d0fb 100644 --- a/client/client.go +++ b/client/client.go @@ -4,7 +4,6 @@ import ( "fmt" log "github.com/Sirupsen/logrus" "os" - "path/filepath" "strings" "github.com/appscode/go/io" @@ -35,32 +34,16 @@ type Client struct { pb.ProviderServiceClient } -func (c *Client) SetFromEnv() { - c.SetStack(stdcli.GetAppStack()) -} - func NewClient(version string) (*Client, func() error) { - name := stdcli.GetAppStack() - - v, err := io.ReadFile(filepath.Join(models.ConfigPath, name, "api_host")) - if err != nil { - log.Fatal(err) - } - host := strings.TrimSpace(v) - - p, err := io.ReadFile(filepath.Join(models.ConfigPath, name, "api_key")) - if err != nil { - log.Fatal(err) - } - password := strings.TrimSpace(p) + auth, _ := stdcli.GetAuthOrDie() - psc, close := GrpcClient(host, password) + psc, close := GrpcClient(auth.ApiServer, auth.ApiKey) conn := &Client{ Version: version, ProviderServiceClient: psc, } - conn.SetStack(name) + conn.SetStack(fmt.Sprintf("%s@%s", auth.Name, auth.Project)) return conn, close } diff --git a/cmd/logs.go b/cmd/logs.go index 0849a120..630f6e40 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -14,9 +14,9 @@ func init() { Action: cmdAppLogStream, Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "follow", + Name: "follow", Aliases: []string{"f"}, - Usage: "keep streaming new log output (default)", + Usage: "keep streaming new log output (default)", }, &cli.DurationFlag{ Name: "since", diff --git a/cmd/main.go b/cmd/main.go index 2fc6f237..9a84d3e0 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -50,12 +50,6 @@ func main() { app.Run(os.Args) } -func getClient(c *cli.Context) *client.Client { - conn := &client.Client{Version: c.App.Version} - conn.SetFromEnv() - return conn -} - func getApiClient(c *cli.Context) (*client.Client, func() error) { return client.NewClient(c.App.Version) } diff --git a/cmd/provider/gcp/gcp.go b/cmd/provider/gcp/gcp.go index 1002d785..7569666c 100644 --- a/cmd/provider/gcp/gcp.go +++ b/cmd/provider/gcp/gcp.go @@ -168,7 +168,7 @@ func TeardownStack(name, project, bucket string) error { gsService := storageService(name) resp, err := gsService.Objects.List(bucket).Do() if err != nil { - return err + return fmt.Errorf("listing items inside bucket err: %v", err) } for _, obj := range resp.Items { diff --git a/cmd/stack.go b/cmd/stack.go index 152cba6e..0adefc12 100644 --- a/cmd/stack.go +++ b/cmd/stack.go @@ -166,8 +166,13 @@ func initialize(opts *gcp.InitOptions, nodes int, optout bool) error { opts.ClusterNotExists = false } - apis := []string{"datastore.googleapis.com", "cloudbuild.googleapis.com", - "deploymentmanager", "iam.googleapis.com"} + apis := []string{ + "datastore.googleapis.com", + "cloudbuild.googleapis.com", + "deploymentmanager", + "iam.googleapis.com", + } + url := fmt.Sprintf("https://console.cloud.google.com/flows/enableapi?apiid=%s&project=%s", strings.Join(apis, ","), opts.Project) fmt.Printf("\nDatacol needs to communicate with various APIs provided by cloud platform, please enable APIs by opening following link in browser and click Continue: \n%s\n", url) @@ -180,33 +185,27 @@ func initialize(opts *gcp.InitOptions, nodes int, optout bool) error { fmt.Printf("\nStack hostIP %s\n", res.Host) fmt.Printf("Stack password: %s [Please keep is secret]\n", res.Password) + fmt.Println("The above configuration has been saved in your home directory at ~/.datacol/config.json") return dumpParams(opts.Name, opts.Project, opts.Bucket, res.Host, res.Password) } func teardown() error { - name := stdcli.CurrentStack() - project := stdcli.ReadSetting(name, "project") - bucket := stdcli.ReadSetting(name, "bucket") + auth, rc := stdcli.GetAuthOrDie() + if err := gcp.TeardownStack(auth.Name, auth.Project, auth.Bucket); err != nil { + return err + } - if err := gcp.TeardownStack(name, project, bucket); err != nil { + if err := rc.DeleteAuth(); err != nil { return err } - os.Remove(filepath.Join(pb.ConfigPath, "stack")) - return os.RemoveAll(filepath.Join(pb.ConfigPath, name)) + return os.RemoveAll(filepath.Join(pb.ConfigPath, auth.Name)) } func createStackDir(name string) error { cfgroot := filepath.Join(pb.ConfigPath, name) - if err := os.MkdirAll(cfgroot, 0700); err != nil { - return err - } - - if err := ioutil.WriteFile(filepath.Join(pb.ConfigPath, "stack"), []byte(name), 0700); err != nil { - return err - } - return nil + return os.MkdirAll(cfgroot, 0700) } func saveCredential(name string, data []byte) error { @@ -220,8 +219,13 @@ func saveCredential(name string, data []byte) error { } func dumpParams(name, project, bucket, host, api_key string) error { - stdcli.WriteSetting(name, "project", project) - stdcli.WriteSetting(name, "api_key", api_key) - stdcli.WriteSetting(name, "api_host", host) - return stdcli.WriteSetting(name, "bucket", bucket) + auth := &stdcli.Auth{ + Name: name, + Project: project, + Bucket: bucket, + ApiServer: host, + ApiKey: api_key, + } + + return stdcli.SetAuth(auth) } diff --git a/cmd/stdcli/apprc.go b/cmd/stdcli/apprc.go new file mode 100644 index 00000000..9122e653 --- /dev/null +++ b/cmd/stdcli/apprc.go @@ -0,0 +1,127 @@ +package stdcli + +import ( + "os" + "github.com/appscode/go/io" + pb "github.com/dinesh/datacol/api/models" + term "github.com/appscode/go-term" +) + +var apprcPath string + +func init() { + apprcPath = pb.ApprcPath +} + +type Auth struct { + Name string `json:"name,omitempty"` + ApiServer string `json:"api_server,omitempty"` + ApiKey string `json:"api_key,omitempty"` + Project string `json:"project,omitempty"` + Bucket string `json:"bucket,omitempty"` +} + +type Apprc struct { + Context string `json:"context,omitempty"` + Auths []*Auth `json:"auths,omitempty"` +} + +func (rc *Apprc) GetAuth() *Auth { + if rc.Context != "" { + for _, a := range rc.Auths { + if a.Name == rc.Context { + return a + } + } + } + return nil +} + +func (rc *Apprc) SetAuth(a *Auth) error { + for i, b := range rc.Auths { + if b.Name == a.Name { + rc.Auths = append(rc.Auths[:i], rc.Auths[i+1:]...) + break + } + } + rc.Context = a.Name + rc.Auths = append(rc.Auths, a) + return rc.Write() +} + +func (rc *Apprc) DeleteAuth() error { + if rc.Context != "" { + for i, a := range rc.Auths { + if a.Name == rc.Context { + rc.Auths = append(rc.Auths[:i], rc.Auths[i+1:]...) + rc.Context = "" + break + } + } + } + return rc.Write() +} + +func (rc *Apprc) Write() error { + err := io.WriteJson(apprcPath, rc) + if err != nil { + return err + } + os.Chmod(apprcPath, 0600) + return nil +} + +func LoadApprc() (*Apprc, error) { + if _, err := os.Stat(apprcPath); err != nil { + return nil, err + } + + os.Chmod(apprcPath, 0600) + rc := &Apprc{} + err := io.ReadFileAs(apprcPath, rc) + if err != nil { + return nil, err + } + return rc, nil +} + +/* Exits if there is any error.*/ +func GetAuthOrDie() (*Auth, *Apprc) { + rc, err := LoadApprc() + if err != nil { + term.Fatalln("Command requires authentication, please run `datacol login`") + } + a := rc.GetAuth() + if a == nil { + term.Fatalln("Command requires authentication, please run `datacol login`") + } + return a, rc +} + +/* Exits if there is any error.*/ +func GetAuthOrAnon() (*Auth, bool) { + rc, err := LoadApprc() + if err != nil { + return NewAnonAUth(), false + } + a := rc.GetAuth() + if a == nil { + return NewAnonAUth(), false + } + return a, true +} + +func SetAuth(a *Auth) error { + rc, err := LoadApprc() + if err != nil { + rc = &Apprc{} + rc.Auths = make([]*Auth, 0) + } + return rc.SetAuth(a) +} + +func NewAnonAUth() *Auth { + a := &Auth{ApiServer: "localhost"} + return a +} +