Skip to content

Commit 96dd7e1

Browse files
authored
Merge pull request #355 from justinsb/refactor_storage
mockkubeapiserver: Refactor storage to be pluggable
2 parents e772071 + ccba24e commit 96dd7e1

32 files changed

+3608
-3059
lines changed

mockkubeapiserver/apiserver.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,47 @@ import (
2222
"strings"
2323

2424
"k8s.io/klog/v2"
25+
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver/hooks"
26+
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver/storage"
27+
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver/storage/memorystorage"
2528
)
2629

27-
func NewMockKubeAPIServer(addr string) (*MockKubeAPIServer, error) {
30+
func NewMockKubeAPIServer(addr string, options ...Option) (*MockKubeAPIServer, error) {
2831
s := &MockKubeAPIServer{}
2932
if addr == "" {
3033
addr = ":http"
3134
}
3235

3336
s.httpServer = &http.Server{Addr: addr, Handler: s}
3437

35-
var err error
38+
for _, option := range options {
39+
if err := option(s); err != nil {
40+
return nil, err
41+
}
42+
}
3643

37-
s.storage, err = NewMemoryStorage(NewTestClock(), NewTestUIDGenerator())
38-
if err != nil {
39-
return nil, err
44+
// If storage wasn't set with an option, default to memory storage
45+
if s.storage == nil {
46+
storage, err := memorystorage.NewMemoryStorage(storage.NewTestClock(), storage.NewTestUIDGenerator())
47+
if err != nil {
48+
return nil, err
49+
}
50+
s.storage = storage
4051
}
4152

53+
// These hooks mock behaviour that would otherwise require full controllers
54+
s.storage.AddStorageHook(&hooks.CRDHook{})
55+
s.storage.AddStorageHook(&hooks.NamespaceHook{})
56+
s.storage.AddStorageHook(&hooks.DeploymentHook{})
57+
4258
return s, nil
4359
}
4460

4561
type MockKubeAPIServer struct {
4662
httpServer *http.Server
4763
listener net.Listener
4864

49-
storage *MemoryStorage
65+
storage storage.Storage
5066

5167
hooks []Hook
5268
}
@@ -337,3 +353,13 @@ func (s *MockKubeAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
337353
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
338354
}
339355
}
356+
357+
type Option func(config *MockKubeAPIServer) error
358+
359+
// WithStorage is an Option that allows specifying the storage implementation.
360+
func WithStorage(storage storage.Storage) Option {
361+
return func(config *MockKubeAPIServer) error {
362+
config.storage = storage
363+
return nil
364+
}
365+
}

mockkubeapiserver/controllers.go

Lines changed: 0 additions & 213 deletions
This file was deleted.

mockkubeapiserver/deleteresource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (req *deleteResource) Run(ctx context.Context, s *MockKubeAPIServer) error
4444
return fmt.Errorf("unexpected subresource on delete %q", req.SubResource)
4545
}
4646

47-
deletedObject, err := s.storage.DeleteObject(ctx, resource, id)
47+
deletedObject, err := resource.DeleteObject(ctx, id)
4848
if err != nil {
4949
return err
5050
}

mockkubeapiserver/getresource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (req *getResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
5252

5353
id := types.NamespacedName{Namespace: req.Namespace, Name: req.Name}
5454

55-
object, found, err := s.storage.GetObject(ctx, resource, id)
55+
object, found, err := resource.GetObject(ctx, id)
5656
if err != nil {
5757
return err
5858
}

mockkubeapiserver/hooks/crd.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package hooks
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/runtime/schema"
21+
"k8s.io/klog/v2"
22+
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver/storage"
23+
)
24+
25+
// CRDHook implements functionality for CRD objects (the definitions themselves, not instances of CRDs)
26+
type CRDHook struct {
27+
storage storage.Storage
28+
}
29+
30+
func (s *CRDHook) OnWatchEvent(ev *storage.WatchEvent) {
31+
switch ev.GroupKind() {
32+
case schema.GroupKind{Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"}:
33+
// When a CRD is created, we notify the storage layer so it can store instances of the CRD
34+
if err := s.storage.UpdateCRD(ev); err != nil {
35+
klog.Warningf("crd change was invalid: %v", err)
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)