### Install Dependencies with npm Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md Run this command to install project dependencies for local development. ```bash npm install ``` -------------------------------- ### Start Hugo Development Server Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md Starts the Hugo development server for the documentation site. Access the site at http://localhost:1313. ```bash hugo server ``` -------------------------------- ### Caffeine Bounded Cache Implementation Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/eventing.md This example demonstrates the usage of Caffeine for implementing bounded caches for Kubernetes resources. It is part of the integration tests and shows how to manage resource caching with eviction policies. ```java AbstractTestReconciler.java ``` -------------------------------- ### Adding Vert.X HTTP Client Implementation Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v4-3-migration.md Example from a POM file showing how to add the Vert.X based HTTP client implementation dependency. ```xml io.java-operator-sdk kubernetes-httpclient-vertx ${project.version} ``` -------------------------------- ### Install Helm Chart Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/helm-chart.md Command to install the generic Helm chart for a Java operator, specifying a custom values file and namespace. ```shell helm install my-operator ./helm/generic-helm-chart -f my-values.yaml --namespace my-ns ``` -------------------------------- ### WebPageDependentsWorkflowReconciler Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/dependent-resource-and-workflows/workflows.md Demonstrates how to manually build a workflow using standalone dependent resources within a reconciler. This setup is useful when you need explicit control over the workflow's dependent resources and their reconciliation order. ```java @ControllerConfiguration( labelSelector = WebPageDependentsWorkflowReconciler.DEPENDENT_RESOURCE_LABEL_SELECTOR) public class WebPageDependentsWorkflowReconciler implements Reconciler, ErrorStatusHandler { public static final String DEPENDENT_RESOURCE_LABEL_SELECTOR = "!low-level"; private static final Logger log = LoggerFactory.getLogger(WebPageDependentsWorkflowReconciler.class); private KubernetesDependentResource configMapDR; private KubernetesDependentResource deploymentDR; private KubernetesDependentResource serviceDR; private KubernetesDependentResource ingressDR; private final Workflow workflow; public WebPageDependentsWorkflowReconciler(KubernetesClient kubernetesClient) { initDependentResources(kubernetesClient); workflow = new WorkflowBuilder() .addDependentResource(configMapDR) .addDependentResource(deploymentDR) .addDependentResource(serviceDR) .addDependentResource(ingressDR).withReconcilePrecondition(new ExposedIngressCondition()) .build(); } @Override public Map prepareEventSources(EventSourceContext context) { return EventSourceUtils.nameEventSources( configMapDR.initEventSource(context), deploymentDR.initEventSource(context), serviceDR.initEventSource(context), ingressDR.initEventSource(context)); } @Override public UpdateControl reconcile(WebPage webPage, Context context) { var result = workflow.reconcile(webPage, context); webPage.setStatus(createStatus(result)); return UpdateControl.patchStatus(webPage); } // omitted code } ``` -------------------------------- ### Register Reconciler and Start Operator Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/configuration.md This snippet shows the basic setup for registering a reconciler, installing a shutdown hook, and starting the operator. The `RegisteredController` can be used later to dynamically change watched namespaces. ```java public static void main(String[] args) { 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 } ``` -------------------------------- ### TimerEventSource Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-release.md Illustrates how to create a TimerEventSource for triggering reconcilers when direct EventSource capabilities are not needed. ```java TimerEventSource timerEventSource = TimerEventSource.builder().withEventSourceManager(eventSourceManager).build(); ``` -------------------------------- ### Registering an InformerEventSource Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/eventing.md Override `prepareEventSources` to return a list of event sources. This example shows how to configure and register an `InformerEventSource` for `Deployment` resources, filtered by a label selector. ```java import java.util.List; @ControllerConfiguration public class WebappReconciler implements Reconciler, Cleaner, EventSourceInitializer { // ommitted code @Override public List> prepareEventSources(EventSourceContext context) { InformerEventSourceConfiguration configuration = InformerEventSourceConfiguration.from(Deployment.class, Webapp.class) .withLabelSelector(SELECTOR) .build(); return List.of(new InformerEventSource<>(configuration, context)); } } ``` -------------------------------- ### Example Helm Chart Values for Metrics Processing Operator Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/helm-chart.md An example of a values.yaml file for deploying the metrics-processing sample operator using the generic Helm chart. It specifies the image repository, pull policy, tag, and custom resources. ```yaml image: repository: metrics-processing-operator pullPolicy: Never tag: "latest" nameOverride: "metrics-processing-operator" resources: {} primaryResources: - apiGroup: "sample.javaoperatorsdk" resources: - metricshandlingcustomresource1s - metricshandlingcustomresource2s ``` -------------------------------- ### Example of a Read-only Dependent Resource Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/dependent-resource-and-workflows/dependent-resources.md This example demonstrates a read-only dependent resource, specifically a ConfigMap, used for configuring primary resources. It is intended for integration testing purposes. ```java package io.javaoperatorsdk.operator.dependent.primarytosecondaydependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; import io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow; import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowExecutionMetadata; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ResourceIDProvider; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.Managed import java.util.Optional; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.client.KubernetesClient; public class ConfigMapDependent implements DependentResource { private final KubernetesClient client; public ConfigMapDependent(KubernetesClient client) { this.client = client; } @Override public Class resourceType() { return ConfigMap.class; } @Override public Optional getResource(PrimaryResource primary, Context context) { return Optional.ofNullable(client.configMaps().inNamespace(primary.getMetadata().getNamespace()) .withName(primary.getSpec().getConfigMapName()).get()); } @Override public ReconcileResult reconcile(PrimaryResource primary, Context context) { ConfigMap desired = new ConfigMap(); ObjectMeta meta = new ObjectMeta(); meta.setName(primary.getSpec().getConfigMapName()); meta.setNamespace(primary.getMetadata().getNamespace()); desired.setMetadata(meta); desired.getMetadata().setLabels(primary.getMetadata().getLabels()); desired.getData().put("key", "value"); client.configMaps().inNamespace(primary.getMetadata().getNamespace()).createOrReplace(desired); return ReconcileResult.resourceCreated(desired); } @Override public void cleanup(PrimaryResource primary, Context context) { client.configMaps().inNamespace(primary.getMetadata().getNamespace()) .withName(primary.getSpec().getConfigMapName()).delete(); } @Override public boolean isReadonly() { return true; } } ``` -------------------------------- ### Expose MySQL Service and Connect via CLI Source: https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/mysql-schema/README.md Expose the MySQL service using `minikube service` to get its URL, then connect using the MySQL CLI to verify the created schema. This requires the MySQL server to be running and accessible. ```bash $ minikube service mysql -n mysql --url http://192.168.49.2:30317 $ mysql -h 192.168.49.2 -P 30317 --protocol=tcp -u root -ppassword ... MariaDB [(none)]> show schemas; +--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.000 sec) ``` -------------------------------- ### Parallel Build Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Initiates a clean install build using parallel execution, leveraging one thread per CPU core for faster compilation and testing. ```bash ./mvnw -T1C clean install ``` -------------------------------- ### Excluding Default HTTP Client Implementation Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v4-3-migration.md Example from a POM file showing how to exclude the default Okhttp HTTP client implementation from the operator-framework dependency. ```xml io.java-operator-sdk operator-framework ${project.version} io.fabric8 okhttp-httpclient ``` -------------------------------- ### Manual Observed Generation Handling Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-release.md Demonstrates how to manually implement observed generation handling within a reconciler, as the automated feature has been removed. ```java package io.javaoperatorsdk.operator.sample; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow; @ControllerConfiguration(labelSelector = "app=my-app") public class MyServiceReconciler implements Reconciler { @Dependent private final Workflow workflow = new Workflow(new MyServiceDependentResource()); @Override public UpdateControl reconcile(MyService primary, Context context) { // primary is the custom resource // context contains information about the reconciliation // Manual observed generation handling: // 1. Get the current observed generation from the primary resource // 2. Update the observed generation after reconciliation // 3. Use it to determine if reconciliation is needed // Example: Check if observed generation needs update if (primary.getStatus() == null || primary.getStatus().getObservedGeneration() != primary.getMetadata().getGeneration()) { // Perform reconciliation logic // ... // Update observed generation in status primary.getStatus().setObservedGeneration(primary.getMetadata().getGeneration()); return UpdateControl.updateStatus(primary); } return UpdateControl.noUpdate(); } @Override public void onDeletion(MyService primary, Context context) { // Cleanup logic if needed } } ``` -------------------------------- ### EventSourceInitializer Interface Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v2-migration.md Demonstrates the EventSourceInitializer interface, which is responsible for preparing and returning a list of EventSource implementations for the controller to register. ```java public interface EventSourceInitializer

> { /** * Initializes and returns the event sources to be registered with the controller. * * @param context the context object containing information about the current reconciliation * @return a list of EventSource implementations */ List prepareEventSources(C context); } ``` -------------------------------- ### Example User Data in JSON Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/news/etcd-as-app-db.md This JSON object represents a typical user structure. It demonstrates the format and fields that might be stored. Note that this example contains sensitive information and its size (approx. 0.5 KB) is relevant to ETCD's data size limitations. ```json { "username": "myname", "enabled": true, "email": "myname@test.com", "firstName": "MyFirstName", "lastName": "MyLastName", "credentials": [ { "type": "password", "value": "test" }, { "type": "token", "value": "oidc" } ], "realmRoles": [ "user", "viewer", "admin" ], "clientRoles": { "account": [ "view-profile", "change-group", "manage-account" ] } } ``` -------------------------------- ### WebPageReconciler Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/glossary/_index.md Illustrates a basic reconciler implementation without advanced features like Dependent Resources or Workflows. It serves as an example of the low-level API. ```java package io.javaoperatorsdk.operator.sample; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; public class WebPageReconciler implements Reconciler { @Override public UpdateControl reconcile(WebPage webPage, Context context) { // ... reconciliation logic ... return UpdateControl.updateStatus(webPage); } } ``` -------------------------------- ### WebPageManagedDependentsReconciler Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/glossary/_index.md Demonstrates how to implement reconciliation logic using Dependent Resources and Workflows, which are higher-level abstractions provided by the Java Operator SDK. ```java package io.javaoperatorsdk.operator.sample; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; public class WebPageManagedDependentsReconciler implements Reconciler { @Override public UpdateControl reconcile(WebPage webPage, Context context) { // ... reconciliation logic using dependent resources and workflows ... return UpdateControl.updateStatus(webPage); } } ``` -------------------------------- ### Configure InformerEventSource with InformerConfiguration Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v3-migration.md In v3, InformerEventSource constructor arguments are moved to InformerConfiguration. This example shows how to configure an InformerEventSource using the new configuration object. ```java eventSourceInitializer.registerEventSource(new InformerEventSource(new WebPageCustomResourceController(), InformerConfiguration.from(new InformerConfiguration("webpage")))); ``` -------------------------------- ### Event Class Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v2-migration.md Demonstrates the simplified Event class, which event sources now produce when an event occurs. It encapsulates the resource and its associated ResourceID. ```java public final class Event { private final ResourceID resourceID; private final Object event; public Event(ResourceID resourceID, Object event) { this.resourceID = resourceID; this.event = event; } public ResourceID getResourceID() { return resourceID; } public Object getEvent() { return event; } } ``` -------------------------------- ### External State Tracking with Bulk Dependent Resources Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/dependent-resource-and-workflows/dependent-resources.md When combining bulk and external state tracking, a separate state-tracking resource is created for each bulk dependent resource. This example illustrates the concept, though no direct code is provided. -------------------------------- ### Configure KubernetesDependentResource with @Configured Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/configuration.md This example shows how to annotate a KubernetesDependentResource with @Configured to enable custom configuration via annotations. It specifies the annotation class, configuration class, and converter. ```java @Configured( by = KubernetesDependent.class, with = KubernetesDependentResourceConfig.class, converter = KubernetesDependentConverter.class) public abstract class KubernetesDependentResource extends AbstractEventSourceHolderDependentResource> implements ConfiguredDependentResource> { // code omitted } ``` -------------------------------- ### Reconciler Interface Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v2-migration.md Illustrates the new Reconciler interface, which replaces ResourceController. It shows the renamed reconcile and cleanup methods and the preparation of event sources. ```java public interface Reconciler

> extends EventSourceInitializer { /** * The primary reconciliation logic. This method is called when a change is detected in the primary resource or any of the secondary resources. * * @param primaryResource the primary resource to reconcile * @param context the context object containing information about the current reconciliation * @return the desired state of the primary resource */ ResourceState

reconcile(P primaryResource, C context); /** * Cleans up resources associated with the primary resource. This method is called when the primary resource is deleted. * * @param primaryResource the primary resource to clean up * @param context the context object containing information about the current cleanup */ void cleanup(P primaryResource, C context); /** * Initializes and returns the event sources to be registered with the controller. * * @param context the context object containing information about the current reconciliation * @return a list of EventSource implementations */ @Override default List prepareEventSources(C context) { return Collections.emptyList(); } } ``` -------------------------------- ### Reconcile Deployment Resource with Java Operator SDK Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/features.md Implement a reconciler for standard Kubernetes Deployment resources using the Java Operator SDK. This example shows the basic structure for a `Reconciler` implementation. ```java public class DeploymentReconciler implements Reconciler { @Override public UpdateControl reconcile( Deployment resource, Context context) { // omitted code } } ``` -------------------------------- ### Customizing Matching Logic with Matcher Interface Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/dependent-resource-and-workflows/dependent-resources.md Implement the Matcher interface to customize how the SDK determines if the actual dependent resource state matches the desired state. This example shows how to include annotations and labels in the matching process. ```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); } } ``` -------------------------------- ### Operator and Reconciler Configuration with Custom Provider Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-3-release.md Construct the Operator and register reconcilers using a custom ConfigLoader. This example demonstrates applying both general operator configurations and reconciler-specific controller configurations. ```java var configLoader = new ConfigLoader(new SmallRyeConfigProvider(smallRyeConfig)); Operator operator = new Operator(configLoader.applyConfigs()); operator.register(new MyReconciler(), configLoader.applyControllerConfigs(MyReconciler.NAME)); ``` -------------------------------- ### Multiple Dependent Resources with Informer Name Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-release.md Specifies a unique name for the informer when using multiple dependent resources of the same type with activation conditions to avoid informer registration conflicts. ```java public class ConfigMapDependentResource1 extends KubernetesDependentResource { public ConfigMapDependentResource1() { super(ConfigMap.class); setInformerName("configmap-dependent-resource-1"); // Unique informer name } @Override protected void configureWith(MyService primary, Context context) { // Configuration logic specific to this dependent resource } @Override protected ConfigMap desired(MyService primary, Context context) { // Desired state logic return new ConfigMapBuilder() .withNewMetadata() .withName(primary.getMetadata().getName() + "-configmap-1") .endMetadata() .withData(Collections.singletonMap("key1", "value1")) .build(); } @Override public Optional get(MyService primary, Context context) { // Get logic return Optional.ofNullable(getReconciler()) .flatMap(r -> r.get(primary, context)) .map(p -> p.getSecondaryResource(ConfigMap.class, ResourceID.fromName(primary.getMetadata().getName() + "-configmap-1"))) .orElse(Optional.empty()); } } ``` -------------------------------- ### Compose Multiple Config Sources with AggregatePriorityListConfigProvider Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/configuration.md Use AggregatePriorityListConfigProvider to define an ordered list of configuration providers, where the first provider to return a value wins. This example prioritizes environment variables, then system properties, and finally a YAML file. ```java var configLoader = new ConfigLoader( new AggregatePriorityListConfigProvider(List.of( new EnvVarConfigProvider(), // highest priority PropertiesConfigProvider.systemProperties(), new YamlConfigProvider(Path.of("config/operator.yaml")) // lowest priority ))); ``` -------------------------------- ### Install Operator into Cluster Source: https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/tomcat-operator/README.md Deploy the Tomcat Operator to your Kubernetes cluster using its YAML definition. Ensure CRDs are installed first. ```bash kubectl apply -f k8s/operator.yaml ``` -------------------------------- ### Full Build with Tests Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Executes a clean build of the project including all tests. Use this for a complete verification of the codebase. ```bash ./mvnw clean install ``` -------------------------------- ### Apply Sample Custom Resource (Shell Command) Source: https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/README.md Command to create a Webserver Custom Resource instance in your Kubernetes cluster. ```shell kubectl apply -f k8s/webpage.yaml ``` -------------------------------- ### Apply Code Formatting Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Automatically formats the project's code according to the established style guidelines using the Spotless Maven plugin. ```bash ./mvnw spotless:apply ``` -------------------------------- ### Create MicrometerMetricsV2 Instance Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/metrics.md Instantiate `MicrometerMetricsV2` using a `MeterRegistry`. This is the recommended micrometer-based implementation for metrics reporting. ```java MeterRegistry registry; Metrics metrics = MicrometerMetricsV2.newBuilder(registry).build(); ``` -------------------------------- ### Initialize MicrometerMetricsV2 Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-3-release.md Instantiate MicrometerMetricsV2 with a MeterRegistry. Attach the metrics to the Operator. This implementation is designed for low cardinality. ```java MeterRegistry registry; // initialize your registry Metrics metrics = MicrometerMetricsV2.newBuilder(registry).build(); Operator operator = new Operator(client, o -> o.withMetrics(metrics)); ``` -------------------------------- ### Build Docker Image with Jib (Shell Command) Source: https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/webpage/README.md Builds a Docker image for the sample operator using Maven Jib. The JAR is built locally and then copied into the Docker image. ```shell mvn jib:dockerBuild ``` -------------------------------- ### ControllerConfiguration Annotation Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v2-migration.md Shows the usage of the @ControllerConfiguration annotation, which replaces the @Controller annotation for configuring reconciler behavior. ```java @ControllerConfiguration(labelSelector = "app=my-app", finalizerName = "my-app.example.com/finalizer") public class MyServiceReconciler implements Reconciler { // ... reconciler implementation ... } ``` -------------------------------- ### Bootstrap Operator with Default Configuration Source: https://context7.com/operator-framework/java-operator-sdk/llms.txt Instantiate the Operator class with default settings to register reconcilers and start the operator runtime. ```java import io.javaoperatorsdk.operator.Operator; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceOverrider; public class MyOperatorMain { public static void main(String[] args) { // Option 1: Simple operator with defaults Operator operator = new Operator(); operator.register(new MyAppReconciler()); operator.start(); ``` -------------------------------- ### Build Docker Compose Container Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md Builds the Docker container for running the documentation site locally. ```bash docker-compose build ``` -------------------------------- ### Troubleshoot Module Compatibility Error Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md This console output indicates a potential issue with the Hugo version. Ensure Hugo v0.110.0 or higher is installed. ```console Error: Error building site: failed to extract shortcode: template for shortcode "blocks/cover" not found ``` -------------------------------- ### Create Legacy MicrometerMetrics Instance Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/metrics.md Use this to create an instance of the legacy MicrometerMetrics implementation that behaves as it historically has. Ensure your MeterRegistry implementation is initialized. ```java MeterRegistry registry; // initialize your registry implementation Metrics metrics = MicrometerMetrics.newMicrometerMetricsBuilder(registry).build(); ``` -------------------------------- ### Check License Headers Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Ensures all source files include the required Apache 2.0 license headers. ```bash ./mvnw -N license:check ``` -------------------------------- ### Run Unit Tests Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Executes all unit tests within the project. This is a quick way to verify individual components. ```bash ./mvnw test ``` -------------------------------- ### Migrating Condition API Usage Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v4-3-migration.md Example of how to access the secondary resource from the dependent resource in the new Condition API. This is used to migrate from the former API. ```java dependentResource.getSecondaryResource(primary,context) ``` -------------------------------- ### Load Operator Configuration with Default ConfigLoader Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/operations/configuration.md This snippet demonstrates initializing an Operator using the default ConfigLoader, which automatically bridges environment variables and system properties to the operator's configuration. Environment variables take precedence over system properties. ```java // uses env vars + system properties out of the box Operator operator = new Operator(ConfigLoader.getDefault().applyConfigs()); ``` -------------------------------- ### Run Docker Compose Container Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md Runs the Docker container for the documentation site. Access the site at http://localhost:1313. ```bash docker-compose up ``` -------------------------------- ### ResourceID Class Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v2-migration.md Illustrates the ResourceID class, used for addressing resources within event sources. It now uses a combination of name and namespace instead of UID. ```java public final class ResourceID { private final String name; private final String namespace; public ResourceID(String name, String namespace) { this.name = name; this.namespace = namespace; } public String getName() { return name; } public String getNamespace() { return namespace; } // equals and hashCode implementation based on name and namespace } ``` -------------------------------- ### Custom Target Secondary Resource ID Example Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-release.md Overrides the targetSecondaryResourceID method in KubernetesDependentResource to specify how to select a target resource when the desired state calculation is costly or unnecessary. ```java public class MyConfigMapDependentResource extends KubernetesDependentResource { public MyConfigMapDependentResource() { super(ConfigMap.class); } @Override protected ResourceID targetSecondaryResourceID(MyService primary, Context context) { // Example: Directly use a name from the primary resource return ResourceID.fromName("my-configmap-" + primary.getMetadata().getName()); } // ... other methods like createOrUpdate, get, delete ... } ``` -------------------------------- ### Migrate Event Source Initialization Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/migration/v3-migration.md Use the utility method to easily migrate event source registration to a default name. This is useful when event sources are now registered with a name in v3. ```java eventSourceInitializer.registerEventSource(new InformerEventSource(new WebPageCustomResourceController(), new InformerConfiguration("webpage"))); ``` -------------------------------- ### Reconcile with Server-Side Apply and Cache Read Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/reconciler.md Use `context.resourceOperations().serverSideApply()` to update a resource and then immediately read the fresh resource from the cache using `context.getSecondaryResource()`. This pattern is useful when you need to ensure subsequent operations in the same reconciliation use the most up-to-date resource state. ```java public UpdateControl reconcile(WebPage webPage, Context context) { ConfigMap managedConfigMap = prepareConfigMap(webPage); // filtering and caching update context.resourceOperations().serverSideApply(managedConfigMap); // fresh resource instantly available from our update in the cache var upToDateResource = context.getSecondaryResource(ConfigMap.class); makeStatusChanges(webPage); // built in update methods by default use this feature return UpdateControl.patchStatus(webPage); } ``` -------------------------------- ### Troubleshoot SCSS Processing Error Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/README.md This console output suggests an issue with SCSS processing, likely due to an older Hugo version. Ensure the extended version of Hugo is installed. ```console Error: TOCSS: failed to transform "scss/main.scss" ``` -------------------------------- ### Configure CRD Generator Maven Plugin Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/releases/v5-release.md Configure the CRD generator Maven plugin by adding this stanza to your project's POM build configuration. This is required starting with v5.0. ```xml io.fabric8 crd-generator-maven-plugin ${fabric8-client.version} generate ``` -------------------------------- ### Check Code Formatting Source: https://github.com/operator-framework/java-operator-sdk/blob/main/AGENTS.md Verifies that the project's code adheres to the defined formatting standards using the Spotless Maven plugin. ```bash ./mvnw spotless:check ``` -------------------------------- ### ConfigMap Dependent Resource Example Source: https://context7.com/operator-framework/java-operator-sdk/llms.txt Defines a dependent resource for managing a Kubernetes ConfigMap. Override the 'desired' method to specify the desired state of the ConfigMap, including its metadata and data. ```java import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import java.util.Map; @KubernetesDependent public class ConfigMapDependentResource extends CRUDKubernetesDependentResource implements GarbageCollected { public ConfigMapDependentResource() { super(ConfigMap.class); } @Override protected ConfigMap desired(MyApp primary, Context context) { return new ConfigMapBuilder() .withNewMetadata() .withName(primary.getMetadata().getName() + "-config") .withNamespace(primary.getMetadata().getNamespace()) .withLabels(Map.of( "app", primary.getMetadata().getName(), "managed-by", "myapp-operator" )) .endMetadata() .withData(Map.of( "application.properties", buildConfig(primary), "replicas", String.valueOf(primary.getSpec().getReplicas()) )) .build(); } private String buildConfig(MyApp primary) { return "app.name=" + primary.getSpec().getName() + "\n" + "app.replicas=" + primary.getSpec().getReplicas(); } } ``` -------------------------------- ### Configure LinearRateLimiter with Annotation Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/docs/documentation/rate-limiting.md Use the @RateLimited annotation on your Reconciler class to configure the default LinearRateLimiter. This example limits resources to a maximum of 2 reconciliations within a 3-second interval. ```java @RateLimited(maxReconciliations = 2, within = 3, unit = TimeUnit.SECONDS) @ControllerConfiguration public class MyReconciler implements Reconciler { } ``` -------------------------------- ### Sequence Diagram for Read-Cache-After-Write Consistency Source: https://github.com/operator-framework/java-operator-sdk/blob/main/docs/content/en/blog/news/read-after-write-consistency.md This diagram illustrates the flow of operations for achieving read-cache-after-write consistency, including updating a resource, caching it, and handling informer events. ```mermaid sequenceDiagram box rgba(50,108,229,0.1) participant K8S as ⎈ Kubernetes API Server end box rgba(232,135,58,0.1) participant R as Reconciler end box rgba(58,175,169,0.1) participant I as Informer participant IC as Informer Cache participant TRC as Temporary Resource Cache end R->>K8S: 1. Update resource K8S-->>R: Updated resource (with new resourceVersion) R->>TRC: 2. Cache updated resource in TRC I-)K8S: 3. Watch event (resource updated) I->>TRC: On event: event resourceVersion ≥ TRC version? alt Yes: event is up-to-date I-->>TRC: Evict resource from TRC else No: stale event Note over TRC: TRC entry retained end R->>TRC: 4. Read resource from cache alt Resource found in TRC TRC-->>R: Return cached resource else Not in TRC R->>IC: Read from Informer Cache IC-->>R: Return resource end ``` -------------------------------- ### Standalone Dependents Reconciler with Manual Workflow Source: https://context7.com/operator-framework/java-operator-sdk/llms.txt Implement a reconciler that manually controls the workflow of dependent resources. This example demonstrates building a workflow programmatically and invoking its reconcile and cleanup methods. ```java import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow; import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowBuilder; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.apps.Deployment; @ControllerConfiguration public class StandaloneDependentsReconciler implements Reconciler, Cleaner { private final ConfigMapDependentResource configMapDR; private final DeploymentDependentResource deploymentDR; private Workflow workflow; public StandaloneDependentsReconciler() { this.configMapDR = new ConfigMapDependentResource(); this.deploymentDR = new DeploymentDependentResource(); } @Override public java.util.List> prepareEventSources(EventSourceContext context) { // Build workflow programmatically this.workflow = new WorkflowBuilder() .addDependentResource(configMapDR) .addDependentResource(deploymentDR) .dependsOn(configMapDR) .build(); // Return event sources from dependent resources return java.util.List.of( configMapDR.eventSource(context).orElseThrow(), deploymentDR.eventSource(context).orElseThrow() ); } @Override public UpdateControl reconcile(MyApp resource, Context context) { // Manual workflow invocation var result = workflow.reconcile(resource, context); // Check for errors if (result.erroredDependentsExist()) { var errors = result.getErroredDependents(); errors.forEach((dr, exception) -> System.err.println("Error in " + dr.name() + ": " + exception.getMessage()) ); resource.getStatus().setState("Error"); return UpdateControl.patchStatus(resource); } // Get secondary resources for status var configMap = context.getSecondaryResource(ConfigMap.class); var deployment = context.getSecondaryResource(Deployment.class); if (configMap.isPresent() && deployment.isPresent()) { int readyReplicas = deployment.get().getStatus() != null ? deployment.get().getStatus().getReadyReplicas() != null ? deployment.get().getStatus().getReadyReplicas() : 0 : 0; resource.getStatus().setState( readyReplicas >= resource.getSpec().getReplicas() ? "Ready" : "Scaling" ); } else { resource.getStatus().setState("Provisioning"); } return UpdateControl.patchStatus(resource); } @Override public DeleteControl cleanup(MyApp resource, Context context) { // Cleanup workflow handles deletion in reverse order workflow.cleanup(resource, context); return DeleteControl.defaultDelete(); } } ``` -------------------------------- ### Build Docker Image Source: https://github.com/operator-framework/java-operator-sdk/blob/main/sample-operators/tomcat-operator/README.md Build the operator's Docker image using Maven and Jib. This command produces an image that can be pushed to a registry. ```bash mvn install jib:dockerBuild ```