Skip to content

Commit

Permalink
test: Add shim provider unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmidyson committed Nov 23, 2022
1 parent d5d0554 commit 39b4f1d
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 35 deletions.
7 changes: 4 additions & 3 deletions pkg/credentialprovider/shim/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func init() {
type shimProvider struct {
cfg *v1alpha1.KubeletImageCredentialProviderShimConfig

providersMutex sync.Mutex
providersMutex sync.RWMutex
providers map[string]Provider
}

Expand Down Expand Up @@ -117,13 +117,14 @@ func (p *shimProvider) registerCredentialProvider(name string, provider *pluginP
p.providers[name] = provider
}

var ErrTooManyCredentials = errors.New("too many credentials")

func (p *shimProvider) GetCredentials(
_ context.Context,
img string,
_ []string,
) (*credentialproviderv1beta1.CredentialProviderResponse, error) {
p.providersMutex.RLock()
defer p.providersMutex.RUnlock()

authMap := map[string]credentialproviderv1beta1.AuthConfig{}

mirrorAuthConfig, cacheDuration, mirrorAuthFound, err := p.getMirrorCredentialsForImage(img)
Expand Down
147 changes: 115 additions & 32 deletions pkg/credentialprovider/shim/shim_test.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,131 @@
// Copyright 2022 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package shim
package shim_test

import (
"context"
"encoding/json"
"log"
"os"
"path/filepath"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
credentialproviderv1beta1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1"

"github.com/mesosphere/kubelet-image-credential-provider-shim/pkg/credentialprovider/shim"
)

func ExampleCredentialProvider_GetCredentials() {
p, err := NewProviderFromConfigFile(filepath.Join("testdata", "config.yaml"))
if err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
}
func Test_shimProvider_GetCredentials(t *testing.T) {
//nolint:revive // Dummy duration ok in tests.
expectedDummyDuration := 5 * time.Second

creds, err := p.GetCredentials(context.Background(), "img.v1beta1/abc/def:v1.2.3", nil)
if err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
}
const (
dummyImage = "img.v1beta1/abc/def:v1.2.3"
mirrorUser = "mirroruser"
mirrorPassword = "mirrorpassword"
wildcardDomain = "*.*"
credentialProviderResponseKind = "CredentialProviderResponse" //nolint:gosec // No actual credentials here.
)

if err := json.NewEncoder(os.Stdout).Encode(creds); err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
}
//nolint:lll // Long example output.
// Output: {"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Image","cacheDuration":"5s","auth":{"img.v1beta1/abc/def:v1.2.3":{"username":"v1beta1user","password":"v1beta1password"}}}
}
t.Parallel()
tests := []struct {
name string
cfgFile string
img string
want *credentialproviderv1beta1.CredentialProviderResponse
wantErr error
}{{
name: "mirror only",
cfgFile: filepath.Join("testdata", "config-with-mirror-only.yaml"),
img: dummyImage,
want: &credentialproviderv1beta1.CredentialProviderResponse{
TypeMeta: v1.TypeMeta{
APIVersion: credentialproviderv1beta1.SchemeGroupVersion.String(),
Kind: credentialProviderResponseKind,
},
CacheKeyType: credentialproviderv1beta1.ImagePluginCacheKeyType,
CacheDuration: &v1.Duration{Duration: expectedDummyDuration},
Auth: map[string]credentialproviderv1beta1.AuthConfig{
dummyImage: {Username: mirrorUser, Password: mirrorPassword},
},
},
}, {
name: "mirror first",
cfgFile: filepath.Join("testdata", "config-with-mirror-first.yaml"),
img: dummyImage,
want: &credentialproviderv1beta1.CredentialProviderResponse{
TypeMeta: v1.TypeMeta{
APIVersion: credentialproviderv1beta1.SchemeGroupVersion.String(),
Kind: credentialProviderResponseKind,
},
CacheKeyType: credentialproviderv1beta1.ImagePluginCacheKeyType,
CacheDuration: &v1.Duration{Duration: expectedDummyDuration},
Auth: map[string]credentialproviderv1beta1.AuthConfig{
dummyImage: {Username: mirrorUser, Password: mirrorPassword},
wildcardDomain: {Username: "v1beta1user", Password: "v1beta1password"},
},
},
}, {
name: "mirror last",
cfgFile: filepath.Join("testdata", "config-with-mirror-last.yaml"),
img: dummyImage,
want: &credentialproviderv1beta1.CredentialProviderResponse{
TypeMeta: v1.TypeMeta{
APIVersion: credentialproviderv1beta1.SchemeGroupVersion.String(),
Kind: credentialProviderResponseKind,
},
CacheKeyType: credentialproviderv1beta1.ImagePluginCacheKeyType,
CacheDuration: &v1.Duration{Duration: expectedDummyDuration},
Auth: map[string]credentialproviderv1beta1.AuthConfig{
wildcardDomain: {Username: mirrorUser, Password: mirrorPassword},
dummyImage: {Username: "v1beta1user", Password: "v1beta1password"},
},
},
}, {
name: "mirror and no matching origin",
cfgFile: filepath.Join("testdata", "config-with-mirror-last.yaml"),
img: "noorigin/image:v1.2.3.4",
want: &credentialproviderv1beta1.CredentialProviderResponse{
TypeMeta: v1.TypeMeta{
APIVersion: credentialproviderv1beta1.SchemeGroupVersion.String(),
Kind: credentialProviderResponseKind,
},
CacheKeyType: credentialproviderv1beta1.ImagePluginCacheKeyType,
CacheDuration: &v1.Duration{Duration: expectedDummyDuration},
Auth: map[string]credentialproviderv1beta1.AuthConfig{
wildcardDomain: {Username: mirrorUser, Password: mirrorPassword},
},
},
}, {
name: "no mirror",
cfgFile: filepath.Join("testdata", "config-no-mirror.yaml"),
img: dummyImage,
want: &credentialproviderv1beta1.CredentialProviderResponse{
TypeMeta: v1.TypeMeta{
APIVersion: credentialproviderv1beta1.SchemeGroupVersion.String(),
Kind: credentialProviderResponseKind,
},
CacheKeyType: credentialproviderv1beta1.ImagePluginCacheKeyType,
CacheDuration: &v1.Duration{Duration: expectedDummyDuration},
Auth: map[string]credentialproviderv1beta1.AuthConfig{
dummyImage: {Username: "v1beta1user", Password: "v1beta1password"},
},
},
}}
for _, tt := range tests {
tt := tt // Capture range variable.

func ExampleCredentialProvider_GetCredentials_withMirror() {
p, err := NewProviderFromConfigFile(filepath.Join("testdata", "config-with-mirror.yaml"))
if err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
}
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

creds, err := p.GetCredentials(context.Background(), "img.v1beta1/abc/def:v1.2.3", nil)
if err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
}
p, err := shim.NewProviderFromConfigFile(tt.cfgFile)
require.NoError(t, err)

if err := json.NewEncoder(os.Stdout).Encode(creds); err != nil {
log.Fatal(err) //nolint:revive // Allow fatal in examples.
got, err := p.GetCredentials(context.Background(), tt.img, nil)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
}
//nolint:lll // Long example output.
// Output: {"kind":"CredentialProviderResponse","apiVersion":"credentialprovider.kubelet.k8s.io/v1beta1","cacheKeyType":"Image","cacheDuration":"5s","auth":{"*.*":{"username":"v1beta1user","password":"v1beta1password"},"img.v1beta1/abc/def:v1.2.3":{"username":"mirroruser","password":"mirrorpassword"}}}
}
25 changes: 25 additions & 0 deletions pkg/credentialprovider/shim/testdata/config-with-mirror-last.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2022 D2iQ, Inc. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: config.kubeletimagecredentialprovidershim.d2iq.com/v1alpha1
kind: KubeletImageCredentialProviderShimConfig
mirror:
endpoint: someregistry.com
credentialsStrategy: MirrorCredentialsLast
credentialProviderPluginBinDir: testdata
credentialProviders:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: CredentialProviderConfig
providers:
- name: staticcredentialprovider-v1alpha1.sh
matchImages:
- '*.v1alpha1'
apiVersion: credentialprovider.kubelet.k8s.io/v1alpha1
- name: staticcredentialprovider-v1beta1.sh
matchImages:
- '*.v1beta1'
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1
- name: staticcredentialprovider-mirror.sh
matchImages:
- someregistry.com
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1
25 changes: 25 additions & 0 deletions pkg/credentialprovider/shim/testdata/config-with-mirror-only.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2022 D2iQ, Inc. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: config.kubeletimagecredentialprovidershim.d2iq.com/v1alpha1
kind: KubeletImageCredentialProviderShimConfig
mirror:
endpoint: someregistry.com
credentialsStrategy: MirrorCredentialsOnly
credentialProviderPluginBinDir: testdata
credentialProviders:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: CredentialProviderConfig
providers:
- name: staticcredentialprovider-v1alpha1.sh
matchImages:
- '*.v1alpha1'
apiVersion: credentialprovider.kubelet.k8s.io/v1alpha1
- name: staticcredentialprovider-v1beta1.sh
matchImages:
- '*.v1beta1'
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1
- name: staticcredentialprovider-mirror.sh
matchImages:
- someregistry.com
apiVersion: credentialprovider.kubelet.k8s.io/v1beta1

0 comments on commit 39b4f1d

Please sign in to comment.