From ceb547d05cc7461bedc93dbdf4f3720367137c3e Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Sun, 10 Sep 2017 23:11:26 +0100 Subject: [PATCH 1/7] Add function GetLatestImage --- client/client.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client/client.go b/client/client.go index 7d468c54..c549f9e6 100644 --- a/client/client.go +++ b/client/client.go @@ -3,6 +3,7 @@ package client import ( "bytes" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -69,6 +70,22 @@ func (c Client) delete(url string) (*http.Response, error) { return http.DefaultClient.Do(req) } +func (c Client) GetLatestImage() (models.Image, error) { + var image models.Image + images, err := c.ListImages() + + if err != nil { + fmt.Printf("error: %s\n", err) + return image, err + } + + if len(images) > 0 { + return images[len(images)-1], nil + } + + return image, errors.New("no images available") +} + func (c Client) GetImage(id string) (models.Image, error) { var image models.Image resp, err := c.get(c.URL + "/images/" + id) From a571773d2343a8e5fd3cf8d206b779620545a49d Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Sun, 10 Sep 2017 23:12:05 +0100 Subject: [PATCH 2/7] Make instance create command use latest image by default Before this commit, `instance create` took an `` as the last argument. This introduces a default of `` if nothing is passed as an argument to `instance create`. This should make the usage of the command slightly more friendly to shells. --- cli/main.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cli/main.go b/cli/main.go index dd74cc3d..6c6e46ae 100644 --- a/cli/main.go +++ b/cli/main.go @@ -120,16 +120,23 @@ func main() { Name: "create", Usage: "create a new instance", Action: func(c *cli.Context) error { - id := c.Args().First() - if id == "" { - fmt.Println("error: must supply an image id") - return nil - } - - image, err := client.GetImage(id) - if err != nil { - fmt.Printf("error: %s\n", err) - return err + var image models.Image + if c.NArg() == 0 { + image, err = client.GetLatestImage() + if err != nil { + return err + } + } else { + id := c.Args().First() + if id == "" { + fmt.Println("error: must supply an image id") + return nil + } + image, err = client.GetImage(id) + if err != nil { + fmt.Printf("error: %s\n", err) + return err + } } instance, err := client.CreateInstance(image) @@ -138,7 +145,7 @@ func main() { return err } - fmt.Println("Created") + fmt.Printf("Created with image ID: %d\n", image.ID) fmt.Println(InstanceToString(instance)) return nil }, From 34a465c99247afab295d01bf272139348cc5aea9 Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Sun, 10 Sep 2017 23:28:03 +0100 Subject: [PATCH 3/7] Add auto command to facilitate shell use cases Instead of needing to call multiple commands to - create instance from image - finding instance ID returned - printing environment for instance returned after this commit one only needs to - `eval $(./draupnir-client auto) && psql` to get a new instance sql prompt. --- cli/main.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/cli/main.go b/cli/main.go index 6c6e46ae..334d5969 100644 --- a/cli/main.go +++ b/cli/main.go @@ -244,8 +244,28 @@ func main() { return err } - fmt.Printf("export PGHOST=%s PGPORT=%d PGUSER=postgres PGPASSWORD=''\n", CONFIG.Domain, instance.Port) + showExportCommand(CONFIG, instance) + return nil + }, + }, + { + Name: "auto", + Aliases: []string{}, + Usage: "show the environment variables to a newly created instance", + Action: func(c *cli.Context) error { + image, err := client.GetLatestImage() + if err != nil { + fmt.Printf("error: %s\n", err) + return err + } + + instance, err := client.CreateInstance(image) + if err != nil { + fmt.Printf("error: %s\n", err) + return err + } + showExportCommand(CONFIG, instance) return nil }, }, @@ -254,6 +274,10 @@ func main() { app.Run(os.Args) } +func showExportCommand(config Config, instance models.Instance) { + fmt.Printf("export PGHOST=%s PGPORT=%d PGUSER=postgres PGPASSWORD=''\n", config.Domain, instance.Port) +} + func ImageToString(i models.Image) string { return fmt.Sprintf("%d [ %s - READY: %5t ]", i.ID, i.BackedUpAt.Format(time.RFC3339), i.Ready) } From 7b1534866da17c374a0524b1ed0d0c73805a7cff Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Sun, 10 Sep 2017 23:58:25 +0100 Subject: [PATCH 4/7] Better conditionals in create instance --- cli/main.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/cli/main.go b/cli/main.go index 334d5969..94b00f68 100644 --- a/cli/main.go +++ b/cli/main.go @@ -121,22 +121,16 @@ func main() { Usage: "create a new instance", Action: func(c *cli.Context) error { var image models.Image + if c.NArg() == 0 { image, err = client.GetLatestImage() - if err != nil { - return err - } } else { - id := c.Args().First() - if id == "" { - fmt.Println("error: must supply an image id") - return nil - } - image, err = client.GetImage(id) - if err != nil { - fmt.Printf("error: %s\n", err) - return err - } + image, err = client.GetImage(c.Args().First()) + } + + if err != nil { + fmt.Printf("error: %s\n", err) + return err } instance, err := client.CreateInstance(image) From c9feef49c4c4a76d83658fec7c7af2f7c383ec2c Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Mon, 11 Sep 2017 00:02:56 +0100 Subject: [PATCH 5/7] Filter images in Ready state when finding latest image --- client/client.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index c549f9e6..b898957a 100644 --- a/client/client.go +++ b/client/client.go @@ -80,7 +80,11 @@ func (c Client) GetLatestImage() (models.Image, error) { } if len(images) > 0 { - return images[len(images)-1], nil + for i := len(images) - 1; i >= 0; i-- { + if images[i].Ready { + return images[i], nil + } + } } return image, errors.New("no images available") From 70ae8d2736732511b2c01b694bd6407f680fe83e Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Mon, 11 Sep 2017 09:05:09 +0100 Subject: [PATCH 6/7] Sort images by UpdatedAt before finding latest --- client/client.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/client.go b/client/client.go index b898957a..e41e140d 100644 --- a/client/client.go +++ b/client/client.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "reflect" + "sort" "strconv" "strings" @@ -79,11 +80,15 @@ func (c Client) GetLatestImage() (models.Image, error) { return image, err } - if len(images) > 0 { - for i := len(images) - 1; i >= 0; i-- { - if images[i].Ready { - return images[i], nil - } + // Make sure they are all sorted by UpdatedAt + // The most up to date should be the first of the slice + sort.Slice(images, func(i, j int) bool { + return images[i].UpdatedAt.After(images[j].UpdatedAt) + }) + + for _, image := range images { + if image.Ready { + return image, nil } } From 3550b57d890c76cdaf8f64d5d8e5e5fdc4ee6f14 Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Mon, 11 Sep 2017 09:08:28 +0100 Subject: [PATCH 7/7] Change auto to new --- cli/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/main.go b/cli/main.go index 94b00f68..ddee4492 100644 --- a/cli/main.go +++ b/cli/main.go @@ -243,7 +243,7 @@ func main() { }, }, { - Name: "auto", + Name: "new", Aliases: []string{}, Usage: "show the environment variables to a newly created instance", Action: func(c *cli.Context) error {