Skip to content

Commit

Permalink
Updates to controller-runtime v0.15 API
Browse files Browse the repository at this point in the history
  • Loading branch information
dagan committed Jul 23, 2023
1 parent a291d66 commit 5704329
Show file tree
Hide file tree
Showing 10 changed files with 601 additions and 228 deletions.
8 changes: 4 additions & 4 deletions api/v1alpha1/userref_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import (

// UserRefSpec defines the desired state of UserRef
type UserRefSpec struct {

// UserName sets the username that will be impersonated when this UserRef
// is used.
UserName string `json:"username,omitempty"`
User string `json:"user,omitempty"`
UID string `json:"uid,omitempty"`
Groups []string `json:"groups,omitempty"`
Extra map[string][]string `json:"extra,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
22 changes: 21 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

222 changes: 173 additions & 49 deletions config/crd/bases/konfirm.goraft.tech_testruns.yaml

Large diffs are not rendered by default.

209 changes: 161 additions & 48 deletions config/crd/bases/konfirm.goraft.tech_tests.yaml

Large diffs are not rendered by default.

227 changes: 174 additions & 53 deletions config/crd/bases/konfirm.goraft.tech_testsuites.yaml

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions config/crd/bases/konfirm.goraft.tech_userrefs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,19 @@ spec:
spec:
description: UserRefSpec defines the desired state of UserRef
properties:
username:
description: UserName sets the username that will be impersonated
when this UserRef is used.
extra:
additionalProperties:
items:
type: string
type: array
type: object
groups:
items:
type: string
type: array
uid:
type: string
user:
type: string
type: object
type: object
Expand Down
4 changes: 2 additions & 2 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func setUpDefaultUserRef(ctx context.Context, k8sClient client.Client) {
Name: impersonate.DefaultUserRef.Name,
},
Spec: konfirmv1alpha1.UserRefSpec{
UserName: "konfirm-tester",
User: "konfirm-tester",
},
}
err = k8sClient.Create(ctx, &defaultUserRef)
Expand All @@ -209,7 +209,7 @@ func setUpDefaultUserRef(ctx context.Context, k8sClient client.Client) {
{
APIGroup: "rbac.authorization.k8s.io",
Kind: "User",
Name: defaultUserRef.Spec.UserName,
Name: defaultUserRef.Spec.User,
},
},
RoleRef: rbac.RoleRef{
Expand Down
44 changes: 23 additions & 21 deletions controllers/testsuite_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}

// Handle errors


// Handle changes to scheduling
if sched := testSuite.Spec.When.Schedule; sched != "" {
Expand Down Expand Up @@ -715,26 +714,29 @@ func (r *TestSuiteReconciler) doSetUp(ctx context.Context, testSuite *konfirm.Te
return true
}

logger := logging.FromContextWithName(ctx, testSuiteControllerLoggerName)
var err error

// Get impersonator
var user client.Client
logger.Trace("initiating impersonation")
if user, err = r.Impersonate(ctx, testSuite.Namespace, testSuite.Spec.RunAs); err != nil {
logger.Error(err, "error initializing impersonation")
return false
}
logger.Debug("impersonation initialized")

// Get the Helm secret
if name := testSuite.Spec.SetUp.Helm.SecretName; name != "" {
secret := v1.Secret{}
if err :=
} else {
return true
}
return
panic("not implemented")

//logger := logging.FromContextWithName(ctx, testSuiteControllerLoggerName)
//var err error
//
//// Get impersonator
//var user client.Client
//logger.Trace("initiating impersonation")
//if user, err = r.Impersonate(ctx, testSuite.Namespace, testSuite.Spec.RunAs); err != nil {
// logger.Error(err, "error initializing impersonation")
// return false
//}
//logger.Debug("impersonation initialized")
//
//// Get the Helm secret
//if name := testSuite.Spec.SetUp.Helm.SecretName; name != "" {
// secret := v1.Secret{}
// if err :=
//} else {
// return true
//}
//
//return
}

// doTearDown performs any required teardown and returns true w
Expand Down
73 changes: 29 additions & 44 deletions internal/impersonate/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package impersonate

import (
"context"
"errors"
konfirm "github.com/raft-tech/konfirm/api/v1alpha1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand All @@ -19,28 +19,16 @@ var (

type Client interface {
client.Client
Impersonate(ctx context.Context, namespace string, name string) (client.Client, error)
Impersonate(ctx context.Context, namespace string, name string) (Client, error)
}

// NewImpersonatingClient creates a caching impersonatingClient with support for impersonation
func NewImpersonatingClient(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {

c, err := client.New(config, options)
if err != nil {
return nil, err
}

if dc, err := client.NewDelegatingClient(client.NewDelegatingClientInput{
CacheReader: cache,
Client: c,
UncachedObjects: uncachedObjects,
}); err == nil {
func NewImpersonatingClient(config *rest.Config, options client.Options) (client.Client, error) {
if c, err := client.New(config, options); err == nil {
return &impersonatingClient{
Client: dc,
cache: cache,
config: config,
options: options,
uncachedObjects: uncachedObjects,
Client: c,
config: config,
options: options,
}, nil
} else {
return nil, err
Expand All @@ -49,19 +37,24 @@ func NewImpersonatingClient(cache cache.Cache, config *rest.Config, options clie

type impersonatingClient struct {
client.Client
cache cache.Cache
config *rest.Config
options client.Options
uncachedObjects []client.Object
config *rest.Config
options client.Options
}

func (ic impersonatingClient) Impersonate(ctx context.Context, namespace string, name string) (client.Client, error) {
// Impersonate returns a client.Client configured to impersonate the specified api.UserRef.
// namespace is required. If name is empty, the default UserRef name will be used
// (generally "default"). If name is empty and the default UserRef is not found in the
// specified namespace, the default UserRef will be used (generally, "konfirm-system/default".)
func (ic *impersonatingClient) Impersonate(ctx context.Context, namespace string, name string) (Client, error) {

// Default to "default" userRefName if not explicitly set
userRefName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
if userRefName.Namespace == "" {
return nil, errors.New("namespace must not be empty")
}
if userRefName.Name == "" {
userRefName.Name = DefaultUserRef.Name
}
Expand All @@ -70,37 +63,29 @@ func (ic impersonatingClient) Impersonate(ctx context.Context, namespace string,
var userRef konfirm.UserRef
if err := ic.Get(ctx, userRefName, &userRef); err != nil {
if apierrors.IsNotFound(err) && name == "" {
// Name was explicitly omitted, so the system default can be used
if err = ic.Get(ctx, DefaultUserRef, &userRef); err != nil {
return nil, err
return nil, errors.New("default UserRef not found")
}
} else {
return nil, err
return nil, errors.Join(errors.New("error retrieving specified UserRef"), err)
}
}

// Copy the rest.Config and add impersonation
config := rest.CopyConfig(ic.config)
if user := userRef.Spec.UserName; user != "" {
config.Impersonate.UserName = user
}

c, err := client.New(config, ic.options)
if err != nil {
return nil, err
config.Impersonate = rest.ImpersonationConfig{
UserName: userRef.Spec.User,
UID: userRef.Spec.UID,
Groups: userRef.Spec.Groups,
Extra: userRef.Spec.Extra,
}

// Create a new impersonatingClient but maintain a reference to the original config
if dc, err := client.NewDelegatingClient(client.NewDelegatingClientInput{
CacheReader: ic.cache,
Client: c,
UncachedObjects: ic.uncachedObjects,
}); err == nil {
if _client, err := client.New(config, ic.options); err == nil {
return &impersonatingClient{
Client: dc,
cache: ic.cache,
config: ic.config,
options: ic.options,
uncachedObjects: ic.uncachedObjects,
Client: _client,
config: config,
options: ic.options,
}, nil
} else {
return nil, err
Expand Down
4 changes: 1 addition & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ func main() {

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// TODO: Set impersonate.DefaultUserRef.Namespace to controller namespace

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Expand All @@ -102,7 +100,7 @@ func main() {
os.Exit(1)
}
if err = (&controllers.TestRunReconciler{
Client: mgr.GetClient(),
Client: mgr.GetClient().(impersonate.Client),
Scheme: mgr.GetScheme(),
Recorder: recorder,
ErrRequeueDelay: time.Minute,
Expand Down

0 comments on commit 5704329

Please sign in to comment.