Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add shim provider unit tests #30

Merged
merged 1 commit into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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