-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Frank Jogeleit <[email protected]>
- Loading branch information
Frank Jogeleit
committed
Apr 28, 2024
1 parent
76797be
commit 6410d00
Showing
3 changed files
with
253 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package namespaces_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"testing" | ||
|
||
gocache "github.com/patrickmn/go-cache" | ||
"github.com/stretchr/testify/assert" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes/fake" | ||
v1 "k8s.io/client-go/kubernetes/typed/core/v1" | ||
|
||
"github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" | ||
) | ||
|
||
func newFakeClient() v1.NamespaceInterface { | ||
return fake.NewSimpleClientset( | ||
&corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "default", | ||
Labels: map[string]string{ | ||
"team": "team-a", | ||
"name": "default", | ||
}, | ||
}, | ||
}, | ||
&corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "user", | ||
Labels: map[string]string{ | ||
"team": "team-a", | ||
"name": "user", | ||
}, | ||
}, | ||
}, | ||
).CoreV1().Namespaces() | ||
} | ||
|
||
type nsErrorClient struct { | ||
v1.NamespaceInterface | ||
} | ||
|
||
func (s *nsErrorClient) List(ctx context.Context, opts metav1.ListOptions) (*corev1.NamespaceList, error) { | ||
return nil, errors.New("error") | ||
} | ||
|
||
func TestClient(t *testing.T) { | ||
t.Run("read from api", func(t *testing.T) { | ||
client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration)) | ||
|
||
list, err := client.List(context.Background(), map[string]string{"name": "default"}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 1, len(list)) | ||
}) | ||
|
||
t.Run("read from cache", func(t *testing.T) { | ||
fake := newFakeClient() | ||
cache := gocache.New(gocache.NoExpiration, gocache.NoExpiration) | ||
|
||
client := namespaces.NewClient(fake, cache) | ||
|
||
list, err := client.List(context.Background(), map[string]string{"team": "team-a"}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 2, len(list)) | ||
|
||
fake.Create(context.Background(), &corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "finance", | ||
Labels: map[string]string{ | ||
"team": "team-a", | ||
"name": "finance", | ||
}, | ||
}, | ||
}, metav1.CreateOptions{}) | ||
|
||
list, err = client.List(context.Background(), map[string]string{"team": "team-a"}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 2, len(list)) | ||
|
||
cache.Flush() | ||
|
||
list, err = client.List(context.Background(), map[string]string{"team": "team-a"}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 3, len(list)) | ||
}) | ||
t.Run("return error", func(t *testing.T) { | ||
client := namespaces.NewClient(&nsErrorClient{NamespaceInterface: newFakeClient()}, gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration)) | ||
|
||
_, err := client.List(context.Background(), map[string]string{"team": "team-a"}) | ||
|
||
assert.NotNil(t, err) | ||
assert.Equal(t, "error", err.Error()) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package kubernetes_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"testing" | ||
|
||
"github.com/kyverno/policy-reporter/pkg/kubernetes" | ||
"github.com/stretchr/testify/assert" | ||
corev1 "k8s.io/api/core/v1" | ||
kerr "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes/fake" | ||
v1 "k8s.io/client-go/kubernetes/typed/core/v1" | ||
) | ||
|
||
func newFakeClient() v1.NamespaceInterface { | ||
return fake.NewSimpleClientset( | ||
&corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "default", | ||
Labels: map[string]string{ | ||
"team": "team-a", | ||
"name": "default", | ||
}, | ||
}, | ||
}, | ||
&corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "user", | ||
Labels: map[string]string{ | ||
"team": "team-a", | ||
"name": "user", | ||
}, | ||
}, | ||
}, | ||
).CoreV1().Namespaces() | ||
} | ||
|
||
type ns struct { | ||
maxRetry int | ||
try int | ||
err bool | ||
v1.NamespaceInterface | ||
} | ||
|
||
func (s *ns) List(ctx context.Context, opts metav1.ListOptions) (*corev1.NamespaceList, error) { | ||
if !s.err { | ||
if s.try >= s.maxRetry { | ||
return s.NamespaceInterface.List(ctx, opts) | ||
} | ||
|
||
s.try++ | ||
} | ||
|
||
return nil, errors.New("error") | ||
} | ||
|
||
func TestRetry(t *testing.T) { | ||
t.Run("direct success", func(t *testing.T) { | ||
client := &ns{NamespaceInterface: newFakeClient()} | ||
|
||
list, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { | ||
return client.List(context.Background(), metav1.ListOptions{}) | ||
}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 2, len(list.Items)) | ||
}) | ||
|
||
t.Run("retry success", func(t *testing.T) { | ||
client := &ns{maxRetry: 1, NamespaceInterface: newFakeClient()} | ||
|
||
list, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { | ||
return client.List(context.Background(), metav1.ListOptions{}) | ||
}) | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 2, len(list.Items)) | ||
}) | ||
|
||
t.Run("retry error", func(t *testing.T) { | ||
client := &ns{NamespaceInterface: newFakeClient(), err: true} | ||
|
||
_, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { | ||
return client.List(context.Background(), metav1.ListOptions{}) | ||
}) | ||
|
||
assert.NotNil(t, err) | ||
}) | ||
|
||
t.Run("retry timeout", func(t *testing.T) { | ||
try := 0 | ||
|
||
_, err := kubernetes.Retry(func() (any, error) { | ||
try++ | ||
|
||
return nil, &kerr.StatusError{ | ||
ErrStatus: metav1.Status{Reason: metav1.StatusReasonTimeout}, | ||
} | ||
}) | ||
|
||
assert.Equal(t, 5, try) | ||
assert.NotNil(t, err) | ||
}) | ||
|
||
t.Run("retry server timeout", func(t *testing.T) { | ||
try := 0 | ||
|
||
_, err := kubernetes.Retry(func() (any, error) { | ||
try++ | ||
|
||
return nil, &kerr.StatusError{ | ||
ErrStatus: metav1.Status{Reason: metav1.StatusReasonServerTimeout}, | ||
} | ||
}) | ||
|
||
assert.Equal(t, 5, try) | ||
assert.NotNil(t, err) | ||
}) | ||
|
||
t.Run("retry service unavailable", func(t *testing.T) { | ||
try := 0 | ||
|
||
_, err := kubernetes.Retry(func() (any, error) { | ||
try++ | ||
|
||
return nil, &kerr.StatusError{ | ||
ErrStatus: metav1.Status{Reason: metav1.StatusReasonServiceUnavailable}, | ||
} | ||
}) | ||
|
||
assert.Equal(t, 5, try) | ||
assert.NotNil(t, err) | ||
}) | ||
|
||
t.Run("retry ignore other status", func(t *testing.T) { | ||
try := 0 | ||
|
||
_, err := kubernetes.Retry(func() (any, error) { | ||
try++ | ||
|
||
return nil, &kerr.StatusError{ | ||
ErrStatus: metav1.Status{Reason: metav1.StatusReasonForbidden}, | ||
} | ||
}) | ||
|
||
assert.Equal(t, 1, try) | ||
assert.NotNil(t, err) | ||
}) | ||
} |