Skip to content

Commit

Permalink
feat: add globalcontext controller (kyverno#9601)
Browse files Browse the repository at this point in the history
* feat: add globalcontext controller

Signed-off-by: Khaled Emara <khaled.emara@nirmata.com>

* rework controller

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* rbac

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* cmd

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix rbac

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* engine

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* k8s resources

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* k8s resource

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* resync zero

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* api call

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* api call

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* clean

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix linter

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Khaled Emara <khaled.emara@nirmata.com>
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
  • Loading branch information
KhaledEmaraDev and eddycharly authored Feb 2, 2024
1 parent 3510998 commit 226fa95
Show file tree
Hide file tree
Showing 22 changed files with 611 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ rules:
- update
- watch
- deletecollection
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- reports.kyverno.io
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ rules:
- update
- watch
- deletecollection
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- ''
resources:
Expand Down
7 changes: 7 additions & 0 deletions charts/kyverno/templates/cleanup-controller/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ rules:
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
Expand Down
7 changes: 7 additions & 0 deletions charts/kyverno/templates/reports-controller/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ rules:
- get
- list
- watch
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
Expand Down
1 change: 1 addition & 0 deletions cmd/background-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func main() {
internal.WithKyvernoDynamicClient(),
internal.WithEventsClient(),
internal.WithApiServerClient(),
internal.WithGlobalContext(),
internal.WithFlagSets(flagset),
)
// parse flags
Expand Down
14 changes: 14 additions & 0 deletions cmd/cleanup-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import (
"github.com/kyverno/kyverno/pkg/controllers/cleanup"
genericloggingcontroller "github.com/kyverno/kyverno/pkg/controllers/generic/logging"
genericwebhookcontroller "github.com/kyverno/kyverno/pkg/controllers/generic/webhook"
"github.com/kyverno/kyverno/pkg/controllers/globalcontext"
ttlcontroller "github.com/kyverno/kyverno/pkg/controllers/ttl"
globalcontextstore "github.com/kyverno/kyverno/pkg/engine/globalcontext/store"
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/informers"
"github.com/kyverno/kyverno/pkg/leaderelection"
Expand Down Expand Up @@ -101,6 +103,7 @@ func main() {
internal.WithDeferredLoading(),
internal.WithMetadataClient(),
internal.WithApiServerClient(),
internal.WithGlobalContext(),
internal.WithFlagSets(flagset),
)
// parse flags
Expand Down Expand Up @@ -156,6 +159,16 @@ func main() {
eventGenerator,
event.Workers,
)
store := globalcontextstore.New()
gceController := internal.NewController(
globalcontext.ControllerName,
globalcontext.NewController(
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
setup.KyvernoDynamicClient,
store,
),
globalcontext.Workers,
)
// start informers and wait for cache sync
if !internal.StartInformersAndWaitForCacheSync(ctx, setup.Logger, kubeInformer, kyvernoInformer) {
os.Exit(1)
Expand Down Expand Up @@ -349,6 +362,7 @@ func main() {
defer server.Stop()
// start non leader controllers
eventController.Run(ctx, setup.Logger, &wg)
gceController.Run(ctx, setup.Logger, &wg)
// start leader election
le.Run(ctx)
// wait for everything to shut down and exit
Expand Down
12 changes: 12 additions & 0 deletions cmd/internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Configuration interface {
UsesMetadataClient() bool
UsesKyvernoDynamicClient() bool
UsesEventsClient() bool
UsesGlobalContext() bool
FlagSets() []*flag.FlagSet
}

Expand Down Expand Up @@ -139,6 +140,12 @@ func WithEventsClient() ConfigurationOption {
}
}

func WithGlobalContext() ConfigurationOption {
return func(c *configuration) {
c.usesGlobalContext = true
}
}

func WithFlagSets(flagsets ...*flag.FlagSet) ConfigurationOption {
return func(c *configuration) {
c.flagSets = append(c.flagSets, flagsets...)
Expand All @@ -163,6 +170,7 @@ type configuration struct {
usesMetadataClient bool
usesKyvernoDynamicClient bool
usesEventsClient bool
usesGlobalContext bool
flagSets []*flag.FlagSet
}

Expand Down Expand Up @@ -234,6 +242,10 @@ func (c *configuration) UsesEventsClient() bool {
return c.usesEventsClient
}

func (c *configuration) UsesGlobalContext() bool {
return c.usesGlobalContext
}

func (c *configuration) FlagSets() []*flag.FlagSet {
return c.flagSets
}
14 changes: 14 additions & 0 deletions cmd/internal/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ var (
imageVerifyCacheEnabled bool
imageVerifyCacheTTLDuration time.Duration
imageVerifyCacheMaxSize int64
// global context
enableGlobalContext bool
)

func initLoggingFlags() {
Expand Down Expand Up @@ -135,6 +137,10 @@ func initCleanupFlags() {
flag.StringVar(&cleanupServerPort, "cleanupServerPort", "9443", "kyverno cleanup server port, defaults to '9443'.")
}

func initGlobalContextFlags() {
flag.BoolVar(&enableGlobalContext, "enableGlobalContext", true, "Enable global context feature.")
}

type options struct {
clientRateLimitQPS float64
clientRateLimitBurst int
Expand Down Expand Up @@ -218,6 +224,10 @@ func initFlags(config Configuration, opts ...Option) {
if config.UsesLeaderElection() {
initLeaderElectionFlags()
}
// leader election
if config.UsesGlobalContext() {
initGlobalContextFlags()
}
initCleanupFlags()
for _, flagset := range config.FlagSets() {
flagset.VisitAll(func(f *flag.Flag) {
Expand Down Expand Up @@ -255,6 +265,10 @@ func CleanupServerPort() string {
return cleanupServerPort
}

func GlobalContextEnabled() bool {
return enableGlobalContext
}

func printFlagSettings(logger logr.Logger) {
logger = logger.WithName("flag")
flag.VisitAll(func(f *flag.Flag) {
Expand Down
1 change: 1 addition & 0 deletions cmd/kyverno/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func main() {
internal.WithKyvernoDynamicClient(),
internal.WithEventsClient(),
internal.WithApiServerClient(),
internal.WithGlobalContext(),
internal.WithFlagSets(flagset),
)
// parse flags
Expand Down
1 change: 1 addition & 0 deletions cmd/reports-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ func main() {
internal.WithKyvernoDynamicClient(),
internal.WithEventsClient(),
internal.WithApiServerClient(),
internal.WithGlobalContext(),
internal.WithFlagSets(flagset),
)
// parse flags
Expand Down
28 changes: 28 additions & 0 deletions config/install-latest-testing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50588,6 +50588,13 @@ rules:
- update
- watch
- deletecollection
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- reports.kyverno.io
resources:
Expand Down Expand Up @@ -50711,6 +50718,13 @@ rules:
- update
- watch
- deletecollection
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- ''
resources:
Expand Down Expand Up @@ -50833,6 +50847,13 @@ rules:
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
Expand Down Expand Up @@ -51137,6 +51158,13 @@ rules:
- get
- list
- watch
- apiGroups:
- kyverno.io
resources:
- globalcontextentries
verbs:
- list
- watch
- apiGroups:
- kyverno.io
resources:
Expand Down
107 changes: 107 additions & 0 deletions pkg/controllers/globalcontext/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package globalcontext

import (
"context"
"errors"
"time"

"github.com/go-logr/logr"
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/controllers"
"github.com/kyverno/kyverno/pkg/engine/adapters"
"github.com/kyverno/kyverno/pkg/engine/globalcontext/externalapi"
"github.com/kyverno/kyverno/pkg/engine/globalcontext/k8sresource"
"github.com/kyverno/kyverno/pkg/engine/globalcontext/store"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/util/workqueue"
)

const (
// Workers is the number of workers for this controller
Workers = 1
ControllerName = "global-context"
maxRetries = 10
)

type controller struct {
// listers
gceLister kyvernov2alpha1listers.GlobalContextEntryLister

// queue
queue workqueue.RateLimitingInterface

// state
dclient dclient.Interface
store store.Store
}

func NewController(
gceInformer kyvernov2alpha1informers.GlobalContextEntryInformer,
dclient dclient.Interface,
storage store.Store,
) controllers.Controller {
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
_, _, err := controllerutils.AddDefaultEventHandlers(logger, gceInformer.Informer(), queue)
if err != nil {
logger.Error(err, "failed to register event handlers")
}
return &controller{
gceLister: gceInformer.Lister(),
queue: queue,
dclient: dclient,
store: storage,
}
}

func (c *controller) Run(ctx context.Context, workers int) {
controllerutils.Run(ctx, logger, ControllerName, time.Second, c.queue, workers, maxRetries, c.reconcile)
}

func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, _, name string) error {
gce, err := c.getEntry(name)
if err != nil {
if apierrors.IsNotFound(err) {
// entry was deleted, remove it from the store
c.store.Delete(name)
return nil
}
return err
}
// either it's a new entry or an existing entry changed
// create a new element and set it in the store
entry, err := c.makeStoreEntry(ctx, gce)
if err != nil {
return err
}
c.store.Set(name, entry)
return nil
}

func (c *controller) getEntry(name string) (*kyvernov2alpha1.GlobalContextEntry, error) {
return c.gceLister.Get(name)
}

func (c *controller) makeStoreEntry(ctx context.Context, gce *kyvernov2alpha1.GlobalContextEntry) (store.Entry, error) {
// TODO: should be done at validation time
if gce.Spec.KubernetesResource == nil && gce.Spec.APICall == nil {
return nil, errors.New("global context entry neither has K8sResource nor APICall")
}
// TODO: should be done at validation time
if gce.Spec.KubernetesResource != nil && gce.Spec.APICall != nil {
return nil, errors.New("global context entry has both K8sResource and APICall")
}
if gce.Spec.KubernetesResource != nil {
gvr := schema.GroupVersionResource{
Group: gce.Spec.KubernetesResource.Group,
Version: gce.Spec.KubernetesResource.Version,
Resource: gce.Spec.KubernetesResource.Resource,
}
return k8sresource.New(ctx, c.dclient.GetDynamicInterface(), gvr, gce.Spec.KubernetesResource.Namespace)
}
return externalapi.New(ctx, logger, adapters.Client(c.dclient), gce.Spec.APICall.APICall, time.Duration(gce.Spec.APICall.RefreshIntervalSeconds))
}
5 changes: 5 additions & 0 deletions pkg/controllers/globalcontext/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package globalcontext

import "github.com/kyverno/kyverno/pkg/logging"

var logger = logging.ControllerLogger(ControllerName)
Loading

0 comments on commit 226fa95

Please sign in to comment.