Skip to content

Commit 2778cd7

Browse files
authored
Allow organization BE ref validation to be skipped. (#201)
Required for migration when we switch off the BE part of the API-Server.
1 parent 0810551 commit 2778cd7

File tree

3 files changed

+40
-27
lines changed

3 files changed

+40
-27
lines changed

api.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ import (
3131
func APICommand() *cobra.Command {
3232
roles := []string{}
3333
usernamePrefix := ""
34-
var allowEmptyBillingEntity bool
34+
var allowEmptyBillingEntity, skipBillingEntityValidation bool
3535

3636
ob := &odooStorageBuilder{}
37-
ost := orgStore.New(&roles, &usernamePrefix, &allowEmptyBillingEntity)
37+
ost := orgStore.New(&roles, &usernamePrefix, &allowEmptyBillingEntity, &skipBillingEntityValidation)
3838
ib := &invitationStorageBuilder{usernamePrefix: &usernamePrefix}
3939

4040
cmd, err := builder.APIServer.
@@ -55,6 +55,7 @@ func APICommand() *cobra.Command {
5555
cmd.Flags().StringSliceVar(&roles, "cluster-roles", []string{}, "Cluster Roles to bind when creating an organization")
5656
cmd.Flags().StringVar(&usernamePrefix, "username-prefix", "", "Prefix prepended to username claims. Usually the same as \"--oidc-username-prefix\" of the Kubernetes API server")
5757
cmd.Flags().BoolVar(&allowEmptyBillingEntity, "allow-empty-billing-entity", true, "Allow empty billing entity references")
58+
cmd.Flags().BoolVar(&skipBillingEntityValidation, "organization-skip-billing-entity-validation", false, "Skip validation of billing entity references")
5859

5960
cmd.Flags().StringVar(&ob.billingEntityStorage, "billing-entity-storage", "fake", "Storage backend for billing entities. Supported values: fake, odoo8, odoo16")
6061

apiserver/organization/billingentity_validate.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package organization
33
import (
44
"context"
55
"fmt"
6+
"os"
67

78
"k8s.io/apiserver/pkg/authentication/user"
89
"k8s.io/apiserver/pkg/endpoints/request"
@@ -45,29 +46,38 @@ func (c impersonatorFromRestconf) Impersonate(u user.Info) (client.Client, error
4546
// billingEntityValidator validates that the billing entity exists and the requesting user has access to it.
4647
// it does so by impersonating the user and trying to get the billing entity.
4748
func (s *organizationStorage) billingEntityValidator(ctx context.Context, org, oldOrg *orgv1.Organization) error {
48-
// check if changed
49-
if oldOrg != nil && oldOrg.Spec.BillingEntityRef == org.Spec.BillingEntityRef {
50-
return nil
51-
}
52-
// check if we allow empty billing entities
53-
if org.Spec.BillingEntityRef == "" && s.allowEmptyBillingEntity {
54-
return nil
55-
}
49+
validate := func() error {
50+
// check if changed
51+
if oldOrg != nil && oldOrg.Spec.BillingEntityRef == org.Spec.BillingEntityRef {
52+
return nil
53+
}
54+
// check if we allow empty billing entities
55+
if org.Spec.BillingEntityRef == "" && s.allowEmptyBillingEntity {
56+
return nil
57+
}
5658

57-
user, ok := request.UserFrom(ctx)
58-
if !ok {
59-
return fmt.Errorf("no user in context")
60-
}
59+
user, ok := request.UserFrom(ctx)
60+
if !ok {
61+
return fmt.Errorf("no user in context")
62+
}
6163

62-
var be billingv1.BillingEntity
63-
c, err := s.impersonator.Impersonate(user)
64-
if err != nil {
65-
return fmt.Errorf("failed to impersonate user: %w", err)
66-
}
64+
var be billingv1.BillingEntity
65+
c, err := s.impersonator.Impersonate(user)
66+
if err != nil {
67+
return fmt.Errorf("failed to impersonate user: %w", err)
68+
}
69+
70+
if err := c.Get(ctx, client.ObjectKey{Name: org.Spec.BillingEntityRef}, &be); err != nil {
71+
return err
72+
}
6773

68-
if err := c.Get(ctx, client.ObjectKey{Name: org.Spec.BillingEntityRef}, &be); err != nil {
69-
return err
74+
return nil
7075
}
7176

72-
return nil
77+
err := validate()
78+
if err != nil && s.skipBillingEntityValidation {
79+
fmt.Fprintf(os.Stderr, "Warning: billing entity validation for %q (ref: %q) would have failed: %v\n", org.Name, org.Spec.BillingEntityRef, err)
80+
return nil
81+
}
82+
return err
7383
}

apiserver/organization/organization.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
// +kubebuilder:rbac:groups="flowcontrol.apiserver.k8s.io",resources=prioritylevelconfigurations;flowschemas,verbs=get;list;watch
2929

3030
// New returns a new storage provider for Organizations
31-
func New(clusterRoles *[]string, usernamePrefix *string, allowEmptyBillingEntity *bool) restbuilder.ResourceHandlerProvider {
31+
func New(clusterRoles *[]string, usernamePrefix *string, allowEmptyBillingEntity, skipBillingEntityValidation *bool) restbuilder.ResourceHandlerProvider {
3232
return func(s *runtime.Scheme, g genericregistry.RESTOptionsGetter) (rest.Storage, error) {
3333
masterConfig := loopback.GetLoopbackMasterClientConfig()
3434

@@ -54,9 +54,10 @@ func New(clusterRoles *[]string, usernamePrefix *string, allowEmptyBillingEntity
5454
members: kubeMemberProvider{
5555
Client: c,
5656
},
57-
usernamePrefix: *usernamePrefix,
58-
impersonator: impersonatorFromRestconf{masterConfig, client.Options{Scheme: c.Scheme()}},
59-
allowEmptyBillingEntity: *allowEmptyBillingEntity,
57+
usernamePrefix: *usernamePrefix,
58+
impersonator: impersonatorFromRestconf{masterConfig, client.Options{Scheme: c.Scheme()}},
59+
allowEmptyBillingEntity: *allowEmptyBillingEntity,
60+
skipBillingEntityValidation: *skipBillingEntityValidation,
6061
}
6162

6263
return authwrapper.NewAuthorizedStorage(stor, metav1.GroupVersionResource{
@@ -78,7 +79,8 @@ type organizationStorage struct {
7879

7980
impersonator impersonator
8081

81-
allowEmptyBillingEntity bool
82+
skipBillingEntityValidation bool
83+
allowEmptyBillingEntity bool
8284
}
8385

8486
func (s organizationStorage) New() runtime.Object {

0 commit comments

Comments
 (0)