Skip to content

Commit fff02ee

Browse files
committed
Refactor and test Get and Create
1 parent 2348994 commit fff02ee

File tree

8 files changed

+357
-27
lines changed

8 files changed

+357
-27
lines changed

.codeclimate.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ exclude_patterns:
2727
- '**/*.d.ts'
2828
- 'e2e/lib/'
2929
- '**/zz_generated.deepcopy.go'
30+
- '**/mock/'

apiserver/organization/mock/namespace.go

Lines changed: 127 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apiserver/organization/namespace.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,25 @@ import (
1313
"sigs.k8s.io/controller-runtime/pkg/client"
1414
)
1515

16+
// namespaceProvider is an abstraction for interacting with the Kubernetes API
17+
//go:generate mockgen -source=$GOFILE -destination=./mock/$GOFILE
18+
type namespaceProvider interface {
19+
GetNamespace(ctx context.Context, name string, options *metav1.GetOptions) (*corev1.Namespace, error)
20+
DeleteNamespace(ctx context.Context, name string, options *metav1.DeleteOptions) (*corev1.Namespace, error)
21+
CreateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.CreateOptions) error
22+
UpdateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.UpdateOptions) error
23+
ListNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*corev1.NamespaceList, error)
24+
WatchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
25+
}
26+
1627
type loopbackNamespaceProvider struct {
1728
initOnce sync.Once
1829
client client.WithWatch
1930
}
2031

2132
func (p *loopbackNamespaceProvider) init() error {
33+
// The LoopbackMasterClientConfig is initialized lazily by the runtime
34+
// We initialize the client once from which ever method is called first
2235
var err error
2336
p.initOnce.Do(func() {
2437
if p.client == nil {
@@ -28,7 +41,7 @@ func (p *loopbackNamespaceProvider) init() error {
2841
return err
2942
}
3043

31-
func (p *loopbackNamespaceProvider) getNamespace(ctx context.Context, name string, options *metav1.GetOptions) (*corev1.Namespace, error) {
44+
func (p *loopbackNamespaceProvider) GetNamespace(ctx context.Context, name string, options *metav1.GetOptions) (*corev1.Namespace, error) {
3245
err := p.init()
3346
if err != nil {
3447
return nil, err
@@ -38,7 +51,7 @@ func (p *loopbackNamespaceProvider) getNamespace(ctx context.Context, name strin
3851
return &ns, err
3952
}
4053

41-
func (p *loopbackNamespaceProvider) deleteNamespace(ctx context.Context, name string, options *metav1.DeleteOptions) (*corev1.Namespace, error) {
54+
func (p *loopbackNamespaceProvider) DeleteNamespace(ctx context.Context, name string, options *metav1.DeleteOptions) (*corev1.Namespace, error) {
4255
err := p.init()
4356
if err != nil {
4457
return nil, err
@@ -51,7 +64,7 @@ func (p *loopbackNamespaceProvider) deleteNamespace(ctx context.Context, name st
5164
return &ns, err
5265
}
5366

54-
func (p *loopbackNamespaceProvider) createNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.CreateOptions) error {
67+
func (p *loopbackNamespaceProvider) CreateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.CreateOptions) error {
5568
err := p.init()
5669
if err != nil {
5770
return err
@@ -61,7 +74,7 @@ func (p *loopbackNamespaceProvider) createNamespace(ctx context.Context, ns *cor
6174
})
6275
}
6376

64-
func (p *loopbackNamespaceProvider) updateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.UpdateOptions) error {
77+
func (p *loopbackNamespaceProvider) UpdateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.UpdateOptions) error {
6578
err := p.init()
6679
if err != nil {
6780
return err
@@ -71,7 +84,7 @@ func (p *loopbackNamespaceProvider) updateNamespace(ctx context.Context, ns *cor
7184
})
7285
}
7386

74-
func (p *loopbackNamespaceProvider) listNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*corev1.NamespaceList, error) {
87+
func (p *loopbackNamespaceProvider) ListNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*corev1.NamespaceList, error) {
7588
err := p.init()
7689
if err != nil {
7790
return nil, err
@@ -89,7 +102,7 @@ func (p *loopbackNamespaceProvider) listNamespaces(ctx context.Context, options
89102
return &nl, nil
90103
}
91104

92-
func (p *loopbackNamespaceProvider) watchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
105+
func (p *loopbackNamespaceProvider) WatchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
93106
err := p.init()
94107
if err != nil {
95108
return nil, err

apiserver/organization/organization.go

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package organization
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67

78
orgv1 "github.com/appuio/control-api/apis/organization/v1"
89

910
corev1 "k8s.io/api/core/v1"
11+
apierrors "k8s.io/apimachinery/pkg/api/errors"
1012
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
1113
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1214
"k8s.io/apimachinery/pkg/labels"
1315
"k8s.io/apimachinery/pkg/runtime"
16+
"k8s.io/apimachinery/pkg/runtime/schema"
1417
"k8s.io/apimachinery/pkg/selection"
1518
"k8s.io/apimachinery/pkg/watch"
1619
genericregistry "k8s.io/apiserver/pkg/registry/generic"
@@ -30,14 +33,6 @@ func New() restbuilder.ResourceHandlerProvider {
3033
type organizationStorage struct {
3134
namepaces namespaceProvider
3235
}
33-
type namespaceProvider interface {
34-
getNamespace(ctx context.Context, name string, options *metav1.GetOptions) (*corev1.Namespace, error)
35-
deleteNamespace(ctx context.Context, name string, options *metav1.DeleteOptions) (*corev1.Namespace, error)
36-
createNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.CreateOptions) error
37-
updateNamespace(ctx context.Context, ns *corev1.Namespace, options *metav1.UpdateOptions) error
38-
listNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (*corev1.NamespaceList, error)
39-
watchNamespaces(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
40-
}
4136

4237
func (s organizationStorage) New() runtime.Object {
4338
return &orgv1.Organization{}
@@ -52,13 +47,17 @@ func (s *organizationStorage) NamespaceScoped() bool {
5247
var _ rest.Getter = &organizationStorage{}
5348

5449
func (s *organizationStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
55-
ns, err := s.namepaces.getNamespace(ctx, name, options)
50+
org := &orgv1.Organization{}
51+
ns, err := s.namepaces.GetNamespace(ctx, name, options)
5652
if err != nil {
57-
return nil, err
53+
return nil, convertNamespaceError(err)
5854
}
59-
60-
// TODO(glrf) Check that this is actually an organization and not a random namespace
61-
return orgv1.NewOrganizationFromNS(ns), nil
55+
org = orgv1.NewOrganizationFromNS(ns)
56+
if org == nil {
57+
// This namespace is not an organization
58+
return nil, apierrors.NewNotFound(org.GetGroupVersionResource().GroupResource(), name)
59+
}
60+
return org, nil
6261
}
6362

6463
var _ rest.Creater = &organizationStorage{}
@@ -74,8 +73,8 @@ func (s *organizationStorage) Create(ctx context.Context, obj runtime.Object, cr
7473
return nil, err
7574
}
7675

77-
if err := s.namepaces.createNamespace(ctx, org.ToNamespace(), options); err != nil {
78-
return nil, err
76+
if err := s.namepaces.CreateNamespace(ctx, org.ToNamespace(), options); err != nil {
77+
return nil, convertNamespaceError(err)
7978
}
8079
return org, nil
8180
}
@@ -92,7 +91,7 @@ func (s *organizationStorage) List(ctx context.Context, options *metainternalver
9291
return nil, err
9392
}
9493
options.LabelSelector = options.LabelSelector.Add(*orgNamspace)
95-
namespaces, err := s.namepaces.listNamespaces(ctx, options)
94+
namespaces, err := s.namepaces.ListNamespaces(ctx, options)
9695
if err != nil {
9796
return nil, err
9897
}
@@ -141,7 +140,7 @@ func (s *organizationStorage) Update(ctx context.Context, name string, objInfo r
141140
}
142141
}
143142

144-
return newOrg, false, s.namepaces.updateNamespace(ctx, newOrg.ToNamespace(), options)
143+
return newOrg, false, s.namepaces.UpdateNamespace(ctx, newOrg.ToNamespace(), options)
145144
}
146145

147146
var _ rest.GracefulDeleter = &organizationStorage{}
@@ -159,7 +158,7 @@ func (s *organizationStorage) Delete(ctx context.Context, name string, deleteVal
159158
}
160159
}
161160

162-
ns, err := s.namepaces.deleteNamespace(ctx, name, options)
161+
ns, err := s.namepaces.DeleteNamespace(ctx, name, options)
163162
return orgv1.NewOrganizationFromNS(ns), false, err
164163
}
165164

@@ -172,7 +171,7 @@ func (s *organizationStorage) Watch(ctx context.Context, options *metainternalve
172171
}
173172
options.LabelSelector = options.LabelSelector.Add(*orgNamspace)
174173

175-
nsWatcher, err := s.namepaces.watchNamespaces(ctx, options)
174+
nsWatcher, err := s.namepaces.WatchNamespaces(ctx, options)
176175
if err != nil {
177176
return nil, err
178177
}
@@ -194,3 +193,21 @@ func (s *organizationStorage) Watch(ctx context.Context, options *metainternalve
194193
return in, true
195194
}), nil
196195
}
196+
197+
func convertNamespaceError(err error) error {
198+
groupResource := schema.GroupResource{
199+
Group: orgv1.GroupVersion.Group,
200+
Resource: "organizations",
201+
}
202+
statusErr := &apierrors.StatusError{}
203+
204+
if errors.As(err, &statusErr) {
205+
switch {
206+
case apierrors.IsNotFound(err):
207+
return apierrors.NewNotFound(groupResource, statusErr.ErrStatus.Details.Name)
208+
case apierrors.IsAlreadyExists(err):
209+
return apierrors.NewAlreadyExists(groupResource, statusErr.ErrStatus.Details.Name)
210+
}
211+
}
212+
return err
213+
}

0 commit comments

Comments
 (0)