Merge pull request #228 from keel-hq/feature/registry_cfg
Feature/registry cfggen-manifests-from-chart 0.9.3
commit
df7ed4ae09
|
@ -6,7 +6,7 @@ jobs:
|
|||
build:
|
||||
docker:
|
||||
# specify the version
|
||||
- image: circleci/golang:1.9.3
|
||||
- image: circleci/golang:1.10.3
|
||||
|
||||
#### TEMPLATE_NOTE: go expects specific checkout path representing url
|
||||
#### expecting it in the form of
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.9.3
|
||||
FROM golang:1.10.3
|
||||
COPY . /go/src/github.com/keel-hq/keel
|
||||
WORKDIR /go/src/github.com/keel-hq/keel
|
||||
RUN make install
|
||||
|
|
|
@ -59,6 +59,10 @@ const (
|
|||
|
||||
EnvHelmProvider = "HELM_PROVIDER" // helm provider
|
||||
EnvHelmTillerAddress = "TILLER_ADDRESS" // helm provider
|
||||
|
||||
// EnvDefaultDockerRegistryCfg - default registry configuration that can be passed into
|
||||
// keel for polling trigger
|
||||
EnvDefaultDockerRegistryCfg = "DOCKER_REGISTRY_CFG"
|
||||
)
|
||||
|
||||
// kubernetes config, if empty - will default to InCluster
|
||||
|
@ -174,7 +178,18 @@ func main() {
|
|||
providers := setupProviders(implementer, sender, approvalsManager, &t.GenericResourceCache)
|
||||
|
||||
// registering secrets based credentials helper
|
||||
secretsGetter := secrets.NewGetter(implementer)
|
||||
dockerConfig := make(secrets.DockerCfg)
|
||||
if os.Getenv(EnvDefaultDockerRegistryCfg) != "" {
|
||||
dockerConfigStr := os.Getenv(EnvDefaultDockerRegistryCfg)
|
||||
dockerConfig, err = secrets.DecodeDockerCfgJson([]byte(dockerConfigStr))
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"error": err,
|
||||
}).Fatalf("failed to decode secret provided in %s env variable", EnvDefaultDockerRegistryCfg)
|
||||
}
|
||||
}
|
||||
secretsGetter := secrets.NewGetter(implementer, dockerConfig)
|
||||
|
||||
ch := secretsCredentialsHelper.New(secretsGetter)
|
||||
credentialshelper.RegisterCredentialsHelper("secrets", ch)
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ spec:
|
|||
spec:
|
||||
serviceAccountName: keel
|
||||
containers:
|
||||
- image: keelhq/keel:0.8.3
|
||||
- image: keelhq/keel:alpha
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
# - name: POLL
|
||||
|
@ -42,6 +42,10 @@ spec:
|
|||
# value: "1"
|
||||
# - name: TILLER_ADDRESS
|
||||
# value: tiller-deploy.kube-system.svc.cluster.local:44134
|
||||
# Default Docker registry configuration (will override secrets if there are any)
|
||||
# 'auth' parameter is base 64 encoded username:password pair. Ideally this environment variable would be a Kubernetes secret.
|
||||
# - name: DOCKER_REGISTRY_CFG
|
||||
# value: '{"auths":{"https://index.docker.io/v1/":{"username":"login","password":"somepass","email":"email@email.com","auth":"longbase64secret"}}}'
|
||||
- name: PROJECT_ID
|
||||
value: "my-project-id"
|
||||
# - name: WEBHOOK_ENDPOINT
|
||||
|
|
|
@ -86,7 +86,7 @@ spec:
|
|||
spec:
|
||||
serviceAccountName: keel
|
||||
containers:
|
||||
- image: keelhq/keel:0.8.3
|
||||
- image: keelhq/keel:0.9.3
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
# - name: POLL
|
||||
|
@ -96,6 +96,10 @@ spec:
|
|||
# Enable/disable Helm provider
|
||||
# - name: HELM_PROVIDER
|
||||
# value: "1"
|
||||
# Default Docker registry configuration (will override secrets if there are any)
|
||||
# 'auth' parameter is base 64 encoded username:password pair. Ideally this environment variable would be a Kubernetes secret.
|
||||
# - name: DOCKER_REGISTRY_CFG
|
||||
# value: '{"auths":{"https://index.docker.io/v1/":{"username":"login","password":"somepass","email":"email@email.com","auth":"longbase64secret"}}}'
|
||||
- name: PROJECT_ID
|
||||
value: "my-project-id"
|
||||
# - name: WEBHOOK_ENDPOINT
|
||||
|
|
|
@ -16,7 +16,7 @@ spec:
|
|||
spec:
|
||||
serviceAccountName: keel
|
||||
containers:
|
||||
- image: keelhq/keel:0.8.3
|
||||
- image: keelhq/keel:0.9.3
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
# - name: POLL
|
||||
|
|
|
@ -36,12 +36,20 @@ type Getter interface {
|
|||
// DefaultGetter - default kubernetes secret getter implementation
|
||||
type DefaultGetter struct {
|
||||
kubernetesImplementer kubernetes.Implementer
|
||||
defaultDockerConfig DockerCfg // default configuration supplied by optional environment variable
|
||||
}
|
||||
|
||||
// NewGetter - create new default getter
|
||||
func NewGetter(implementer kubernetes.Implementer) *DefaultGetter {
|
||||
func NewGetter(implementer kubernetes.Implementer, defaultDockerConfig DockerCfg) *DefaultGetter {
|
||||
|
||||
// initialising empty configuration
|
||||
if defaultDockerConfig == nil {
|
||||
defaultDockerConfig = make(DockerCfg)
|
||||
}
|
||||
|
||||
return &DefaultGetter{
|
||||
kubernetesImplementer: implementer,
|
||||
defaultDockerConfig: defaultDockerConfig,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +59,12 @@ func (g *DefaultGetter) Get(image *types.TrackedImage) (*types.Credentials, erro
|
|||
return nil, ErrNamespaceNotSpecified
|
||||
}
|
||||
|
||||
// checking in default creds
|
||||
creds, found := g.lookupDefaultDockerConfig(image)
|
||||
if found {
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
switch image.Provider {
|
||||
case helm.ProviderName:
|
||||
// looking up secrets based on selector
|
||||
|
@ -66,6 +80,10 @@ func (g *DefaultGetter) Get(image *types.TrackedImage) (*types.Credentials, erro
|
|||
return g.getCredentialsFromSecret(image)
|
||||
}
|
||||
|
||||
func (g *DefaultGetter) lookupDefaultDockerConfig(image *types.TrackedImage) (*types.Credentials, bool) {
|
||||
return credentialsFromConfig(image, g.defaultDockerConfig)
|
||||
}
|
||||
|
||||
func (g *DefaultGetter) lookupSecrets(image *types.TrackedImage) ([]string, error) {
|
||||
secrets := []string{}
|
||||
|
||||
|
@ -170,7 +188,7 @@ func (g *DefaultGetter) getCredentialsFromSecret(image *types.TrackedImage) (*ty
|
|||
continue
|
||||
}
|
||||
|
||||
dockerCfg, err = decodeJSONSecret(secretDataBts)
|
||||
dockerCfg, err = DecodeDockerCfgJson(secretDataBts)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"image": image.Image.Repository(),
|
||||
|
@ -192,15 +210,37 @@ func (g *DefaultGetter) getCredentialsFromSecret(image *types.TrackedImage) (*ty
|
|||
continue
|
||||
}
|
||||
|
||||
creds, found := credentialsFromConfig(image, dockerCfg)
|
||||
if found {
|
||||
return creds, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(image.Secrets) > 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"namespace": image.Namespace,
|
||||
"provider": image.Provider,
|
||||
"registry": image.Image.Registry(),
|
||||
"image": image.Image.Repository(),
|
||||
"secrets": image.Secrets,
|
||||
}).Warn("secrets.defaultGetter.lookupSecrets: docker credentials were not found among secrets")
|
||||
}
|
||||
|
||||
return credentials, nil
|
||||
}
|
||||
|
||||
func credentialsFromConfig(image *types.TrackedImage, cfg DockerCfg) (*types.Credentials, bool) {
|
||||
credentials := &types.Credentials{}
|
||||
found := false
|
||||
// looking for our registry
|
||||
for registry, auth := range dockerCfg {
|
||||
for registry, auth := range cfg {
|
||||
h, err := hostname(registry)
|
||||
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"image": image.Image.Repository(),
|
||||
"namespace": image.Namespace,
|
||||
"registry": registry,
|
||||
"secret_ref": secretRef,
|
||||
"error": err,
|
||||
}).Error("secrets.defaultGetter: failed to parse hostname")
|
||||
continue
|
||||
|
@ -217,19 +257,18 @@ func (g *DefaultGetter) getCredentialsFromSecret(image *types.TrackedImage) (*ty
|
|||
"image": image.Image.Repository(),
|
||||
"namespace": image.Namespace,
|
||||
"registry": registry,
|
||||
"secret_ref": secretRef,
|
||||
"error": err,
|
||||
}).Error("secrets.defaultGetter: failed to decode auth secret")
|
||||
continue
|
||||
}
|
||||
credentials.Username = username
|
||||
credentials.Password = password
|
||||
found = true
|
||||
} else {
|
||||
log.WithFields(log.Fields{
|
||||
"image": image.Image.Repository(),
|
||||
"namespace": image.Namespace,
|
||||
"registry": registry,
|
||||
"secret_ref": secretRef,
|
||||
"error": err,
|
||||
}).Warn("secrets.defaultGetter: secret doesn't have username, password and base64 encoded auth, skipping")
|
||||
continue
|
||||
|
@ -242,22 +281,10 @@ func (g *DefaultGetter) getCredentialsFromSecret(image *types.TrackedImage) (*ty
|
|||
"image": image.Image.Repository(),
|
||||
}).Debug("secrets.defaultGetter: secret looked up successfully")
|
||||
|
||||
return credentials, nil
|
||||
return credentials, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(image.Secrets) > 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"namespace": image.Namespace,
|
||||
"provider": image.Provider,
|
||||
"registry": image.Image.Registry(),
|
||||
"image": image.Image.Repository(),
|
||||
"secrets": image.Secrets,
|
||||
}).Warn("secrets.defaultGetter.lookupSecrets: docker credentials were not found among secrets")
|
||||
}
|
||||
|
||||
return credentials, nil
|
||||
return credentials, found
|
||||
}
|
||||
|
||||
func decodeBase64Secret(authSecret string) (username, password string, err error) {
|
||||
|
@ -296,7 +323,7 @@ func decodeSecret(data []byte) (DockerCfg, error) {
|
|||
return cfg, nil
|
||||
}
|
||||
|
||||
func decodeJSONSecret(data []byte) (DockerCfg, error) {
|
||||
func DecodeDockerCfgJson(data []byte) (DockerCfg, error) {
|
||||
var cfg DockerCfgJSON
|
||||
err := json.Unmarshal(data, &cfg)
|
||||
if err != nil {
|
||||
|
|
|
@ -39,7 +39,7 @@ func TestGetSecret(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -73,7 +73,7 @@ func TestGetDockerConfigJSONSecret(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -106,7 +106,7 @@ func TestGetDockerConfigJSONSecretUsernmePassword(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -128,6 +128,45 @@ func TestGetDockerConfigJSONSecretUsernmePassword(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetFromDefaultCredentials(t *testing.T) {
|
||||
imgRef, _ := image.Parse("karolisr/webhook-demo:0.0.11")
|
||||
|
||||
impl := &testutil.FakeK8sImplementer{
|
||||
AvailableSecret: &v1.Secret{
|
||||
Data: map[string][]byte{
|
||||
dockerConfigJSONKey: []byte(secretDockerConfigJSONPayloadWithUsernamePassword),
|
||||
},
|
||||
Type: v1.SecretTypeDockerConfigJson,
|
||||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl, DockerCfg{
|
||||
"https://index.docker.io/v1/": &Auth{
|
||||
Username: "aa",
|
||||
Password: "bb",
|
||||
},
|
||||
})
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
Namespace: "default",
|
||||
Secrets: []string{"myregistrysecret"},
|
||||
}
|
||||
|
||||
creds, err := getter.Get(trackedImage)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get creds: %s", err)
|
||||
}
|
||||
|
||||
if creds.Username != "aa" {
|
||||
t.Errorf("unexpected username: %s", creds.Username)
|
||||
}
|
||||
|
||||
if creds.Password != "bb" {
|
||||
t.Errorf("unexpected pass: %s", creds.Password)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSecretNotFound(t *testing.T) {
|
||||
imgRef, _ := image.Parse("karolisr/webhook-demo:0.0.11")
|
||||
|
||||
|
@ -135,7 +174,7 @@ func TestGetSecretNotFound(t *testing.T) {
|
|||
Error: fmt.Errorf("some error"),
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -183,7 +222,7 @@ func TestLookupHelmSecret(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -229,7 +268,7 @@ func TestLookupHelmEncodedSecret(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
@ -270,7 +309,7 @@ func TestLookupHelmNoSecretsFound(t *testing.T) {
|
|||
Error: fmt.Errorf("not found"),
|
||||
}
|
||||
|
||||
getter := NewGetter(impl)
|
||||
getter := NewGetter(impl, nil)
|
||||
|
||||
trackedImage := &types.TrackedImage{
|
||||
Image: imgRef,
|
||||
|
|
Loading…
Reference in New Issue