From 13f95c9b14c5f92889e439d82540fafd3d18959f Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Wed, 13 Nov 2024 23:24:50 +0100 Subject: [PATCH] fix: fix broken write to docker config.json (#273) --- docs/data/data.yaml | 6 ++--- go.mod | 4 ++++ go.sum | 1 + plugin/impl.go | 8 ++++++- plugin/plugin.go | 8 +++---- plugin/util.go | 19 ++++++++++----- plugin/util_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 plugin/util_test.go diff --git a/docs/data/data.yaml b/docs/data/data.yaml index f8eaf2d..37b1f5c 100644 --- a/docs/data/data.yaml +++ b/docs/data/data.yaml @@ -94,11 +94,11 @@ properties: defaultValue: false required: false - - name: config + - name: registry_config description: | - Content of the docker daemon json config. + Content of the registry credentials store file. type: string - defaultValue: $DOCKER_PLUGIN_CONFIG + defaultValue: $DOCKER_REGISTRY_CONFIG required: false - name: containerfile diff --git a/go.mod b/go.mod index 72822c3..a7b0a2a 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23.3 require ( github.com/cenkalti/backoff/v4 v4.3.0 github.com/rs/zerolog v1.33.0 + github.com/stretchr/testify v1.9.0 github.com/thegeeklab/wp-plugin-go/v3 v3.0.9 github.com/urfave/cli/v2 v2.27.5 ) @@ -15,6 +16,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/joho/godotenv v1.5.1 // indirect @@ -22,6 +24,7 @@ require ( github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/spf13/cast v1.7.0 // indirect @@ -29,4 +32,5 @@ require ( golang.org/x/crypto v0.29.0 // indirect golang.org/x/net v0.31.0 // indirect golang.org/x/sys v0.27.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index bee6812..e859e6d 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/plugin/impl.go b/plugin/impl.go index 9165d74..6fb0b70 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "path/filepath" "time" "github.com/cenkalti/backoff/v4" @@ -129,7 +130,12 @@ func (p *Plugin) Execute() error { } if p.Settings.Registry.Config != "" { - if err := WriteDockerConf(homeDir, p.Settings.Registry.Config); err != nil { + path := filepath.Join(homeDir, ".docker", "config.json") + if err := os.MkdirAll(filepath.Dir(path), strictFilePerm); err != nil { + return err + } + + if err := WriteDockerConf(path, p.Settings.Registry.Config); err != nil { return fmt.Errorf("error writing docker config: %w", err) } } diff --git a/plugin/plugin.go b/plugin/plugin.go index 5b6eb55..dc933e5 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -333,11 +333,11 @@ func Flags(settings *Settings, category string) []cli.Flag { Category: category, }, &cli.StringFlag{ - Name: "docker.config", - EnvVars: []string{"PLUGIN_CONFIG", "DOCKER_PLUGIN_CONFIG"}, - Usage: "content of the docker daemon json config", + Name: "registry.config", + EnvVars: []string{"PLUGIN_REGISTRY_CONFIG", "DOCKER_REGISTRY_CONFIG"}, + Usage: "content of the registry credentials store file", Destination: &settings.Registry.Config, - DefaultText: "$DOCKER_PLUGIN_CONFIG", + DefaultText: "$DOCKER_REGISTRY_CONFIG", Category: category, }, &cli.BoolFlag{ diff --git a/plugin/util.go b/plugin/util.go index 91f6296..e16435c 100644 --- a/plugin/util.go +++ b/plugin/util.go @@ -1,11 +1,14 @@ package plugin import ( + "encoding/json" + "fmt" "net" "os" - "path/filepath" ) +var errInvalidDockerConfig = fmt.Errorf("invalid docker config") + func GetContainerIP() (string, error) { netInterfaceAddrList, err := net.InterfaceAddrs() if err != nil { @@ -23,13 +26,17 @@ func GetContainerIP() (string, error) { } func WriteDockerConf(path, conf string) error { - confPath := filepath.Join(path, ".docker", "config.json") - - if err := os.MkdirAll(confPath, strictFilePerm); err != nil { - return err + var jsonData interface{} + if err := json.Unmarshal([]byte(conf), &jsonData); err != nil { + return fmt.Errorf("%w: %w", errInvalidDockerConfig, err) } - err := os.WriteFile(path, []byte(conf), strictFilePerm) + jsonBytes, err := json.Marshal(jsonData) + if err != nil { + return fmt.Errorf("%w: %w", errInvalidDockerConfig, err) + } + + err = os.WriteFile(path, jsonBytes, strictFilePerm) if err != nil { return err } diff --git a/plugin/util_test.go b/plugin/util_test.go new file mode 100644 index 0000000..e80f95a --- /dev/null +++ b/plugin/util_test.go @@ -0,0 +1,56 @@ +package plugin + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWriteDockerConf(t *testing.T) { + tests := []struct { + name string + conf string + wantErr bool + }{ + { + name: "valid json config", + conf: `{"auths":{"registry.example.com":{"auth":"dXNlcjpwYXNz"}}}`, + wantErr: false, + }, + { + name: "invalid json config", + conf: `{"auths":invalid}`, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpFile := filepath.Join(t.TempDir(), "config.json") + + err := WriteDockerConf(tmpFile, tt.conf) + if tt.wantErr { + assert.ErrorAs(t, err, &errInvalidDockerConfig) + + return + } + + assert.NoError(t, err) + + content, err := os.ReadFile(tmpFile) + assert.NoError(t, err, "Failed to read config file") + + var got, want interface{} + err = json.Unmarshal(content, &got) + assert.NoError(t, err, "Failed to parse written config") + + err = json.Unmarshal([]byte(tt.conf), &want) + assert.NoError(t, err, "Failed to parse test config") + + assert.Equal(t, want, got, "Written config does not match expected") + }) + } +}