Skip to content

Commit 45d6520

Browse files
authored
Merge pull request #295 from DirectXMan12/docs/overview-and-fixup
📖 Add project overview to docs, clean up docs, structure
2 parents 6443f37 + cb0aefb commit 45d6520

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+671
-124
lines changed

FAQ.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# FAQ
2+
3+
### Q: How do I know which type of object a controller references?
4+
5+
**A**: Each controller should only reconcile one object type. Other
6+
affected objects should be mapped to a single type of root object, using
7+
the `EnqueueRequestForOwner` or `EnqueueRequestsFromMapFunc` event
8+
handlers, and potentially indicies. Then, your Reconcile method should
9+
attempt to reconcile *all* state for that given root objects.
10+
11+
### Q: How do I have different logic in my reconciler for different types of events (e.g. create, update, delete)?
12+
13+
**A**: You should not. Reconcile functions should be idempotent, and
14+
should always reconcile state by reading all the state it needs, then
15+
writing updates. This allows your reconciler to correctly respond to
16+
generic events, adjust to skipped or coalesced events, and easily deal
17+
with application startup. The controller will enqueue reconcile requests
18+
for both old and new objects if a mapping changes, but it's your
19+
responsibility to make sure you have enough information to be able clean
20+
up state that's no longer referenced.
21+
22+
### Q: My cache might be stale if I read from a cache! How should I deal with that?
23+
24+
**A**: There are several different approaches that can be taken, depending
25+
on your situation.
26+
27+
- When you can, take advantage of optimistic locking: use deterministic
28+
names for objects you create, so that the Kubernetes API server will
29+
warn you if the object already exists. Many controllers in Kubernetes
30+
take this approach: the StatefulSet controller appends a specific number
31+
to each pod that it creates, while the Deployment controller hashes the
32+
pod template spec and appends that.
33+
34+
- In the few cases when you cannot take advantage of deterministic names
35+
(e.g. when using generateName), it may be useful in to track which
36+
actions you took, and assume that they need to be repeated if they don't
37+
occur after a given time (e.g. using a requeue result). This is what
38+
the ReplicaSet controller does.
39+
40+
In general, write your controller with the assumption that information
41+
will eventually be correct, but may be slightly out of date. Make sure
42+
that your reconcile function enforces the entire state of the world each
43+
time it runs. If none of this works for you, you can always construct
44+
a client that reads directly from the API server, but this is generally
45+
considered to be a last resort, and the two approaches above should
46+
generally cover most circumstances.
47+
48+
### Q: Where's the fake client? How do I use it?
49+
50+
**A**: The fake client
51+
[exists](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client/fake),
52+
but we generally recommend using
53+
[envtest.Environment](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest#Environment)
54+
to test against a real API server. In our experience, tests using fake
55+
clients gradually re-implement poorly-written impressions of a real API
56+
server, which leads to hard-to-maintain, complex test code.
57+
58+
### Q: How should I write tests? Any suggestions for getting started?
59+
60+
- Use the aforementioned
61+
[envtest.Environment](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/envtest#Environment)
62+
to spin up a real API server instead of trying to mock one out.
63+
64+
- Structure your tests to check that the state of the world is as you
65+
expect it, *not* that a particular set of API calls were made, when
66+
working with Kubernetes APIs. This will allow you to more easily
67+
refactor and improve the internals of your controllers without changing
68+
your tests.
69+
70+
- Remember that any time you're interacting with the API server, changes
71+
may have some delay between write time and reconcile time.
72+
73+
### Q: What are these errors about no Kind being registered for a type?
74+
75+
**A**: You're probably missing a fully-set-up Scheme. Schemes record the
76+
mapping between Go types and group-version-kinds in Kubernetes. In
77+
general, your application should have its own Scheme containing the types
78+
from the API groups that it needs (be they Kubernetes types or your own).
79+
See the [scheme builder
80+
docs](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/scheme) for
81+
more information.

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Users:
2121

2222
- We follow [Semantic Versioning (semver)](https://semver.org)
2323
- Use releases with your dependency management to ensure that you get compatible code
24-
- The master branch contains all the latest code, some of which may break compatibility (so "normal" `go get` is not reccomended)
24+
- The master branch contains all the latest code, some of which may break compatibility (so "normal" `go get` is not recommended)
2525

2626
Contributors:
2727

@@ -34,6 +34,10 @@ Contributors:
3434
* [Documentation Changes](/.github/PULL_REQUEST_TEMPLATE/docs.md)
3535
* [Test/Build/Other Changes](/.github/PULL_REQUEST_TEMPLATE/other.md)
3636

37+
## FAQ
38+
39+
See [FAQ.md](FAQ.md)
40+
3741
## Community, discussion, contribution, and support
3842

3943
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).

TMP-LOGGING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ logger.V(1).Info("this is particularly verbose!", "state of the world",
7474
allKubernetesObjectsEverywhere)
7575
```
7676

77-
While it's possible to use higher log levels, it's reccomended that you
77+
While it's possible to use higher log levels, it's recommended that you
7878
stick with `V(1)` or V(0)` (which is equivalent to not specifying `V`),
7979
and then filter later based on key-value pairs or messages; different
8080
numbers tend to lose meaning easily over time, and you'll be left

VERSIONING.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Use releases with your dependency management to ensure that you get
1111
compatible code
1212
- The master branch contains all the latest code, some of which may break
13-
compatibility (so "normal" `go get` is not reccomended)
13+
compatibility (so "normal" `go get` is not recommended)
1414

1515
### Contributors
1616

@@ -32,7 +32,7 @@ Don't be lazy, read the rest of this doc :-)
3232
## Overview
3333

3434
controller-runtime (and friends) follow [Semantic
35-
Versioning](https://semver.org). I'd reccomend reading the aforementioned
35+
Versioning](https://semver.org). I'd recommend reading the aforementioned
3636
link if you're not familiar, but essentially, for any given release X.Y.Z:
3737

3838
- an X (*major*) release indicates a set of backwards-compatible code.

alias.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// Package controllerruntime alias' common functions and types to improve discoverability and reduce
18-
// the number of imports for simple Controllers.
1917
package controllerruntime
2018

2119
import (
@@ -27,8 +25,8 @@ import (
2725
"sigs.k8s.io/controller-runtime/pkg/manager"
2826
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2927
"sigs.k8s.io/controller-runtime/pkg/log"
30-
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
31-
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
28+
"sigs.k8s.io/controller-runtime/pkg/scheme"
29+
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
3230
)
3331

3432
// Builder builds an Application ControllerManagedBy (e.g. Operator) and returns a manager.Manager to start it.

doc.go

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package controllerruntime provides tools to construct Kubernetes-style
18+
// controllers that manipulate both Kubernetes CRDs and aggregated/built-in
19+
// Kubernetes APIs.
20+
//
21+
// It defines easy helpers for the common use cases when building CRDs, built
22+
// on top of customizable layers of abstraction. Common cases should be easy,
23+
// and uncommon cases should be possible. In general, controller-runtime tries
24+
// to guide users towards Kubernetes controller best-practices.
25+
//
26+
// Getting Started
27+
//
28+
// The main entrypoint for controller-runtime is this root package, which
29+
// contains all of the common types needed to get started building controllers:
30+
// import (
31+
// controllers "sigs.k8s.io/controller-runtime"
32+
// )
33+
//
34+
// The examples in this package walk through a basic controller setup. The
35+
// kubebuilder book (https://book.kubebuilder.io) has some more in-depth
36+
// walkthroughs.
37+
//
38+
// controller-runtime favors structs with sane defaults over constructors, so
39+
// it's fairly common to see structs being used directly in controller-runtime.
40+
//
41+
// Organization
42+
//
43+
// A brief-ish walkthrough of the layout of this library can be found below. Each
44+
// package contains more information about how to use it.
45+
//
46+
// Frequently asked questions about using controller-runtime and designing
47+
// controllers can be found at
48+
// https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.
49+
//
50+
// Managers
51+
//
52+
// Every controller and webhook is ultimately run by a Manager (pkg/manager). A
53+
// manager is responsible for running controllers and webhooks, and setting up
54+
// common dependencies (pkg/runtime/inject), like shared caches and clients, as
55+
// well as managing leader election (pkg/leaderelection). Managers are
56+
// generally configured to gracefully shut down controllers on pod termination
57+
// by wiring up a signal handler (pkg/manager/signals).
58+
//
59+
// Controllers
60+
//
61+
// Controllers (pkg/controller) use events (pkg/events) to eventually trigger
62+
// reconcile requests. They may be constructed manually, but are often
63+
// constructed with a Builder (pkg/builder), which eases the wiring of event
64+
// sources (pkg/source), like Kubernetes API object changes, to event handlers
65+
// (pkg/handler), like "enqueue a reconcile request for the object owner".
66+
// Predicates (pkg/predicate) can be used to filter which events actually
67+
// trigger reconciles. There are pre-written utilies for the common cases, and
68+
// interfaces and helpers for advanced cases.
69+
//
70+
// Reconcilers
71+
//
72+
// Controller logic is implemented in terms of Reconcilers (pkg/reconcile). A
73+
// Reconciler implements a function which takes a reconcile Request containing
74+
// the name and namespace of the object to reconcile, reconciles the object,
75+
// and returns a Response or an error indicating whether to requeue for a
76+
// second round of processing.
77+
//
78+
// Clients and Caches
79+
//
80+
// Reconcilers use Clients (pkg/client) to access API objects. The default
81+
// client provided by the manager reads from a local shared cache (pkg/cache)
82+
// and writes directly to the API server, but clients can be constructed that
83+
// only talk to the API server, without a cache. The Cache will auto-populate
84+
// with watched objects, as well as when other structured objects are
85+
// requested. Caches may also have indexes, which can be created via a
86+
// FieldIndexer (pkg/client) obtained from the manager. Indexes can used to
87+
// quickly and easily look up all objects with certain fields set. Reconcilers
88+
// may retrieve event recorders (pkg/recorder) to emit events using the
89+
// manager.
90+
//
91+
// Schemes
92+
//
93+
// Clients, Caches, and many other things in Kubernetes use Schemes
94+
// (pkg/scheme) to associate Go types to Kubernetes API Kinds
95+
// (Group-Version-Kinds, to be specific).
96+
//
97+
// Webhooks
98+
//
99+
// Similarly, webhooks (pkg/webhook/admission) may be implemented directly, but
100+
// are often constructed using a builder (pkg/webhook/admission/builder). They
101+
// are run via a server (pkg/webhook) which is managed by a Manager.
102+
//
103+
// Logging and Metrics
104+
//
105+
// Logging (pkg/log) in controller-runtime is done via structured logs, using a
106+
// log set of interfaces called logr
107+
// (https://godoc.org/github.com/go-logr/logr). While controller-runtime
108+
// provides easy setup for using Zap (https://go.uber.org/zap, pkg/log/zap),
109+
// you can provide any implementation of logr as the base logger for
110+
// controller-runtime.
111+
//
112+
// Metrics (pkg/metrics) provided by controller-runtime are registered into a
113+
// controller-runtime-specific Prometheus metrics registery. The manager can
114+
// serve these by an HTTP endpoint, and additional metrics may be registered to
115+
// this Registry as normal.
116+
//
117+
// Testing
118+
//
119+
// You can easily build integration and unit tests for your controllers and
120+
// webhooks using the test Environment (pkg/envtest). This will automatically
121+
// stand up a copy of etcd and kube-apiserver, and provide the correct options
122+
// to connect to the API server. It's designed to work well with the Ginkgo
123+
// testing framework, but should work with any testing setup.
124+
package controllerruntime

example/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/manager"
3232
logf "sigs.k8s.io/controller-runtime/pkg/log"
3333
"sigs.k8s.io/controller-runtime/pkg/log/zap"
34-
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
34+
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
3535
"sigs.k8s.io/controller-runtime/pkg/source"
3636
"sigs.k8s.io/controller-runtime/pkg/webhook"
3737
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/builder"

pkg/builder/example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030
"sigs.k8s.io/controller-runtime/pkg/client/config"
3131
"sigs.k8s.io/controller-runtime/pkg/manager"
3232
"sigs.k8s.io/controller-runtime/pkg/reconcile"
33-
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
33+
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
3434
)
3535

3636
// This example creates a simple application ControllerManagedBy that is configured for ReplicaSets and Pods.

pkg/cache/cache.go

+12-13
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,20 @@ import (
3434

3535
var log = logf.RuntimeLog.WithName("object-cache")
3636

37-
// Cache implements CacheReader by reading objects from a cache populated by InformersMap
37+
// Cache knows how to load Kubernetes objects, fetch informers to request
38+
// to receive events for Kubernetes objects (at a low-level),
39+
// and add indicies to fields on the objects stored in the cache.
3840
type Cache interface {
39-
// Cache implements the client CacheReader
41+
// Cache acts as a client to objects stored in the cache.
4042
client.Reader
4143

42-
// Cache implements InformersMap
44+
// Cache loads informers and adds field indicies.
4345
Informers
4446
}
4547

46-
// Informers knows how to create or fetch informers for different group-version-kinds.
47-
// It's safe to call GetInformer from multiple threads.
48+
// Informers knows how to create or fetch informers for different
49+
// group-version-kinds, and add indicies to those informers. It's safe to call
50+
// GetInformer from multiple threads.
4851
type Informers interface {
4952
// GetInformer fetches or constructs an informer for the given object that corresponds to a single
5053
// API kind and resource.
@@ -61,15 +64,11 @@ type Informers interface {
6164
// WaitForCacheSync waits for all the caches to sync. Returns false if it could not sync a cache.
6265
WaitForCacheSync(stop <-chan struct{}) bool
6366

64-
// IndexField adds an index with the given field name on the given object type
65-
// by using the given function to extract the value for that field. If you want
66-
// compatibility with the Kubernetes API server, only return one key, and only use
67-
// fields that the API server supports. Otherwise, you can return multiple keys,
68-
// and "equality" in the field selector means that at least one key matches the value.
69-
IndexField(obj runtime.Object, field string, extractValue client.IndexerFunc) error
67+
// Informers knows how to add indicies to the caches (informers) that it manages.
68+
client.FieldIndexer
7069
}
7170

72-
// Options are the optional arguments for creating a new InformersMap object
71+
// Options are the optional arguments for creating a new set of Informers.
7372
type Options struct {
7473
// Scheme is the scheme to use for mapping objects to GroupVersionKinds
7574
Scheme *runtime.Scheme
@@ -87,7 +86,7 @@ type Options struct {
8786

8887
var defaultResyncTime = 10 * time.Hour
8988

90-
// New initializes and returns a new Cache
89+
// New initializes and returns a new Cache.
9190
func New(config *rest.Config, opts Options) (Cache, error) {
9291
opts, err := defaultOpts(config, opts)
9392
if err != nil {

pkg/cache/doc.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package cache provides object caches that act as caching client.Reader
18+
// instances and help drive Kubernetes-object-based event handlers.
19+
package cache

pkg/client/apiutil/apimachinery.go

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17+
// Package apiutil contains utilities for working with raw Kubernetes
18+
// API machinery, such as creating RESTMappers and raw REST clients,
19+
// and extracting the GVK of an object.
1720
package apiutil
1821

1922
import (

pkg/client/client.go

+9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ type Options struct {
4141
}
4242

4343
// New returns a new Client using the provided config and Options.
44+
// The returned client reads *and* writes directly from the server
45+
// (it doesn't use object caches). It understands how to work with
46+
// normal types (both custom resources and aggregated/built-in resources),
47+
// as well as unstructured types.
48+
//
49+
// In the case of normal types, the scheme will be used to look up the
50+
// corresponding group, version, and kind for the given type. In the
51+
// case of unstrctured types, the group, version, and kind will be extracted
52+
// from the corresponding fields on the object.
4453
func New(config *rest.Config, options Options) (Client, error) {
4554
if config == nil {
4655
return nil, fmt.Errorf("must provide non-nil rest.Config to client.New")

pkg/client/config/doc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// Package config contains libraries for initializing rest configs for talking to the Kubernetes API
17+
// Package config contains libraries for initializing REST configs for talking to the Kubernetes API
1818
package config

0 commit comments

Comments
 (0)