From 0539f2f914b98497533768285790e7c48be0c436 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Mon, 17 Sep 2018 14:41:00 +0200 Subject: [PATCH] Auto configure authentication helper for gcr.io Fixes #966 Signed-off-by: David Gageot --- pkg/skaffold/docker/auth.go | 4 ++ pkg/skaffold/gcp/auth.go | 49 ++++++++++++++ pkg/skaffold/gcp/auth_test.go | 117 ++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 pkg/skaffold/gcp/auth.go create mode 100644 pkg/skaffold/gcp/auth_test.go diff --git a/pkg/skaffold/docker/auth.go b/pkg/skaffold/docker/auth.go index f1cd99a445a..d94826d5f5d 100644 --- a/pkg/skaffold/docker/auth.go +++ b/pkg/skaffold/docker/auth.go @@ -23,6 +23,7 @@ import ( "os" "path/filepath" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/gcp" "github.com/docker/cli/cli/config" "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" @@ -64,6 +65,9 @@ func (credsHelper) GetAuthConfig(registry string) (types.AuthConfig, error) { if err != nil { return types.AuthConfig{}, errors.Wrap(err, "docker config") } + + gcp.AutoConfigureGCRCredentialHelper(cf, registry) + return cf.GetAuthConfig(registry) } diff --git a/pkg/skaffold/gcp/auth.go b/pkg/skaffold/gcp/auth.go new file mode 100644 index 00000000000..1e18441a947 --- /dev/null +++ b/pkg/skaffold/gcp/auth.go @@ -0,0 +1,49 @@ +/* +Copyright 2018 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gcp + +import ( + "os/exec" + "strings" + + "github.com/docker/cli/cli/config/configfile" + "github.com/sirupsen/logrus" +) + +// AutoConfigureGCRCredentialHelper automatically adds the `gcloud` credential helper +// to docker's configuration. +// This doesn't modify the ~/.docker/config.json. It's only in-memory +func AutoConfigureGCRCredentialHelper(cf *configfile.ConfigFile, registry string) { + if registry != "gcr.io" && !strings.HasSuffix(registry, ".gcr.io") { + return + } + + if cf.CredentialHelpers != nil && cf.CredentialHelpers[registry] != "" { + return + } + + if path, _ := exec.LookPath("docker-credential-gcloud"); path == "" { + return + } + + logrus.Debugf("Adding `gcloud` as a docker credential helper for [%s]", registry) + + if cf.CredentialHelpers == nil { + cf.CredentialHelpers = make(map[string]string) + } + cf.CredentialHelpers[registry] = "gcloud" +} diff --git a/pkg/skaffold/gcp/auth_test.go b/pkg/skaffold/gcp/auth_test.go new file mode 100644 index 00000000000..d0c78aa99a4 --- /dev/null +++ b/pkg/skaffold/gcp/auth_test.go @@ -0,0 +1,117 @@ +/* +Copyright 2018 The Skaffold Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gcp + +import ( + "testing" + + "github.com/GoogleContainerTools/skaffold/testutil" + "github.com/docker/cli/cli/config/configfile" +) + +func TestAutoConfigureGCRCredentialHelper(t *testing.T) { + var tests = []struct { + description string + registry string + helperInPath bool + config *configfile.ConfigFile + expected *configfile.ConfigFile + }{ + { + description: "add to nil map", + registry: "gcr.io", + helperInPath: true, + config: &configfile.ConfigFile{}, + expected: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{ + "gcr.io": "gcloud", + }, + }, + }, + { + description: "add to empty map", + registry: "gcr.io", + helperInPath: true, + config: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{}, + }, + expected: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{ + "gcr.io": "gcloud", + }, + }, + }, + { + description: "leave existing helper", + registry: "gcr.io", + config: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{ + "gcr.io": "existing", + }, + }, + expected: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{ + "gcr.io": "existing", + }, + }, + }, + { + description: "any.gcr.io", + registry: "any.gcr.io", + helperInPath: true, + config: &configfile.ConfigFile{}, + expected: &configfile.ConfigFile{ + CredentialHelpers: map[string]string{ + "any.gcr.io": "gcloud", + }, + }, + }, + { + description: "case is important", + registry: "GCR.io", + helperInPath: true, + config: &configfile.ConfigFile{}, + expected: &configfile.ConfigFile{}, + }, + { + description: "ignore if gcloud is not in PATH", + registry: "gcr.io", + helperInPath: false, + config: &configfile.ConfigFile{}, + expected: &configfile.ConfigFile{}, + }, + } + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + tmp, cleanup := testutil.NewTempDir(t) + defer cleanup() + + reset := testutil.SetEnvs(t, map[string]string{ + "PATH": tmp.Root(), + }) + defer reset(t) + + if test.helperInPath { + tmp.Write("docker-credential-gcloud", "") + } + + AutoConfigureGCRCredentialHelper(test.config, test.registry) + + testutil.CheckDeepEqual(t, test.expected, test.config) + }) + } +}