From 42f3eef911076aedc9c59289755affdc07bc124f Mon Sep 17 00:00:00 2001 From: Karl Date: Wed, 11 Jun 2025 23:24:33 +1000 Subject: [PATCH 01/12] addkey should add the key to the config Signed-off-by: Karl --- external/docker/commands/addkey.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/external/docker/commands/addkey.go b/external/docker/commands/addkey.go index 7be1455b..e43b36f4 100644 --- a/external/docker/commands/addkey.go +++ b/external/docker/commands/addkey.go @@ -7,6 +7,7 @@ import ( "strings" . "github.com/logrusorgru/aurora" + "github.com/spf13/viper" "github.com/pygmystack/pygmy/external/docker/setup" "github.com/pygmystack/pygmy/internal/runtime/docker/internals" @@ -94,7 +95,20 @@ func SshKeyAdd(c setup.Config, key string) error { } _ = Container.Remove(ctx, cli) + writeKeys := []setup.Key{ + { + Path: key, + }, + } + + for _, key := range c.Keys { + if key.Path != writeKeys[0].Path { + writeKeys = append(writeKeys, key) + } + } + viper.Set("keys", writeKeys) + viper.WriteConfig() } } From 286f2b3f1397021128e17e9e88aed80f0208b8e3 Mon Sep 17 00:00:00 2001 From: Karl Date: Wed, 11 Jun 2025 23:31:42 +1000 Subject: [PATCH 02/12] error checking for config writes Signed-off-by: Karl --- external/docker/commands/addkey.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/external/docker/commands/addkey.go b/external/docker/commands/addkey.go index e43b36f4..3812b5db 100644 --- a/external/docker/commands/addkey.go +++ b/external/docker/commands/addkey.go @@ -108,7 +108,10 @@ func SshKeyAdd(c setup.Config, key string) error { } viper.Set("keys", writeKeys) - viper.WriteConfig() + err = viper.WriteConfig() + if err != nil { + return err + } } } From f3a84be0ee435a6f714312da85f7b3c73b728fec Mon Sep 17 00:00:00 2001 From: Karl Date: Wed, 11 Jun 2025 23:38:14 +1000 Subject: [PATCH 03/12] remove brews from goreleaser config Signed-off-by: Karl --- .goreleaser.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 19e0b999..0afc694f 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -49,17 +49,3 @@ builds: snapshot: version_template: "{{ .Version }}-SNAPSHOT-{{.ShortCommit}}" - -brews: - - ids: - - pygmy - repository: - owner: pygmystack - name: homebrew-pygmy - branch: main - token: "${{ .Env.GITHUB_TOKEN }}" - homepage: "https://github.com/pygmystack/pygmy" - description: "amazee.io's local development helper tool" - skip_upload: false - test: system "#{bin}/pygmy version" - install: bin.install "pygmy" \ No newline at end of file From af454fcc865ca53b43a4c36af1d995eac4e4be8f Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:12:54 +1000 Subject: [PATCH 04/12] Remove default keys; url validation Signed-off-by: Karl --- cmd/status.go | 2 -- cmd/up.go | 9 ++--- external/docker/commands/status.go | 57 ++++++++++++++++++++++++++---- external/docker/commands/up.go | 30 +++++++++++++--- 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/cmd/status.go b/cmd/status.go index 28fe2a50..81c3fba5 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -22,7 +22,6 @@ package cmd import ( "fmt" - "github.com/spf13/cobra" "github.com/pygmystack/pygmy/external/docker/commands" @@ -48,7 +47,6 @@ This includes the docker services, the resolver and SSH key status`, if err != nil { fmt.Println(err) } - commands.Status(ctx, cli, c) }, diff --git a/cmd/up.go b/cmd/up.go index f51abd25..de8dab62 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -22,9 +22,6 @@ package cmd import ( "fmt" - "os" - - "github.com/mitchellh/go-homedir" "github.com/pygmystack/pygmy/external/docker/commands" "github.com/pygmystack/pygmy/external/docker/setup" "github.com/spf13/cobra" @@ -79,11 +76,9 @@ It includes dnsmasq, haproxy, mailhog, resolv and ssh-agent.`, func init() { - homedir, _ := homedir.Dir() - keypath := fmt.Sprintf("%v%v.ssh%vid_rsa", homedir, string(os.PathSeparator), string(os.PathSeparator)) - rootCmd.AddCommand(upCmd) - upCmd.Flags().StringP("key", "", keypath, "Path of SSH key to add") + upCmd.Flags().StringP("key", "", "", "Path of SSH key to add") upCmd.Flags().BoolP("no-addkey", "", false, "Skip adding the SSH key") upCmd.Flags().BoolP("no-resolver", "", false, "Skip adding or removing the Resolver") + upCmd.Flags().BoolVarP(&debugFlag, "debug", "", false, "Debug mode") } diff --git a/external/docker/commands/status.go b/external/docker/commands/status.go index e3729010..343dc4a4 100644 --- a/external/docker/commands/status.go +++ b/external/docker/commands/status.go @@ -4,6 +4,9 @@ import ( "context" "encoding/json" "fmt" + "net" + urltools "net/url" + "os" "strings" "github.com/docker/docker/client" @@ -48,6 +51,7 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { agentPresent = true } if enabled && !discrete && name != "" { + start(c.Debug, fmt.Sprintf("Checking Service for SSH Role: %s", Container.Names[0])) if s, _ := Service.Status(ctx, cli); s { c.JSONStatus.Services[name] = setup.StatusJSONStatus{ Container: name, @@ -60,13 +64,15 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { ImageRef: Service.Image, } } + finish(c.Debug, fmt.Sprintf("Checking Service for SSH Role: %s", Container.Names[0])) } } } } } - for _, Service := range c.Services { + for n, Service := range c.Services { + start(c.Debug, fmt.Sprintf("Checking Service Status: %s", n)) if s, _ := Service.Status(ctx, cli); !s { name, _ := Service.GetFieldString(ctx, cli, "name") discrete, _ := Service.GetFieldBool(ctx, cli, "discrete") @@ -77,38 +83,48 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { } } } + finish(c.Debug, fmt.Sprintf("Checking Service Status: %s", n)) } for _, Network := range c.Networks { + start(c.Debug, fmt.Sprintf("Checking Network Connection: %s", Network.Name)) for _, Container := range Network.Containers { + start(c.Debug, fmt.Sprintf("Checking Network Connection Status: %s", Container.Name)) if x, _ := networks.Connected(ctx, cli, Network.Name, Container.Name); !x { c.JSONStatus.Networks = append(c.JSONStatus.Networks, fmt.Sprintf("%s is not connected to the network %s", Container.Name, Network.Name)) } else { c.JSONStatus.Networks = append(c.JSONStatus.Networks, fmt.Sprintf("%s is connected to the network %s", Container.Name, Network.Name)) } + finish(c.Debug, fmt.Sprintf("Checking Network Connection Status: %s", Container.Name)) } + finish(c.Debug, fmt.Sprintf("Checking Network Connection: %s", Network.Name)) } for _, resolver := range c.Resolvers { + start(c.Debug, fmt.Sprintf("Checking Resolver Status: %s", resolver.Name)) r := resolv.Resolv{Name: resolver.Name, Data: resolver.Data, Folder: resolver.Folder, File: resolver.File} if s := r.Status(&docker.Params{Domain: c.Domain}); s { c.JSONStatus.Resolvers = append(c.JSONStatus.Resolvers, fmt.Sprintf("Resolv %s is properly connected", resolver.Name)) } else { c.JSONStatus.Resolvers = append(c.JSONStatus.Resolvers, fmt.Sprintf("Resolv %s is not properly connected", resolver.Name)) } + finish(c.Debug, fmt.Sprintf("Checking Resolver Status: %s", resolver.Name)) } for _, volume := range c.Volumes { + start(c.Debug, fmt.Sprintf("Checking Volume Status: %s", volume.Name)) if s, _ := volumes.Exists(ctx, cli, volume.Name); s { c.JSONStatus.Volumes = append(c.JSONStatus.Volumes, fmt.Sprintf("Volume %s has been created", volume.Name)) } else { c.JSONStatus.Volumes = append(c.JSONStatus.Volumes, fmt.Sprintf("Volume %s has not been created", volume.Name)) } + finish(c.Debug, fmt.Sprintf("Checking Volume Status: %s", volume.Name)) } // Show ssh-keys in the agent if agentPresent { for _, v := range c.Services { + start(c.Debug, fmt.Sprintf("Checking for SSH Agent: %s", v.Config.Labels["pygmy.name"])) purpose, _ := v.GetFieldString(ctx, cli, "purpose") if purpose == "sshagent" { l, _ := runtimecontainers.Exec(ctx, cli, v.Config.Labels["pygmy.name"], "ssh-add -l") @@ -118,6 +134,7 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { output = strings.Trim(output, "\n") c.JSONStatus.SSHMessages = append(c.JSONStatus.SSHMessages, output) } + finish(c.Debug, fmt.Sprintf("Checking for SSH Agent: %s", v.Config.Labels["pygmy.name"])) } } @@ -127,8 +144,18 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { for _, Container := range c.Services { Status, _ := Container.Status(ctx, cli) url, _ := Container.GetFieldString(ctx, cli, "url") - if url != "" && Status { - urls = append(urls, url) + + cleanUrl, err := urltools.Parse(url) + if err != nil { + fmt.Println(err.Error()) + continue + } + if Status { + if strings.Contains(cleanUrl.String(), "docker.amazee.io") { + finalUrl := strings.Trim(cleanUrl.String(), "[]") + fmt.Printf("Added %s\n", finalUrl) + urls = append(urls, finalUrl) + } } } @@ -147,15 +174,31 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { urls = append(urls, url) } } + } else { + finish(c.Debug, fmt.Sprintf("Not a Pygmy Container: %s", container.ID)) } + finish(c.Debug, fmt.Sprintf("Inspecting Container Status: %s", container.ID)) } cleanurls := setup.Unique(urls) for _, url := range cleanurls { - result := endpoint.Validate(url) + start(c.Debug, fmt.Sprintf("Validating Endpoint: %s", url)) + + cleanUrl, err := urltools.Parse(url) + if err != nil { + fmt.Println(err.Error()) + continue + } + if os.Getenv("PYGMY_WEB_PORT") != "" { + cleanUrl.Host = net.JoinHostPort(cleanUrl.Host, os.Getenv("PYGMY_WEB_PORT")) + } + finalUrl := strings.Trim(cleanUrl.String(), "[]") + + result, statuscode := endpoint.Validate(finalUrl) c.JSONStatus.URLValidations = append(c.JSONStatus.URLValidations, setup.StatusJSONURLValidation{ - Endpoint: url, - Success: result, + Endpoint: finalUrl, + Success: result, + StatusCode: statuscode, }) } @@ -222,7 +265,7 @@ func PrintStatusHumanReadable(c setup.Config) { if v.Success { fmt.Printf(" - %s\n", v.Endpoint) } else { - fmt.Printf(" ! %s\n", v.Endpoint) + fmt.Printf(" ! %s (Status Code %v)\n", v.Endpoint, v.StatusCode) } } diff --git a/external/docker/commands/up.go b/external/docker/commands/up.go index b6c1a895..29b45d6e 100644 --- a/external/docker/commands/up.go +++ b/external/docker/commands/up.go @@ -1,7 +1,10 @@ package commands import ( + "errors" "fmt" + "net" + urltools "net/url" "os" "strings" @@ -69,6 +72,7 @@ func Up(c setup.Config) error { if se := service.Setup(ctx, cli); se == nil { fmt.Print(Green(fmt.Sprintf("Successfully pulled %s\n", service.Config.Image))) } + if status, _ := service.Status(ctx, cli); !status { if ce := service.Create(ctx, cli); ce != nil { // If the status is false but the container is already created, we can ignore that error. @@ -76,6 +80,7 @@ func Up(c setup.Config) error { fmt.Printf("Failed to create %s: %s\n", Red(name), ce) } } + if se := service.Start(ctx, cli); se == nil { fmt.Print(Green(fmt.Sprintf("Successfully started %s\n", name))) } else { @@ -136,8 +141,15 @@ func Up(c setup.Config) error { // Add ssh-keys to the agent if agentPresent { for _, v := range c.Keys { - if e := SshKeyAdd(c, v.Path); e != nil { - color.Print(Red(fmt.Sprintf("%v\n", e))) + if v.Path != "" { + _, err := os.Stat(v.Path) + if !errors.Is(err, os.ErrNotExist) { + if e := SshKeyAdd(c, v.Path); e != nil { + color.Print(Red(fmt.Sprintf("%v\n", e))) + } + } else { + color.Print(Red(fmt.Sprintf("Unable to add SSH key '%s': does not exist\n", v.Path))) + } } } } @@ -166,10 +178,18 @@ func Up(c setup.Config) error { // Look for the environment variable $LAGOON_ROUTE. if strings.Contains(v, "LAGOON_ROUTE=") { url := strings.TrimPrefix(v, "LAGOON_ROUTE=") - if !strings.HasPrefix(url, "http") && !strings.HasPrefix(url, "https") { - url = "http://" + url + cleanUrl, err := urltools.Parse(url) + if err != nil { + fmt.Println(err.Error()) + continue + } + if os.Getenv("PYGMY_WEB_PORT") != "" { + cleanUrl.Host = net.JoinHostPort(cleanUrl.Host, os.Getenv("PYGMY_WEB_PORT")) + } + if strings.Contains(cleanUrl.String(), "docker.amazee.io") { + finalUrl := strings.Trim(cleanUrl.String(), "[]") + urls = append(urls, finalUrl) } - urls = append(urls, url) } } } From 256200075b04822ff014d0cea7ba048468b089bb Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:18:54 +1000 Subject: [PATCH 05/12] update Signed-off-by: Karl --- external/docker/commands/status.go | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/external/docker/commands/status.go b/external/docker/commands/status.go index 343dc4a4..b54568ab 100644 --- a/external/docker/commands/status.go +++ b/external/docker/commands/status.go @@ -72,7 +72,6 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { } for n, Service := range c.Services { - start(c.Debug, fmt.Sprintf("Checking Service Status: %s", n)) if s, _ := Service.Status(ctx, cli); !s { name, _ := Service.GetFieldString(ctx, cli, "name") discrete, _ := Service.GetFieldBool(ctx, cli, "discrete") @@ -83,48 +82,38 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { } } } - finish(c.Debug, fmt.Sprintf("Checking Service Status: %s", n)) } for _, Network := range c.Networks { - start(c.Debug, fmt.Sprintf("Checking Network Connection: %s", Network.Name)) for _, Container := range Network.Containers { - start(c.Debug, fmt.Sprintf("Checking Network Connection Status: %s", Container.Name)) if x, _ := networks.Connected(ctx, cli, Network.Name, Container.Name); !x { c.JSONStatus.Networks = append(c.JSONStatus.Networks, fmt.Sprintf("%s is not connected to the network %s", Container.Name, Network.Name)) } else { c.JSONStatus.Networks = append(c.JSONStatus.Networks, fmt.Sprintf("%s is connected to the network %s", Container.Name, Network.Name)) } - finish(c.Debug, fmt.Sprintf("Checking Network Connection Status: %s", Container.Name)) } - finish(c.Debug, fmt.Sprintf("Checking Network Connection: %s", Network.Name)) } for _, resolver := range c.Resolvers { - start(c.Debug, fmt.Sprintf("Checking Resolver Status: %s", resolver.Name)) r := resolv.Resolv{Name: resolver.Name, Data: resolver.Data, Folder: resolver.Folder, File: resolver.File} if s := r.Status(&docker.Params{Domain: c.Domain}); s { c.JSONStatus.Resolvers = append(c.JSONStatus.Resolvers, fmt.Sprintf("Resolv %s is properly connected", resolver.Name)) } else { c.JSONStatus.Resolvers = append(c.JSONStatus.Resolvers, fmt.Sprintf("Resolv %s is not properly connected", resolver.Name)) } - finish(c.Debug, fmt.Sprintf("Checking Resolver Status: %s", resolver.Name)) } for _, volume := range c.Volumes { - start(c.Debug, fmt.Sprintf("Checking Volume Status: %s", volume.Name)) if s, _ := volumes.Exists(ctx, cli, volume.Name); s { c.JSONStatus.Volumes = append(c.JSONStatus.Volumes, fmt.Sprintf("Volume %s has been created", volume.Name)) } else { c.JSONStatus.Volumes = append(c.JSONStatus.Volumes, fmt.Sprintf("Volume %s has not been created", volume.Name)) } - finish(c.Debug, fmt.Sprintf("Checking Volume Status: %s", volume.Name)) } // Show ssh-keys in the agent if agentPresent { for _, v := range c.Services { - start(c.Debug, fmt.Sprintf("Checking for SSH Agent: %s", v.Config.Labels["pygmy.name"])) purpose, _ := v.GetFieldString(ctx, cli, "purpose") if purpose == "sshagent" { l, _ := runtimecontainers.Exec(ctx, cli, v.Config.Labels["pygmy.name"], "ssh-add -l") @@ -134,7 +123,6 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { output = strings.Trim(output, "\n") c.JSONStatus.SSHMessages = append(c.JSONStatus.SSHMessages, output) } - finish(c.Debug, fmt.Sprintf("Checking for SSH Agent: %s", v.Config.Labels["pygmy.name"])) } } @@ -174,15 +162,11 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { urls = append(urls, url) } } - } else { - finish(c.Debug, fmt.Sprintf("Not a Pygmy Container: %s", container.ID)) } - finish(c.Debug, fmt.Sprintf("Inspecting Container Status: %s", container.ID)) } cleanurls := setup.Unique(urls) for _, url := range cleanurls { - start(c.Debug, fmt.Sprintf("Validating Endpoint: %s", url)) cleanUrl, err := urltools.Parse(url) if err != nil { @@ -194,11 +178,10 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { } finalUrl := strings.Trim(cleanUrl.String(), "[]") - result, statuscode := endpoint.Validate(finalUrl) + result := endpoint.Validate(finalUrl) c.JSONStatus.URLValidations = append(c.JSONStatus.URLValidations, setup.StatusJSONURLValidation{ - Endpoint: finalUrl, - Success: result, - StatusCode: statuscode, + Endpoint: finalUrl, + Success: result, }) } @@ -265,7 +248,7 @@ func PrintStatusHumanReadable(c setup.Config) { if v.Success { fmt.Printf(" - %s\n", v.Endpoint) } else { - fmt.Printf(" ! %s (Status Code %v)\n", v.Endpoint, v.StatusCode) + fmt.Printf(" ! %s\n", v.Endpoint) } } From 87214816eaa7a4d6381dc27ec98e8ba914151aa8 Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:21:26 +1000 Subject: [PATCH 06/12] update Signed-off-by: Karl --- cmd/status.go | 3 ++- cmd/up.go | 2 +- external/docker/commands/status.go | 4 +--- external/docker/commands/up.go | 2 -- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/cmd/status.go b/cmd/status.go index 81c3fba5..a4dabd7c 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -22,6 +22,7 @@ package cmd import ( "fmt" + "github.com/spf13/cobra" "github.com/pygmystack/pygmy/external/docker/commands" @@ -47,8 +48,8 @@ This includes the docker services, the resolver and SSH key status`, if err != nil { fmt.Println(err) } - commands.Status(ctx, cli, c) + commands.Status(ctx, cli, c) }, } diff --git a/cmd/up.go b/cmd/up.go index de8dab62..94034051 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -22,6 +22,7 @@ package cmd import ( "fmt" + "github.com/pygmystack/pygmy/external/docker/commands" "github.com/pygmystack/pygmy/external/docker/setup" "github.com/spf13/cobra" @@ -80,5 +81,4 @@ func init() { upCmd.Flags().StringP("key", "", "", "Path of SSH key to add") upCmd.Flags().BoolP("no-addkey", "", false, "Skip adding the SSH key") upCmd.Flags().BoolP("no-resolver", "", false, "Skip adding or removing the Resolver") - upCmd.Flags().BoolVarP(&debugFlag, "debug", "", false, "Debug mode") } diff --git a/external/docker/commands/status.go b/external/docker/commands/status.go index b54568ab..daac5701 100644 --- a/external/docker/commands/status.go +++ b/external/docker/commands/status.go @@ -51,7 +51,6 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { agentPresent = true } if enabled && !discrete && name != "" { - start(c.Debug, fmt.Sprintf("Checking Service for SSH Role: %s", Container.Names[0])) if s, _ := Service.Status(ctx, cli); s { c.JSONStatus.Services[name] = setup.StatusJSONStatus{ Container: name, @@ -64,14 +63,13 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { ImageRef: Service.Image, } } - finish(c.Debug, fmt.Sprintf("Checking Service for SSH Role: %s", Container.Names[0])) } } } } } - for n, Service := range c.Services { + for _, Service := range c.Services { if s, _ := Service.Status(ctx, cli); !s { name, _ := Service.GetFieldString(ctx, cli, "name") discrete, _ := Service.GetFieldBool(ctx, cli, "discrete") diff --git a/external/docker/commands/up.go b/external/docker/commands/up.go index 29b45d6e..8f34abbb 100644 --- a/external/docker/commands/up.go +++ b/external/docker/commands/up.go @@ -72,7 +72,6 @@ func Up(c setup.Config) error { if se := service.Setup(ctx, cli); se == nil { fmt.Print(Green(fmt.Sprintf("Successfully pulled %s\n", service.Config.Image))) } - if status, _ := service.Status(ctx, cli); !status { if ce := service.Create(ctx, cli); ce != nil { // If the status is false but the container is already created, we can ignore that error. @@ -80,7 +79,6 @@ func Up(c setup.Config) error { fmt.Printf("Failed to create %s: %s\n", Red(name), ce) } } - if se := service.Start(ctx, cli); se == nil { fmt.Print(Green(fmt.Sprintf("Successfully started %s\n", name))) } else { From 0c022da1501df92646b02e3f29702c1806df9a31 Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:34:07 +1000 Subject: [PATCH 07/12] user friendliness Signed-off-by: Karl --- cmd/addkey.go | 8 +++++++- cmd/status.go | 1 + external/docker/commands/up.go | 20 ++++++++++++-------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cmd/addkey.go b/cmd/addkey.go index e2d94138..5d790dd8 100644 --- a/cmd/addkey.go +++ b/cmd/addkey.go @@ -23,6 +23,7 @@ package cmd import ( "fmt" "github.com/pygmystack/pygmy/external/docker/setup" + "strings" . "github.com/logrusorgru/aurora" "github.com/spf13/cobra" @@ -73,7 +74,12 @@ var addkeyCmd = &cobra.Command{ if purpose == "sshagent" { name, _ := service.GetFieldString(ctx, cli, "name") d, _ := containers.Exec(ctx, cli, name, "ssh-add -l") - fmt.Println(string(d)) + if strings.Contains(string(d), "The agent has no identities.") { + fmt.Println(Red("Agent has no identities, the key could not be added.")) + fmt.Println(Red("Start the SSH Agent, add the SSH key and try again.")) + } else { + fmt.Println(string(d)) + } } } diff --git a/cmd/status.go b/cmd/status.go index a4dabd7c..28fe2a50 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -50,6 +50,7 @@ This includes the docker services, the resolver and SSH key status`, } commands.Status(ctx, cli, c) + }, } diff --git a/external/docker/commands/up.go b/external/docker/commands/up.go index 8f34abbb..0a882f4e 100644 --- a/external/docker/commands/up.go +++ b/external/docker/commands/up.go @@ -138,15 +138,19 @@ func Up(c setup.Config) error { // Add ssh-keys to the agent if agentPresent { - for _, v := range c.Keys { - if v.Path != "" { - _, err := os.Stat(v.Path) - if !errors.Is(err, os.ErrNotExist) { - if e := SshKeyAdd(c, v.Path); e != nil { - color.Print(Red(fmt.Sprintf("%v\n", e))) + if len(c.Keys) == 0 || c.Keys[0].Path == "" { + color.Print(Red(fmt.Sprintf("No SSH keys are configured, use `pygmy addkey --key=/path/to/key` to add one.\n"))) + } else { + for _, v := range c.Keys { + if v.Path != "" { + _, err := os.Stat(v.Path) + if !errors.Is(err, os.ErrNotExist) { + if e := SshKeyAdd(c, v.Path); e != nil { + color.Print(Red(fmt.Sprintf("%v\n", e))) + } + } else { + color.Print(Red(fmt.Sprintf("Unable to add SSH key '%s': does not exist\n", v.Path))) } - } else { - color.Print(Red(fmt.Sprintf("Unable to add SSH key '%s': does not exist\n", v.Path))) } } } From 96d03b924584e894daedc5e0776a913d9ab55b60 Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:48:50 +1000 Subject: [PATCH 08/12] linting Signed-off-by: Karl --- external/docker/commands/up.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/docker/commands/up.go b/external/docker/commands/up.go index 0a882f4e..dfc711b8 100644 --- a/external/docker/commands/up.go +++ b/external/docker/commands/up.go @@ -139,7 +139,7 @@ func Up(c setup.Config) error { // Add ssh-keys to the agent if agentPresent { if len(c.Keys) == 0 || c.Keys[0].Path == "" { - color.Print(Red(fmt.Sprintf("No SSH keys are configured, use `pygmy addkey --key=/path/to/key` to add one.\n"))) + color.Print(Red(fmt.Sprint("No SSH keys are configured, use `pygmy addkey --key=/path/to/key` to add one.\n"))) } else { for _, v := range c.Keys { if v.Path != "" { From f63ba08e0b100b07520537d00704c2cc70f42bd3 Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:55:38 +1000 Subject: [PATCH 09/12] fixes to json output/validation Signed-off-by: Karl --- .github/workflows/pygmy.yml | 2 +- external/docker/commands/status.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pygmy.yml b/.github/workflows/pygmy.yml index acc24639..48e8e825 100644 --- a/.github/workflows/pygmy.yml +++ b/.github/workflows/pygmy.yml @@ -106,7 +106,7 @@ jobs: ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml pull; ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml up; ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml status --json > pygmy.noresolv.json - cat pygmy.noresolv.json | jq -r '.resolvers' | grep 'null' + cat pygmy.noresolv.json | jq -r '.resolvers' | grep 'not properly connected' ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml clean; - name: Switch pygmy configs from vanilla to basic diff --git a/external/docker/commands/status.go b/external/docker/commands/status.go index daac5701..13b39662 100644 --- a/external/docker/commands/status.go +++ b/external/docker/commands/status.go @@ -139,7 +139,6 @@ func Status(ctx context.Context, cli *client.Client, c setup.Config) { if Status { if strings.Contains(cleanUrl.String(), "docker.amazee.io") { finalUrl := strings.Trim(cleanUrl.String(), "[]") - fmt.Printf("Added %s\n", finalUrl) urls = append(urls, finalUrl) } } From 49c336665f7b74017f7630959966c40456512b7d Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 22:59:58 +1000 Subject: [PATCH 10/12] revert Signed-off-by: Karl --- .github/workflows/pygmy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pygmy.yml b/.github/workflows/pygmy.yml index 48e8e825..acc24639 100644 --- a/.github/workflows/pygmy.yml +++ b/.github/workflows/pygmy.yml @@ -106,7 +106,7 @@ jobs: ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml pull; ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml up; ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml status --json > pygmy.noresolv.json - cat pygmy.noresolv.json | jq -r '.resolvers' | grep 'not properly connected' + cat pygmy.noresolv.json | jq -r '.resolvers' | grep 'null' ./pygmy-linux-amd64 --config examples/pygmy.noresolv.yml clean; - name: Switch pygmy configs from vanilla to basic From a01fdbcba718cd8ed4f7d9154a12ccfa2d104873 Mon Sep 17 00:00:00 2001 From: Karl Date: Thu, 12 Jun 2025 23:00:49 +1000 Subject: [PATCH 11/12] gosimple Signed-off-by: Karl --- external/docker/commands/up.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/docker/commands/up.go b/external/docker/commands/up.go index dfc711b8..aa5d03ff 100644 --- a/external/docker/commands/up.go +++ b/external/docker/commands/up.go @@ -139,7 +139,7 @@ func Up(c setup.Config) error { // Add ssh-keys to the agent if agentPresent { if len(c.Keys) == 0 || c.Keys[0].Path == "" { - color.Print(Red(fmt.Sprint("No SSH keys are configured, use `pygmy addkey --key=/path/to/key` to add one.\n"))) + color.Print(Red("No SSH keys are configured, use `pygmy addkey --key=/path/to/key` to add one.\n")) } else { for _, v := range c.Keys { if v.Path != "" { From 8424e948fcd0a0fa9b6f328d91f483b4ba281a56 Mon Sep 17 00:00:00 2001 From: Karl Date: Fri, 13 Jun 2025 21:46:30 +1000 Subject: [PATCH 12/12] Add default config provisioner Signed-off-by: Karl --- cmd/root.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 2332d6ab..92e0578b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -117,10 +117,13 @@ func findConfig() string { } // Provide a default. - if runtime.GOOS == "linux" { - return strings.Join([]string{"etc", "pygmy", "config.yml"}, string(os.PathSeparator)) + defaultFilePath := strings.Join([]string{home, ".pygmy.yml"}, string(os.PathSeparator)) + file, err := os.Create(defaultFilePath) + if err != nil { + panic("could not create pygmy config file") } - return strings.Join([]string{home, ".pygmy.yml"}, string(os.PathSeparator)) + defer file.Close() + return defaultFilePath } // initConfig reads in config file and ENV variables if set.