Skip to content

Commit f6f4e9f

Browse files
committed
add doc comments to packages
1 parent f8cd314 commit f6f4e9f

File tree

22 files changed

+256
-25
lines changed

22 files changed

+256
-25
lines changed

NOTICE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ktrllib
1+
controller-idioms
22
Copyright 2022 Authzed, Inc
33

44
This product includes software developed at

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ secrets, err := secretIndexer.ByIndex("my-index-name", "my-index-value")
147147

148148
### Controllers and Managers
149149

150-
The `manager` package provides an optional lightweight controller `Manager` abstraction (similar to kubernetes controller manager, or the manager from controller runtime). It also provides a simple `Controller` abstraction and some basic implementations. Both are optional, `ktrllib` can be used without these.
150+
The `manager` package provides an optional lightweight controller `Manager` abstraction (similar to kubernetes controller manager, or the manager from controller runtime). It also provides a simple `Controller` abstraction and some basic implementations.
151151

152-
The rest of `ktrllib` can be used without using these if you are already using another solution.
152+
The rest of `controller-idioms` can be used without using these if you are already using another solution.
153153

154154
#### `Manager`
155155

adopt/adopt.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,51 @@ import (
3939
// TODO: a variant where there can only be one owner (label only, fail if labelled for someone else)
4040
// TODO: a variant where a real client is used to check for existence before applying
4141

42+
// Annotator is any type that can have annotations added to it. All standard
43+
// applyconfiguration packages from client-go implement this type. Custom types
44+
// should implement it themselves.
4245
type Annotator[T any] interface {
4346
WithAnnotations(entries map[string]string) T
4447
}
4548

49+
// Labeler is any type that can have labels added to it. All standard
50+
// applyconfiguration packages from client-go implement this type. Custom types
51+
// should implement it themselves.
4652
type Labeler[T any] interface {
4753
WithLabels(entries map[string]string) T
4854
}
4955

56+
// Adoptable is any type that can be labelled and annotated.
57+
// Labels are used for including in a watch stream, and annotations are used
58+
// to indicated ownership by a specific object.
5059
type Adoptable[T any] interface {
5160
Annotator[T]
5261
Labeler[T]
5362
}
5463

64+
// Object is satisfied by any standard kube object.
5565
type Object interface {
5666
comparable
5767
runtime.Object
5868
metav1.Object
5969
}
6070

71+
// ApplyFunc should apply a patch defined by the object A with server-side apply
72+
// and should return the base type. For example a SecretApplyConfiguration would
73+
// be applied with a client-go Patch call, and return a Secret.
6174
type ApplyFunc[K Object, A Adoptable[A]] func(ctx context.Context, object A, opts metav1.ApplyOptions) (result K, err error)
6275

76+
// IndexKeyFunc returns the name of an index to use and the value to query it for.
6377
type IndexKeyFunc func(ctx context.Context) (indexName string, indexValue string)
6478

79+
// Owned is used in object annotations to indicate an object is managed.
6580
const Owned = "owned"
6681

82+
// AdoptionHandler implements handler.Handler to "adopt" an existing resource
83+
// under the controller's management. See the package description for more info.
6784
type AdoptionHandler[K Object, A Adoptable[A]] struct {
85+
// OperationsContext allows the adoption handler to control the sync loop
86+
// it's called from to deal with transient errors.
6887
queue.OperationsContext
6988

7089
// ControllerFieldManager is the value to use when adopting the object
@@ -88,8 +107,8 @@ type AdoptionHandler[K Object, A Adoptable[A]] struct {
88107
// ObjectAdoptedFunc is called when an adoption was performed
89108
ObjectAdoptedFunc func(ctx context.Context, obj K)
90109

91-
// TODO: GetFromCache and Indexer should be replaced with an informer factory that can be
92-
// used to get both
110+
// TODO: GetFromCache and Indexer could be replaced with an informerfactory
111+
// that can be used to get both
93112

94113
// GetFromCache is where we expect to find the object if it is being watched
95114
// This will usually be a wrapper around an informer cache `Get`.

bootstrap/cr.go

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
// Package bootstrap implements utilities for boostrapping a kube cluster
2+
// with resources on controller start.
3+
//
4+
// Typically this is used to bootstrap CRDs and CRs (of the types defined by the
5+
// CRDs) so that a controller can be continuously deployed and still include
6+
// breaking changes.
7+
//
8+
// The bootstrap approach allows the controller to determine when and how to
9+
// coordinate updates to the apis it manages. It should not typically be used
10+
// by end-users of an operator, who may be using one or more other tools to
11+
// manage the deployment of the operator and the resources it manages, and may
12+
// not wish to grant the privileges required to bootstrap.
113
package bootstrap
214

315
import (
@@ -20,6 +32,7 @@ import (
2032
"sigs.k8s.io/controller-runtime/pkg/client"
2133
)
2234

35+
// KubeResourceObject is satisfied by any standard kube object.
2336
type KubeResourceObject interface {
2437
metav1.Object
2538
runtime.Object

cachekeys/keys.go

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Package cachekeys provides standard utilites for creating and parsing cache
2+
// keys for use in client-go caches and workqueus.
3+
//
4+
// These allow one to build queues that process multiple types of objects by
5+
// annotating the standard namespace/name keys with the GVR.
16
package cachekeys
27

38
import (
@@ -8,10 +13,12 @@ import (
813
"k8s.io/client-go/tools/cache"
914
)
1015

16+
// GVRMetaNamespaceKeyer creates a cache/queue key from a gvr and an object key
1117
func GVRMetaNamespaceKeyer(gvr schema.GroupVersionResource, key string) string {
1218
return fmt.Sprintf("%s.%s.%s::%s", gvr.Resource, gvr.Version, gvr.Group, key)
1319
}
1420

21+
// GVRMetaNamespaceKeyFunc creates cache/queue key from a gvr and an object.
1522
func GVRMetaNamespaceKeyFunc(gvr schema.GroupVersionResource, obj interface{}) (string, error) {
1623
if d, ok := obj.(cache.DeletedFinalStateUnknown); ok {
1724
return d.Key, nil
@@ -23,6 +30,7 @@ func GVRMetaNamespaceKeyFunc(gvr schema.GroupVersionResource, obj interface{}) (
2330
return GVRMetaNamespaceKeyer(gvr, key), nil
2431
}
2532

33+
// SplitGVRMetaNamespaceKey splits a cache key into gvr, namespace, and name.
2634
func SplitGVRMetaNamespaceKey(key string) (gvr *schema.GroupVersionResource, namespace, name string, err error) {
2735
before, after, ok := strings.Cut(key, "::")
2836
if !ok {

component/component.go

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
// Package component implements a common controller pattern: an object is
2+
// specified by a user, and another kube object needs to be created in response.
3+
//
4+
// `Component`specifies how to find these related objects in the cluster.
5+
//
6+
// `ContextHandler` is a handler.Handler implementation that can pick out
7+
// a component from a cluster and add it into a context.Context key.
8+
//
9+
// `EnsureComponent` is a handler.Handler implementation that ensures that a
10+
// component with a given specification exists. It handles creating the object
11+
// if it doesn't exist and updating it only if the calculated object has
12+
// changed. It also cleans up duplicate matching component objects by deleting
13+
// any that match the component selector but do not match the calculated object.
114
package component
215

316
import (
@@ -13,21 +26,22 @@ import (
1326
"github.com/authzed/controller-idioms/typed"
1427
)
1528

29+
// KubeObject is satisfied by any standard kube object.
1630
type KubeObject interface {
1731
metav1.Object
1832
runtime.Object
1933
}
2034

21-
// Component represents an KubeObject in the cluster that is "related" to another
22-
// i.e. a pod would be a component of a deployment (though direct ownership is
35+
// Component represents a KubeObject in the cluster that is "related" to another
36+
// i.e. a pod could be a component of a deployment (though direct ownership is
2337
// not required).
2438
type Component[K KubeObject] struct {
2539
indexer *typed.Indexer[K]
2640
selectorFunc func(ctx context.Context) labels.Selector
2741
indexName string
2842
}
2943

30-
// NewIndexedComponent creates a component from an index
44+
// NewIndexedComponent creates a Component from an index
3145
func NewIndexedComponent[K KubeObject](indexer *typed.Indexer[K], indexName string, selectorFunc func(ctx context.Context) labels.Selector) *Component[K] {
3246
return &Component[K]{
3347
indexer: indexer,
@@ -59,13 +73,17 @@ func (c *Component[K]) List(ctx context.Context, indexValue fmt.Stringer) (out [
5973
}
6074

6175
// HashableComponent is a Component with an annotation that stores a hash of the
62-
// previous configuration the controller wrote
76+
// previous configuration written by the controller. The hash is used to
77+
// determine if work still needs to be done.
6378
type HashableComponent[K KubeObject] struct {
6479
*Component[K]
6580
hash.ObjectHasher
6681
HashAnnotationKey string
6782
}
6883

84+
// NewHashableComponent creates HashableComponent from a Component and a
85+
// hash.ObjectHasher, plus an annotation key to use to store the hash on the
86+
// object.
6987
func NewHashableComponent[K KubeObject](component *Component[K], hasher hash.ObjectHasher, key string) *HashableComponent[K] {
7088
return &HashableComponent[K]{
7189
Component: component,

component/component_handler.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/authzed/controller-idioms/typedctx"
1010
)
1111

12-
// ContextHandler fills the value for a Key with the result of
12+
// ContextHandler fills the value for a context.Key with the result of
1313
// fetching a component.
1414
type ContextHandler[K KubeObject] struct {
1515
owner typedctx.MustValueContext[types.NamespacedName]
@@ -18,6 +18,7 @@ type ContextHandler[K KubeObject] struct {
1818
next handler.ContextHandler
1919
}
2020

21+
// NewComponentContextHandler creates a new ContextHandler.
2122
func NewComponentContextHandler[K KubeObject](contextKey typedctx.SettableContext[[]K], component *Component[K], owner typedctx.MustValueContext[types.NamespacedName], next handler.ContextHandler) *ContextHandler[K] {
2223
return &ContextHandler[K]{
2324
owner: owner,

component/ensure_component.go

+6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ import (
1212
"github.com/authzed/controller-idioms/typedctx"
1313
)
1414

15+
// Annotator is any type that can have annotations added to it. All standard
16+
// applyconfiguration packages from client-go implement this type. Custom types
17+
// should implement it themselves.
1518
type Annotator[T any] interface {
1619
WithAnnotations(entries map[string]string) T
1720
}
1821

22+
// EnsureComponentByHash is a handler.Handler implementation that
23+
// will create a component object and ensure it has the computed spec.
1924
type EnsureComponentByHash[K KubeObject, A Annotator[A]] struct {
2025
*HashableComponent[K]
2126
ctrls *typedctx.Key[queue.Interface]
@@ -27,6 +32,7 @@ type EnsureComponentByHash[K KubeObject, A Annotator[A]] struct {
2732

2833
var _ handler.ContextHandler = &EnsureComponentByHash[*corev1.Service, *applycorev1.ServiceApplyConfiguration]{}
2934

35+
// NewEnsureComponentByHash returns a new EnsureComponentByHash handler.
3036
func NewEnsureComponentByHash[K KubeObject, A Annotator[A]](
3137
component *HashableComponent[K],
3238
owner typedctx.MustValueContext[types.NamespacedName],

fileinformer/file_informer.go

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Package fileinformer implements a kube-style Informer and InformerFactory
2+
// that can be used to watch files instead of kube apis.
13
package fileinformer
24

35
import (
@@ -15,11 +17,14 @@ import (
1517
"k8s.io/klog/v2"
1618
)
1719

20+
// FileGroupVersion is a sythetic GroupVersion that the informers use.
1821
var FileGroupVersion = schema.GroupVersion{
1922
Group: "//LocalFile",
2023
Version: "v1",
2124
}
2225

26+
// Factory implements dynamicinformer.DynamicSharedInformerFactory, but for
27+
// starting and managing FileInformers.
2328
type Factory struct {
2429
sync.Mutex
2530
informers map[schema.GroupVersionResource]informers.GenericInformer
@@ -30,13 +35,15 @@ type Factory struct {
3035

3136
var _ dynamicinformer.DynamicSharedInformerFactory = &Factory{}
3237

38+
// NewFileInformerFactory creates a new Factory.
3339
func NewFileInformerFactory() (*Factory, error) {
3440
return &Factory{
3541
informers: make(map[schema.GroupVersionResource]informers.GenericInformer),
3642
startedInformers: make(map[schema.GroupVersionResource]bool),
3743
}, nil
3844
}
3945

46+
// Start starts watching the files defined byt the informers.
4047
func (f *Factory) Start(stopCh <-chan struct{}) {
4148
f.Lock()
4249
defer f.Unlock()
@@ -49,6 +56,7 @@ func (f *Factory) Start(stopCh <-chan struct{}) {
4956
}
5057
}
5158

59+
// ForResource will create an informer for a specific file.
5260
func (f *Factory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer {
5361
f.Lock()
5462
defer f.Unlock()
@@ -72,6 +80,7 @@ func (f *Factory) ForResource(gvr schema.GroupVersionResource) informers.Generic
7280
return informer
7381
}
7482

83+
// WaitForCacheSync waits until all files in the informers have been synced once.
7584
func (f *Factory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool {
7685
infs := func() map[schema.GroupVersionResource]cache.SharedIndexInformer {
7786
f.Lock()
@@ -93,6 +102,7 @@ func (f *Factory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersi
93102
return res
94103
}
95104

105+
// FileInformer is an informer that watches files instead of the kube api.
96106
type FileInformer struct {
97107
fileName string
98108
watcher *fsnotify.Watcher
@@ -101,6 +111,7 @@ type FileInformer struct {
101111

102112
var _ informers.GenericInformer = &FileInformer{}
103113

114+
// NewFileInformer returns a new FileInformer.
104115
func NewFileInformer(watcher *fsnotify.Watcher, gvr schema.GroupVersionResource) (*FileInformer, error) {
105116
return &FileInformer{
106117
fileName: gvr.Resource,
@@ -292,3 +303,8 @@ func (f *FileSharedIndexInformer) GetIndexer() cache.Indexer {
292303
// TODO implement me
293304
panic("implement me")
294305
}
306+
307+
func (f *FileSharedIndexInformer) SetTransform(handler cache.TransformFunc) error {
308+
// TODO implement me
309+
panic("implement me")
310+
}

handler/handler.go

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
package handler
2-
3-
import (
4-
"context"
5-
"fmt"
6-
)
7-
8-
// This package contains the basic Handler units used to compose reconciliation
9-
// loops for a controller.
1+
// Package handler contains the basic Handler units used to compose
2+
// reconciliation loops for a controller.
103
//
114
// You write functions or types that implement the ContextHandler interface, and
125
// then compose them via Handlers and Builders.
@@ -17,6 +10,12 @@ import (
1710
// behavior respectively), so each type has methods to convert between them.
1811
//
1912
// See other files for helpers to compose or wrap handlers and builders.
13+
package handler
14+
15+
import (
16+
"context"
17+
"fmt"
18+
)
2019

2120
// ContextHandler is the interface for a "chunk" of reconciliation. It either
2221
// returns, often by adjusting the current key's place in the queue (i.e. via

0 commit comments

Comments
 (0)