mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
vendor files
This commit is contained in:
53
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/BUILD
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/BUILD
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"jwt.go",
|
||||
"metadata.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/credentialprovider/gcp",
|
||||
deps = [
|
||||
"//pkg/credentialprovider:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/golang.org/x/oauth2:go_default_library",
|
||||
"//vendor/golang.org/x/oauth2/google:go_default_library",
|
||||
"//vendor/golang.org/x/oauth2/jwt:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"jwt_test.go",
|
||||
"metadata_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/credentialprovider/gcp",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/credentialprovider:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
12
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/OWNERS
generated
vendored
Executable file
12
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/OWNERS
generated
vendored
Executable file
@ -0,0 +1,12 @@
|
||||
reviewers:
|
||||
- thockin
|
||||
- deads2k
|
||||
- yujuhong
|
||||
- derekwaynecarr
|
||||
- vishh
|
||||
- mikedanese
|
||||
- davidopp
|
||||
- eparis
|
||||
- dims
|
||||
- david-mcmahon
|
||||
- therc
|
19
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/doc.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes 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_credentials contains implementations of DockerConfigProvider
|
||||
// for Google Cloud Platform.
|
||||
package gcp_credentials // import "k8s.io/kubernetes/pkg/credentialprovider/gcp"
|
116
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt.go
generated
vendored
Normal file
116
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes 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_credentials
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/jwt"
|
||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
const (
|
||||
storageReadOnlyScope = "https://www.googleapis.com/auth/devstorage.read_only"
|
||||
)
|
||||
|
||||
var (
|
||||
flagJwtFile = pflag.String("google-json-key", "",
|
||||
"The Google Cloud Platform Service Account JSON Key to use for authentication.")
|
||||
)
|
||||
|
||||
// A DockerConfigProvider that reads its configuration from Google
|
||||
// Compute Engine metadata.
|
||||
type jwtProvider struct {
|
||||
path *string
|
||||
config *jwt.Config
|
||||
tokenUrl string
|
||||
}
|
||||
|
||||
// init registers the various means by which credentials may
|
||||
// be resolved on GCP.
|
||||
func init() {
|
||||
credentialprovider.RegisterCredentialProvider("google-jwt-key",
|
||||
&credentialprovider.CachingDockerConfigProvider{
|
||||
Provider: &jwtProvider{
|
||||
path: flagJwtFile,
|
||||
},
|
||||
Lifetime: 30 * time.Minute,
|
||||
})
|
||||
}
|
||||
|
||||
// Enabled implements DockerConfigProvider for the JSON Key based implementation.
|
||||
func (j *jwtProvider) Enabled() bool {
|
||||
if *j.path == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(*j.path)
|
||||
if err != nil {
|
||||
glog.Errorf("while reading file %s got %v", *j.path, err)
|
||||
return false
|
||||
}
|
||||
config, err := google.JWTConfigFromJSON(data, storageReadOnlyScope)
|
||||
if err != nil {
|
||||
glog.Errorf("while parsing %s data got %v", *j.path, err)
|
||||
return false
|
||||
}
|
||||
|
||||
j.config = config
|
||||
if j.tokenUrl != "" {
|
||||
j.config.TokenURL = j.tokenUrl
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// LazyProvide implements DockerConfigProvider. Should never be called.
|
||||
func (j *jwtProvider) LazyProvide() *credentialprovider.DockerConfigEntry {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provide implements DockerConfigProvider
|
||||
func (j *jwtProvider) Provide() credentialprovider.DockerConfig {
|
||||
cfg := credentialprovider.DockerConfig{}
|
||||
|
||||
ts := j.config.TokenSource(oauth2.NoContext)
|
||||
token, err := ts.Token()
|
||||
if err != nil {
|
||||
glog.Errorf("while exchanging json key %s for access token %v", *j.path, err)
|
||||
return cfg
|
||||
}
|
||||
if !token.Valid() {
|
||||
glog.Errorf("Got back invalid token: %v", token)
|
||||
return cfg
|
||||
}
|
||||
|
||||
entry := credentialprovider.DockerConfigEntry{
|
||||
Username: "_token",
|
||||
Password: token.AccessToken,
|
||||
Email: j.config.Email,
|
||||
}
|
||||
|
||||
// Add our entry for each of the supported container registry URLs
|
||||
for _, k := range containerRegistryUrls {
|
||||
cfg[k] = entry
|
||||
}
|
||||
return cfg
|
||||
}
|
127
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt_test.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt_test.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes 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_credentials
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||
)
|
||||
|
||||
const email = "foo@bar.com"
|
||||
|
||||
// From oauth2/jwt_test.go
|
||||
var (
|
||||
dummyPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAx4fm7dngEmOULNmAs1IGZ9Apfzh+BkaQ1dzkmbUgpcoghucE
|
||||
DZRnAGd2aPyB6skGMXUytWQvNYav0WTR00wFtX1ohWTfv68HGXJ8QXCpyoSKSSFY
|
||||
fuP9X36wBSkSX9J5DVgiuzD5VBdzUISSmapjKm+DcbRALjz6OUIPEWi1Tjl6p5RK
|
||||
1w41qdbmt7E5/kGhKLDuT7+M83g4VWhgIvaAXtnhklDAggilPPa8ZJ1IFe31lNlr
|
||||
k4DRk38nc6sEutdf3RL7QoH7FBusI7uXV03DC6dwN1kP4GE7bjJhcRb/7jYt7CQ9
|
||||
/E9Exz3c0yAp0yrTg0Fwh+qxfH9dKwN52S7SBwIDAQABAoIBAQCaCs26K07WY5Jt
|
||||
3a2Cw3y2gPrIgTCqX6hJs7O5ByEhXZ8nBwsWANBUe4vrGaajQHdLj5OKfsIDrOvn
|
||||
2NI1MqflqeAbu/kR32q3tq8/Rl+PPiwUsW3E6Pcf1orGMSNCXxeducF2iySySzh3
|
||||
nSIhCG5uwJDWI7a4+9KiieFgK1pt/Iv30q1SQS8IEntTfXYwANQrfKUVMmVF9aIK
|
||||
6/WZE2yd5+q3wVVIJ6jsmTzoDCX6QQkkJICIYwCkglmVy5AeTckOVwcXL0jqw5Kf
|
||||
5/soZJQwLEyBoQq7Kbpa26QHq+CJONetPP8Ssy8MJJXBT+u/bSseMb3Zsr5cr43e
|
||||
DJOhwsThAoGBAPY6rPKl2NT/K7XfRCGm1sbWjUQyDShscwuWJ5+kD0yudnT/ZEJ1
|
||||
M3+KS/iOOAoHDdEDi9crRvMl0UfNa8MAcDKHflzxg2jg/QI+fTBjPP5GOX0lkZ9g
|
||||
z6VePoVoQw2gpPFVNPPTxKfk27tEzbaffvOLGBEih0Kb7HTINkW8rIlzAoGBAM9y
|
||||
1yr+jvfS1cGFtNU+Gotoihw2eMKtIqR03Yn3n0PK1nVCDKqwdUqCypz4+ml6cxRK
|
||||
J8+Pfdh7D+ZJd4LEG6Y4QRDLuv5OA700tUoSHxMSNn3q9As4+T3MUyYxWKvTeu3U
|
||||
f2NWP9ePU0lV8ttk7YlpVRaPQmc1qwooBA/z/8AdAoGAW9x0HWqmRICWTBnpjyxx
|
||||
QGlW9rQ9mHEtUotIaRSJ6K/F3cxSGUEkX1a3FRnp6kPLcckC6NlqdNgNBd6rb2rA
|
||||
cPl/uSkZP42Als+9YMoFPU/xrrDPbUhu72EDrj3Bllnyb168jKLa4VBOccUvggxr
|
||||
Dm08I1hgYgdN5huzs7y6GeUCgYEAj+AZJSOJ6o1aXS6rfV3mMRve9bQ9yt8jcKXw
|
||||
5HhOCEmMtaSKfnOF1Ziih34Sxsb7O2428DiX0mV/YHtBnPsAJidL0SdLWIapBzeg
|
||||
KHArByIRkwE6IvJvwpGMdaex1PIGhx5i/3VZL9qiq/ElT05PhIb+UXgoWMabCp84
|
||||
OgxDK20CgYAeaFo8BdQ7FmVX2+EEejF+8xSge6WVLtkaon8bqcn6P0O8lLypoOhd
|
||||
mJAYH8WU+UAy9pecUnDZj14LAGNVmYcse8HFX71MoshnvCTFEPVo4rZxIAGwMpeJ
|
||||
5jgQ3slYLpqrGlcbLgUXBUgzEO684Wk/UV9DFPlHALVqCfXQ9dpJPg==
|
||||
-----END RSA PRIVATE KEY-----`
|
||||
|
||||
jsonKey = fmt.Sprintf(`{"private_key":"%[1]s", "client_email":"%[2]s", "type": "service_account"}`,
|
||||
strings.Replace(dummyPrivateKey, "\n", "\\n", -1), email)
|
||||
)
|
||||
|
||||
func TestJwtProvider(t *testing.T) {
|
||||
token := "asdhflkjsdfkjhsdf"
|
||||
|
||||
// Modeled after oauth2/jwt_test.go
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(fmt.Sprintf(`{
|
||||
"access_token": "%[1]s",
|
||||
"scope": "user",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 3600
|
||||
}`, token)))
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
file, err := ioutil.TempFile(os.TempDir(), "temp")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating temp file: %v", err)
|
||||
}
|
||||
filename := file.Name()
|
||||
defer os.Remove(filename)
|
||||
|
||||
_, err = file.WriteString(jsonKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Error writing temp file: %v", err)
|
||||
}
|
||||
|
||||
provider := &jwtProvider{
|
||||
path: &filename,
|
||||
tokenUrl: ts.URL,
|
||||
}
|
||||
if !provider.Enabled() {
|
||||
t.Fatalf("Provider is unexpectedly disabled")
|
||||
}
|
||||
|
||||
keyring := &credentialprovider.BasicDockerKeyring{}
|
||||
keyring.Add(provider.Provide())
|
||||
|
||||
// Verify that we get the expected username/password combo for
|
||||
// a gcr.io image name.
|
||||
registryUrl := "gcr.io/foo/bar"
|
||||
creds, ok := keyring.Lookup(registryUrl)
|
||||
if !ok {
|
||||
t.Errorf("Didn't find expected URL: %s", registryUrl)
|
||||
return
|
||||
}
|
||||
if len(creds) > 1 {
|
||||
t.Errorf("Got more hits than expected: %s", creds)
|
||||
}
|
||||
val := creds[0]
|
||||
|
||||
if "_token" != val.Username {
|
||||
t.Errorf("Unexpected username value, want: _token, got: %s", val.Username)
|
||||
}
|
||||
if token != val.Password {
|
||||
t.Errorf("Unexpected password value, want: %s, got: %s", token, val.Password)
|
||||
}
|
||||
if email != val.Email {
|
||||
t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
|
||||
}
|
||||
}
|
298
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata.go
generated
vendored
Normal file
298
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata.go
generated
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes 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_credentials
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||
)
|
||||
|
||||
const (
|
||||
metadataUrl = "http://metadata.google.internal./computeMetadata/v1/"
|
||||
metadataAttributes = metadataUrl + "instance/attributes/"
|
||||
dockerConfigKey = metadataAttributes + "google-dockercfg"
|
||||
dockerConfigUrlKey = metadataAttributes + "google-dockercfg-url"
|
||||
serviceAccounts = metadataUrl + "instance/service-accounts/"
|
||||
metadataScopes = metadataUrl + "instance/service-accounts/default/scopes"
|
||||
metadataToken = metadataUrl + "instance/service-accounts/default/token"
|
||||
metadataEmail = metadataUrl + "instance/service-accounts/default/email"
|
||||
storageScopePrefix = "https://www.googleapis.com/auth/devstorage"
|
||||
cloudPlatformScopePrefix = "https://www.googleapis.com/auth/cloud-platform"
|
||||
googleProductName = "Google"
|
||||
defaultServiceAccount = "default/"
|
||||
)
|
||||
|
||||
// Product file path that contains the cloud service name.
|
||||
// This is a variable instead of a const to enable testing.
|
||||
var gceProductNameFile = "/sys/class/dmi/id/product_name"
|
||||
|
||||
// For these urls, the parts of the host name can be glob, for example '*.gcr.io" will match
|
||||
// "foo.gcr.io" and "bar.gcr.io".
|
||||
var containerRegistryUrls = []string{"container.cloud.google.com", "gcr.io", "*.gcr.io"}
|
||||
|
||||
var metadataHeader = &http.Header{
|
||||
"Metadata-Flavor": []string{"Google"},
|
||||
}
|
||||
|
||||
// A DockerConfigProvider that reads its configuration from Google
|
||||
// Compute Engine metadata.
|
||||
type metadataProvider struct {
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
// A DockerConfigProvider that reads its configuration from a specific
|
||||
// Google Compute Engine metadata key: 'google-dockercfg'.
|
||||
type dockerConfigKeyProvider struct {
|
||||
metadataProvider
|
||||
}
|
||||
|
||||
// A DockerConfigProvider that reads its configuration from a URL read from
|
||||
// a specific Google Compute Engine metadata key: 'google-dockercfg-url'.
|
||||
type dockerConfigUrlKeyProvider struct {
|
||||
metadataProvider
|
||||
}
|
||||
|
||||
// A DockerConfigProvider that provides a dockercfg with:
|
||||
// Username: "_token"
|
||||
// Password: "{access token from metadata}"
|
||||
type containerRegistryProvider struct {
|
||||
metadataProvider
|
||||
}
|
||||
|
||||
// init registers the various means by which credentials may
|
||||
// be resolved on GCP.
|
||||
func init() {
|
||||
tr := utilnet.SetTransportDefaults(&http.Transport{})
|
||||
metadataHTTPClientTimeout := time.Second * 10
|
||||
httpClient := &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: metadataHTTPClientTimeout,
|
||||
}
|
||||
credentialprovider.RegisterCredentialProvider("google-dockercfg",
|
||||
&credentialprovider.CachingDockerConfigProvider{
|
||||
Provider: &dockerConfigKeyProvider{
|
||||
metadataProvider{Client: httpClient},
|
||||
},
|
||||
Lifetime: 60 * time.Second,
|
||||
})
|
||||
|
||||
credentialprovider.RegisterCredentialProvider("google-dockercfg-url",
|
||||
&credentialprovider.CachingDockerConfigProvider{
|
||||
Provider: &dockerConfigUrlKeyProvider{
|
||||
metadataProvider{Client: httpClient},
|
||||
},
|
||||
Lifetime: 60 * time.Second,
|
||||
})
|
||||
|
||||
credentialprovider.RegisterCredentialProvider("google-container-registry",
|
||||
// Never cache this. The access token is already
|
||||
// cached by the metadata service.
|
||||
&containerRegistryProvider{
|
||||
metadataProvider{Client: httpClient},
|
||||
})
|
||||
}
|
||||
|
||||
// Returns true if it finds a local GCE VM.
|
||||
// Looks at a product file that is an undocumented API.
|
||||
func onGCEVM() bool {
|
||||
data, err := ioutil.ReadFile(gceProductNameFile)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error while reading product_name: %v", err)
|
||||
return false
|
||||
}
|
||||
return strings.Contains(string(data), googleProductName)
|
||||
}
|
||||
|
||||
// Enabled implements DockerConfigProvider for all of the Google implementations.
|
||||
func (g *metadataProvider) Enabled() bool {
|
||||
return onGCEVM()
|
||||
}
|
||||
|
||||
// LazyProvide implements DockerConfigProvider. Should never be called.
|
||||
func (g *dockerConfigKeyProvider) LazyProvide() *credentialprovider.DockerConfigEntry {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provide implements DockerConfigProvider
|
||||
func (g *dockerConfigKeyProvider) Provide() credentialprovider.DockerConfig {
|
||||
// Read the contents of the google-dockercfg metadata key and
|
||||
// parse them as an alternate .dockercfg
|
||||
if cfg, err := credentialprovider.ReadDockerConfigFileFromUrl(dockerConfigKey, g.Client, metadataHeader); err != nil {
|
||||
glog.Errorf("while reading 'google-dockercfg' metadata: %v", err)
|
||||
} else {
|
||||
return cfg
|
||||
}
|
||||
|
||||
return credentialprovider.DockerConfig{}
|
||||
}
|
||||
|
||||
// LazyProvide implements DockerConfigProvider. Should never be called.
|
||||
func (g *dockerConfigUrlKeyProvider) LazyProvide() *credentialprovider.DockerConfigEntry {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provide implements DockerConfigProvider
|
||||
func (g *dockerConfigUrlKeyProvider) Provide() credentialprovider.DockerConfig {
|
||||
// Read the contents of the google-dockercfg-url key and load a .dockercfg from there
|
||||
if url, err := credentialprovider.ReadUrl(dockerConfigUrlKey, g.Client, metadataHeader); err != nil {
|
||||
glog.Errorf("while reading 'google-dockercfg-url' metadata: %v", err)
|
||||
} else {
|
||||
if strings.HasPrefix(string(url), "http") {
|
||||
if cfg, err := credentialprovider.ReadDockerConfigFileFromUrl(string(url), g.Client, nil); err != nil {
|
||||
glog.Errorf("while reading 'google-dockercfg-url'-specified url: %s, %v", string(url), err)
|
||||
} else {
|
||||
return cfg
|
||||
}
|
||||
} else {
|
||||
// TODO(mattmoor): support reading alternate scheme URLs (e.g. gs:// or s3://)
|
||||
glog.Errorf("Unsupported URL scheme: %s", string(url))
|
||||
}
|
||||
}
|
||||
|
||||
return credentialprovider.DockerConfig{}
|
||||
}
|
||||
|
||||
// runcWithBackoff runs input function `f` with an exponential backoff.
|
||||
// Note that this method can block indefinitely.
|
||||
func runWithBackoff(f func() ([]byte, error)) []byte {
|
||||
var backoff = 100 * time.Millisecond
|
||||
const maxBackoff = time.Minute
|
||||
for {
|
||||
value, err := f()
|
||||
if err == nil {
|
||||
return value
|
||||
}
|
||||
time.Sleep(backoff)
|
||||
backoff = backoff * 2
|
||||
if backoff > maxBackoff {
|
||||
backoff = maxBackoff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled implements a special metadata-based check, which verifies the
|
||||
// storage scope is available on the GCE VM.
|
||||
// If running on a GCE VM, check if 'default' service account exists.
|
||||
// If it does not exist, assume that registry is not enabled.
|
||||
// If default service account exists, check if relevant scopes exist in the default service account.
|
||||
// The metadata service can become temporarily inaccesible. Hence all requests to the metadata
|
||||
// service will be retried until the metadata server returns a `200`.
|
||||
// It is expected that "http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/" will return a `200`
|
||||
// and "http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/default/scopes" will also return `200`.
|
||||
// More information on metadata service can be found here - https://cloud.google.com/compute/docs/storing-retrieving-metadata
|
||||
func (g *containerRegistryProvider) Enabled() bool {
|
||||
if !onGCEVM() {
|
||||
return false
|
||||
}
|
||||
// Given that we are on GCE, we should keep retrying until the metadata server responds.
|
||||
value := runWithBackoff(func() ([]byte, error) {
|
||||
value, err := credentialprovider.ReadUrl(serviceAccounts, g.Client, metadataHeader)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Failed to Get service accounts from gce metadata server: %v", err)
|
||||
}
|
||||
return value, err
|
||||
})
|
||||
// We expect the service account to return a list of account directories separated by newlines, e.g.,
|
||||
// sv-account-name1/
|
||||
// sv-account-name2/
|
||||
// ref: https://cloud.google.com/compute/docs/storing-retrieving-metadata
|
||||
defaultServiceAccountExists := false
|
||||
for _, sa := range strings.Split(string(value), "\n") {
|
||||
if strings.TrimSpace(sa) == defaultServiceAccount {
|
||||
defaultServiceAccountExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !defaultServiceAccountExists {
|
||||
glog.V(2).Infof("'default' service account does not exist. Found following service accounts: %q", string(value))
|
||||
return false
|
||||
}
|
||||
url := metadataScopes + "?alt=json"
|
||||
value = runWithBackoff(func() ([]byte, error) {
|
||||
value, err := credentialprovider.ReadUrl(url, g.Client, metadataHeader)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Failed to Get scopes in default service account from gce metadata server: %v", err)
|
||||
}
|
||||
return value, err
|
||||
})
|
||||
var scopes []string
|
||||
if err := json.Unmarshal(value, &scopes); err != nil {
|
||||
glog.Errorf("Failed to unmarshal scopes: %v", err)
|
||||
return false
|
||||
}
|
||||
for _, v := range scopes {
|
||||
// cloudPlatformScope implies storage scope.
|
||||
if strings.HasPrefix(v, storageScopePrefix) || strings.HasPrefix(v, cloudPlatformScopePrefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
glog.Warningf("Google container registry is disabled, no storage scope is available: %s", value)
|
||||
return false
|
||||
}
|
||||
|
||||
// tokenBlob is used to decode the JSON blob containing an access token
|
||||
// that is returned by GCE metadata.
|
||||
type tokenBlob struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
// LazyProvide implements DockerConfigProvider. Should never be called.
|
||||
func (g *containerRegistryProvider) LazyProvide() *credentialprovider.DockerConfigEntry {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provide implements DockerConfigProvider
|
||||
func (g *containerRegistryProvider) Provide() credentialprovider.DockerConfig {
|
||||
cfg := credentialprovider.DockerConfig{}
|
||||
|
||||
tokenJsonBlob, err := credentialprovider.ReadUrl(metadataToken, g.Client, metadataHeader)
|
||||
if err != nil {
|
||||
glog.Errorf("while reading access token endpoint: %v", err)
|
||||
return cfg
|
||||
}
|
||||
|
||||
email, err := credentialprovider.ReadUrl(metadataEmail, g.Client, metadataHeader)
|
||||
if err != nil {
|
||||
glog.Errorf("while reading email endpoint: %v", err)
|
||||
return cfg
|
||||
}
|
||||
|
||||
var parsedBlob tokenBlob
|
||||
if err := json.Unmarshal([]byte(tokenJsonBlob), &parsedBlob); err != nil {
|
||||
glog.Errorf("while parsing json blob %s: %v", tokenJsonBlob, err)
|
||||
return cfg
|
||||
}
|
||||
|
||||
entry := credentialprovider.DockerConfigEntry{
|
||||
Username: "_token",
|
||||
Password: parsedBlob.AccessToken,
|
||||
Email: string(email),
|
||||
}
|
||||
|
||||
// Add our entry for each of the supported container registry URLs
|
||||
for _, k := range containerRegistryUrls {
|
||||
cfg[k] = entry
|
||||
}
|
||||
return cfg
|
||||
}
|
441
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata_test.go
generated
vendored
Normal file
441
vendor/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata_test.go
generated
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes 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_credentials
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||
)
|
||||
|
||||
func createProductNameFile() (string, error) {
|
||||
file, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create temporary test file: %v", err)
|
||||
}
|
||||
return file.Name(), ioutil.WriteFile(file.Name(), []byte("Google"), 0600)
|
||||
}
|
||||
|
||||
func TestDockerKeyringFromGoogleDockerConfigMetadata(t *testing.T) {
|
||||
registryUrl := "hello.kubernetes.io"
|
||||
email := "foo@bar.baz"
|
||||
username := "foo"
|
||||
password := "bar"
|
||||
auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
|
||||
sampleDockerConfig := fmt.Sprintf(`{
|
||||
"https://%s": {
|
||||
"email": %q,
|
||||
"auth": %q
|
||||
}
|
||||
}`, registryUrl, email, auth)
|
||||
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
const probeEndpoint = "/computeMetadata/v1/"
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the one metadata key.
|
||||
if probeEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else if strings.HasSuffix(dockerConfigKey, r.URL.Path) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, sampleDockerConfig)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
keyring := &credentialprovider.BasicDockerKeyring{}
|
||||
provider := &dockerConfigKeyProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if !provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly disabled")
|
||||
}
|
||||
|
||||
keyring.Add(provider.Provide())
|
||||
|
||||
creds, ok := keyring.Lookup(registryUrl)
|
||||
if !ok {
|
||||
t.Errorf("Didn't find expected URL: %s", registryUrl)
|
||||
return
|
||||
}
|
||||
if len(creds) > 1 {
|
||||
t.Errorf("Got more hits than expected: %s", creds)
|
||||
}
|
||||
val := creds[0]
|
||||
|
||||
if username != val.Username {
|
||||
t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
|
||||
}
|
||||
if password != val.Password {
|
||||
t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
|
||||
}
|
||||
if email != val.Email {
|
||||
t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerKeyringFromGoogleDockerConfigMetadataUrl(t *testing.T) {
|
||||
registryUrl := "hello.kubernetes.io"
|
||||
email := "foo@bar.baz"
|
||||
username := "foo"
|
||||
password := "bar"
|
||||
auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
|
||||
sampleDockerConfig := fmt.Sprintf(`{
|
||||
"https://%s": {
|
||||
"email": %q,
|
||||
"auth": %q
|
||||
}
|
||||
}`, registryUrl, email, auth)
|
||||
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
const probeEndpoint = "/computeMetadata/v1/"
|
||||
const valueEndpoint = "/my/value"
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the URL key and the value endpoint
|
||||
if probeEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else if valueEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, sampleDockerConfig)
|
||||
} else if strings.HasSuffix(dockerConfigUrlKey, r.URL.Path) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/text")
|
||||
fmt.Fprint(w, "http://foo.bar.com"+valueEndpoint)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
keyring := &credentialprovider.BasicDockerKeyring{}
|
||||
provider := &dockerConfigUrlKeyProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if !provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly disabled")
|
||||
}
|
||||
|
||||
keyring.Add(provider.Provide())
|
||||
|
||||
creds, ok := keyring.Lookup(registryUrl)
|
||||
if !ok {
|
||||
t.Errorf("Didn't find expected URL: %s", registryUrl)
|
||||
return
|
||||
}
|
||||
if len(creds) > 1 {
|
||||
t.Errorf("Got more hits than expected: %s", creds)
|
||||
}
|
||||
val := creds[0]
|
||||
|
||||
if username != val.Username {
|
||||
t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
|
||||
}
|
||||
if password != val.Password {
|
||||
t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
|
||||
}
|
||||
if email != val.Email {
|
||||
t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerRegistryBasics(t *testing.T) {
|
||||
registryUrl := "container.cloud.google.com"
|
||||
email := "1234@project.gserviceaccount.com"
|
||||
token := &tokenBlob{AccessToken: "ya26.lots-of-indiscernible-garbage"}
|
||||
|
||||
const (
|
||||
serviceAccountsEndpoint = "/computeMetadata/v1/instance/service-accounts/"
|
||||
defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/"
|
||||
scopeEndpoint = defaultEndpoint + "scopes"
|
||||
emailEndpoint = defaultEndpoint + "email"
|
||||
tokenEndpoint = defaultEndpoint + "token"
|
||||
)
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the URL key and the value endpoint
|
||||
if scopeEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, `["%s.read_write"]`, storageScopePrefix)
|
||||
} else if emailEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, email)
|
||||
} else if tokenEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
bytes, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
fmt.Fprintln(w, string(bytes))
|
||||
} else if serviceAccountsEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "default/\ncustom")
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
keyring := &credentialprovider.BasicDockerKeyring{}
|
||||
provider := &containerRegistryProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if !provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly disabled")
|
||||
}
|
||||
|
||||
keyring.Add(provider.Provide())
|
||||
|
||||
creds, ok := keyring.Lookup(registryUrl)
|
||||
if !ok {
|
||||
t.Errorf("Didn't find expected URL: %s", registryUrl)
|
||||
return
|
||||
}
|
||||
if len(creds) > 1 {
|
||||
t.Errorf("Got more hits than expected: %s", creds)
|
||||
}
|
||||
val := creds[0]
|
||||
|
||||
if "_token" != val.Username {
|
||||
t.Errorf("Unexpected username value, want: %s, got: %s", "_token", val.Username)
|
||||
}
|
||||
if token.AccessToken != val.Password {
|
||||
t.Errorf("Unexpected password value, want: %s, got: %s", token.AccessToken, val.Password)
|
||||
}
|
||||
if email != val.Email {
|
||||
t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerRegistryNoServiceAccount(t *testing.T) {
|
||||
const (
|
||||
serviceAccountsEndpoint = "/computeMetadata/v1/instance/service-accounts/"
|
||||
)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the URL key and the value endpoint
|
||||
if serviceAccountsEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
bytes, err := json.Marshal([]string{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
fmt.Fprintln(w, string(bytes))
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
provider := &containerRegistryProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerRegistryNoStorageScope(t *testing.T) {
|
||||
const (
|
||||
serviceAccountsEndpoint = "/computeMetadata/v1/instance/service-accounts/"
|
||||
defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/"
|
||||
scopeEndpoint = defaultEndpoint + "scopes"
|
||||
)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the URL key and the value endpoint
|
||||
if scopeEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprint(w, `["https://www.googleapis.com/auth/compute.read_write"]`)
|
||||
} else if serviceAccountsEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "default/\ncustom")
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
provider := &containerRegistryProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestComputePlatformScopeSubstitutesStorageScope(t *testing.T) {
|
||||
const (
|
||||
serviceAccountsEndpoint = "/computeMetadata/v1/instance/service-accounts/"
|
||||
defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/"
|
||||
scopeEndpoint = defaultEndpoint + "scopes"
|
||||
)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Only serve the URL key and the value endpoint
|
||||
if scopeEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprint(w, `["https://www.googleapis.com/auth/compute.read_write","https://www.googleapis.com/auth/cloud-platform.read-only"]`)
|
||||
} else if serviceAccountsEndpoint == r.URL.Path {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, "default/\ncustom")
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
var err error
|
||||
gceProductNameFile, err = createProductNameFile()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create gce product name file: %v", err)
|
||||
}
|
||||
defer os.Remove(gceProductNameFile)
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
provider := &containerRegistryProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
}
|
||||
|
||||
if !provider.Enabled() {
|
||||
t.Errorf("Provider is unexpectedly disabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllProvidersNoMetadata(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
// Make a transport that reroutes all traffic to the example server
|
||||
transport := utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return url.Parse(server.URL + req.URL.Path)
|
||||
},
|
||||
})
|
||||
|
||||
providers := []credentialprovider.DockerConfigProvider{
|
||||
&dockerConfigKeyProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
},
|
||||
&dockerConfigUrlKeyProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
},
|
||||
&containerRegistryProvider{
|
||||
metadataProvider{Client: &http.Client{Transport: transport}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, provider := range providers {
|
||||
if provider.Enabled() {
|
||||
t.Errorf("Provider %s is unexpectedly enabled", reflect.TypeOf(provider).String())
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user