Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
e82a221
✨ Extend files whitelist for init cmd
w3st3ry Apr 28, 2021
a42a397
fix(v3/scaffolds/dockerignore): correctly ignore non-go files
busser Mar 10, 2021
9e94fe0
add go-apidiff to verify api differences
Mar 4, 2021
f870897
Merge pull request #2061 from goutamtadi1/add-go-apidiff
k8s-ci-robot May 27, 2021
9a5cf35
Fix typo in api-design.md
slashpai May 28, 2021
e92259e
Merge pull request #2192 from slashpai/master
k8s-ci-robot May 28, 2021
6239034
Merge pull request #2160 from w3st3ry/fix-existing-files-whitelist
k8s-ci-robot May 28, 2021
1e07665
🐛 fix: incorrect cert-manager kustomize comments
timmyers May 28, 2021
5cb07f6
Replace broken Travis CI badge in README with GitHub Lint & Unit Test…
vorburger May 31, 2021
12bba0b
Merge pull request #2196 from timmyers/cert-manager
k8s-ci-robot Jun 1, 2021
f3e5c62
Merge pull request #2199 from vorburger/patch-1
k8s-ci-robot Jun 1, 2021
fb22f29
Update kubernetes-sigs/controller-tools to v0.5.0
Birdrock Jun 2, 2021
b260018
Fix CI for 1.16
pwittrock Jun 6, 2021
1c23bd8
Merge pull request #2203 from pwittrock/test
k8s-ci-robot Jun 7, 2021
68495c9
Refactor `kubebuilder alpha config-gen` to use embed
pwittrock Jun 4, 2021
e4ae397
Merge pull request #2204 from pwittrock/config-gen
pwittrock Jun 8, 2021
68a8f0b
update controller-tool version for config-gen command
pwittrock Jun 4, 2021
6884971
Update config-gen flags to v3 names
pwittrock Jun 4, 2021
6e7641b
config-gen only generate webhooks if enabled
pwittrock Jun 8, 2021
1c545c5
Merge pull request #2205 from pwittrock/config-gen
pwittrock Jun 9, 2021
724dddd
Fix config-gen documentation bug
pwittrock Jun 10, 2021
0e1124b
Link to v2 book as well from intro page
fgrehm Jun 10, 2021
2eb8206
Merge pull request #2200 from Birdrock/master
estroz Jun 10, 2021
d4be5e7
Merge pull request #2211 from fgrehm/patch-1
k8s-ci-robot Jun 13, 2021
b6ecf5e
Merge pull request #2210 from pwittrock/config-gen
k8s-ci-robot Jun 14, 2021
1efe80d
Move directxman12 to approvers-emeritus
DirectXMan12 Jun 14, 2021
da116ba
fix component config tutorial
Iceber Jun 16, 2021
90647ae
doc(quick-start): fix blog post link
JulienBreux Jun 16, 2021
6b47b40
doc(quick-start): fix blog post link after review
JulienBreux Jun 16, 2021
2af16c4
doc(quick-start): fix missing space on footer link
JulienBreux Jun 16, 2021
4b171da
doc(quick-start): fix Go Modules blogpost link
JulienBreux Jun 16, 2021
01c9d5b
Merge pull request #2219 from JulienBreux/patch-1
k8s-ci-robot Jun 16, 2021
2f8940f
Merge pull request #2081 from busser/fix/dockerignore
k8s-ci-robot Jun 16, 2021
18b38aa
Merge pull request #2218 from Iceber/fix-book
k8s-ci-robot Jun 16, 2021
0443601
docs: fix the broken link in the generating-crd.md
Iceber Jun 17, 2021
cb1b600
Merge pull request #2226 from Iceber/fix-book
k8s-ci-robot Jun 17, 2021
a7b2d25
Merge pull request #2212 from DirectXMan12/infra/maintainer-emeritus-…
k8s-ci-robot Jun 18, 2021
43a1bd1
Updated custom metrics docs
VenkatRamaraju Jun 14, 2021
52a8c12
Merge pull request #2217 from VenkatRamaraju/custom-metrics-docs
k8s-ci-robot Jun 21, 2021
ede1b49
Fix `version` command
SeriyBg Jun 29, 2021
f86a161
Make markers more easily copyable
imjasonh Jun 29, 2021
68ecb1a
Merge pull request #2241 from SeriyBg/patch-1
k8s-ci-robot Jun 30, 2021
3b251ce
:sparkles: bump k8s dependencies to 1.21
varshaprasad96 Jun 9, 2021
66a0311
update testdata
varshaprasad96 Jun 22, 2021
3a2b80b
bump kb declarative pattern and update dependencies
varshaprasad96 Jun 30, 2021
1831527
Merge pull request #2208 from varshaprasad96/bump/k8s-1.21
estroz Jul 1, 2021
7429836
Merge pull request #2249 from imjasonh/marker-before
k8s-ci-robot Jul 2, 2021
9338264
Fixed small typo
mdrakiburrahman Jul 3, 2021
1d38edf
Update README.md
soumitraj Jul 4, 2021
e8715b3
docs: add the --repo flag to init example of the cronjob tutorial
minchao Jul 4, 2021
65062ab
fix(scaffolds): better defaults
longkai Jul 6, 2021
359e8aa
Merge pull request #2253 from minchao/cronjob-tutorial
k8s-ci-robot Jul 7, 2021
2e98e69
Clean up extra spaces
jayonlau Jul 9, 2021
8555b72
Merge pull request #2261 from jayonlau/clean_up
k8s-ci-robot Jul 11, 2021
ed98532
Merge pull request #2251 from soumitraj/patch-1
k8s-ci-robot Jul 11, 2021
bb47130
Clean up extra spaces
jayonlau Jul 12, 2021
0b3c0aa
Fix name: kube-auth-proxy -> kube-rbac-proxy
bells17 Jul 12, 2021
c06ce41
Clarify artifacts documentation to explicitly state Kubernetes version
rashmigottipati Jul 13, 2021
81349c9
Merge pull request #2265 from rashmigottipati/minor-doc-fix
k8s-ci-robot Jul 13, 2021
5525c1e
Merge pull request #2263 from bells17/fix-name
k8s-ci-robot Jul 16, 2021
112923a
Merge pull request #2250 from mdrakiburrahman/patch-1
k8s-ci-robot Jul 16, 2021
1e63a0e
Merge pull request #2255 from longkai/better-defaults
k8s-ci-robot Jul 16, 2021
fde793f
Merge pull request #2262 from jayonlau/master
k8s-ci-robot Jul 16, 2021
8822b1e
Include additional info in error messages. (#2271)
porridge Jul 29, 2021
35f2da2
update generating crd link (#2277)
pravarag Jul 29, 2021
4a905a7
:bug: add the path to Kubebuilder assets in go/v3 (#2272)
varshaprasad96 Aug 3, 2021
51e4a9a
chore(owners): add estroz to OWNERS_ALIASES admins, (#2280)
estroz Aug 3, 2021
7259fba
Ask user for make manifests (#2236)
guhaneswaran Aug 4, 2021
2427c3d
chore(golang): refactor go version check for per-plugin configuration
estroz Aug 10, 2021
a7a1ec9
Merge pull request #2290 from estroz/chore/fix-go-version
estroz Aug 11, 2021
2b3a589
Update the linter version. (#2275)
davidlanouette Aug 11, 2021
cc270dd
📖 Update go Prerequisites for the latest release (#2257)
devinleee Aug 18, 2021
5ca8884
Use an existing marker for the example. (#2288)
porridge Aug 20, 2021
f969129
Fix generate test to not always do declarative
justinsb Aug 29, 2021
7561ccf
:seedling: fix lint issues on master (#2316)
camilamacedo86 Aug 30, 2021
7cecf9d
Plugin Phase 2 Design Proposal (#2243)
rashmigottipati Aug 31, 2021
45980fb
fix(release,book): fix documented k8s version, 1.19 -> 1.21
estroz Aug 31, 2021
eac4386
fix(netlify): fix broken redirect resource
estroz Aug 31, 2021
b6c94ab
Merge pull request #2321 from estroz/fix/netlify-redirect-fn
k8s-ci-robot Aug 31, 2021
44df0f6
Spec for Phase 2 Plugins
rashmigottipati Aug 3, 2021
b05a6f6
Merge pull request #2281 from rashmigottipati/phase2-plugins-spec
k8s-ci-robot Aug 31, 2021
490de9f
Merge pull request #2322 from estroz/fix/doc-k8s-version
k8s-ci-robot Sep 1, 2021
1ed4de2
Merge pull request #2319 from justinsb/no_channels
k8s-ci-robot Sep 1, 2021
fbc6a30
Update the cronjob-tutorial project files
hickeyma Aug 18, 2021
0c4ffef
Fix test in cronjob_tutorial
hickeyma Sep 7, 2021
e761b39
Add reference page in book for Watching resources
HoustonPutman Feb 9, 2021
58b87e2
relaign go modules as generated by scaffold scripts
hickeyma Sep 8, 2021
9817db7
Merge pull request #2302 from hickeyma/fix/sync-crontab-tutorial-with…
k8s-ci-robot Sep 8, 2021
835345e
Update Configuring EnvTest binary directory docs
Birdrock Sep 9, 2021
ca5dc73
Defer GinkgoRecover() in test goroutines
armsnyder Sep 20, 2021
60803e8
update deps to use k8s 1.22
camilamacedo86 Sep 17, 2021
2647fff
Merge pull request #2345 from armsnyder/ginkgo-recover
k8s-ci-robot Sep 21, 2021
9b1d8c8
Fix typo in bug report and feature request templates
cimnine Sep 23, 2021
a89ce41
Merge pull request #2346 from cimnine/patch-1
estroz Sep 23, 2021
c85a1eb
Include base.go.kubebuilder.io plugin in CLI
armsnyder Sep 26, 2021
c65e6c5
Increase timeout for e2e tests
hickeyma Sep 29, 2021
ae8a57e
Fix Tutorial Section 1.2 Missing Colon
stevemcquaid Oct 1, 2021
cab133d
Merge pull request #2358 from stevemcquaid/fix-2337
k8s-ci-robot Oct 1, 2021
7e067a4
Fix Tutorial Section 1.2 Missing Colon (2/2)
stevemcquaid Oct 1, 2021
ecce96f
Merge pull request #2340 from camilamacedo86/update-controller-runtime
camilamacedo86 Oct 1, 2021
87eb9d5
Merge pull request #2356 from hickeyma/fix/e2e-test-timeout
k8s-ci-robot Oct 1, 2021
a0187eb
Merge pull request #2359 from stevemcquaid/fix-2337
k8s-ci-robot Oct 1, 2021
bbf4fbb
Merge pull request #2350 from armsnyder/base-golang-plugin
k8s-ci-robot Oct 2, 2021
e5f7f0a
Improve scaffolding to filter existing multiline code fragments
armsnyder Sep 3, 2021
4a5e8fe
Merge pull request #2343 from armsnyder/scaffold-multiline-dedup
k8s-ci-robot Oct 2, 2021
3c339c9
Merge pull request #2000 from HoustonPutman/book-watching-objects
k8s-ci-robot Oct 2, 2021
d8cd79f
add camilamacedo86 as admin
camilamacedo86 Oct 2, 2021
7876dc5
Merge pull request #2364 from camilamacedo86/admin-owner
k8s-ci-robot Oct 2, 2021
b3c2b28
:sparkles: ensure that the whole code has the same nomenclature TODO(…
camilamacedo86 Oct 3, 2021
e47d9cf
:sparkles: Add todo(user) to make clear the need to optimize the valu…
camilamacedo86 Oct 3, 2021
adaddbb
fix(book): update the example to enable webhook and cert manager
lizzzcai Oct 3, 2021
624fdb7
Merge pull request #2367 from lizzzcai/fix-webhook-example
k8s-ci-robot Oct 4, 2021
089fb28
:sparkles: increase resources limits to be less restrictive and match…
camilamacedo86 Oct 4, 2021
d028d18
Merge pull request #2366 from camilamacedo86/todo-code
k8s-ci-robot Oct 4, 2021
3431eaa
Add flag for ignore-not-found to make undeploy and uninstall
perdasilva Sep 22, 2021
955bbdf
Merge pull request #2341 from perdasilva/ignore-not-found
k8s-ci-robot Oct 4, 2021
26803e6
Merge pull request #2365 from camilamacedo86/memory
k8s-ci-robot Oct 4, 2021
dfe8597
Update component config book tutorial
hickeyma Sep 13, 2021
ea0cd76
Upgrade e2e test for latest Kubernetes versions
hickeyma Oct 4, 2021
170981e
Merge pull request #2336 from hickeyma/fix/component-config-tutorial
k8s-ci-robot Oct 9, 2021
7e7b938
Update the Kind version
hickeyma Oct 11, 2021
827b3ef
Merge pull request #2371 from hickeyma/feat/upg-e2e-tst-k8s-sup
k8s-ci-robot Oct 11, 2021
99a0be3
Add default-container annotation
JustinKuli Oct 6, 2021
0467c34
Merge pull request #2376 from JustinKuli/add-default-container
k8s-ci-robot Oct 12, 2021
cbd105e
fix: typo todo text for resource values
camilamacedo86 Oct 12, 2021
a2e5d00
Merge pull request #2378 from camilamacedo86/fix-typo
k8s-ci-robot Oct 13, 2021
d335014
fix: use cancel to stop controller tests with K8s version 1.20+
erikgb Oct 13, 2021
29a1280
Merge pull request #2379 from erikgb/fix-test-shutdown
k8s-ci-robot Oct 13, 2021
040da5d
chore(test): clean up e2e setup scripts, unit test utils
estroz Oct 13, 2021
56daffe
chore(docs): update CRD_OPTIONS and controller-gen docs
estroz Oct 14, 2021
631b627
remove install.sh
devinleee Jul 23, 2021
29e317f
Merge pull request #2256 from yuswift/fix_install.sh
k8s-ci-robot Oct 14, 2021
b6c36fa
Merge pull request #2368 from camilamacedo86/change-values
k8s-ci-robot Oct 14, 2021
fac0208
feat(book): add go path note
ChrisKujawa Oct 15, 2021
751f982
Merge pull request #2385 from Zelldon/patch-1
k8s-ci-robot Oct 15, 2021
c02d98f
Merge pull request #2384 from estroz/chore/update-crd-options-docs
k8s-ci-robot Oct 15, 2021
9dbdbd2
Merge pull request #2382 from estroz/chore/clean-up-test-setup
k8s-ci-robot Oct 15, 2021
5f18771
chore(deps): use equivalent tools version for cluster version
estroz Oct 15, 2021
59f6649
Merge pull request #2386 from estroz/chore/k8s-tools-1.22
k8s-ci-robot Oct 15, 2021
f80a317
Merge pull request #2332 from Birdrock/configuring-envtest-bin-dir-docs
k8s-ci-robot Oct 16, 2021
26a8982
Tag bollerplate Makefile targets as .PHONY
zhengtianbao Oct 25, 2021
e420b3a
Merge pull request #2397 from zhengtianbao/makefile-phony
k8s-ci-robot Oct 27, 2021
75646a6
:book: fix typo issue into controller test
camilamacedo86 Oct 28, 2021
edead38
Merge pull request #2401 from kubernetes-sigs/nit
k8s-ci-robot Oct 28, 2021
dfbca08
:bugfix: fixes default value for the --ignore-not-found flag in the i…
camilamacedo86 Oct 28, 2021
57688c5
Merge pull request #2406 from camilamacedo86/fix-issue-make
k8s-ci-robot Oct 28, 2021
a138637
Merge branch 'master' into release-3
camilamacedo86 Oct 29, 2021
e9458de
Merge branch 'release-3' into release-3
camilamacedo86 Oct 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@

- [Generating CRDs](./reference/generating-crd.md)
- [Using Finalizers](./reference/using-finalizers.md)
- [Watching Resources](./reference/watching-resources.md)
- [Resources Managed by the Operator](./reference/watching-resources/operator-managed.md)
- [Externally Managed Resources](./reference/watching-resources/externally-managed.md)
- [Kind cluster](reference/kind.md)
- [What's a webhook?](reference/webhook-overview.md)
- [Admission webhook](reference/admission-webhook.md)
Expand Down
5 changes: 5 additions & 0 deletions docs/book/src/reference/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
Finalizers are a mechanism to
execute any custom logic related to a resource before it gets deleted from
Kubernetes cluster.
- [Watching Resources](watching-resources.md)
Watch resources in the Kubernetes cluster to be informed and take actions on changes.
- [Resources Managed by the Operator](watching-resources/operator-managed.md)
- [Externally Managed Resources](watching-resources/externally-managed.md)
Controller Runtime provides the ability to watch additional resources relevant to the controlled ones.
- [Kind cluster](kind.md)
- [What's a webhook?](webhook-overview.md)
Webhooks are HTTP callbacks, there are 3
Expand Down
16 changes: 16 additions & 0 deletions docs/book/src/reference/watching-resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Watching Resources

Inside a `Reconcile()` control loop, you are looking to do a collection of operations until it has the desired state on the cluster.
Therefore, it can be necessary to know when a resource that you care about is changed.
In the case that there is an action (create, update, edit, delete, etc.) on a watched resource, `Reconcile()` should be called for the resources watching it.

[Controller Runtime libraries](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/builder) provide many ways for resources to be managed and watched.
This ranges from the easy and obvious use cases, such as watching the resources which were created and managed by the controller, to more unique and advanced use cases.

See each subsection for explanations and examples of the different ways in which your controller can _Watch_ the resources it cares about.

- [Watching Operator Managed Resources](watching-resources/operator-managed.md) -
These resources are created and managed by the same operator as the resource watching them.
This section covers both if they are managed by the same controller or separate controllers.
- [Watching Externally Managed Resources](watching-resources/externally-managed.md) -
These resources could be manually created, or managed by other operators/controllers or the Kubernetes control plane.
31 changes: 31 additions & 0 deletions docs/book/src/reference/watching-resources/externally-managed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Watching Externally Managed Resources

By default, Kubebuilder and the Controller Runtime libraries allow for controllers
to easily watch the resources that they manage as well as dependent resources that are `Owned` by the controller.
However, those are not always the only resources that need to be watched in the cluster.

## User Specified Resources

There are many examples of Resource Specs that allow users to reference external resources.
- Ingresses have references to Service objects
- Pods have references to ConfigMaps, Secrets and Volumes
- Deployments and Services have references to Pods

This same functionality can be added to CRDs and custom controllers.
This will allow for resources to be reconciled when another resources it references is changed.

As an example, we are going to create a `ConfigDeployment` resource.
The `ConfigDeployment`'s purpose is to manage a `Deployment` whose pods are always using the latest version of a `ConfigMap`.
While ConfigMaps are auto-updated within Pods, applications may not always be able to auto-refresh config from the file system.
Some applications require restarts to apply configuration updates.
- The `ConfigDeployment` CRD will hold a reference to a ConfigMap inside its Spec.
- The `ConfigDeployment` controller will be in charge of creating a deployment with Pods that use the ConfigMap.
These pods should be updated anytime that the referenced ConfigMap changes, therefore the ConfigDeployments will need to be reconciled on changes to the referenced ConfigMap.

### Allow for linking of resources in the `Spec`

{{#literatego ./testdata/external-indexed-field/api.go}}

### Watch linked resources

{{#literatego ./testdata/external-indexed-field/controller.go}}
24 changes: 24 additions & 0 deletions docs/book/src/reference/watching-resources/operator-managed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Watching Operator Managed Resources

Kubebuilder and the Controller Runtime libraries allow for controllers
to implement the logic of their CRD through easy management of Kubernetes resources.

## Controlled & Owned Resources

Managing dependency resources is fundamental to a controller, and it's not possible to manage them without watching for changes to their state.
- Deployments must know when the ReplicaSets that they manage are changed
- ReplicaSets must know when their Pods are deleted, or change from healthy to unhealthy.

Through the `Owns()` functionality, Controller Runtime provides an easy way to watch dependency resources for changes.

As an example, we are going to create a `SimpleDeployment` resource.
The `SimpleDeployment`'s purpose is to manage a `Deployment` that users can change certain aspects of, through the `SimpleDeployment` Spec.
The `SimpleDeployment` controller's purpose is to make sure that it's owned `Deployment` always uses the settings provided by the user.

### Provide basic templating in the `Spec`

{{#literatego ./testdata/owned-resource/api.go}}

### Manage the Owned Resource

{{#literatego ./testdata/owned-resource/controller.go}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +kubebuilder:docs-gen:collapse=Apache License
/* */
package external_indexed_field

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +kubebuilder:docs-gen:collapse=Imports

/*
In our type's Spec, we want to allow the user to pass in a reference to a configMap in the same namespace.
It's also possible for this to be a namespaced reference, but in this example we will assume that the referenced object
lives in the same namespace.

This field does not need to be optional.
If the field is required, the indexing code in the controller will need to be modified.
*/

// ConfigDeploymentSpec defines the desired state of ConfigDeployment
type ConfigDeploymentSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Name of an existing ConfigMap in the same namespace, to add to the deployment
// +optional
ConfigMap string `json:"configMap,omitempty"`
}

/*
The rest of the API configuration is covered in the CronJob tutorial.
*/
/* */
// ConfigDeploymentStatus defines the observed state of ConfigDeployment
type ConfigDeploymentStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// ConfigDeployment is the Schema for the configdeployments API
type ConfigDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ConfigDeploymentSpec `json:"spec,omitempty"`
Status ConfigDeploymentStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// ConfigDeploymentList contains a list of ConfigDeployment
type ConfigDeploymentList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ConfigDeployment `json:"items"`
}

func init() {
SchemeBuilder.Register(&ConfigDeployment{}, &ConfigDeploymentList{})
}
// +kubebuilder:docs-gen:collapse=Remaining API Code
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +kubebuilder:docs-gen:collapse=Apache License

/*
Along with the standard imports, we need additional controller-runtime and apimachinery libraries.
All additional libraries, necessary for Watching, have the comment `Required For Watching` appended.
*/
package external_indexed_field

import (
"context"

"github.com/go-logr/logr"
kapps "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/fields" // Required for Watching
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" // Required for Watching
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder" // Required for Watching
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/handler" // Required for Watching
"sigs.k8s.io/controller-runtime/pkg/predicate" // Required for Watching
"sigs.k8s.io/controller-runtime/pkg/reconcile" // Required for Watching
"sigs.k8s.io/controller-runtime/pkg/source" // Required for Watching

appsv1 "tutorial.kubebuilder.io/project/api/v1"
)

/*
Determine the path of the field in the ConfigDeployment CRD that we wish to use as the "object reference".
This will be used in both the indexing and watching.
*/
const (
configMapField = ".spec.configMap"
)

/*
*/

// ConfigDeploymentReconciler reconciles a ConfigDeployment object
type ConfigDeploymentReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:docs-gen:collapse=Reconciler Declaration

/*
There are two additional resources that the controller needs to have access to, other than ConfigDeployments.
- It needs to be able to fully manage Deployments, as well as check their status.
- It also needs to be able to get, list and watch ConfigMaps.
All 3 of these are important, and you will see usages of each below.
*/

//+kubebuilder:rbac:groups=apps.tutorial.kubebuilder.io,resources=configdeployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=apps.tutorial.kubebuilder.io,resources=configdeployments/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=apps.tutorial.kubebuilder.io,resources=configdeployments/finalizers,verbs=update
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch

/*
`Reconcile` will be in charge of reconciling the state of ConfigDeployments.
ConfigDeployments are used to manage Deployments whose pods are updated whenever the configMap that they use is updated.

For that reason we need to add an annotation to the PodTemplate within the Deployment we create.
This annotation will keep track of the latest version of the data within the referenced ConfigMap.
Therefore when the version of the configMap is changed, the PodTemplate in the Deployment will change.
This will cause a rolling upgrade of all Pods managed by the Deployment.

Skip down to the `SetupWithManager` function to see how we ensure that `Reconcile` is called when the referenced `ConfigMaps` are updated.
*/
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
func (r *ConfigDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
/* */
log := r.Log.WithValues("configDeployment", req.NamespacedName)

var configDeployment appsv1.ConfigDeployment
if err := r.Get(ctx, req.NamespacedName, &configDeployment); err != nil {
log.Error(err, "unable to fetch ConfigDeployment")
// we'll ignore not-found errors, since they can't be fixed by an immediate
// requeue (we'll need to wait for a new notification), and we can get them
// on deleted requests.
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// +kubebuilder:docs-gen:collapse=Begin the Reconcile

// your logic here

var configMapVersion string
if configDeployment.Spec.ConfigMap != "" {
configMapName := configDeployment.Spec.ConfigMap
foundConfigMap := &corev1.ConfigMap{}
err := r.Get(ctx, types.NamespacedName{Name: configMapName, Namespace: configDeployment.Namespace}, foundConfigMap)
if err != nil {
// If a configMap name is provided, then it must exist
// You will likely want to create an Event for the user to understand why their reconcile is failing.
return ctrl.Result{}, err
}

// Hash the data in some way, or just use the version of the Object
configMapVersion = foundConfigMap.ResourceVersion
}

// Logic here to add the configMapVersion as an annotation on your Deployment Pods.

return ctrl.Result{}, nil
}

/*
Finally, we add this reconciler to the manager, so that it gets started
when the manager is started.

Since we create dependency Deployments during the reconcile, we can specify that the controller `Owns` Deployments.

However the ConfigMaps that we want to watch are not owned by the ConfigDeployment object.
Therefore we must specify a custom way of watching those objects.
This watch logic is complex, so we have split it into a separate method.
*/

// SetupWithManager sets up the controller with the Manager.
func (r *ConfigDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error {
/*
The `configMap` field must be indexed by the manager, so that we will be able to lookup `ConfigDeployments` by a referenced `ConfigMap` name.
This will allow for quickly answer the question:
- If ConfigMap _x_ is updated, which ConfigDeployments are affected?
*/

if err := mgr.GetFieldIndexer().IndexField(context.Background(), &appsv1.ConfigDeployment{}, configMapField, func(rawObj client.Object) []string {
// Extract the ConfigMap name from the ConfigDeployment Spec, if one is provided
configDeployment := rawObj.(*appsv1.ConfigDeployment)
if configDeployment.Spec.ConfigMap == "" {
return nil
}
return []string{configDeployment.Spec.ConfigMap}
}); err != nil {
return err
}

/*
As explained in the CronJob tutorial, the controller will first register the Type that it manages, as well as the types of subresources that it controls.
Since we also want to watch ConfigMaps that are not controlled or managed by the controller, we will need to use the `Watches()` functionality as well.

The `Watches()` function is a controller-runtime API that takes:
- A Kind (i.e. `ConfigMap`)
- A mapping function that converts a `ConfigMap` object to a list of reconcile requests for `ConfigDeployments`.
We have separated this out into a separate function.
- A list of options for watching the `ConfigMaps`
- In our case, we only want the watch to be triggered when the ResourceVersion of the ConfigMap is changed.
*/

return ctrl.NewControllerManagedBy(mgr).
For(&appsv1.ConfigDeployment{}).
Owns(&kapps.Deployment{}).
Watches(
&source.Kind{Type: &corev1.ConfigMap{}},
handler.EnqueueRequestsFromMapFunc(r.findObjectsForConfigMap),
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}),
).
Complete(r)
}

/*
Because we have already created an index on the `configMap` reference field, this mapping function is quite straight forward.
We first need to list out all `ConfigDeployments` that use `ConfigMap` given in the mapping function.
This is done by merely submitting a List request using our indexed field as the field selector.

When the list of `ConfigDeployments` that reference the `ConfigMap` is found,
we just need to loop through the list and create a reconcile request for each one.
If an error occurs fetching the list, or no `ConfigDeployments` are found, then no reconcile requests will be returned.
*/
func (r *ConfigDeploymentReconciler) findObjectsForConfigMap(configMap client.Object) []reconcile.Request {
attachedConfigDeployments := &appsv1.ConfigDeploymentList{}
listOps := &client.ListOptions{
FieldSelector: fields.OneTermEqualSelector(configMapField, configMap.GetName()),
Namespace: configMap.GetNamespace(),
}
err := r.List(context.TODO(), attachedConfigDeployments, listOps)
if err != nil {
return []reconcile.Request{}
}

requests := make([]reconcile.Request, len(attachedConfigDeployments.Items))
for i, item := range attachedConfigDeployments.Items {
requests[i] = reconcile.Request{
NamespacedName: types.NamespacedName{
Name: item.GetName(),
Namespace: item.GetNamespace(),
},
}
}
return requests
}
Loading