Skip to content

Commit

Permalink
Merge pull request #16 from iawia002/cache-client
Browse files Browse the repository at this point in the history
kubernetes/client: add a new function to generate cache client only
  • Loading branch information
iawia002 authored Aug 29, 2023
2 parents 275ff0c + 5d33ccd commit c5fce15
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 45 deletions.
105 changes: 81 additions & 24 deletions kubernetes/client/generic/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package generic
import (
"context"
"errors"
"net/http"
"time"

"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
Expand All @@ -19,6 +21,8 @@ type Options struct {
scheme *runtime.Scheme
cacheReader bool
ctx context.Context
httpClient *http.Client
mapper meta.RESTMapper
}

// WithSyncPeriod sets the SyncPeriod time option.
Expand Down Expand Up @@ -53,6 +57,61 @@ func WithContext(ctx context.Context) func(opts *Options) {
}
}

// WithHTTPClient sets the HTTPClient for the client.
func WithHTTPClient(httpClient *http.Client) func(opts *Options) {
return func(opts *Options) {
opts.httpClient = httpClient
}
}

// WithMapper sets the Mapper for the client.
func WithMapper(mapper meta.RESTMapper) func(opts *Options) {
return func(opts *Options) {
opts.mapper = mapper
}
}

// NewCache returns a controller-runtime cache client implementation.
func NewCache(config *rest.Config, options ...func(*Options)) (cache.Cache, error) {
opts := &Options{
scheme: scheme.Scheme,
ctx: context.Background(),
}
for _, f := range options {
f(opts)
}

if opts.httpClient == nil {
httpClient, err := rest.HTTPClientFor(config)
if err != nil {
return nil, err
}
opts.httpClient = httpClient
}
if opts.mapper == nil {
mapper, err := apiutil.NewDynamicRESTMapper(config, opts.httpClient)
if err != nil {
return nil, err
}
opts.mapper = mapper
}

cacheClient, err := cache.New(config, cache.Options{
HTTPClient: opts.httpClient,
Scheme: opts.scheme,
Mapper: opts.mapper,
SyncPeriod: opts.syncPeriod,
})
if err != nil {
return nil, err
}
go cacheClient.Start(opts.ctx) // nolint
if !cacheClient.WaitForCacheSync(opts.ctx) {
return nil, errors.New("WaitForCacheSync failed")
}
return cacheClient, nil
}

// NewClient returns a controller-runtime generic Client implementation.
func NewClient(config *rest.Config, options ...func(*Options)) (client.Client, error) {
opts := &Options{
Expand All @@ -64,44 +123,42 @@ func NewClient(config *rest.Config, options ...func(*Options)) (client.Client, e
f(opts)
}

httpClient, err := rest.HTTPClientFor(config)
if err != nil {
return nil, err
if opts.httpClient == nil {
httpClient, err := rest.HTTPClientFor(config)
if err != nil {
return nil, err
}
opts.httpClient = httpClient
}
mapper, err := apiutil.NewDynamicRESTMapper(config, httpClient)
if err != nil {
return nil, err
if opts.mapper == nil {
mapper, err := apiutil.NewDynamicRESTMapper(config, opts.httpClient)
if err != nil {
return nil, err
}
opts.mapper = mapper
}

clientOptions := client.Options{
HTTPClient: httpClient,
HTTPClient: opts.httpClient,
Scheme: opts.scheme,
Mapper: mapper,
Mapper: opts.mapper,
}

if opts.cacheReader {
cacheClient, err := cache.New(config, cache.Options{
HTTPClient: httpClient,
Scheme: opts.scheme,
Mapper: mapper,
SyncPeriod: opts.syncPeriod,
})
cacheClient, err := NewCache(config,
WithHTTPClient(opts.httpClient),
WithScheme(opts.scheme),
WithMapper(opts.mapper),
WithSyncPeriod(opts.syncPeriod),
WithContext(opts.ctx),
)
if err != nil {
return nil, err
}
go cacheClient.Start(opts.ctx) // nolint
if !cacheClient.WaitForCacheSync(opts.ctx) {
return nil, errors.New("WaitForCacheSync failed")
}
clientOptions.Cache = &client.CacheOptions{
Reader: cacheClient,
Unstructured: true,
}
}

genericClient, err := client.New(config, clientOptions)
if err != nil {
return nil, err
}
return genericClient, nil
return client.New(config, clientOptions)
}
2 changes: 1 addition & 1 deletion kubernetes/client/typed/typed.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewTypedClient(gvk schema.GroupVersionKind, opts ...func(*options)) (Client
}
o.config = inClusterConfig
}
cache, err := genericclient.NewClient(o.config, genericclient.WithScheme(o.scheme))
cache, err := genericclient.NewCache(o.config, genericclient.WithScheme(o.scheme))
if err != nil {
return nil, err
}
Expand Down
20 changes: 10 additions & 10 deletions kubernetes/client/typed/typed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

Expand All @@ -24,15 +24,15 @@ var (
func TestTypedGet(t *testing.T) {
tests := []struct {
name string
objs []client.Object
objs []runtime.Object
gvk schema.GroupVersionKind
key types.NamespacedName
isErr bool
wanted string
}{
{
name: "normal test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
key: types.NamespacedName{
Name: pod1Name,
Expand All @@ -41,7 +41,7 @@ func TestTypedGet(t *testing.T) {
},
{
name: "not exists test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
key: types.NamespacedName{
Name: "aaa",
Expand All @@ -50,7 +50,7 @@ func TestTypedGet(t *testing.T) {
},
{
name: "wrong type test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod1"),
key: types.NamespacedName{
Name: pod1Name,
Expand All @@ -60,7 +60,7 @@ func TestTypedGet(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := fake.NewClientBuilder().WithObjects(tt.objs...).Build()
c := fake.NewFakeClient(tt.objs...)
typedClient, _ := NewTypedClient(tt.gvk, WithClientReader(c))

got, err := typedClient.Get(context.TODO(), tt.key)
Expand All @@ -81,27 +81,27 @@ func TestTypedGet(t *testing.T) {
func TestTypedList(t *testing.T) {
tests := []struct {
name string
objs []client.Object
objs []runtime.Object
gvk schema.GroupVersionKind
isErr bool
wanted int
}{
{
name: "normal test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
wanted: 1,
},
{
name: "wrong type test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod1"),
isErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := fake.NewClientBuilder().WithObjects(tt.objs...).Build()
c := fake.NewFakeClient(tt.objs...)
typedClient, _ := NewTypedClient(tt.gvk, WithClientReader(c))

got, err := typedClient.List(context.TODO(), metav1.NamespaceAll)
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/client/typed/unstructured.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewUnstructuredTypedClient(gvk schema.GroupVersionKind, opts ...func(*optio
}
o.config = inClusterConfig
}
cache, err := genericclient.NewClient(o.config)
cache, err := genericclient.NewCache(o.config)
if err != nil {
return nil, err
}
Expand Down
18 changes: 9 additions & 9 deletions kubernetes/client/typed/unstructured_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

unstructuredutils "github.com/iawia002/lia/kubernetes/unstructured"
Expand All @@ -18,15 +18,15 @@ import (
func TestUnstructuredGet(t *testing.T) {
tests := []struct {
name string
objs []client.Object
objs []runtime.Object
gvk schema.GroupVersionKind
key types.NamespacedName
isErr bool
wanted string
}{
{
name: "normal test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
key: types.NamespacedName{
Name: pod1Name,
Expand All @@ -35,7 +35,7 @@ func TestUnstructuredGet(t *testing.T) {
},
{
name: "not exists test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
key: types.NamespacedName{
Name: "aaa",
Expand All @@ -44,7 +44,7 @@ func TestUnstructuredGet(t *testing.T) {
},
{
name: "wrong type test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod1"),
key: types.NamespacedName{
Name: pod1Name,
Expand All @@ -54,7 +54,7 @@ func TestUnstructuredGet(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := fake.NewClientBuilder().WithObjects(tt.objs...).Build()
c := fake.NewFakeClient(tt.objs...)
typedClient, _ := NewUnstructuredTypedClient(tt.gvk, WithClientReader(c))

got, err := typedClient.Get(context.TODO(), tt.key)
Expand All @@ -76,21 +76,21 @@ func TestUnstructuredGet(t *testing.T) {
func TestUnstructuredList(t *testing.T) {
tests := []struct {
name string
objs []client.Object
objs []runtime.Object
gvk schema.GroupVersionKind
isErr bool
wanted int
}{
{
name: "normal test",
objs: []client.Object{pod1},
objs: []runtime.Object{pod1},
gvk: corev1.SchemeGroupVersion.WithKind("Pod"),
wanted: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := fake.NewClientBuilder().WithObjects(tt.objs...).Build()
c := fake.NewFakeClient(tt.objs...)
typedClient, _ := NewUnstructuredTypedClient(tt.gvk, WithClientReader(c))

got, err := typedClient.List(context.TODO(), metav1.NamespaceAll)
Expand Down

0 comments on commit c5fce15

Please sign in to comment.