diff --git a/docsy/.gitignore b/docsy/.gitignore
new file mode 100644
index 0000000000..40b67f41a7
--- /dev/null
+++ b/docsy/.gitignore
@@ -0,0 +1,5 @@
+/public
+resources/
+node_modules/
+package-lock.json
+.hugo_build.lock
\ No newline at end of file
diff --git a/docsy/.nvmrc b/docsy/.nvmrc
new file mode 100644
index 0000000000..b009dfb9d9
--- /dev/null
+++ b/docsy/.nvmrc
@@ -0,0 +1 @@
+lts/*
diff --git a/docsy/CONTRIBUTING.md b/docsy/CONTRIBUTING.md
new file mode 100644
index 0000000000..db177d4ac7
--- /dev/null
+++ b/docsy/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
diff --git a/docsy/Dockerfile b/docsy/Dockerfile
new file mode 100644
index 0000000000..232d8f70c4
--- /dev/null
+++ b/docsy/Dockerfile
@@ -0,0 +1,4 @@
+FROM floryn90/hugo:ext-alpine
+
+RUN apk add git && \
+ git config --global --add safe.directory /src
diff --git a/docsy/LICENSE b/docsy/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/docsy/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/docsy/README.md b/docsy/README.md
new file mode 100644
index 0000000000..481ce67413
--- /dev/null
+++ b/docsy/README.md
@@ -0,0 +1,184 @@
+# Docsy Example
+
+[Docsy][] is a [Hugo theme module][] for technical documentation sites, providing easy
+site navigation, structure, and more. This **Docsy Example Project** uses the Docsy
+theme component as a hugo module and provides a skeleton documentation structure for you to use.
+You can clone/copy this project and edit it with your own content, or use it as an example.
+
+In this project, the Docsy theme is pulled in as a Hugo module, together with
+its dependencies:
+
+```console
+$ hugo mod graph
+...
+```
+
+For Docsy documentation, see [Docsy user guide][].
+
+This Docsy Example Project is hosted on [Netlify][] at [example.docsy.dev][].
+You can view deploy logs from the [deploy section of the project's Netlify
+dashboard][deploys], or this [alternate dashboard][].
+
+This is not an officially supported Google product. This project is currently maintained.
+
+## Using the Docsy Example Project as a template
+
+A simple way to get started is to use this project as a template, which gives you a site project that is set up and ready to use. To do this:
+
+1. Use the dropdown for switching branches/tags to change to the **latest** released tag.
+
+2. Click **Use this template**.
+
+3. Select a name for your new project and click **Create repository from template**.
+
+4. Make your own local working copy of your new repo using git clone, replacing https://github.com/me/example.git with your repo’s web URL:
+
+```bash
+git clone --depth 1 https://github.com/me/example.git
+```
+
+You can now edit your own versions of the site’s source files.
+
+If you want to do SCSS edits and want to publish these, you need to install `PostCSS`
+
+```bash
+npm install
+```
+
+## Running the website locally
+
+Building and running the site locally requires a recent `extended` version of [Hugo](https://gohugo.io).
+You can find out more about how to install Hugo for your environment in our
+[Getting started](https://www.docsy.dev/docs/getting-started/#prerequisites-and-installation) guide.
+
+Once you've made your working copy of the site repo, from the repo root folder, run:
+
+```bash
+hugo server
+```
+
+## Running a container locally
+
+You can run docsy-example inside a [Docker](https://docs.docker.com/)
+container, the container runs with a volume bound to the `docsy-example`
+folder. This approach doesn't require you to install any dependencies other
+than [Docker Desktop](https://www.docker.com/products/docker-desktop) on
+Windows and Mac, and [Docker Compose](https://docs.docker.com/compose/install/)
+on Linux.
+
+1. Build the docker image
+
+ ```bash
+ docker-compose build
+ ```
+
+1. Run the built image
+
+ ```bash
+ docker-compose up
+ ```
+
+ > NOTE: You can run both commands at once with `docker-compose up --build`.
+
+1. Verify that the service is working.
+
+ Open your web browser and type `http://localhost:1313` in your navigation bar,
+ This opens a local instance of the docsy-example homepage. You can now make
+ changes to the docsy example and those changes will immediately show up in your
+ browser after you save.
+
+### Cleanup
+
+To stop Docker Compose, on your terminal window, press **Ctrl + C**.
+
+To remove the produced images run:
+
+```bash
+docker-compose rm
+```
+For more information see the [Docker Compose documentation][].
+
+## Using a local Docsy clone
+
+Make sure your installed go version is `1.18` or higher.
+
+Clone the latest version of the docsy theme into the parent folder of your project. The newly created repo should now reside in a sibling folder of your site's root folder.
+
+```shell
+cd root-of-your-site
+git clone --branch v0.7.2 https://github.com/google/docsy.git ../docsy
+```
+
+Now run:
+
+```shell
+HUGO_MODULE_WORKSPACE=docsy.work hugo server --ignoreVendorPaths "**"
+```
+
+or, when using npm, prepend `local` to the script you want to invoke, e.g.:
+
+```shell
+npm run local serve
+```
+
+By using the `HUGO_MODULE_WORKSPACE` directive (either directly or via prefix `local` when using npm), the server now watches all files and directories inside the sibling directory `../docsy` , too. Any changes inside the local `docsy` theme clone are now immediately picked up (hot reload), you can instantly see the effect of your local edits.
+
+In the command above, we used the environment variable `HUGO_MODULE_WORKSPACE` to tell hugo about the local workspace file `docsy.work`. Alternatively, you can declare the workspace file inside your settings file `hugo.toml`:
+
+```toml
+[module]
+ workspace = "docsy.work"
+```
+
+Your project's `hugo.toml` file already contains these lines, the directive for workspace assignment is commented out, however. Remove the two trailing comment characters '//' so that this line takes effect.
+
+## Troubleshooting
+
+As you run the website locally, you may run into the following error:
+
+```console
+$ hugo server
+WARN 2023/06/27 16:59:06 Module "project" is not compatible with this Hugo version; run "hugo mod graph" for more information.
+Start building sites …
+hugo v0.101.0-466fa43c16709b4483689930a4f9ac8add5c9f66+extended windows/amd64 BuildDate=2022-06-16T07:09:16Z VendorInfo=gohugoio
+Error: Error building site: "C:\Users\foo\path\to\docsy-example\content\en\_index.md:5:1": failed to extract shortcode: template for shortcode "blocks/cover" not found
+Built in 27 ms
+```
+
+This error occurs if you are running an outdated version of Hugo. As of docsy theme version `v0.7.0`, hugo version `0.110.0` or higher is required.
+See this [section](https://www.docsy.dev/docs/get-started/docsy-as-module/installation-prerequisites/#install-hugo) of the user guide for instructions on how to install Hugo.
+
+Or you may be confronted with the following error:
+
+```console
+$ hugo server
+
+INFO 2021/01/21 21:07:55 Using config file:
+Building sites … INFO 2021/01/21 21:07:55 syncing static files to /
+Built in 288 ms
+Error: Error building site: TOCSS: failed to transform "scss/main.scss" (text/x-scss): resource "scss/scss/main.scss_9fadf33d895a46083cdd64396b57ef68" not found in file cache
+```
+
+This error occurs if you have not installed the extended version of Hugo.
+See this [section](https://www.docsy.dev/docs/get-started/docsy-as-module/installation-prerequisites/#install-hugo) of the user guide for instructions on how to install Hugo.
+
+Or you may encounter the following error:
+
+```console
+$ hugo server
+
+Error: failed to download modules: binary with name "go" not found
+```
+
+This error occurs if you have not installed the `go` programming language on your system.
+See this [section](https://www.docsy.dev/docs/get-started/docsy-as-module/installation-prerequisites/#install-go-language) of the user guide for instructions on how to install `go`.
+
+
+[alternate dashboard]: https://app.netlify.com/sites/goldydocs/deploys
+[deploys]: https://app.netlify.com/sites/docsy-example/deploys
+[Docsy user guide]: https://docsy.dev/docs
+[Docsy]: https://github.com/google/docsy
+[example.docsy.dev]: https://example.docsy.dev
+[Hugo theme module]: https://gohugo.io/hugo-modules/use-modules/#use-a-module-for-a-theme
+[Netlify]: https://netlify.com
+[Docker Compose documentation]: https://docs.docker.com/compose/gettingstarted/
diff --git a/docsy/assets/icons/logo.svg b/docsy/assets/icons/logo.svg
new file mode 100644
index 0000000000..0048fdf4d6
--- /dev/null
+++ b/docsy/assets/icons/logo.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/docsy/assets/scss/_variables_project.scss b/docsy/assets/scss/_variables_project.scss
new file mode 100644
index 0000000000..35523dc3f4
--- /dev/null
+++ b/docsy/assets/scss/_variables_project.scss
@@ -0,0 +1,10 @@
+/*
+
+Add styles or override variables from the theme here.
+
+*/
+
+//$primary: #fc9c62;;
+$primary: #da5504;
+$secondary: #fc9c62
+//$secondary: white;
\ No newline at end of file
diff --git a/docsy/config.yaml b/docsy/config.yaml
new file mode 100644
index 0000000000..9070e384f0
--- /dev/null
+++ b/docsy/config.yaml
@@ -0,0 +1,15 @@
+# THIS IS A TEST CONFIG ONLY!
+# FOR THE CONFIGURATION OF YOUR SITE USE hugo.yaml.
+#
+# As of Docsy 0.7.0, Hugo 0.110.0 or later must be used.
+#
+# The sole purpose of this config file is to detect Hugo-module builds that use
+# an older version of Hugo.
+#
+# DO NOT add any config parameters to this file. You can safely delete this file
+# if your project is using the required Hugo version.
+
+module:
+ hugoVersion:
+ extended: true
+ min: 0.110.0
diff --git a/docsy/content/en/_index.md b/docsy/content/en/_index.md
new file mode 100644
index 0000000000..9da4a292d8
--- /dev/null
+++ b/docsy/content/en/_index.md
@@ -0,0 +1,73 @@
+---
+title: Java Operator SDK Documentation
+---
+
+{{< blocks/cover title="Welcome to Java Operator SDK Documentation!" image_anchor="top" height="full" >}}
+
+ Learn More
+
+
+ Download
+
+
Implement Kubernetes operators in Java without hassle
+{{< blocks/link-down color="info" >}}
+{{< /blocks/cover >}}
+
+
+{{% blocks/lead color="gray" %}}
+Whether you want to build applications that operate themselves or provision infrastructure from Java code, Kubernetes Operators are the way to go.
+Java Operator SDK is based on the fabric8 Kubernetes client and will make it easy for Java developers to embrace this new way of automation.
+{{% /blocks/lead %}}
+
+
+{{% blocks/section color="secondary" type="row" %}}
+{{% blocks/feature icon="fab fa-slack" title="Contact us on Slack" url="https://kubernetes.slack.com/archives/CAW0GV7A5" %}}
+Feel free to reach out on [Kuberentes Slack](https://kubernetes.slack.com/archives/CAW0GV7A5)
+
+Ask any question, we are happy to answer!
+{{% /blocks/feature %}}
+
+
+{{% blocks/feature icon="fab fa-github" title="Contributions welcome!" url="https://github.com/operator-framework/java-operator-sdk" %}}
+We do a [Pull Request](https://github.com/operator-framework/java-operator-sdk/pulls) contributions workflow on **GitHub**. New users are always welcome!
+{{% /blocks/feature %}}
+
+
+{{% blocks/feature icon="fab fa-twitter" title="Follow us on Twitter!" url="https://twitter.com/javaoperatorsdk" %}}
+For announcement of latest features etc.
+{{% /blocks/feature %}}
+
+
+{{% /blocks/section %}}
+
+
+{{% blocks/section %}}
+
+Sponsored by:
+{.h1 .text-center}
+
+
+ &
+{.h1 .text-center}
+
+{{% /blocks/section %}}
+
+
+{{% blocks/section type="row" %}}
+
+{{% blocks/feature icon="no_icon" %}}
+{{% /blocks/feature %}}
+
+{{% blocks/feature %}}
+Java Operator SDK if member of CNCF as a subproject of Operator Framework
+{.h3 .text-center}
+
+
+
+{{% /blocks/feature %}}
+
+{{% blocks/feature icon="no_icon" %}}
+{{% /blocks/feature %}}
+
+{{% /blocks/section %}}
+
diff --git a/docsy/content/en/blog/_index.md b/docsy/content/en/blog/_index.md
new file mode 100644
index 0000000000..c8219f7994
--- /dev/null
+++ b/docsy/content/en/blog/_index.md
@@ -0,0 +1,8 @@
+---
+title: Blog
+menu: {main: {weight: 30}}
+---
+
+This is the **blog** section. It has two categories: News and Releases.
+
+Content is coming soon.
diff --git a/docsy/content/en/blog/news/_index.md b/docsy/content/en/blog/news/_index.md
new file mode 100644
index 0000000000..c609aa2543
--- /dev/null
+++ b/docsy/content/en/blog/news/_index.md
@@ -0,0 +1,4 @@
+---
+title: News
+weight: 20
+---
diff --git a/docsy/content/en/blog/releases/_index.md b/docsy/content/en/blog/releases/_index.md
new file mode 100644
index 0000000000..9143a23148
--- /dev/null
+++ b/docsy/content/en/blog/releases/_index.md
@@ -0,0 +1,4 @@
+---
+title: Releases
+weight: 20
+---
diff --git a/docsy/content/en/community/_index.md b/docsy/content/en/community/_index.md
new file mode 100644
index 0000000000..3f237b8a79
--- /dev/null
+++ b/docsy/content/en/community/_index.md
@@ -0,0 +1,6 @@
+---
+title: Community
+menu: {main: {weight: 40}}
+---
+
+
diff --git a/docsy/content/en/docs/_index.md b/docsy/content/en/docs/_index.md
new file mode 100755
index 0000000000..76486e22f7
--- /dev/null
+++ b/docsy/content/en/docs/_index.md
@@ -0,0 +1,8 @@
+---
+title: Documentation
+linkTitle: Docs
+menu: {main: {weight: 20}}
+weight: 20
+---
+
+
diff --git a/docsy/content/en/docs/architecture/_index.md b/docsy/content/en/docs/architecture/_index.md
new file mode 100644
index 0000000000..a29f70c4f6
--- /dev/null
+++ b/docsy/content/en/docs/architecture/_index.md
@@ -0,0 +1,65 @@
+---
+title: Architecture and Internals
+weight: 90
+---
+
+
+This document gives an overview of the internal structure and components of Java Operator SDK core,
+in order to make it easier for developers to understand and contribute to it. This document is
+not intended to be a comprehensive reference, rather an introduction to the core concepts and we
+hope that the other parts should be fairly easy to understand. We will evolve this document
+based on the community's feedback.
+
+## The Big Picture and Core Components
+
+![JOSDK architecture](/images/architecture.svg)
+
+An [Operator](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java)
+is a set of
+independent [controllers](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java)
+.
+The `Controller` class, however, is an internal class managed by the framework itself and
+usually shouldn't interacted with directly by end users. It
+manages all the processing units involved with reconciling a single type of Kubernetes resource.
+
+Other components include:
+
+- [Reconciler](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java)
+ is the primary entry-point for the developers of the framework to implement the reconciliation
+ logic.
+- [EventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/EventSource.java)
+ represents a source of events that might eventually trigger a reconciliation.
+- [EventSourceManager](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java)
+ aggregates all the event sources associated with a controller. Manages the event sources'
+ lifecycle.
+- [ControllerResourceEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java)
+ is a central event source that watches the resources associated with the controller (also
+ called primary resources) for changes, propagates events and caches the related state.
+- [EventProcessor](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventProcessor.java)
+ processes the incoming events and makes sure they are executed in a sequential manner, that is
+ making sure that the events are processed in the order they are received for a given resource,
+ despite requests being processed concurrently overall. The `EventProcessor` also takes care of
+ re-scheduling or retrying requests as needed.
+- [ReconcilerDispatcher](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java)
+ is responsible for dispatching requests to the appropriate `Reconciler` method and handling
+ the reconciliation results, making the instructed Kubernetes API calls.
+
+## Typical Workflow
+
+A typical workflows looks like following:
+
+1. An `EventSource` produces an event, that is propagated to the `EventProcessor`.
+2. The resource associated with the event is read from the internal cache.
+3. If the resource is not already being processed, a reconciliation request is
+ submitted to the executor service to be executed in a different thread, encapsulated in a
+ `ControllerExecution` instance.
+4. This, in turns, calls the `ReconcilerDispatcher` which dispatches the call to the appropriate
+ `Reconciler` method, passing along all the required information.
+5. Once the `Reconciler` is done, what happens depends on the result returned by the
+ `Reconciler`. If needed, the `ReconcilerDispatcher` will make the appropriate calls to the
+ Kubernetes API server.
+6. Once the `Reconciler` is done, the `EventProcessor` is called back to finalize the
+ execution and update the controller's state.
+7. The `EventProcessor` checks if the request needs to be rescheduled or retried and if there are no
+ subsequent events received for the same resource.
+8. When none of this happens, the processing of the event is finished.
diff --git a/docsy/content/en/docs/configuration/_index.md b/docsy/content/en/docs/configuration/_index.md
new file mode 100644
index 0000000000..11929e3358
--- /dev/null
+++ b/docsy/content/en/docs/configuration/_index.md
@@ -0,0 +1,68 @@
+---
+title: Configuring JOSDK
+layout: docs
+permalink: /docs/configuration
+---
+
+# Configuration options
+
+The Java Operator SDK (JOSDK) provides several abstractions that work great out of the
+box. However, while we strive to cover the most common cases with the default behavior, we also
+recognize that that default behavior is not always what any given user might want for their
+operator. Numerous configuration options are therefore provided to help people tailor the
+framework to their needs.
+
+Configuration options act at several levels, depending on which behavior you wish to act upon:
+- `Operator`-level using `ConfigurationService`
+- `Reconciler`-level using `ControllerConfiguration`
+- `DependentResouce`-level using the `DependentResourceConfigurator` interface
+- `EventSource`-level: some event sources, such as `InformerEventSource`, might need to be
+ fine-tuned to properly identify which events will trigger the associated reconciler.
+
+## Operator-level configuration
+
+Configuration that impacts the whole operator is performed via the `ConfigurationService` class.
+`ConfigurationService` is an abstract class, and the implementation can be different based
+on which flavor of the framework is used. For example Quarkus Operator SDK replaces the
+default implementation. Configurations are initialized with sensible defaults, but can
+be changed during initialization.
+
+For instance, if you wish to not validate that the CRDs are present on your cluster when the
+operator starts and configure leader election, you would do something similar to:
+
+```java
+Operator operator = new Operator( override -> override
+ .checkingCRDAndValidateLocalModel(false)
+ .withLeaderElectionConfiguration(new LeaderElectionConfiguration("bar", "barNS")));
+```
+
+## Reconciler-level configuration
+
+While reconcilers are typically configured using the `@ControllerConfiguration` annotation, it
+is also possible to override the configuration at runtime, when the reconciler is registered
+with the operator instance, either by passing it a completely new `ControllerConfiguration`
+instance or by preferably overriding some aspects of the current configuration using a
+`ControllerConfigurationOverrider` `Consumer`:
+
+```java
+Operator operator;
+Reconciler reconciler;
+...
+operator.register(reconciler, configOverrider ->
+ configOverrider.withFinalizer("my-nifty-operator/finalizer").withLabelSelector("foo=bar"));
+```
+
+## DependentResource-level configuration
+
+`DependentResource` implementations can implement the `DependentResourceConfigurator` interface
+to pass information to the implementation. For example, the SDK
+provides specific support for the `KubernetesDependentResource`, which can be configured via the
+`@KubernetesDependent` annotation. This annotation is, in turn, converted into a
+`KubernetesDependentResourceConfig` instance, which is then passed to the `configureWith` method
+implementation.
+
+TODO: still subject to change / uniformization
+
+## EventSource-level configuration
+
+TODO
diff --git a/docsy/content/en/docs/contributing/_index.md b/docsy/content/en/docs/contributing/_index.md
new file mode 100644
index 0000000000..e67c45ebb6
--- /dev/null
+++ b/docsy/content/en/docs/contributing/_index.md
@@ -0,0 +1,84 @@
+---
+title: Contributing To Java Operator SDK
+weight: 100
+---
+
+First of all, we'd like to thank you for considering contributing to the project! We really
+hope to create a vibrant community around this project but this won't happen without help from
+people like you!
+
+## Code of Conduct
+
+We are serious about making this a welcoming, happy project. We will not tolerate discrimination,
+aggressive or insulting behaviour.
+
+To this end, the project and everyone participating in it is bound by the [Code of
+Conduct]({{baseurl}}/coc). By participating, you are expected to uphold this code. Please report
+unacceptable behaviour to any of the project admins.
+
+## Bugs
+
+If you find a bug,
+please [open an issue](https://github.com/java-operator-sdk/java-operator-sdk/issues)! Do try
+to include all the details needed to recreate your problem. This is likely to include:
+
+- The version of the Operator SDK being used
+- The exact platform and version of the platform that you're running on
+- The steps taken to cause the bug
+- Reproducer code is also very welcome to help us diagnose the issue and fix it quickly
+
+## Building Features and Documentation
+
+If you're looking for something to work on, take look at the issue tracker, in particular any items
+labelled [good first issue](https://github.com/java-operator-sdk/java-operator-sdk/labels/good%20first%20issue)
+.
+Please leave a comment on the issue to mention that you have started work, in order to avoid
+multiple people working on the same issue.
+
+If you have an idea for a feature - whether or not you have time to work on it - please also open an
+issue describing your feature and label it "enhancement". We can then discuss it as a community and
+see what can be done. Please be aware that some features may not align with the project goals and
+might therefore be closed. In particular, please don't start work on a new feature without
+discussing it first to avoid wasting effort. We do commit to listening to all proposals and will do
+our best to work something out!
+
+Once you've got the go ahead to work on a feature, you can start work. Feel free to communicate with
+team via updates on the issue tracker or the [Discord channel](https://discord.gg/DacEhAy) and ask
+for feedback, pointers etc. Once you're happy with your code, go ahead and open a Pull Request.
+
+## Pull Request Process
+
+First, please format your commit messages so that they follow
+the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) format.
+
+On opening a PR, a GitHub action will execute the test suite against the new code. All code is
+required to pass the tests, and new code must be accompanied by new tests.
+
+All PRs have to be reviewed and signed off by another developer before being merged. This review
+will likely ask for some changes to the code - please don't be alarmed or upset
+at this; it is expected that all PRs will need tweaks and a normal part of the process.
+
+The PRs are checked to be compliant with the Java Google code style.
+
+Be aware that all Operator SDK code is released under the [Apache 2.0 licence](LICENSE).
+
+## Development environment setup
+
+### Code style
+
+The SDK modules and samples are formatted to follow the Java Google code style.
+On every `compile` the code gets formatted automatically, however, to make things simpler (i.e.
+avoid getting a PR rejected simply because of code style issues), you can import one of the
+following code style schemes based on the IDE you use:
+
+- for *Intellij IDEA*
+ import [contributing/intellij-google-style.xml](contributing/intellij-google-style.xml)
+- for *Eclipse*
+ import [contributing/eclipse-google-style.xml](contributing/eclipse-google-style.xml)
+
+## Thanks
+
+These guidelines were based on several sources, including
+[Atom](https://github.com/atom/atom/blob/master/CONTRIBUTING.md), [PurpleBooth's
+advice](https://gist.github.com/PurpleBooth/b24679402957c63ec426) and the [Contributor
+Covenant](https://www.contributor-covenant.org/).
diff --git a/docsy/content/en/docs/dependent-resources/_index.md b/docsy/content/en/docs/dependent-resources/_index.md
new file mode 100644
index 0000000000..51738869e3
--- /dev/null
+++ b/docsy/content/en/docs/dependent-resources/_index.md
@@ -0,0 +1,552 @@
+---
+title: Dependent Resources
+weight: 60
+---
+
+## Motivations and Goals
+
+Most operators need to deal with secondary resources when trying to realize the desired state
+described by the primary resource they are in charge of. For example, the Kubernetes-native
+`Deployment` controller needs to manage `ReplicaSet` instances as part of a `Deployment`'s
+reconciliation process. In this instance, `ReplicatSet` is considered a secondary resource for
+the `Deployment` controller.
+
+Controllers that deal with secondary resources typically need to perform the following steps, for
+each secondary resource:
+
+
+flowchart TD
+
+compute[Compute desired secondary resource based on primary state] --> A
+A{Secondary resource exists?}
+A -- Yes --> match
+A -- No --> Create --> Done
+
+match{Matches desired state?}
+match -- Yes --> Done
+match -- No --> Update --> Done
+
+
+
+While these steps are not difficult in and of themselves, there are some subtleties that can lead to
+bugs or sub-optimal code if not done right. As this process is pretty much similar for each
+dependent resource, it makes sense for the SDK to offer some level of support to remove the
+boilerplate code associated with encoding these repetitive actions. It should
+be possible to handle common cases (such as dealing with Kubernetes-native secondary resources) in a
+semi-declarative way with only a minimal amount of code, JOSDK taking care of wiring everything
+accordingly.
+
+Moreover, in order for your reconciler to get informed of events on these secondary resources, you
+need to configure and create event sources and maintain them. JOSDK already makes it rather easy
+to deal with these, but dependent resources makes it even simpler.
+
+Finally, there are also opportunities for the SDK to transparently add features that are even
+trickier to get right, such as immediate caching of updated or created resources (so that your
+reconciler doesn't need to wait for a cluster roundtrip to continue its work) and associated
+event filtering (so that something your reconciler just changed doesn't re-trigger a
+reconciliation, for example).
+
+## Design
+
+### `DependentResource` vs. `AbstractDependentResource`
+
+The new
+[`DependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java)
+interface lies at the core of the design and strives to encapsulate the logic that is required
+to reconcile the state of the associated secondary resource based on the state of the primary
+one. For most cases, this logic will follow the flow expressed above and JOSDK provides a very
+convenient implementation of this logic in the form of the
+[`AbstractDependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java)
+class. If your logic doesn't fit this pattern, though, you can still provide your
+own `reconcile` method implementation. While the benefits of using dependent resources are less
+obvious in that case, this allows you to separate the logic necessary to deal with each
+secondary resource in its own class that can then be tested in isolation via unit tests. You can
+also use the declarative support with your own implementations as we shall see later on.
+
+`AbstractDependentResource` is designed so that classes extending it specify which functionality
+they support by implementing trait interfaces. This design has been selected to express the fact
+that not all secondary resources are completely under the control of the primary reconciler:
+some dependent resources are only ever created or updated for example and we needed a way to let
+JOSDK know when that is the case. We therefore provide trait interfaces: `Creator`,
+`Updater` and `Deleter` to express that the `DependentResource` implementation will provide custom
+functionality to create, update and delete its associated secondary resources, respectively. If
+these traits are not implemented then parts of the logic described above is never triggered: if
+your implementation doesn't implement `Creator`, for example, `AbstractDependentResource` will
+never try to create the associated secondary resource, even if it doesn't exist. It is even
+possible to not implement any of these traits and therefore create read-only dependent resources
+that will trigger your reconciler whenever a user interacts with them but that are never
+modified by your reconciler itself - however note that read-only dependent resources rarely make
+sense, as it is usually simpler to register an event source for the target resource.
+
+All subclasses
+of [`AbstractDependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java)
+can also implement
+the [`Matcher`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Matcher.java)
+interface to customize how the SDK decides whether or not the actual state of the dependent
+matches the desired state. This makes it convenient to use these abstract base classes for your
+implementation, only customizing the matching logic. Note that in many cases, there is no need
+to customize that logic as the SDK already provides convenient default implementations in the
+form
+of [`DesiredEqualsMatcher`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DesiredEqualsMatcher.java)
+and
+[`GenericKubernetesResourceMatcher`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java)
+implementations, respectively. If you want to provide custom logic, you only need your
+`DependentResource` implementation to implement the `Matcher` interface as below, which shows
+how to customize the default matching logic for Kubernetes resources to also consider annotations
+and labels, which are ignored by default:
+
+```java
+public class MyDependentResource extends KubernetesDependentResource
+ implements Matcher {
+ // your implementation
+
+ public Result match(MyDependent actualResource, MyPrimary primary,
+ Context context) {
+ return GenericKubernetesResourceMatcher.match(this, actualResource, primary, context, true);
+ }
+}
+```
+
+### Batteries included: convenient DependentResource implementations!
+
+JOSDK also offers several other convenient implementations building on top of
+`AbstractDependentResource` that you can use as starting points for your own implementations.
+
+One such implementation is the `KubernetesDependentResource` class that makes it really easy to work
+with Kubernetes-native resources. In this case, you usually only need to provide an implementation
+for the `desired` method to tell JOSDK what the desired state of your secondary resource should
+be based on the specified primary resource state.
+
+JOSDK takes care of everything else using default implementations that you can override in case you
+need more precise control of what's going on.
+
+We also provide implementations that make it easy to cache
+(`AbstractExternalDependentResource`) or poll for changes in external resources
+(`PollingDependentResource`, `PerResourcePollingDependentResource`). All the provided
+implementations can be found in the `io/javaoperatorsdk/operator/processing/dependent` package of
+the `operator-framework-core` module.
+
+### Sample Kubernetes Dependent Resource
+
+A typical use case, when a Kubernetes resource is fully managed - Created, Read, Updated and
+Deleted (or set to be garbage collected). The following example shows how to create a
+`Deployment` dependent resource:
+
+```java
+
+@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
+class DeploymentDependentResource extends CRUDKubernetesDependentResource {
+
+ public DeploymentDependentResource() {
+ super(Deployment.class);
+ }
+
+ @Override
+ protected Deployment desired(WebPage webPage, Context context) {
+ var deploymentName = deploymentName(webPage);
+ Deployment deployment = loadYaml(Deployment.class, getClass(), "deployment.yaml");
+ deployment.getMetadata().setName(deploymentName);
+ deployment.getMetadata().setNamespace(webPage.getMetadata().getNamespace());
+ deployment.getSpec().getSelector().getMatchLabels().put("app", deploymentName);
+
+ deployment.getSpec().getTemplate().getMetadata().getLabels()
+ .put("app", deploymentName);
+ deployment.getSpec().getTemplate().getSpec().getVolumes().get(0)
+ .setConfigMap(new ConfigMapVolumeSourceBuilder().withName(configMapName(webPage)).build());
+ return deployment;
+ }
+}
+```
+
+The only thing that you need to do is to extend the `CRUDKubernetesDependentResource` and
+specify the desired state for your secondary resources based on the state of the primary one. In
+the example above, we're handling the state of a `Deployment` secondary resource associated with
+a `WebPage` custom (primary) resource.
+
+The `@KubernetesDependent` annotation can be used to further configure **managed** dependent
+resource that are extending `KubernetesDependentResource`.
+
+See the full source
+code [here](https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/DeploymentDependentResource.java)
+.
+
+## Managed Dependent Resources
+
+As mentioned previously, one goal of this implementation is to make it possible to declaratively
+create and wire dependent resources. You can annotate your reconciler with `@Dependent`
+annotations that specify which `DependentResource` implementation it depends upon.
+JOSDK will take the appropriate steps to wire everything together and call your
+`DependentResource` implementations `reconcile` method before your primary resource is reconciled.
+This makes sense in most use cases where the logic associated with the primary resource is
+usually limited to status handling based on the state of the secondary resources and the
+resources are not dependent on each other.
+
+See [Workflows](https://javaoperatorsdk.io/docs/workflows) for more details on how the dependent
+resources are reconciled.
+
+This behavior and automated handling is referred to as "managed" because the `DependentResource`
+instances are managed by JOSDK, an example of which can be seen below:
+
+```java
+
+@ControllerConfiguration(
+ labelSelector = SELECTOR,
+ dependents = {
+ @Dependent(type = ConfigMapDependentResource.class),
+ @Dependent(type = DeploymentDependentResource.class),
+ @Dependent(type = ServiceDependentResource.class)
+ })
+public class WebPageManagedDependentsReconciler
+ implements Reconciler, ErrorStatusHandler {
+
+ // omitted code
+
+ @Override
+ public UpdateControl reconcile(WebPage webPage, Context context) {
+
+ final var name = context.getSecondaryResource(ConfigMap.class).orElseThrow()
+ .getMetadata().getName();
+ webPage.setStatus(createStatus(name));
+ return UpdateControl.patchStatus(webPage);
+ }
+
+}
+```
+
+See the full source code of
+sample [here](https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageManagedDependentsReconciler.java)
+.
+
+## Standalone Dependent Resources
+
+It is also possible to wire dependent resources programmatically. In practice this means that the
+developer is responsible for initializing and managing the dependent resources as well as calling
+their `reconcile` method. However, this makes it possible for developers to fully customize the
+reconciliation process. Standalone dependent resources should be used in cases when the managed use
+case does not fit.
+
+Note that [Workflows](https://javaoperatorsdk.io/docs/workflows) also can be invoked from standalone
+resources.
+
+The following sample is similar to the one above, simply performing additional checks, and
+conditionally creating an `Ingress`:
+
+```java
+
+@ControllerConfiguration
+public class WebPageStandaloneDependentsReconciler
+ implements Reconciler, ErrorStatusHandler,
+ EventSourceInitializer {
+
+ private KubernetesDependentResource configMapDR;
+ private KubernetesDependentResource deploymentDR;
+ private KubernetesDependentResource serviceDR;
+ private KubernetesDependentResource ingressDR;
+
+ public WebPageStandaloneDependentsReconciler(KubernetesClient kubernetesClient) {
+ // 1.
+ createDependentResources(kubernetesClient);
+ }
+
+ @Override
+ public List prepareEventSources(EventSourceContext context) {
+ // 2.
+ return List.of(
+ configMapDR.initEventSource(context),
+ deploymentDR.initEventSource(context),
+ serviceDR.initEventSource(context));
+ }
+
+ @Override
+ public UpdateControl reconcile(WebPage webPage, Context context) {
+
+ // 3.
+ if (!isValidHtml(webPage.getHtml())) {
+ return UpdateControl.patchStatus(setInvalidHtmlErrorMessage(webPage));
+ }
+
+ // 4.
+ configMapDR.reconcile(webPage, context);
+ deploymentDR.reconcile(webPage, context);
+ serviceDR.reconcile(webPage, context);
+
+ // 5.
+ if (Boolean.TRUE.equals(webPage.getSpec().getExposed())) {
+ ingressDR.reconcile(webPage, context);
+ } else {
+ ingressDR.delete(webPage, context);
+ }
+
+ // 6.
+ webPage.setStatus(
+ createStatus(configMapDR.getResource(webPage).orElseThrow().getMetadata().getName()));
+ return UpdateControl.patchStatus(webPage);
+ }
+
+ private void createDependentResources(KubernetesClient client) {
+ this.configMapDR = new ConfigMapDependentResource();
+ this.deploymentDR = new DeploymentDependentResource();
+ this.serviceDR = new ServiceDependentResource();
+ this.ingressDR = new IngressDependentResource();
+
+ Arrays.asList(configMapDR, deploymentDR, serviceDR, ingressDR).forEach(dr -> {
+ dr.setKubernetesClient(client);
+ dr.configureWith(new KubernetesDependentResourceConfig()
+ .setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR));
+ });
+ }
+
+ // omitted code
+}
+```
+
+There are multiple things happening here:
+
+1. Dependent resources are explicitly created and can be access later by reference.
+2. Event sources are produced by the dependent resources, but needs to be explicitly registered in
+ this case by implementing
+ the [`EventSourceInitializer`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java)
+ interface.
+3. The input html is validated, and error message is set in case it is invalid.
+4. Reconciliation of dependent resources is called explicitly, but here the workflow
+ customization is fully in the hand of the developer.
+5. An `Ingress` is created but only in case `exposed` flag set to true on custom resource. Tries to
+ delete it if not.
+6. Status is set in a different way, this is just an alternative way to show, that the actual state
+ can be read using the reference. This could be written in a same way as in the managed example.
+
+See the full source code of
+sample [here](https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java)
+.
+
+Note also the Workflows feature makes it possible to also support this conditional creation use
+case in managed dependent resources.
+
+## Creating/Updating Kubernetes Resources
+
+From version 4.4 of the framework the resources are created and updated
+using [Server Side Apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/)
+, thus the desired state is simply sent using this approach to update the actual resource.
+
+## Comparing desired and actual state (matching)
+
+During the reconciliation of a dependent resource, the desired state is matched with the actual
+state from the caches. The dependent resource only gets updated on the server if the actual,
+observed state differs from the desired one. Comparing these two states is a complex problem
+when dealing with Kubernetes resources because a strict equality check is usually not what is
+wanted due to the fact that multiple fields might be automatically updated or added by
+the platform (
+by [dynamic admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)
+or validation webhooks, for example). Solving this problem in a generic way is therefore a tricky
+proposition.
+
+JOSDK provides such a generic matching implementation which is used by default:
+[SSABasedGenericKubernetesResourceMatcher](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcher.java)
+This implementation relies on the managed fields used by the Server Side Apply feature to
+compare only the values of the fields that the controller manages. This ensures that only
+semantically relevant fields are compared. See javadoc for further details.
+
+JOSDK versions prior to 4.4 were using a different matching algorithm as implemented in
+[GenericKubernetesResourceMatcher](https://github.com/java-operator-sdk/java-operator-sdk/blob/e16559fd41bbb8bef6ce9d1f47bffa212a941b09/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java).
+
+Since SSA is a complex feature, JOSDK implements a feature flag allowing users to switch between
+these implementations. See
+in [ConfigurationService](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L332-L358).
+
+It is, however, important to note that these implementations are default, generic
+implementations that the framework can provide expected behavior out of the box. In many
+situations, these will work just fine but it is also possible to provide matching algorithms
+optimized for specific use cases. This is easily done by simply overriding
+the `match(...)` [method](https://github.com/java-operator-sdk/java-operator-sdk/blob/e16559fd41bbb8bef6ce9d1f47bffa212a941b09/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java#L156-L156).
+
+It is also possible to bypass the matching logic altogether to simply rely on the server-side
+apply mechanism if always sending potentially unchanged resources to the cluster is not an issue.
+JOSDK's matching mechanism allows to spare some potentially useless calls to the Kubernetes API
+server. To bypass the matching feature completely, simply override the `match` method to always
+return `false`, thus telling JOSDK that the actual state never matches the desired one, making
+it always update the resources using SSA.
+
+WARNING: Older versions of Kubernetes before 1.25 would create an additional resource version for every SSA update
+performed with certain resources - even though there were no actual changes in the stored resource - leading to infinite
+reconciliations. This behavior was seen with Secrets using `stringData`, Ingresses using empty string fields, and
+StatefulSets using volume claim templates. The operator framework has added built-in handling for the StatefulSet issue.
+If you encounter this issue on an older Kubernetes version, consider changing your desired state, turning off SSA for
+that resource, or even upgrading your Kubernetes version. If you encounter it on a newer Kubernetes version, please log
+an issue with the JOSDK and with upstream Kubernetes.
+
+## Telling JOSDK how to find which secondary resources are associated with a given primary resource
+
+[`KubernetesDependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java)
+automatically maps secondary resource to a primary by owner reference. This behavior can be
+customized by implementing
+[`SecondaryToPrimaryMapper`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/SecondaryToPrimaryMapper.java)
+by the dependent resource.
+
+See sample in one of the integration
+tests [here](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/DependentPrimaryIndexerTestReconciler.java#L25-L25)
+.
+
+## Multiple Dependent Resources of Same Type
+
+When dealing with multiple dependent resources of same type, the dependent resource implementation
+needs to know which specific resource should be targeted when reconciling a given dependent
+resource, since there will be multiple instances of that type which could possibly be used, each
+associated with the same primary resource. In order to do this, JOSDK relies on the
+[resource discriminator](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceDiscriminator.java)
+concept. Resource discriminators uniquely identify the target resource of a dependent resource.
+In the managed Kubernetes dependent resources case, the discriminator can be declaratively set
+using the `@KubernetesDependent` annotation:
+
+```java
+
+@KubernetesDependent(resourceDiscriminator = ConfigMap1Discriminator.class)
+public class MultipleManagedDependentResourceConfigMap1 {
+//...
+}
+```
+
+Dependent resources usually also provide event sources. When dealing with multiple dependents of
+the same type, one needs to decide whether these dependent resources should track the same
+resources and therefore share a common event source, or, to the contrary, track completely
+separate resources, in which case using separate event sources is advised.
+
+Dependents can therefore reuse existing, named event sources by referring to their name. In the
+declarative case, assuming a `configMapSource` `EventSource` has already been declared, this
+would look as follows:
+
+```
+ @Dependent(type = MultipleManagedDependentResourceConfigMap1.class,
+ useEventSourceWithName = "configMapSource")
+```
+
+A sample is provided as an integration test both
+for [managed](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleManagedDependentSameTypeIT.java)
+and
+for [standalone](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleDependentResourceIT.java)
+cases.
+
+## Bulk Dependent Resources
+
+So far, all the cases we've considered were dealing with situations where the number of
+dependent resources needed to reconcile the state expressed by the primary resource is known
+when writing the code for the operator. There are, however, cases where the number of dependent
+resources to be created depends on information found in the primary resource.
+
+These cases are covered by the "bulk" dependent resources feature. To create such dependent
+resources, your implementation should extend `AbstractDependentResource` (at least indirectly) and
+implement the
+[`BulkDependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/BulkDependentResource.java)
+interface.
+
+Various examples are provided
+as [integration tests](https://github.com/java-operator-sdk/java-operator-sdk/tree/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/bulkdependent)
+.
+
+To see how bulk dependent resources interact with workflow conditions, please refer to this
+[integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/bulkdependent/BulkDependentWithConditionIT.java).
+
+## External State Tracking Dependent Resources
+
+It is sometimes necessary for a controller to track external (i.e. non-Kubernetes) state to
+properly manage some dependent resources. For example, your controller might need to track the
+state of a REST API resource, which, after being created, would be refer to by its identifier.
+Such identifier would need to be tracked by your controller to properly retrieve the state of
+the associated resource and/or assess if such a resource exists. While there are several ways to
+support this use case, we recommend storing such information in a dedicated Kubernetes resources
+(usually a `ConfigMap` or a `Secret`), so that it can be manipulated with common Kubernetes
+mechanisms.
+
+This particular use case is supported by the
+[`AbstractExternalDependentResource`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractExternalDependentResource.java)
+class that you can extend to suit your needs, as well as implement the
+[`DependentResourceWithExplicitState`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceWithExplicitState.java)
+interface. Note that most of the JOSDK-provided dependent resource implementations such as
+`PollingDependentResource` or `PerResourcePollingDependentResource` already extends
+`AbstractExternalDependentResource`, thus supporting external state tracking out of the box.
+
+See [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/ExternalStateDependentIT.java)
+as a sample.
+
+For a better understanding it might be worth to study
+a [sample implementation](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateReconciler.java)
+without dependent resources.
+
+Please also refer to the [docs](/docs/patterns-best-practices#managing-state) for managing state in
+general.
+
+## Combining Bulk and External State Tracking Dependent Resources
+
+Both bulk and external state tracking features can be combined. In that
+case, a separate, state-tracking resource will be created for each bulk dependent resource
+created. For example, if three bulk dependent resources associated with external state are created,
+three associated `ConfigMaps` (assuming `ConfigMaps` are used as a state-tracking resource) will
+also be created, one per dependent resource.
+
+See [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/ExternalStateBulkIT.java)
+as a sample.
+
+
+## GenericKubernetesResource based Dependent Resources
+
+In rare circumstances resource handling where there is no class representation or just typeless handling might be needed.
+Fabric8 Client provides [GenericKubernetesResource](https://github.com/fabric8io/kubernetes-client/blob/main/doc/CHEATSHEET.md#resource-typeless-api)
+to support that.
+
+For dependent resource this is supported by [GenericKubernetesDependentResource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java#L8-L8)
+. See samples [here](https://github.com/java-operator-sdk/java-operator-sdk/tree/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource).
+
+## Other Dependent Resource Features
+
+### Caching and Event Handling in [KubernetesDependentResource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java)
+
+1. When a Kubernetes resource is created or updated the related informer (more precisely
+ the `InformerEventSource`), eventually will receive an event and will cache the up-to-date
+ resource. Typically, though, there might be a small time window when calling the
+ `getResource()` of the dependent resource or getting the resource from the `EventSource`
+ itself won't return the just updated resource, in the case where the associated event hasn't
+ been received from the Kubernetes API. The `KubernetesDependentResource` implementation,
+ however, addresses this issue, so you don't have to worry about it by making sure that it or
+ the related `InformerEventSource` always return the up-to-date resource.
+
+2. Another feature of `KubernetesDependentResource` is to make sure that if a resource is created or
+ updated during the reconciliation, this particular change, which normally would trigger the
+ reconciliation again (since the resource has changed on the server), will, in fact, not
+ trigger the reconciliation again since we already know the state is as expected. This is a small
+ optimization. For example if during a reconciliation a `ConfigMap` is updated using dependent
+ resources, this won't trigger a new reconciliation. Such a reconciliation is indeed not
+ needed since the change originated from our reconciler. For this system to work properly,
+ though, it is required that changes are received only by one event source (this is a best
+ practice in general) - so for example if there are two config map dependents, either
+ there should be a shared event source between them, or a label selector on the event sources
+ to select only the relevant events, see
+ in [related integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java)
+ .
+
+## "Read-only" Dependent Resources vs. Event Source
+
+See Integration test for a read-only
+dependent [here](https://github.com/java-operator-sdk/java-operator-sdk/blob/249b41f3c68c4d0e9c77c41eca647a69a24347b0/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java).
+
+Some secondary resources only exist as input for the reconciliation process and are never
+updated *by a controller* (they might, and actually usually do, get updated by users interacting
+with the resources directly, however). This might be the case, for example, of a `ConfigMap`that is
+used to configure common characteristics of multiple resources in one convenient place.
+
+In such situations, one might wonder whether it makes sense to create a dependent resource in
+this case or simply use an `EventSource` so that the primary resource gets reconciled whenever a
+user changes the resource. Typical dependent resources provide a desired state that the
+reconciliation process attempts to match. In the case of so-called read-only dependents, though,
+there is no such desired state because the operator / controller will never update the resource
+itself, just react to external changes to it. An `EventSource` would achieve the same result.
+
+Using a dependent resource for that purpose instead of a simple `EventSource`, however, provides
+several benefits:
+
+- dependents can be created declaratively, while an event source would need to be manually created
+- if dependents are already used in a controller, it makes sense to unify the handling of all
+ secondary resources as dependents from a code organization perspective
+- dependent resources can also interact with the workflow feature, thus allowing the read-only
+ resource to participate in conditions, in particular to decide whether the primary
+ resource needs/can be reconciled using reconcile pre-conditions, block the progression of the workflow altogether with
+ ready post-conditions or have other dependents depend on them, in essence, read-only dependents can participate in
+ workflows just as any other dependents.
\ No newline at end of file
diff --git a/docsy/content/en/docs/faq/_index.md b/docsy/content/en/docs/faq/_index.md
new file mode 100644
index 0000000000..79264332ef
--- /dev/null
+++ b/docsy/content/en/docs/faq/_index.md
@@ -0,0 +1,96 @@
+---
+title: FAQ
+weight: 80
+---
+
+### Q: How can I access the events which triggered the Reconciliation?
+
+In the v1.* version events were exposed to `Reconciler` (which was called `ResourceController`
+then). This included events (Create, Update) of the custom resource, but also events produced by
+Event Sources. After long discussions also with developers of golang version (controller-runtime),
+we decided to remove access to these events. We already advocated to not use events in the
+reconciliation logic, since events can be lost. Instead, reconcile all the resources on every
+execution of reconciliation. On first this might sound a little opinionated, but there is a
+sound agreement between the developers that this is the way to go.
+
+Note that this is also consistent with Kubernetes
+[level based](https://cloud.redhat.com/blog/kubernetes-operators-best-practices) reconciliation approach.
+
+### Q: Can I re-schedule a reconciliation, possibly with a specific delay?
+
+Yes, this can be done
+using [`UpdateControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java)
+and [`DeleteControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DeleteControl.java)
+, see:
+
+```java
+ @Override
+ public UpdateControl reconcile(
+ EventSourceTestCustomResource resource, Context context) {
+ ...
+ return UpdateControl.patchStatus(resource).rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+```
+
+without an update:
+
+```java
+ @Override
+ public UpdateControl reconcile(
+ EventSourceTestCustomResource resource, Context context) {
+ ...
+ return UpdateControl.noUpdate().rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+```
+
+Although you might consider using `EventSources`, to handle reconciliation triggering in a smarter
+way.
+
+### Q: How can I run an operator without cluster scope rights?
+
+By default, JOSDK requires access to CRs at cluster scope. You may not be granted such
+rights and you will see some error at startup that looks like:
+
+```plain
+io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: GET at: https://kubernetes.local.svc/apis/mygroup/v1alpha1/mycr. Message: Forbidden! Configured service account doesn't have access. Service account may have been revoked. mycrs.mygroup is forbidden: User "system:serviceaccount:ns:sa" cannot list resource "mycrs" in API group "mygroup" at the cluster scope.
+```
+
+To restrict the operator to a set of namespaces, you may override which namespaces are watched by a reconciler
+at [Reconciler-level configuration](./configuration.md#reconciler-level-configuration):
+
+```java
+Operator operator;
+Reconciler reconciler;
+...
+operator.register(reconciler, configOverrider ->
+ configOverrider.settingNamespace("mynamespace"));
+```
+Note that configuring the watched namespaces can also be done using the `@ControllerConfiguration` annotation.
+
+Furthermore, you may not be able to list CRDs at startup which is required when `checkingCRDAndValidateLocalModel`
+is `true` (`false` by default). To disable, set it to `false` at [Operator-level configuration](./configuration.md#operator-level-configuration):
+
+```java
+Operator operator = new Operator( override -> override.checkingCRDAndValidateLocalModel(false));
+```
+
+### Q: How to fix `sun.security.provider.certpath.SunCertPathBuilderException` on Rancher Desktop and k3d/k3s Kubernetes
+
+It's a common issue when using k3d and the fabric8 client tries to connect to the cluster an exception is thrown:
+
+```
+Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
+ at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
+ at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:352)
+ at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:295)
+```
+
+The cause is that fabric8 kubernetes client does not handle elliptical curve encryption by default. To fix this, add
+the following dependency on the classpath:
+
+```xml
+
+ org.bouncycastle
+ bcpkix-jdk15on
+
+```
\ No newline at end of file
diff --git a/docsy/content/en/docs/features/_index.md b/docsy/content/en/docs/features/_index.md
new file mode 100644
index 0000000000..b1f0ff166f
--- /dev/null
+++ b/docsy/content/en/docs/features/_index.md
@@ -0,0 +1,860 @@
+---
+title: Features
+weight: 50
+---
+
+The Java Operator SDK (JOSDK) is a high level framework and related tooling aimed at
+facilitating the implementation of Kubernetes operators. The features are by default following
+the best practices in an opinionated way. However, feature flags and other configuration options
+are provided to fine tune or turn off these features.
+
+## Reconciliation Execution in a Nutshell
+
+Reconciliation execution is always triggered by an event. Events typically come from a
+primary resource, most of the time a custom resource, triggered by changes made to that resource
+on the server (e.g. a resource is created, updated or deleted). Reconciler implementations are
+associated with a given resource type and listens for such events from the Kubernetes API server
+so that they can appropriately react to them. It is, however, possible for secondary sources to
+trigger the reconciliation process. This usually occurs via
+the [event source](#handling-related-events-with-event-sources) mechanism.
+
+When an event is received reconciliation is executed, unless a reconciliation is already
+underway for this particular resource. In other words, the framework guarantees that no
+concurrent reconciliation happens for any given resource.
+
+Once the reconciliation is done, the framework checks if:
+
+- an exception was thrown during execution and if yes schedules a retry.
+- new events were received during the controller execution, if yes schedule a new reconciliation.
+- the reconcilier instructed the SDK to re-schedule a reconciliation at a later date, if yes
+ schedules a timer event with the specified delay.
+- none of the above, the reconciliation is finished.
+
+In summary, the core of the SDK is implemented as an eventing system, where events trigger
+reconciliation requests.
+
+## Implementing a [`Reconciler`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java) and/or [`Cleaner`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java)
+
+The lifecycle of a Kubernetes resource can be clearly separated into two phases from the
+perspective of an operator depending on whether a resource is created or updated, or on the
+other hand if it is marked for deletion.
+
+This separation-related logic is automatically handled by the framework. The framework will always
+call the `reconcile` method, unless the custom resource is
+[marked from deletion](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/#how-finalizers-work)
+. On the other, if the resource is marked from deletion and if the `Reconciler` implements the
+`Cleaner` interface, only the `cleanup` method will be called. Implementing the `Cleaner`
+interface allows developers to let the SDK know that they are interested in cleaning related
+state (e.g. out-of-cluster resources). The SDK will therefore automatically add a finalizer
+associated with your `Reconciler` so that the Kubernetes server doesn't delete your resources
+before your `Reconciler` gets a chance to clean things up.
+See [Finalizer support](#finalizer-support) for more details.
+
+### Using `UpdateControl` and `DeleteControl`
+
+These two classes are used to control the outcome or the desired behaviour after the reconciliation.
+
+The [`UpdateControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java)
+can instruct the framework to update the status sub-resource of the resource
+and/or re-schedule a reconciliation with a desired time delay:
+
+```java
+ @Override
+ public UpdateControl reconcile(
+ EventSourceTestCustomResource resource, Context context) {
+ ...
+ return UpdateControl.patchStatus(resource).rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+```
+
+without an update:
+
+```java
+ @Override
+ public UpdateControl reconcile(
+ EventSourceTestCustomResource resource, Context context) {
+ ...
+ return UpdateControl.noUpdate().rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+```
+
+Note, though, that using `EventSources` should be preferred to rescheduling since the
+reconciliation will then be triggered only when needed instead than on a timely basis.
+
+Those are the typical use cases of resource updates, however in some cases there it can happen that
+the controller wants to update the resource itself (for example to add annotations) or not perform
+any updates, which is also supported.
+
+It is also possible to update both the status and the resource with the
+`updateResourceAndStatus` method. In this case, the resource is updated first followed by the
+status, using two separate requests to the Kubernetes API.
+
+You should always state your intent using `UpdateControl` and let the SDK deal with the actual
+updates instead of performing these updates yourself using the actual Kubernetes client so that
+the SDK can update its internal state accordingly.
+
+Resource updates are protected using optimistic version control, to make sure that other updates
+that might have occurred in the mean time on the server are not overwritten. This is ensured by
+setting the `resourceVersion` field on the processed resources.
+
+[`DeleteControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DeleteControl.java)
+typically instructs the framework to remove the finalizer after the dependent
+resource are cleaned up in `cleanup` implementation.
+
+```java
+
+public DeleteControl cleanup(MyCustomResource customResource,Context context){
+ ...
+ return DeleteControl.defaultDelete();
+ }
+
+```
+
+However, it is possible to instruct the SDK to not remove the finalizer, this allows to clean up
+the resources in a more asynchronous way, mostly for cases when there is a long waiting period
+after a delete operation is initiated. Note that in this case you might want to either schedule
+a timed event to make sure `cleanup` is executed again or use event sources to get notified
+about the state changes of the deleted resource.
+
+### Finalizer Support
+
+[Kubernetes finalizers](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/)
+make sure that your `Reconciler` gets a chance to act before a resource is actually deleted
+after it's been marked for deletion. Without finalizers, the resource would be deleted directly
+by the Kubernetes server.
+
+Depending on your use case, you might or might not need to use finalizers. In particular, if
+your operator doesn't need to clean any state that would not be automatically managed by the
+Kubernetes cluster (e.g. external resources), you might not need to use finalizers. You should
+use the
+Kubernetes [garbage collection](https://kubernetes.io/docs/concepts/architecture/garbage-collection/#owners-dependents)
+mechanism as much as possible by setting owner references for your secondary resources so that
+the cluster can automatically deleted them for you whenever the associated primary resource is
+deleted. Note that setting owner references is the responsibility of the `Reconciler`
+implementation, though [dependent resources](https://javaoperatorsdk.io/docs/dependent-resources)
+make that process easier.
+
+If you do need to clean such state, you need to use finalizers so that their
+presence will prevent the Kubernetes server from deleting the resource before your operator is
+ready to allow it. This allows for clean up to still occur even if your operator was down when
+the resources was "deleted" by a user.
+
+JOSDK makes cleaning resources in this fashion easier by taking care of managing finalizers
+automatically for you when needed. The only thing you need to do is let the SDK know that your
+operator is interested in cleaning state associated with your primary resources by having it
+implement
+the [`Cleaner
`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java)
+interface. If your `Reconciler` doesn't implement the `Cleaner` interface, the SDK will consider
+that you don't need to perform any clean-up when resources are deleted and will therefore not
+activate finalizer support. In other words, finalizer support is added only if your `Reconciler`
+implements the `Cleaner` interface.
+
+Finalizers are automatically added by the framework as the first step, thus after a resource
+is created, but before the first reconciliation. The finalizer is added via a separate
+Kubernetes API call. As a result of this update, the finalizer will then be present on the
+resource. The reconciliation can then proceed as normal.
+
+The finalizer that is automatically added will be also removed after the `cleanup` is executed on
+the reconciler. This behavior is customizable as explained
+[above](#using-updatecontrol-and-deletecontrol) when we addressed the use of
+`DeleteControl`.
+
+You can specify the name of the finalizer to use for your `Reconciler` using the
+[`@ControllerConfiguration`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java)
+annotation. If you do not specify a finalizer name, one will be automatically generated for you.
+
+## Automatic Observed Generation Handling
+
+Having an `.observedGeneration` value on your resources' status is a best practice to
+indicate the last generation of the resource which was successfully reconciled by the controller.
+This helps users / administrators diagnose potential issues.
+
+In order to have this feature working:
+
+- the **status class** (not the resource itself) must implement the
+ [`ObservedGenerationAware`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java)
+ interface. See also
+ the [`ObservedGenerationAwareStatus`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java)
+ convenience implementation that you can extend in your own status class implementations.
+- The other condition is that the `CustomResource.getStatus()` method should not return `null`.
+ So the status should be instantiated when the object is returned using the `UpdateControl`.
+
+If these conditions are fulfilled and generation awareness is activated, the observed generation
+is automatically set by the framework after the `reconcile` method is called. Note that the
+observed generation is also updated even when `UpdateControl.noUpdate()` is returned from the
+reconciler. See this feature at work in
+the [WebPage example](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStatus.java#L5)
+.
+
+```java
+public class WebPageStatus extends ObservedGenerationAwareStatus {
+
+ private String htmlConfigMap;
+
+ ...
+}
+```
+
+Initializing status automatically on custom resource could be done by overriding the `initStatus` method
+of `CustomResource`. However, this is NOT advised, since breaks the status patching if you use:
+`UpdateControl.patchStatus`. See
+also [javadocs](https://github.com/java-operator-sdk/java-operator-sdk/blob/3994f5ffc1fb000af81aa198abf72a5f75fd3e97/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java#L41-L42)
+.
+
+```java
+@Group("sample.javaoperatorsdk")
+@Version("v1")
+public class WebPage extends CustomResource
+ implements Namespaced {
+
+ @Override
+ protected WebPageStatus initStatus() {
+ return new WebPageStatus();
+ }
+}
+```
+
+## Generation Awareness and Event Filtering
+
+A best practice when an operator starts up is to reconcile all the associated resources because
+changes might have occurred to the resources while the operator was not running.
+
+When this first reconciliation is done successfully, the next reconciliation is triggered if either
+dependent resources are changed or the primary resource `.spec` field is changed. If other fields
+like `.metadata` are changed on the primary resource, the reconciliation could be skipped. This
+behavior is supported out of the box and reconciliation is by default not triggered if
+changes to the primary resource do not increase the `.metadata.generation` field.
+Note that changes to `.metada.generation` are automatically handled by Kubernetes.
+
+To turn off this feature, set `generationAwareEventProcessing` to `false` for the `Reconciler`.
+
+## Support for Well Known (non-custom) Kubernetes Resources
+
+A Controller can be registered for a non-custom resource, so well known Kubernetes resources like (
+`Ingress`, `Deployment`,...). Note that automatic observed generation handling is not supported
+for these resources, though, in this case, the handling of the observed generation is probably
+handled by the primary controller.
+
+See
+the [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/deployment/DeploymentReconciler.java)
+for reconciling deployments.
+
+```java
+public class DeploymentReconciler
+ implements Reconciler, TestExecutionInfoProvider {
+
+ @Override
+ public UpdateControl reconcile(
+ Deployment resource, Context context) {
+ ...
+ }
+```
+
+## Max Interval Between Reconciliations
+
+When informers / event sources are properly set up, and the `Reconciler` implementation is
+correct, no additional reconciliation triggers should be needed. However, it's
+a [common practice](https://github.com/java-operator-sdk/java-operator-sdk/issues/848#issuecomment-1016419966)
+to have a failsafe periodic trigger in place, just to make sure resources are nevertheless
+reconciled after a certain amount of time. This functionality is in place by default, with a
+rather high time interval (currently 10 hours) after which a reconciliation will be
+automatically triggered even in the absence of other events. See how to override this using the
+standard annotation:
+
+```java
+@ControllerConfiguration(maxReconciliationInterval = @MaxReconciliationInterval(
+ interval = 50,
+ timeUnit = TimeUnit.MILLISECONDS))
+```
+
+The event is not propagated at a fixed rate, rather it's scheduled after each reconciliation. So the
+next reconciliation will occur at most within the specified interval after the last reconciliation.
+
+This feature can be turned off by setting `maxReconciliationInterval`
+to [`Constants.NO_MAX_RECONCILIATION_INTERVAL`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java#L20-L20)
+or any non-positive number.
+
+The automatic retries are not affected by this feature so a reconciliation will be re-triggered
+on error, according to the specified retry policy, regardless of this maximum interval setting.
+
+## Automatic Retries on Error
+
+JOSDK will schedule an automatic retry of the reconciliation whenever an exception is thrown by
+your `Reconciler`. The retry is behavior is configurable but a default implementation is provided
+covering most of the typical use-cases, see
+[GenericRetry](https://github.com/java-operator-sdk/java-operator-sdk/blob/master/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/retry/GenericRetry.java)
+.
+
+```java
+ GenericRetry.defaultLimitedExponentialRetry()
+ .setInitialInterval(5000)
+ .setIntervalMultiplier(1.5D)
+ .setMaxAttempts(5);
+```
+
+You can also configure the default retry behavior using the `@GradualRetry` annotation.
+
+It is possible to provide a custom implementation using the `retry` field of the
+`@ControllerConfiguration` annotation and specifying the class of your custom implementation.
+Note that this class will need to provide an accessible no-arg constructor for automated
+instantiation. Additionally, your implementation can be automatically configured from an
+annotation that you can provide by having your `Retry` implementation implement the
+`AnnotationConfigurable` interface, parameterized with your annotation type. See the
+`GenericRetry` implementation for more details.
+
+Information about the current retry state is accessible from
+the [Context](https://github.com/java-operator-sdk/java-operator-sdk/blob/master/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/Context.java)
+object. Of note, particularly interesting is the `isLastAttempt` method, which could allow your
+`Reconciler` to implement a different behavior based on this status, by setting an error message
+in your resource' status, for example, when attempting a last retry.
+
+Note, though, that reaching the retry limit won't prevent new events to be processed. New
+reconciliations will happen for new events as usual. However, if an error also occurs that
+would normally trigger a retry, the SDK won't schedule one at this point since the retry limit
+is already reached.
+
+A successful execution resets the retry state.
+
+### Setting Error Status After Last Retry Attempt
+
+In order to facilitate error reporting, `Reconciler` can implement the
+[ErrorStatusHandler](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusHandler.java)
+interface:
+
+```java
+public interface ErrorStatusHandler
{
+
+ ErrorStatusUpdateControl
updateErrorStatus(P resource, Context
context, Exception e);
+
+}
+```
+
+The `updateErrorStatus` method is called in case an exception is thrown from the `Reconciler`. It is
+also called even if no retry policy is configured, just after the reconciler execution.
+`RetryInfo.getAttemptCount()` is zero after the first reconciliation attempt, since it is not a
+result of a retry (regardless of whether a retry policy is configured or not).
+
+`ErrorStatusUpdateControl` is used to tell the SDK what to do and how to perform the status
+update on the primary resource, always performed as a status sub-resource request. Note that
+this update request will also produce an event, and will result in a reconciliation if the
+controller is not generation aware.
+
+This feature is only available for the `reconcile` method of the `Reconciler` interface, since
+there should not be updates to resource that have been marked for deletion.
+
+Retry can be skipped in cases of unrecoverable errors:
+
+```java
+ ErrorStatusUpdateControl.patchStatus(customResource).withNoRetry();
+```
+
+### Correctness and Automatic Retries
+
+While it is possible to deactivate automatic retries, this is not desirable, unless for very
+specific reasons. Errors naturally occur, whether it be transient network errors or conflicts
+when a given resource is handled by a `Reconciler` but is modified at the same time by a user in
+a different process. Automatic retries handle these cases nicely and will usually result in a
+successful reconciliation.
+
+## Retry and Rescheduling and Event Handling Common Behavior
+
+Retry, reschedule and standard event processing form a relatively complex system, each of these
+functionalities interacting with the others. In the following, we describe the interplay of
+these features:
+
+1. A successful execution resets a retry and the rescheduled executions which were present before
+ the reconciliation. However, a new rescheduling can be instructed from the reconciliation
+ outcome (`UpdateControl` or `DeleteControl`).
+
+ For example, if a reconciliation had previously been re-scheduled after some amount of time, but an event triggered
+ the reconciliation (or cleanup) in the mean time, the scheduled execution would be automatically cancelled, i.e.
+ re-scheduling a reconciliation does not guarantee that one will occur exactly at that time, it simply guarantees that
+ one reconciliation will occur at that time at the latest, triggering one if no event from the cluster triggered one.
+ Of course, it's always possible to re-schedule a new reconciliation at the end of that "automatic" reconciliation.
+
+ Similarly, if a retry was scheduled, any event from the cluster triggering a successful execution in the mean time
+ would cancel the scheduled retry (because there's now no point in retrying something that already succeeded)
+
+2. In case an exception happened, a retry is initiated. However, if an event is received
+ meanwhile, it will be reconciled instantly, and this execution won't count as a retry attempt.
+3. If the retry limit is reached (so no more automatic retry would happen), but a new event
+ received, the reconciliation will still happen, but won't reset the retry, and will still be
+ marked as the last attempt in the retry info. The point (1) still holds, but in case of an
+ error, no retry will happen.
+
+The thing to keep in mind when it comes to retrying or rescheduling is that JOSDK tries to avoid unnecessary work. When
+you reschedule an operation, you instruct JOSDK to perform that operation at the latest by the end of the rescheduling
+delay. If something occurred on the cluster that triggers that particular operation (reconciliation or cleanup), then
+JOSDK considers that there's no point in attempting that operation again at the end of the specified delay since there
+is now no point to do so anymore. The same idea also applies to retries.
+
+## Rate Limiting
+
+It is possible to rate limit reconciliation on a per-resource basis. The rate limit also takes
+precedence over retry/re-schedule configurations: for example, even if a retry was scheduled for
+the next second but this request would make the resource go over its rate limit, the next
+reconciliation will be postponed according to the rate limiting rules. Note that the
+reconciliation is never cancelled, it will just be executed as early as possible based on rate
+limitations.
+
+Rate limiting is by default turned **off**, since correct configuration depends on the reconciler
+implementation, in particular, on how long a typical reconciliation takes.
+(The parallelism of reconciliation itself can be
+limited [`ConfigurationService`](https://github.com/java-operator-sdk/java-operator-sdk/blob/ce4d996ee073ebef5715737995fc3d33f4751275/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L120-L120)
+by configuring the `ExecutorService` appropriately.)
+
+A default rate limiter implementation is provided, see:
+[`PeriodRateLimiter`](https://github.com/java-operator-sdk/java-operator-sdk/blob/ce4d996ee073ebef5715737995fc3d33f4751275/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/rate/PeriodRateLimiter.java#L14-L14)
+.
+Users can override it by implementing their own
+[`RateLimiter`](https://github.com/java-operator-sdk/java-operator-sdk/blob/ce4d996ee073ebef5715737995fc3d33f4751275/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/rate/RateLimiter.java)
+and specifying this custom implementation using the `rateLimiter` field of the
+`@ControllerConfiguration` annotation. Similarly to the `Retry` implementations,
+`RateLimiter` implementations must provide an accessible, no-arg constructor for instantiation
+purposes and can further be automatically configured from your own, provided annotation provided
+your `RateLimiter` implementation also implements the `AnnotationConfigurable` interface,
+parameterized by your custom annotation type.
+
+To configure the default rate limiter use the `@RateLimited` annotation on your
+`Reconciler` class. The following configuration limits each resource to reconcile at most twice
+within a 3 second interval:
+
+```java
+
+@RateLimited(maxReconciliations = 2, within = 3, unit = TimeUnit.SECONDS)
+@ControllerConfiguration
+public class MyReconciler implements Reconciler {
+
+}
+```
+
+Thus, if a given resource was reconciled twice in one second, no further reconciliation for this
+resource will happen before two seconds have elapsed. Note that, since rate is limited on a
+per-resource basis, other resources can still be reconciled at the same time, as long, of course,
+that they stay within their own rate limits.
+
+## Handling Related Events with Event Sources
+
+See also
+this [blog post](https://csviri.medium.com/java-operator-sdk-introduction-to-event-sources-a1aab5af4b7b)
+.
+
+Event sources are a relatively simple yet powerful and extensible concept to trigger controller
+executions, usually based on changes to dependent resources. You typically need an event source
+when you want your `Reconciler` to be triggered when something occurs to secondary resources
+that might affect the state of your primary resource. This is needed because a given
+`Reconciler` will only listen by default to events affecting the primary resource type it is
+configured for. Event sources act as listen to events affecting these secondary resources so
+that a reconciliation of the associated primary resource can be triggered when needed. Note that
+these secondary resources need not be Kubernetes resources. Typically, when dealing with
+non-Kubernetes objects or services, we can extend our operator to handle webhooks or websockets
+or to react to any event coming from a service we interact with. This allows for very efficient
+controller implementations because reconciliations are then only triggered when something occurs
+on resources affecting our primary resources thus doing away with the need to periodically
+reschedule reconciliations.
+
+![Event Sources architecture diagram](../assets/images/event-sources.png)
+
+There are few interesting points here:
+
+The `CustomResourceEventSource` event source is a special one, responsible for handling events
+pertaining to changes affecting our primary resources. This `EventSource` is always registered
+for every controller automatically by the SDK. It is important to note that events always relate
+to a given primary resource. Concurrency is still handled for you, even in the presence of
+`EventSource` implementations, and the SDK still guarantees that there is no concurrent execution of
+the controller for any given primary resource (though, of course, concurrent/parallel executions
+of events pertaining to other primary resources still occur as expected).
+
+### Caching and Event Sources
+
+Kubernetes resources are handled in a declarative manner. The same also holds true for event
+sources. For example, if we define an event source to watch for changes of a Kubernetes Deployment
+object using an `InformerEventSource`, we always receive the whole associated object from the
+Kubernetes API. This object might be needed at any point during our reconciliation process and
+it's best to retrieve it from the event source directly when possible instead of fetching it
+from the Kubernetes API since the event source guarantees that it will provide the latest
+version. Not only that, but many event source implementations also cache resources they handle
+so that it's possible to retrieve the latest version of resources without needing to make any
+calls to the Kubernetes API, thus allowing for very efficient controller implementations.
+
+Note after an operator starts, caches are already populated by the time the first reconciliation
+is processed for the `InformerEventSource` implementation. However, this does not necessarily
+hold true for all event source implementations (`PerResourceEventSource` for example). The SDK
+provides methods to handle this situation elegantly, allowing you to check if an object is
+cached, retrieving it from a provided supplier if not. See
+related [method](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java#L146)
+.
+
+### Registering Event Sources
+
+To register event sources, your `Reconciler` has to implement the
+[`EventSourceInitializer`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java)
+interface and initialize a list of event sources to register. One way to see this in action is
+to look at the
+[tomcat example](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java)
+(irrelevant details omitted):
+
+```java
+
+@ControllerConfiguration
+public class TomcatReconciler implements Reconciler, EventSourceInitializer {
+
+ @Override
+ public List prepareEventSources(EventSourceContext context) {
+ var configMapEventSource =
+ new InformerEventSource<>(InformerConfiguration.from(Deployment.class, context)
+ .withLabelSelector(SELECTOR)
+ .withSecondaryToPrimaryMapper(
+ Mappers.fromAnnotation(ANNOTATION_NAME, ANNOTATION_NAMESPACE)
+ .build(), context));
+ return EventSourceInitializer.nameEventSources(configMapEventSource);
+ }
+ ...
+}
+```
+
+In the example above an `InformerEventSource` is configured and registered.
+`InformerEventSource` is one of the bundled `EventSource` implementations that JOSDK provides to
+cover common use cases.
+
+### Managing Relation between Primary and Secondary Resources
+
+Event sources let your operator know when a secondary resource has changed and that your
+operator might need to reconcile this new information. However, in order to do so, the SDK needs
+to somehow retrieve the primary resource associated with which ever secondary resource triggered
+the event. In the `Tomcat` example above, when an event occurs on a tracked `Deployment`, the
+SDK needs to be able to identify which `Tomcat` resource is impacted by that change.
+
+Seasoned Kubernetes users already know one way to track this parent-child kind of relationship:
+using owner references. Indeed, that's how the SDK deals with this situation by default as well,
+that is, if your controller properly set owner references on your secondary resources, the SDK
+will be able to follow that reference back to your primary resource automatically without you
+having to worry about it.
+
+However, owner references cannot always be used as they are restricted to operating within a
+single namespace (i.e. you cannot have an owner reference to a resource in a different namespace)
+and are, by essence, limited to Kubernetes resources so you're out of luck if your secondary
+resources live outside of a cluster.
+
+This is why JOSDK provides the `SecondayToPrimaryMapper` interface so that you can provide
+alternative ways for the SDK to identify which primary resource needs to be reconciled when
+something occurs to your secondary resources. We even provide some of these alternatives in the
+[Mappers](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java)
+class.
+
+Note that, while a set of `ResourceID` is returned, this set usually consists only of one
+element. It is however possible to return multiple values or even no value at all to cover some
+rare corner cases. Returning an empty set means that the mapper considered the secondary
+resource event as irrelevant and the SDK will thus not trigger a reconciliation of the primary
+resource in that situation.
+
+Adding a `SecondaryToPrimaryMapper` is typically sufficient when there is a one-to-many relationship
+between primary and secondary resources. The secondary resources can be mapped to its primary
+owner, and this is enough information to also get these secondary resources from the `Context`
+object that's passed to your `Reconciler`.
+
+There are however cases when this isn't sufficient and you need to provide an explicit mapping
+between a primary resource and its associated secondary resources using an implementation of the
+`PrimaryToSecondaryMapper` interface. This is typically needed when there are many-to-one or
+many-to-many relationships between primary and secondary resources, e.g. when the primary resource
+is referencing secondary resources.
+See [PrimaryToSecondaryIT](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryIT.java)
+integration test for a sample.
+
+### Built-in EventSources
+
+There are multiple event-sources provided out of the box, the following are some more central ones:
+
+#### `InformerEventSource`
+
+[InformerEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java)
+is probably the most important `EventSource` implementation to know about. When you create an
+`InformerEventSource`, JOSDK will automatically create and register a `SharedIndexInformer`, a
+fabric8 Kubernetes client class, that will listen for events associated with the resource type
+you configured your `InformerEventSource` with. If you want to listen to Kubernetes resource
+events, `InformerEventSource` is probably the only thing you need to use. It's highly
+configurable so you can tune it to your needs. Take a look at
+[InformerConfiguration](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java)
+and associated classes for more details but some interesting features we can mention here is the
+ability to filter events so that you can only get notified for events you care about. A
+particularly interesting feature of the `InformerEventSource`, as opposed to using your own
+informer-based listening mechanism is that caches are particularly well optimized preventing
+reconciliations from being triggered when not needed and allowing efficient operators to be written.
+
+#### `PerResourcePollingEventSource`
+
+[PerResourcePollingEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java)
+is used to poll external APIs, which don't support webhooks or other event notifications. It
+extends the abstract
+[ExternalResourceCachingEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ExternalResourceCachingEventSource.java)
+to support caching.
+See [MySQL Schema sample](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java)
+for usage.
+
+#### `PollingeEventSource`
+
+[PollingEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSource.java)
+is similar to `PerResourceCachingEventSource` except that, contrary to that event source, it
+doesn't poll a specific API separately per resource, but periodically and independently of
+actually observed primary resources.
+
+#### Inbound event sources
+
+[SimpleInboundEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/inbound/SimpleInboundEventSource.java)
+and
+[CachingInboundEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/inbound/CachingInboundEventSource.java)
+are used to handle incoming events from webhooks and messaging systems.
+
+#### `ControllerResourceEventSource`
+
+[ControllerResourceEventSource](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java)
+is a special `EventSource` implementation that you will never have to deal with directly. It is,
+however, at the core of the SDK is automatically added for you: this is the main event source
+that listens for changes to your primary resources and triggers your `Reconciler` when needed.
+It features smart caching and is really optimized to minimize Kubernetes API accesses and avoid
+triggering unduly your `Reconciler`.
+
+More on the philosophy of the non Kubernetes API related event source see in
+issue [#729](https://github.com/java-operator-sdk/java-operator-sdk/issues/729).
+
+## Contextual Info for Logging with MDC
+
+Logging is enhanced with additional contextual information using
+[MDC](http://www.slf4j.org/manual.html#mdc). The following attributes are available in most
+parts of reconciliation logic and during the execution of the controller:
+
+| MDC Key | Value added from primary resource |
+|:---------------------------|:----------------------------------|
+| `resource.apiVersion` | `.apiVersion` |
+| `resource.kind` | `.kind` |
+| `resource.name` | `.metadata.name` |
+| `resource.namespace` | `.metadata.namespace` |
+| `resource.resourceVersion` | `.metadata.resourceVersion` |
+| `resource.generation` | `.metadata.generation` |
+| `resource.uid` | `.metadata.uid` |
+
+For more information about MDC see this [link](https://www.baeldung.com/mdc-in-log4j-2-logback).
+
+## Dynamically Changing Target Namespaces
+
+A controller can be configured to watch a specific set of namespaces in addition of the
+namespace in which it is currently deployed or the whole cluster. The framework supports
+dynamically changing the list of these namespaces while the operator is running.
+When a reconciler is registered, an instance of
+[`RegisteredController`](https://github.com/java-operator-sdk/java-operator-sdk/blob/ec37025a15046d8f409c77616110024bf32c3416/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/RegisteredController.java#L5)
+is returned, providing access to the methods allowing users to change watched namespaces as the
+operator is running.
+
+A typical scenario would probably involve extracting the list of target namespaces from a
+`ConfigMap` or some other input but this part is out of the scope of the framework since this is
+use-case specific. For example, reacting to changes to a `ConfigMap` would probably involve
+registering an associated `Informer` and then calling the `changeNamespaces` method on
+`RegisteredController`.
+
+```java
+
+public static void main(String[]args)throws IOException{
+ KubernetesClient client=new DefaultKubernetesClient();
+ Operator operator=new Operator(client);
+ RegisteredController registeredController=operator.register(new WebPageReconciler(client));
+ operator.installShutdownHook();
+ operator.start();
+
+ // call registeredController further while operator is running
+ }
+
+```
+
+If watched namespaces change for a controller, it might be desirable to propagate these changes to
+`InformerEventSources` associated with the controller. In order to express this,
+`InformerEventSource` implementations interested in following such changes need to be
+configured appropriately so that the `followControllerNamespaceChanges` method returns `true`:
+
+```java
+
+@ControllerConfiguration
+public class MyReconciler
+ implements Reconciler, EventSourceInitializer {
+
+ @Override
+ public Map prepareEventSources(
+ EventSourceContext context) {
+
+ InformerEventSource configMapES =
+ new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class)
+ .withNamespacesInheritedFromController(context)
+ .build(), context);
+
+ return EventSourceInitializer.nameEventSources(configMapES);
+ }
+
+}
+```
+
+As seen in the above code snippet, the informer will have the initial namespaces inherited from
+controller, but also will adjust the target namespaces if it changes for the controller.
+
+See also
+the [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/ec37025a15046d8f409c77616110024bf32c3416/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java)
+for this feature.
+
+## Leader Election
+
+Operators are generally deployed with a single running or active instance. However, it is
+possible to deploy multiple instances in such a way that only one, called the "leader", processes the
+events. This is achieved via a mechanism called "leader election". While all the instances are
+running, and even start their event sources to populate the caches, only the leader will process
+the events. This means that should the leader change for any reason, for example because it
+crashed, the other instances are already warmed up and ready to pick up where the previous
+leader left off should one of them become elected leader.
+
+See sample configuration in
+the [E2E test](https://github.com/java-operator-sdk/java-operator-sdk/blob/8865302ac0346ee31f2d7b348997ec2913d5922b/sample-operators/leader-election/src/main/java/io/javaoperatorsdk/operator/sample/LeaderElectionTestOperator.java#L21-L23)
+.
+
+## Runtime Info
+
+[RuntimeInfo](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/RuntimeInfo.java#L16-L16)
+is used mainly to check the actual health of event sources. Based on this information it is easy to implement custom
+liveness probes.
+
+[stopOnInformerErrorDuringStartup](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L168-L168)
+setting, where this flag usually needs to be set to false, in order to control the exact liveness properties.
+
+See also an example implementation in the
+[WebPage sample](https://github.com/java-operator-sdk/java-operator-sdk/blob/3e2e7c4c834ef1c409d636156b988125744ca911/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java#L38-L43)
+
+## Automatic Generation of CRDs
+
+Note that this feature is provided by the
+[Fabric8 Kubernetes Client](https://github.com/fabric8io/kubernetes-client), not JOSDK itself.
+
+To automatically generate CRD manifests from your annotated Custom Resource classes, you only need
+to add the following dependencies to your project:
+
+```xml
+
+
+ io.fabric8
+ crd-generator-apt
+ provided
+
+```
+
+The CRD will be generated in `target/classes/META-INF/fabric8` (or
+in `target/test-classes/META-INF/fabric8`, if you use the `test` scope) with the CRD name
+suffixed by the generated spec version. For example, a CR using the `java-operator-sdk.io` group
+with a `mycrs` plural form will result in 2 files:
+
+- `mycrs.java-operator-sdk.io-v1.yml`
+- `mycrs.java-operator-sdk.io-v1beta1.yml`
+
+**NOTE:**
+> Quarkus users using the `quarkus-operator-sdk` extension do not need to add any extra dependency
+> to get their CRD generated as this is handled by the extension itself.
+
+## Metrics
+
+JOSDK provides built-in support for metrics reporting on what is happening with your reconcilers in the form of
+the `Metrics` interface which can be implemented to connect to your metrics provider of choice, JOSDK calling the
+methods as it goes about reconciling resources. By default, a no-operation implementation is provided thus providing a
+no-cost sane default. A [micrometer](https://micrometer.io)-based implementation is also provided.
+
+You can use a different implementation by overriding the default one provided by the default `ConfigurationService`, as
+follows:
+
+```java
+Metrics metrics= …;
+Operator operator = new Operator(client, o -> o.withMetrics());
+```
+
+### Micrometer implementation
+
+The micrometer implementation is typically created using one of the provided factory methods which, depending on which
+is used, will return either a ready to use instance or a builder allowing users to customized how the implementation
+behaves, in particular when it comes to the granularity of collected metrics. It is, for example, possible to collect
+metrics on a per-resource basis via tags that are associated with meters. This is the default, historical behavior but
+this will change in a future version of JOSDK because this dramatically increases the cardinality of metrics, which
+could lead to performance issues.
+
+To create a `MicrometerMetrics` implementation that behaves how it has historically behaved, you can just create an
+instance via:
+
+```java
+MeterRegistry registry= …;
+Metrics metrics=new MicrometerMetrics(registry)
+```
+
+Note, however, that this constructor is deprecated and we encourage you to use the factory methods instead, which either
+return a fully pre-configured instance or a builder object that will allow you to configure more easily how the instance
+will behave. You can, for example, configure whether or not the implementation should collect metrics on a per-resource
+basis, whether or not associated meters should be removed when a resource is deleted and how the clean-up is performed.
+See the relevant classes documentation for more details.
+
+For example, the following will create a `MicrometerMetrics` instance configured to collect metrics on a per-resource
+basis, deleting the associated meters after 5 seconds when a resource is deleted, using up to 2 threads to do so.
+
+```java
+MicrometerMetrics.newPerResourceCollectingMicrometerMetricsBuilder(registry)
+ .withCleanUpDelayInSeconds(5)
+ .withCleaningThreadNumber(2)
+ .build()
+```
+
+The micrometer implementation records the following metrics:
+
+| Meter name | Type | Tag names | Description |
+|-----------------------------------------------------------|----------------|-----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
+| operator.sdk.reconciliations.executions. | gauge | group, version, kind | Number of executions of the named reconciler |
+| operator.sdk.reconciliations.queue.size. | gauge | group, version, kind | How many resources are queued to get reconciled by named reconciler |
+| operator.sdk.