├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yml │ ├── new_feature.yaml │ └── other.yaml ├── actions │ ├── graalvm-build │ │ ├── README.md │ │ └── action.yml │ ├── graalvm-post-build │ │ ├── README.md │ │ └── action.yml │ ├── graalvm-pre-build │ │ ├── README.md │ │ └── action.yml │ ├── gradle-build │ │ ├── README.md │ │ └── action.yml │ ├── gradle-post-build │ │ ├── README.md │ │ └── action.yml │ ├── gradle-pre-build │ │ ├── README.md │ │ └── action.yml │ ├── gradle-publish-github-pages │ │ ├── README.md │ │ └── action.yml │ └── gradle-publish-sona-type │ │ ├── README.md │ │ └── action.yml ├── release.yml ├── renovate.json └── workflows │ ├── .rsync-filter │ ├── central-sync.yml │ ├── graalvm-dev.yml │ ├── graalvm-latest.yml │ ├── gradle.yml │ ├── publish-snapshot.yml │ └── release.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── MAINTAINING.md ├── README.md ├── SECURITY.md ├── build-logic ├── build.gradle ├── settings.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── KubernetesClientOpenApiExtension.java │ │ ├── KubernetesClientOpenApiPlugin.java │ │ └── tasks │ │ ├── CreateWatcherSpec.java │ │ └── DownloadSpec.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── KubernetesClientOpenApiPluginSpec.groovy │ └── resources │ ├── openapi-input-1.yaml │ ├── openapi-input-2.yaml │ ├── openapi-output-1.yaml │ ├── openapi-output-2.yaml │ └── openapi-output-type-mappings.txt ├── build.gradle ├── buildSrc ├── build.gradle ├── settings.gradle └── src │ └── main │ └── groovy │ ├── io.micronaut.build.internal.kubernetes-base.gradle │ ├── io.micronaut.build.internal.kubernetes-examples.gradle │ ├── io.micronaut.build.internal.kubernetes-module.gradle │ └── io.micronaut.build.internal.kubernetes-tests.gradle ├── config ├── HEADER ├── checkstyle │ ├── checkstyle.xml │ ├── custom-suppressions.xml │ └── suppressions.xml └── spotless.license.java ├── examples ├── example-client │ ├── build.gradle │ ├── gradle.properties │ └── src │ │ ├── main │ │ ├── java │ │ │ └── micronaut │ │ │ │ └── client │ │ │ │ ├── Application.java │ │ │ │ ├── ExampleClient.java │ │ │ │ ├── HelloController.java │ │ │ │ └── LegacyEnvEndpointFilter.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── logback.xml │ │ └── test │ │ ├── groovy │ │ └── micronaut │ │ │ └── client │ │ │ ├── HelloControllerSpec.groovy │ │ │ ├── KubernetesHealthIndicatorSpec.groovy │ │ │ └── utils │ │ │ └── KubernetesSpecification.groovy │ │ └── resources │ │ ├── application-test.yml │ │ └── logback.xml ├── example-kubernetes-client-openapi-informer-java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── client │ │ │ ├── Application.java │ │ │ ├── configmap │ │ │ ├── ConfigMapController.java │ │ │ └── ConfigMapInformer.java │ │ │ └── secret │ │ │ ├── SecretController.java │ │ │ └── SecretResourceEventHandler.java │ │ └── resources │ │ ├── application.yml │ │ └── logback.xml ├── example-kubernetes-client-openapi-java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── client │ │ │ ├── Application.java │ │ │ └── PodController.java │ │ └── resources │ │ ├── application.yml │ │ └── logback.xml ├── example-kubernetes-client-openapi-operator-java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── operator │ │ │ ├── Application.java │ │ │ ├── ConfigMapReconciler.java │ │ │ ├── OnAddFilter.java │ │ │ ├── OnDeleteFilter.java │ │ │ ├── OnUpdateFilter.java │ │ │ └── SecretOperator.java │ │ └── resources │ │ ├── application.yml │ │ └── logback.xml ├── example-kubernetes-client-openapi-reactor-java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── client │ │ │ ├── Application.java │ │ │ └── PodController.java │ │ └── resources │ │ ├── application.yml │ │ └── logback.xml ├── example-kubernetes-client-openapi-watcher-java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── client │ │ │ ├── Application.java │ │ │ └── SecretController.java │ │ └── resources │ │ ├── application.yml │ │ └── logback.xml ├── example-kubernetes-client │ ├── build.gradle │ ├── gradle.properties │ ├── micronaut-cli.yml │ └── src │ │ └── main │ │ ├── java │ │ └── micronaut │ │ │ └── service │ │ │ ├── Application.java │ │ │ ├── LegacyEnvEndpointFilter.java │ │ │ └── PodController.java │ │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── logback.xml ├── example-kubernetes-informer │ ├── build.gradle │ ├── gradle.properties │ └── src │ │ ├── main │ │ ├── java │ │ │ └── micronaut │ │ │ │ └── informer │ │ │ │ ├── Application.java │ │ │ │ ├── LegacyEnvEndpointFilter.java │ │ │ │ ├── SecretInformerController.java │ │ │ │ └── SecretResourceEventHandler.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── logback.xml │ │ └── test │ │ ├── groovy │ │ └── micronaut │ │ │ └── informer │ │ │ └── SecretInformerControllerSpec.groovy │ │ └── resources │ │ ├── application-test.yml │ │ └── logback.xml ├── example-kubernetes-operator │ ├── build.gradle │ ├── gradle.properties │ └── src │ │ ├── main │ │ ├── java │ │ │ └── micronaut │ │ │ │ └── operator │ │ │ │ ├── Application.java │ │ │ │ ├── ConfigMapReconciler.java │ │ │ │ ├── CustomLockIdentityProvider.java │ │ │ │ └── LegacyEnvEndpointFilter.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── logback.xml │ │ └── test │ │ ├── groovy │ │ └── micronaut │ │ │ └── operator │ │ │ ├── ConfigMapOperatorControllerSpec.groovy │ │ │ └── utils │ │ │ └── KubernetesSpecification.groovy │ │ └── resources │ │ ├── application-test.yml │ │ └── logback.xml └── example-service │ ├── build.gradle │ ├── gradle.properties │ ├── micronaut-cli.yml │ └── src │ ├── main │ ├── java │ │ └── micronaut │ │ │ └── service │ │ │ ├── Application.java │ │ │ └── HelloController.java │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── logback.xml │ └── test │ ├── java │ └── micronaut │ │ └── service │ │ └── HelloControllerTest.java │ └── resources │ ├── application-test.yml │ └── logback.xml ├── gradle.properties ├── gradle ├── libs.versions.toml ├── license.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── k8s-auth.yml ├── kubernetes-bom └── build.gradle ├── kubernetes-client-openapi-common ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── KubernetesHttpClientConfiguration.java │ │ ├── KubernetesHttpClientFactory.java │ │ ├── KubernetesHttpClientFilter.java │ │ ├── common │ │ ├── KubernetesListObject.java │ │ ├── KubernetesObject.java │ │ └── KubernetesType.java │ │ ├── config │ │ ├── AbstractKubeConfigLoader.java │ │ ├── DefaultKubeConfigLoader.java │ │ ├── KubeConfig.java │ │ ├── KubeConfigLoader.java │ │ ├── KubernetesClientConfiguration.java │ │ └── model │ │ │ ├── AuthInfo.java │ │ │ ├── Cluster.java │ │ │ ├── Context.java │ │ │ ├── ExecConfig.java │ │ │ └── ExecEnvVar.java │ │ ├── credential │ │ ├── ExecCommandCredentialLoader.java │ │ ├── KubeConfigTokenLoader.java │ │ ├── KubernetesTokenLoader.java │ │ ├── ReactiveKubernetesTokenLoader.java │ │ ├── ServiceAccountTokenLoader.java │ │ ├── TokenLoader.java │ │ └── model │ │ │ ├── ExecCredential.java │ │ │ └── ExecCredentialStatus.java │ │ ├── resolver │ │ ├── DefaultNamespaceResolver.java │ │ ├── DefaultPodNameResolver.java │ │ ├── NamespaceResolver.java │ │ └── PodNameResolver.java │ │ ├── ssl │ │ ├── DefaultPrivateKeyLoader.java │ │ ├── KubernetesClientSslBuilder.java │ │ ├── KubernetesPrivateKeyLoader.java │ │ └── PKCS1Util.java │ │ └── util │ │ └── ThreadFactoryUtil.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── KubernetesHttpClientFilterSpec.groovy │ │ ├── config │ │ └── KubeConfigSpec.groovy │ │ ├── credential │ │ └── ServiceAccountTokenLoaderSpec.groovy │ │ ├── resolver │ │ └── DefaultNamespaceResolverSpec.groovy │ │ └── ssl │ │ └── DefaultPrivateKeyLoaderSpec.groovy │ └── resources │ └── key │ ├── pkcs1.key │ ├── pkcs8-ec.key │ ├── pkcs8-rsa.key │ └── sec1.key ├── kubernetes-client-openapi-discovery ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── KubernetesConfiguration.java │ │ ├── configuration │ │ ├── AbstractKubernetesConfigLabelSupplier.java │ │ ├── AbstractKubernetesConfigWatcher.java │ │ ├── AbstractKubernetesConfigWatcherCondition.java │ │ ├── KubernetesConfigMapLabelSupplier.java │ │ ├── KubernetesConfigMapWatcher.java │ │ ├── KubernetesConfigMapWatcherCondition.java │ │ ├── KubernetesConfigUtils.java │ │ ├── KubernetesConfigurationClient.java │ │ ├── KubernetesSecretLabelSupplier.java │ │ ├── KubernetesSecretWatcher.java │ │ └── KubernetesSecretWatcherCondition.java │ │ ├── discovery │ │ ├── KubernetesDiscoveryClient.java │ │ ├── KubernetesServiceConfiguration.java │ │ ├── KubernetesServiceInstanceProvider.java │ │ └── provider │ │ │ ├── AbstractV1EndpointsProvider.java │ │ │ ├── AbstractV1ServiceProvider.java │ │ │ ├── KubernetesDiscoveryUtils.java │ │ │ ├── KubernetesServiceInstanceEndpointInformerProvider.java │ │ │ ├── KubernetesServiceInstanceEndpointProvider.java │ │ │ ├── KubernetesServiceInstanceServiceInformerProvider.java │ │ │ └── KubernetesServiceInstanceServiceProvider.java │ │ ├── health │ │ └── KubernetesHealthIndicator.java │ │ └── util │ │ └── KubernetesUtils.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── K3sContainerSpec.groovy │ │ ├── configuration │ │ └── KubernetesConfigurationClientSpec.groovy │ │ ├── discovery │ │ ├── KubernetesDiscoveryClientSpec.groovy │ │ └── provider │ │ │ ├── KubernetesServiceInstanceEndpointProviderSpec.groovy │ │ │ └── KubernetesServiceInstanceServiceProviderSpec.groovy │ │ └── utils │ │ ├── ModelUtils.groovy │ │ └── OperationUtils.groovy │ └── resources │ ├── kubernetes │ ├── config-maps │ │ ├── mounted.json │ │ └── mounted.yml │ └── secrets │ │ └── foo │ └── logback.xml ├── kubernetes-client-openapi-informer ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── informer │ │ ├── ApiExecMethodProcessor.java │ │ ├── ApiReactorExecMethodProcessor.java │ │ ├── ApiWatcherExecMethodProcessor.java │ │ ├── DefaultSharedIndexInformer.java │ │ ├── DefaultSharedIndexInformerFactory.java │ │ ├── DeletedFinalStateUnknown.java │ │ ├── DeltaConsumer.java │ │ ├── DeltaFifo.java │ │ ├── InformerApiCall.java │ │ ├── InformerApiCallFactory.java │ │ ├── InformerConfiguration.java │ │ ├── InformerFactoryLifecycleListener.java │ │ ├── InformerLogger.java │ │ ├── InformerWatcher.java │ │ ├── ProcessorListener.java │ │ ├── ResyncRunnable.java │ │ ├── SharedIndexInformer.java │ │ ├── SharedIndexInformerFactory.java │ │ ├── SharedInformer.java │ │ ├── SharedProcessor.java │ │ ├── TransformFunc.java │ │ ├── cache │ │ ├── Cache.java │ │ ├── Indexer.java │ │ └── Store.java │ │ └── handler │ │ ├── DefaultInformerLabelSelectorResolver.java │ │ ├── DefaultInformerNamespaceResolver.java │ │ ├── EmptyLabelSupplier.java │ │ ├── EmptyNamespacesSupplier.java │ │ ├── Informer.java │ │ ├── InformerLabelSelectorResolver.java │ │ ├── InformerNamespaceResolver.java │ │ ├── ResourceEventHandler.java │ │ └── ResourceEventHandlerBeanListener.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── informer │ │ ├── ApiExecMethodProcessorSpec.groovy │ │ ├── DefaultSharedIndexInformerFactorySpec.groovy │ │ ├── DefaultSharedIndexInformerSpec.groovy │ │ ├── DeltaFifoSpec.groovy │ │ ├── InformerSpec.groovy │ │ ├── cache │ │ └── CacheSpec.groovy │ │ └── handler │ │ ├── DefaultInformerLabelSelectorResolverSpec.groovy │ │ └── DefaultInformerNamespaceResolverSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-openapi-operator ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── operator │ │ ├── Operator.java │ │ ├── OperatorFilter.java │ │ ├── OperatorResourceLister.java │ │ ├── ResourceReconcilerCreatedListener.java │ │ ├── configuration │ │ ├── LeaderElectionConfiguration.java │ │ └── OperatorConfiguration.java │ │ ├── controller │ │ ├── Controller.java │ │ ├── ControllerFactory.java │ │ ├── ControllerResourceEventHandler.java │ │ ├── ControllersLifecycleListener.java │ │ ├── DefaultController.java │ │ ├── DefaultControllerFactory.java │ │ └── reconciler │ │ │ ├── Request.java │ │ │ ├── ResourceReconciler.java │ │ │ └── Result.java │ │ ├── leaderelection │ │ ├── DefaultLockIdentityProvider.java │ │ ├── LeaderElectionRecord.java │ │ ├── LeaderElector.java │ │ ├── LeaderElectorLifecycleListener.java │ │ ├── LockIdentityProvider.java │ │ ├── event │ │ │ ├── LeaderChangedEvent.java │ │ │ ├── LeaseAcquiredEvent.java │ │ │ └── LeaseLostEvent.java │ │ └── resourcelock │ │ │ ├── AbstractLock.java │ │ │ ├── ConfigMapLock.java │ │ │ ├── EndpointsLock.java │ │ │ ├── LeaseLock.java │ │ │ └── Lock.java │ │ └── workqueue │ │ ├── DefaultDelayingQueue.java │ │ ├── DefaultRateLimitingQueue.java │ │ ├── DefaultWorkQueue.java │ │ ├── DelayingQueue.java │ │ ├── RateLimitingQueue.java │ │ ├── WorkQueue.java │ │ └── ratelimiter │ │ ├── BucketRateLimiter.java │ │ ├── DefaultControllerRateLimiter.java │ │ ├── ItemExponentialFailureRateLimiter.java │ │ ├── ItemFastSlowRateLimiter.java │ │ ├── MaxOfRateLimiter.java │ │ └── RateLimiter.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── operator │ │ ├── K3sContainerSpec.groovy │ │ ├── OperatorSpec.groovy │ │ ├── leaderelection │ │ └── LeaderElectorSpec.groovy │ │ ├── util │ │ ├── ConfigMapOperation.groovy │ │ ├── NamespaceOperation.groovy │ │ └── SecretOperation.groovy │ │ └── workqueue │ │ ├── DefaultDelayingQueueSpec.groovy │ │ ├── DefaultWorkQueueSpec.groovy │ │ └── ratelimiter │ │ ├── BucketRateLimiterSpec.groovy │ │ ├── ItemExponentialFailureRateLimiterSpec.groovy │ │ ├── ItemFastSlowRateLimiterSpec.groovy │ │ └── MaxOfRateLimiterSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-openapi-reactor ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── reactor │ │ └── annotation │ │ └── KubernetesClientApiReactor.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── reactor │ │ ├── ExecCommandTokenAuthSpec.groovy │ │ ├── KubeConfigTokenAuthSpec.groovy │ │ ├── KubernetesBasicAuthSpec.groovy │ │ └── KubernetesClientCertAuthSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-openapi-watcher ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── watcher │ │ ├── WatchEvent.java │ │ ├── WatchEventDeserializer.java │ │ └── annotation │ │ └── KubernetesClientApiWatcher.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ └── watcher │ │ ├── WatchCustomObjectEventSpec.groovy │ │ ├── WatchEventDeserializerSpec.groovy │ │ └── WatchEventsSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-openapi ├── build.gradle └── src │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── openapi │ │ ├── ClientConfigLoaderSpec.groovy │ │ ├── ClientCredentialLoaderSpec.groovy │ │ ├── ExecCommandTokenAuthSpec.groovy │ │ ├── KubeConfigTokenAuthSpec.groovy │ │ ├── KubernetesBasicAuthSpec.groovy │ │ └── KubernetesClientCertAuthSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-processor ├── build.gradle └── src │ └── main │ ├── java │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── processor │ │ └── KubernetesApisProcessor.java │ └── resources │ └── META-INF │ └── services │ └── javax.annotation.processing.Processor ├── kubernetes-client-reactor ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── reactor │ │ └── AsyncCallbackSink.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── reactor │ │ └── CoreV1ApiReactorClientSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-rxjava2 ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── rxjava2 │ │ └── ApiCallbackEmitter.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── rxjava2 │ │ └── CoreV1ApiRxClientSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client-rxjava3 ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── rxjava3 │ │ └── ApiCallbackEmitter.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── rxjava3 │ │ └── CoreV1ApiRxClientSpec.groovy │ └── resources │ └── logback.xml ├── kubernetes-client ├── build.gradle └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── micronaut │ │ │ └── kubernetes │ │ │ └── client │ │ │ ├── ApiClientConfiguration.java │ │ │ ├── ApiClientFactory.java │ │ │ ├── Apis.java │ │ │ ├── ApisAutomaticFeatureMetadata.java │ │ │ ├── DefaultNamespaceResolver.java │ │ │ ├── DefaultPodNameResolver.java │ │ │ ├── DiscoveryCache.java │ │ │ ├── DiscoveryFactory.java │ │ │ ├── ModelMapper.java │ │ │ ├── NamespaceResolver.java │ │ │ ├── OkHttpClientLogging.java │ │ │ ├── PodNameResolver.java │ │ │ └── graalvm │ │ │ └── KubernetesClientFeature.java │ └── resources │ │ └── META-INF │ │ └── native-image │ │ └── io.micronaut.kubernetes │ │ └── micronaut-kubernetes-client │ │ └── native-image.properties │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ ├── ApiClientConfigurationSpec.groovy │ │ ├── ApiClientFactorySpec.groovy │ │ ├── ApisSpec.groovy │ │ ├── DefaultNamespaceResolverSpec.groovy │ │ ├── DiscoveryCacheSpec.groovy │ │ ├── DiscoveryFactorySpec.groovy │ │ ├── ModelMapperSpec.groovy │ │ └── utils │ │ └── KubernetesSpecification.groovy │ ├── java │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── ApiClientListener.java │ └── resources │ ├── k8s │ └── kubernetes-client-example-deployment.yml │ └── logback.xml ├── kubernetes-discovery-client ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ ├── KubernetesConfiguration.java │ │ ├── configuration │ │ ├── AbstractKubernetesConfigLabelSupplier.java │ │ ├── AbstractKubernetesConfigWatcher.java │ │ ├── AbstractKubernetesConfigWatcherCondition.java │ │ ├── KubernetesConfigMapLabelSupplier.java │ │ ├── KubernetesConfigMapWatcher.java │ │ ├── KubernetesConfigMapWatcherCondition.java │ │ ├── KubernetesConfigurationClient.java │ │ ├── KubernetesSecretLabelSupplier.java │ │ ├── KubernetesSecretWatcher.java │ │ └── KubernetesSecretWatcherCondition.java │ │ ├── discovery │ │ ├── AbstractKubernetesServiceInstanceProvider.java │ │ ├── KubernetesDiscoveryClient.java │ │ ├── KubernetesServiceConfiguration.java │ │ ├── KubernetesServiceInstanceList.java │ │ ├── KubernetesServiceInstanceProvider.java │ │ ├── informer │ │ │ ├── IndexerComposite.java │ │ │ ├── IndexerCompositeFactory.java │ │ │ └── InstanceProviderInformerNamespaceResolver.java │ │ └── provider │ │ │ ├── AbstractV1EndpointsProvider.java │ │ │ ├── AbstractV1ServiceProvider.java │ │ │ ├── KubernetesServiceInstanceEndpointInformerProvider.java │ │ │ ├── KubernetesServiceInstanceEndpointProvider.java │ │ │ ├── KubernetesServiceInstanceServiceInformerProvider.java │ │ │ └── KubernetesServiceInstanceServiceProvider.java │ │ ├── health │ │ └── KubernetesHealthIndicator.java │ │ └── util │ │ └── KubernetesUtils.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ ├── KubernetesConfigurationSpec.groovy │ │ ├── configuration │ │ ├── KubernetesConfigMapWatcherSpec.groovy │ │ ├── KubernetesConfigurationClientFilterSpec.groovy │ │ ├── KubernetesConfigurationClientLabelsSpec.groovy │ │ ├── KubernetesConfigurationClientSecretSpec.groovy │ │ ├── KubernetesConfigurationClientSpec.groovy │ │ └── KubernetesSecretWatcherSpec.groovy │ │ ├── discovery │ │ ├── KubernetesDiscoveryClientFilterSpec.groovy │ │ ├── KubernetesDiscoveryClientLabelsSpec.groovy │ │ ├── KubernetesDiscoveryClientSpec.groovy │ │ ├── KubernetesServiceConfigurationSpec.groovy │ │ ├── informer │ │ │ └── InstanceProviderInformerNamespaceResolverSpec.groovy │ │ └── provider │ │ │ ├── KubernetesServiceInstanceEndpointProviderSpec.groovy │ │ │ └── KubernetesServiceInstanceServiceProviderSpec.groovy │ │ └── utils │ │ └── KubernetesSpecification.groovy │ └── resources │ ├── application-test.yml │ └── logback.xml ├── kubernetes-informer ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── informer │ │ ├── DefaultSharedIndexInformerFactory.java │ │ ├── EmptyLabelSupplier.java │ │ ├── EmptyNamespacesSupplier.java │ │ ├── Informer.java │ │ ├── InformerAnnotationUtils.java │ │ ├── InformerConfiguration.java │ │ ├── InformerFactoryLifecycleListener.java │ │ ├── ResourceEventHandlerBeanListener.java │ │ ├── SharedIndexInformerFactory.java │ │ ├── package-info.java │ │ └── resolvers │ │ ├── DefaultInformerApiGroupResolver.java │ │ ├── DefaultInformerLabelSelectorResolver.java │ │ ├── DefaultInformerNamespaceResolver.java │ │ ├── DefaultInformerResourcePluralResolver.java │ │ ├── InformerApiGroupResolver.java │ │ ├── InformerLabelSelectorResolver.java │ │ ├── InformerNamespaceResolver.java │ │ └── InformerResourcePluralResolver.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── informer │ │ ├── ApiClientCreationListenerSpec.groovy │ │ ├── ClusterRoleInformerSpec.groovy │ │ ├── ConfigMapInformerSpec.groovy │ │ ├── ConfigMapLabelSelectorInformerSpec.groovy │ │ ├── DefaultSharedIndexInformerFactorySpec.groovy │ │ ├── DuplicitConfigMapInformerSpec.groovy │ │ ├── InformerSpec.groovy │ │ └── utils │ │ └── KubernetesSpecification.groovy │ ├── java │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── informer │ │ ├── ClusterRoleInformer.java │ │ ├── ConfigMapInformer.java │ │ ├── ConfigMapLabelSelectorInformer.java │ │ ├── DuplicitConfigMapInformer.java │ │ ├── LabelSelectorSupplier.java │ │ ├── SharedIndexInformerFactoryExample.java │ │ └── SharedInformerCache.java │ └── resources │ └── logback.xml ├── kubernetes-operator ├── build.gradle └── src │ ├── main │ └── java │ │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── operator │ │ ├── ControllerConfiguration.java │ │ ├── ControllerConfigurationFactory.java │ │ ├── ControllerConfigurationImpl.java │ │ ├── ControllerFactory.java │ │ ├── Operator.java │ │ ├── OperatorResourceLister.java │ │ ├── ResourceReconciler.java │ │ ├── ResourceReconcilerCreatedListener.java │ │ ├── configuration │ │ ├── LeaderElectionConfiguration.java │ │ ├── LeaderElectionConfigurationProperties.java │ │ └── OperatorConfigurationProperties.java │ │ ├── controller │ │ ├── ControllerBuilder.java │ │ ├── ControllerManagerBuilder.java │ │ ├── ControllerWatchBuilder.java │ │ ├── DefaultControllerBuilder.java │ │ ├── DefaultControllerManagerBuilder.java │ │ ├── DefaultControllerWatchBuilder.java │ │ ├── DefaultLeaderElectingControllerBuilder.java │ │ └── LeaderElectingControllerBuilder.java │ │ ├── event │ │ ├── AbstracLeaderElectingControllerEvent.java │ │ ├── LeaseAcquiredEvent.java │ │ └── LeaseLostEvent.java │ │ ├── filter │ │ ├── DefaultAddFilter.java │ │ ├── DefaultDeleteFilter.java │ │ └── DefaultUpdateFilter.java │ │ ├── leaderelection │ │ ├── DefaultLockIdentityProvider.java │ │ ├── LeaderElectionConfigFactory.java │ │ ├── LockIdentityProvider.java │ │ └── ResourceLockFactory.java │ │ └── queue │ │ └── RateLimitingQueueFactory.java │ └── test │ ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── operator │ │ ├── ConfigMapResourceReconcilerSpec.groovy │ │ ├── ConfigMapResourceReconcilerWithFiltersSpec.groovy │ │ ├── configuration │ │ ├── ControllerConfigurationPropertiesSpec.groovy │ │ └── LeaderElectionConfigurationPropertiesSpec.groovy │ │ ├── controller │ │ ├── DefaultControllerBuilderSpec.groovy │ │ ├── DefaultControllerManagerBuilderSpec.groovy │ │ └── DefaultControllerWatchBuilderSpec.groovy │ │ ├── leaderelection │ │ ├── DefaultLockIdentityProviderSpec.groovy │ │ ├── LeaderElectionConfigFactorySpec.groovy │ │ └── ResourceLockFactorySpec.groovy │ │ ├── queue │ │ └── RateLimitingQueueFactorySpec.groovy │ │ └── utils │ │ └── KubernetesSpecification.groovy │ ├── java │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── client │ │ └── operator │ │ ├── ConfigMapResourceReconciler.java │ │ ├── ConfigMapResourceReconcilerWithFilters.java │ │ ├── OnAddFilter.java │ │ ├── OnDeleteFilter.java │ │ ├── OnUpdateFilter.java │ │ └── TestPodNamespaceResolver.java │ └── resources │ ├── application-test.yml │ └── logback.xml ├── kubernetes.yml ├── redeploy.sh ├── settings.gradle ├── setup-kubernetes.sh ├── setup.sh ├── src └── main │ └── docs │ └── guide │ ├── breaking.adoc │ ├── introduction.adoc │ ├── kubernetes-client-openapi.adoc │ ├── kubernetes-client-openapi │ ├── kubernetes-client-openapi-config-client.adoc │ ├── kubernetes-client-openapi-health-checks.adoc │ ├── kubernetes-client-openapi-informer.adoc │ ├── kubernetes-client-openapi-operator.adoc │ ├── kubernetes-client-openapi-service-discovery.adoc │ └── kubernetes-client-openapi-watcher.adoc │ ├── kubernetes-client.adoc │ ├── kubernetes-client │ ├── config-client.adoc │ ├── health-checks.adoc │ ├── kubernetes-informer.adoc │ ├── kubernetes-operator.adoc │ └── service-discovery.adoc │ ├── kubernetesGuides.adoc │ ├── logging.adoc │ ├── releaseHistory.adoc │ ├── repository.adoc │ ├── toc.yml │ └── whatsNew.adoc ├── teardown.sh └── test-utils ├── build.gradle ├── gradle.properties └── src ├── main ├── groovy │ └── io │ │ └── micronaut │ │ └── kubernetes │ │ └── test │ │ ├── K3sContainerSpec.groovy │ │ ├── KubectlCommands.groovy │ │ ├── KubernetesOperations.groovy │ │ ├── KubernetesSpecification.groovy │ │ └── TestUtils.groovy └── resources │ └── k8s │ ├── example-client-deployment.yml │ ├── example-service-deployment.yml │ ├── game.json │ ├── game.properties │ ├── game.yml │ ├── mounted.yml │ └── secure-deployment.yml └── test ├── groovy └── io │ └── micronaut │ └── kubernetes │ └── test │ ├── KubernetesOperationsSpec.groovy │ └── KubernetesSpecificationSpec.groovy └── resources ├── k8s ├── deployment.yml └── game.yml └── logback.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_style = space 8 | 9 | [{*.sh,gradlew}] 10 | end_of_line = lf 11 | 12 | [{*.bat,*.cmd}] 13 | end_of_line = crlf 14 | 15 | [{*.mustache,*.ftl}] 16 | insert_final_newline = false 17 | 18 | [*.java] 19 | indent_size = 4 20 | tab_width = 4 21 | max_line_length = 100 22 | # Import order can be configured with ij_java_imports_layout=... 23 | # See documentation https://youtrack.jetbrains.com/issue/IDEA-170643#focus=streamItem-27-3708697.0-0 24 | 25 | [*.xml] 26 | indent_size = 4 27 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | *.java text eol=lf 5 | *.groovy text eol=lf 6 | *.html text eol=lf 7 | *.kt text eol=lf 8 | *.kts text eol=lf 9 | *.md text diff=markdown eol=lf 10 | *.py text diff=python executable 11 | *.pl text diff=perl executable 12 | *.pm text diff=perl 13 | *.css text diff=css eol=lf 14 | *.js text eol=lf 15 | *.sql text eol=lf 16 | *.q text eol=lf 17 | 18 | *.sh text eol=lf 19 | gradlew text eol=lf 20 | 21 | *.bat text eol=crlf 22 | *.cmd text eol=crlf 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Micronaut Core Discussions 3 | url: https://github.com/micronaut-projects/micronaut-core/discussions 4 | about: Ask questions about Micronaut on Github 5 | - name: Micronaut Data Discussions 6 | url: https://github.com/micronaut-projects/micronaut-data/discussions 7 | about: Ask Micronaut Data related questions on Github 8 | - name: Stack Overflow 9 | url: https://stackoverflow.com/tags/micronaut 10 | about: Ask questions on Stack Overflow 11 | - name: Chat 12 | url: https://gitter.im/micronautfw/ 13 | about: Chat with us on Gitter. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_feature.yaml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Create a new feature request 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | Please describe the feature you want for Micronaut to implement, before that check if there is already an existing issue to add it. 8 | - type: textarea 9 | attributes: 10 | label: Feature description 11 | placeholder: Tell us what feature you would like for Micronaut to have and what problem is it going to solve 12 | validations: 13 | required: true 14 | 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.yaml: -------------------------------------------------------------------------------- 1 | name: Other 2 | description: Something different 3 | body: 4 | - type: textarea 5 | attributes: 6 | label: Issue description 7 | validations: 8 | required: true 9 | 10 | -------------------------------------------------------------------------------- /.github/actions/graalvm-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform build steps in graalvm workflow 2 | 3 | Build steps for graalvm workflow. -------------------------------------------------------------------------------- /.github/actions/graalvm-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Build steps for GitHub gradle workflow 3 | description: Perform build steps for gradle workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | runs: 9 | using: "composite" 10 | steps: 11 | - name: Build with Gradle 12 | shell: bash 13 | run: | 14 | set -e 15 | for EXAMPLE in $(ls ./examples); do 16 | ./gradlew :examples:${EXAMPLE}:test --continue --no-daemon --no-build-cache 17 | done 18 | env: 19 | TESTCONTAINERS_RYUK_DISABLED: 'true' 20 | PREDICTIVE_TEST_SELECTION: "${{ github.event_name == 'pull_request' && 'true' || 'false' }}" 21 | -------------------------------------------------------------------------------- /.github/actions/graalvm-post-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform post-build steps in graalvm workflow 2 | 3 | Post-build steps for graalvm workflow. -------------------------------------------------------------------------------- /.github/actions/graalvm-post-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Post-build steps for GitHub graalvm workflow 3 | description: Perform post-build steps for graalvm workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | runs: 9 | using: "composite" 10 | steps: 11 | - name: Optional tear down step 12 | shell: bash 13 | env: 14 | JAVA_VERSION: ${{ inputs.java }} 15 | run: | 16 | [ -f ./teardown.sh ] && ./teardown.sh || true 17 | - name: Publish Test Report 18 | if: always() 19 | uses: mikepenz/action-junit-report@v5.5.1 20 | with: 21 | check_name: GraalVM CE CI / Test Report (Java ${{ inputs.java }}) 22 | report_paths: '**/build/test-results/test/TEST-*.xml' 23 | check_retries: 'true' 24 | -------------------------------------------------------------------------------- /.github/actions/graalvm-pre-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform pre-build steps in graalvm workflow 2 | 3 | Pre-build steps for graalvm workflow. -------------------------------------------------------------------------------- /.github/actions/graalvm-pre-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Pre-build steps for GitHub gradle workflow 3 | description: Perform pre-build steps for gradle workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | graalvm: 9 | description: GraalVM version 10 | required: true 11 | runs: 12 | using: "composite" 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/cache@v4 16 | with: 17 | path: ~/.gradle/caches 18 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 19 | restore-keys: | 20 | ${{ runner.os }}-gradle- 21 | - name: Setup GraalVM CE 22 | uses: graalvm/setup-graalvm@v1 23 | with: 24 | version: ${{ inputs.graalvm }} 25 | java-version: ${{ inputs.java }} 26 | components: 'native-image' 27 | - name: Optional setup step 28 | shell: bash 29 | run: | 30 | [ -f ./setup.sh ] && ./setup.sh || true 31 | -------------------------------------------------------------------------------- /.github/actions/gradle-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform build steps in gradle workflow 2 | 3 | Build steps for gradle workflow. -------------------------------------------------------------------------------- /.github/actions/gradle-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Build steps for GitHub gradle workflow 3 | description: Perform build steps for gradle workflow 4 | inputs: 5 | run-in-parallel: 6 | description: provide --parallel to gradle build 7 | required: false 8 | default: 'true' 9 | runs: 10 | using: "composite" 11 | steps: 12 | - name: Build with Gradle 13 | shell: bash 14 | run: ./gradlew check --no-daemon --continue --no-build-cache 15 | env: 16 | TESTCONTAINERS_RYUK_DISABLED: 'true' 17 | PREDICTIVE_TEST_SELECTION: "${{ github.event_name == 'pull_request' && 'true' || 'false' }}" 18 | -------------------------------------------------------------------------------- /.github/actions/gradle-post-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform post-build steps in gradle workflow 2 | 3 | Post-build steps for gradle workflow. -------------------------------------------------------------------------------- /.github/actions/gradle-post-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Post-build steps for GitHub gradle workflow 3 | description: Perform post-build steps for gradle workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | gh-token: 9 | description: github token 10 | required: true 11 | runs: 12 | using: "composite" 13 | steps: 14 | - name: Optional tear down step 15 | shell: bash 16 | env: 17 | JAVA_VERSION: ${{ inputs.java }} 18 | run: | 19 | [ -f ./teardown.sh ] && ./teardown.sh || true 20 | - name: Publish Test Report 21 | if: always() 22 | uses: mikepenz/action-junit-report@v5.5.1 23 | with: 24 | check_name: Java CI / Test Report (${{ inputs.java }}) 25 | report_paths: '**/build/test-results/test/TEST-*.xml' 26 | check_retries: 'true' 27 | - name: "📜 Upload binary compatibility check results" 28 | if: always() 29 | uses: actions/upload-artifact@v4 30 | with: 31 | name: binary-compatibility-reports 32 | path: "**/build/reports/binary-compatibility-*.html" 33 | -------------------------------------------------------------------------------- /.github/actions/gradle-pre-build/README.md: -------------------------------------------------------------------------------- 1 | # Perform pre-build steps in gradle workflow 2 | 3 | Pre-build steps for gradle workflow. -------------------------------------------------------------------------------- /.github/actions/gradle-pre-build/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Pre-build steps for GitHub gradle workflow 3 | description: Perform pre-build steps for gradle workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | runs: 9 | using: "composite" 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/cache@v4 13 | with: 14 | path: ~/.gradle/caches 15 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 16 | restore-keys: | 17 | ${{ runner.os }}-gradle- 18 | - name: Set up JDK 19 | uses: actions/setup-java@v4 20 | with: 21 | distribution: 'adopt' 22 | java-version: ${{ inputs.java }} 23 | - name: Optional setup step 24 | shell: bash 25 | run: | 26 | [ -f ./setup.sh ] && ./setup.sh || true 27 | -------------------------------------------------------------------------------- /.github/actions/gradle-publish-github-pages/README.md: -------------------------------------------------------------------------------- 1 | # Publish Github Pages 2 | 3 | Publish Github Pages. -------------------------------------------------------------------------------- /.github/actions/gradle-publish-github-pages/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Publish Github Pages 3 | description: Perform publish github pages for gradle workflow 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Determine docs target repository 8 | uses: haya14busa/action-cond@v1 9 | id: docs_target 10 | with: 11 | cond: ${{ github.repository == 'micronaut-projects/micronaut-core' }} 12 | if_true: "micronaut-projects/micronaut-docs" 13 | if_false: ${{ github.repository }} 14 | - name: Publish to Github Pages 15 | uses: micronaut-projects/github-pages-deploy-action@master 16 | env: 17 | TARGET_REPOSITORY: ${{ steps.docs_target.outputs.value }} 18 | GH_TOKEN: ${{ inputs.gh-token }} 19 | BRANCH: gh-pages 20 | FOLDER: build/docs 21 | -------------------------------------------------------------------------------- /.github/actions/gradle-publish-sona-type/README.md: -------------------------------------------------------------------------------- 1 | # Publish to Sonatype Snapshots 2 | 3 | Publish to Sonatype Snapshots -------------------------------------------------------------------------------- /.github/actions/gradle-publish-sona-type/action.yml: -------------------------------------------------------------------------------- 1 | #TODO move this action to https://github.com/micronaut-projects/github-actions 2 | name: Pre-build steps for GitHub gradle workflow 3 | description: Perform pre-build steps for gradle workflow 4 | inputs: 5 | java: 6 | description: java version 7 | required: true 8 | runs: 9 | using: "composite" 10 | steps: 11 | - name: Publish to Sonatype Snapshots 12 | shell: bash 13 | run: ./gradlew publishToSonatype docs --no-daemon 14 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | authors: 4 | - micronaut-build 5 | categories: 6 | - title: Breaking Changes 🛠 7 | labels: 8 | - 'type: breaking' 9 | - title: New Features 🎉 10 | labels: 11 | - 'type: enhancement' 12 | - title: Bug Fixes 🐞 13 | labels: 14 | - 'type: bug' 15 | - title: Improvements ⭐ 16 | labels: 17 | - 'type: improvement' 18 | - title: Docs 📖 19 | labels: 20 | - 'type: docs' 21 | - title: Dependency updates 🚀 22 | labels: 23 | - 'type: dependency-upgrade' 24 | - 'dependency-upgrade' 25 | - title: Regressions 🧐 26 | labels: 27 | - 'type: regression' 28 | - title: GraalVM 🏆 29 | labels: 30 | - 'relates-to: graal' 31 | - title: Other Changes 💡 32 | labels: 33 | - "*" 34 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:recommended" 4 | ], 5 | "addLabels": [ 6 | "type: dependency-upgrade" 7 | ], 8 | "schedule": [ 9 | "after 10pm" 10 | ], 11 | "prHourlyLimit": 1, 12 | "prConcurrentLimit": 20, 13 | "timezone": "Europe/Prague", 14 | "packageRules": [ 15 | { 16 | "dependencyDashboardApproval": true, 17 | "matchUpdateTypes": [ 18 | "patch" 19 | ], 20 | "matchCurrentVersion": "!/^0/", 21 | "automerge": true, 22 | "matchPackageNames": [ 23 | "/actions.*/" 24 | ] 25 | }, 26 | { 27 | "matchUpdateTypes": [ 28 | "patch" 29 | ], 30 | "matchCurrentVersion": "!/^0/", 31 | "automerge": true 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/.rsync-filter: -------------------------------------------------------------------------------- 1 | - graalvm.yml 2 | - gradle.yml -------------------------------------------------------------------------------- /.github/workflows/publish-snapshot.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Do not edit this file directly. Instead, go to: 2 | # 3 | # https://github.com/micronaut-projects/micronaut-project-template/tree/master/.github/workflows 4 | # 5 | # and edit them there. Note that it will be sync'ed to all the Micronaut repos 6 | name: Publish snapshot release 7 | on: [workflow_dispatch] 8 | jobs: 9 | build: 10 | if: github.repository != 'micronaut-projects/micronaut-project-template' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/cache@v4 15 | with: 16 | path: ~/.gradle/caches 17 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 18 | restore-keys: | 19 | ${{ runner.os }}-gradle- 20 | - name: Set up JDK 21 | uses: actions/setup-java@v4 22 | with: 23 | distribution: 'temurin' 24 | java-version: '17' 25 | - name: Publish to Sonatype Snapshots 26 | if: success() 27 | env: 28 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 29 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 30 | DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} 31 | DEVELOCITY_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }} 32 | DEVELOCITY_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} 33 | run: ./gradlew publishToSonatype --no-daemon 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .DS_Store 3 | target/ 4 | .gradle/ 5 | .idea/ 6 | build/ 7 | !build-logic/src/main/java/io/micronaut/build 8 | classes/ 9 | out/ 10 | *.db 11 | *.log 12 | *.iml 13 | .classpath 14 | .factorypath 15 | bin/ 16 | .settings/ 17 | .project 18 | */test/ 19 | */META-INF/ 20 | *.ipr 21 | *.iws 22 | .kotlintest 23 | */.kotlintest/ 24 | 25 | # ignore resources, are downloaded via a gradle task from micronaut_docs 26 | src/main/docs/resources/css/highlight/*.css 27 | src/main/docs/resources/css/highlight/*.png 28 | src/main/docs/resources/css/highlight/*.jpg 29 | src/main/docs/resources/css/*.css 30 | src/main/docs/resources/js/*.js 31 | src/main/docs/resources/style/*.html 32 | src/main/docs/resources/img/micronaut-logo-white.svg 33 | 34 | # Ignore files generated by test-resources 35 | **/.micronaut/test-resources/ 36 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for reporting an issue, please review the task list below before submitting the 2 | issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed. 3 | 4 | NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Stack Overflow (https://stackoverflow.com/tags/micronaut) or Gitter (https://gitter.im/micronautfw/). DO NOT use the issue tracker to ask questions. 5 | 6 | ### Task List 7 | 8 | - [ ] Steps to reproduce provided 9 | - [ ] Stacktrace (if present) provided 10 | - [ ] Example that reproduces the problem uploaded to Github 11 | - [ ] Full description of the issue provided (see below) 12 | 13 | ### Steps to Reproduce 14 | 15 | 1. TODO 16 | 2. TODO 17 | 3. TODO 18 | 19 | ### Expected Behaviour 20 | 21 | Tell us what should happen 22 | 23 | ### Actual Behaviour 24 | 25 | Tell us what happens instead 26 | 27 | ### Environment Information 28 | 29 | - **Operating System**: TODO 30 | - **Micronaut Version:** TODO 31 | - **JDK Version:** TODO 32 | 33 | ### Example Application 34 | 35 | - TODO: link to github repository with example that reproduces the issue 36 | 37 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | We release patches for security vulnerabilities. Which versions are eligible 4 | receiving such patches depend on the CVSS v3.0 Rating: 5 | 6 | | CVSS v3.0 | Supported Versions | 7 | |-----------|-------------------------------------------| 8 | | 9.0-10.0 | Releases within the previous three months | 9 | | 4.0-8.9 | Most recent release | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please responsibly disclose (suspected) security vulnerabilities to 14 | **[The Micronaut Foundation](foundation@micronaut.io)**. You will receive a response from 15 | us within 48 hours. If the issue is confirmed, we will release a patch as soon 16 | as possible depending on complexity but historically within a few days. 17 | -------------------------------------------------------------------------------- /build-logic/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'groovy-gradle-plugin' 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | gradlePluginPortal() 8 | } 9 | 10 | dependencies { 11 | implementation("org.yaml:snakeyaml:2.4") 12 | implementation("org.spockframework:spock-core:2.3-groovy-3.0") 13 | implementation("org.spockframework:spock-junit4:2.3-groovy-3.0") 14 | } 15 | 16 | gradlePlugin { 17 | plugins { 18 | kubernetesClientOpenApi { 19 | id = "io.micronaut.kubernetes.client.openapi" 20 | implementationClass = "io.micronaut.kubernetes.client.openapi.KubernetesClientOpenApiPlugin" 21 | } 22 | } 23 | } 24 | 25 | test { 26 | useJUnitPlatform() 27 | } 28 | -------------------------------------------------------------------------------- /build-logic/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "build-logic" 2 | 3 | dependencyResolutionManagement { 4 | versionCatalogs { 5 | libs { 6 | from(files("../gradle/libs.versions.toml")) 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /build-logic/src/test/resources/openapi-output-type-mappings.txt: -------------------------------------------------------------------------------- 1 | ["v1.Namespace": "io.micronaut.kubernetes.client.openapi.watcher.WatchEvent"] -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "io.micronaut.build.internal.docs" 3 | id "io.micronaut.build.internal.quality-reporting" 4 | } 5 | 6 | if (System.getenv("SONAR_TOKEN") != null) { 7 | sonarqube { 8 | properties { 9 | property "sonar.exclusions", "**/examples/**" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /buildSrc/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'groovy-gradle-plugin' 3 | } 4 | 5 | repositories { 6 | gradlePluginPortal() 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | implementation libs.micronaut.gradle.plugin 12 | implementation libs.shadow.plugin 13 | implementation(libs.sonatype.scan) 14 | } 15 | -------------------------------------------------------------------------------- /buildSrc/settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | versionCatalogs { 3 | libs { 4 | from(files("../gradle/libs.versions.toml")) 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/io.micronaut.build.internal.kubernetes-base.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | } 4 | 5 | configurations.all { 6 | resolutionStrategy { 7 | preferProjectModules() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/io.micronaut.build.internal.kubernetes-examples.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "io.micronaut.build.internal.kubernetes-tests" 3 | id "io.micronaut.application" 4 | id 'com.github.johnrengelman.shadow' 5 | } 6 | 7 | dependencies { 8 | runtimeOnly(mn.snakeyaml) 9 | } 10 | 11 | graalvmNative { 12 | toolchainDetection = false 13 | testSupport = false 14 | metadataRepository { 15 | enabled = true 16 | } 17 | } 18 | 19 | dockerfile { 20 | if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { 21 | baseImage("eclipse-temurin:21-jre-jammy") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/io.micronaut.build.internal.kubernetes-module.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "io.micronaut.build.internal.module" 3 | id "io.micronaut.build.internal.kubernetes-base" 4 | id("org.sonatype.gradle.plugins.scan") 5 | } 6 | String ossIndexUsername = System.getenv("OSS_INDEX_USERNAME") ?: project.properties["ossIndexUsername"] 7 | String ossIndexPassword = System.getenv("OSS_INDEX_PASSWORD") ?: project.properties["ossIndexPassword"] 8 | boolean sonatypePluginConfigured = ossIndexUsername != null && ossIndexPassword != null 9 | if (sonatypePluginConfigured) { 10 | ossIndexAudit { 11 | username = ossIndexUsername 12 | password = ossIndexPassword 13 | excludeCompileOnly = true 14 | } 15 | } 16 | 17 | // Fix for JavaDoc not finding generated classes 18 | configurations { 19 | internalJavadocClasspathElements { 20 | outgoing.artifact(tasks.named("jar")) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/io.micronaut.build.internal.kubernetes-tests.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "io.micronaut.build.internal.kubernetes-base" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /config/HEADER: -------------------------------------------------------------------------------- 1 | Copyright ${year} original authors 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /config/checkstyle/custom-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /config/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /config/spotless.license.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-$YEAR original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ -------------------------------------------------------------------------------- /examples/example-client/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id("groovy") 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("spock2") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.client.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.http.client) 22 | implementation(mn.micronaut.management) 23 | implementation projects.micronautKubernetesDiscoveryClient 24 | 25 | runtimeOnly(mnLogging.logback.classic) 26 | 27 | testImplementation projects.testUtils 28 | } 29 | 30 | application { 31 | mainClass.set("micronaut.client.Application") 32 | } 33 | 34 | tasks { 35 | dockerBuild { 36 | images = ['micronaut-kubernetes-example-client'] 37 | } 38 | 39 | dockerBuildNative { 40 | images = ['micronaut-kubernetes-example-client'] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/example-client/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true 2 | -------------------------------------------------------------------------------- /examples/example-client/src/main/java/micronaut/client/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.client; 17 | 18 | import io.micronaut.runtime.Micronaut; 19 | 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | Micronaut.run(Application.class); 24 | } 25 | } -------------------------------------------------------------------------------- /examples/example-client/src/main/java/micronaut/client/ExampleClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.client; 17 | 18 | import io.micronaut.http.MediaType; 19 | import io.micronaut.http.annotation.Get; 20 | import io.micronaut.http.annotation.Post; 21 | import io.micronaut.http.client.annotation.Client; 22 | 23 | import io.micronaut.core.annotation.Nullable; 24 | import java.util.Map; 25 | 26 | @Client("example-service") 27 | public interface ExampleClient { 28 | 29 | @Get(uri = "/hello/{name}", processes = MediaType.TEXT_PLAIN) 30 | String hello(String name); 31 | 32 | @Get(uri = "/hello/enemies", processes = MediaType.TEXT_PLAIN) 33 | String enemiesCheatLevel(); 34 | 35 | @Get(uri = "/hello/config/{key}", processes = MediaType.TEXT_PLAIN) 36 | String config(String key); 37 | 38 | @Post("/refresh") 39 | String refresh(); 40 | 41 | @Get("/env") 42 | String env(); 43 | } -------------------------------------------------------------------------------- /examples/example-client/src/main/java/micronaut/client/LegacyEnvEndpointFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.management.endpoint.env.EnvironmentEndpointFilter; 4 | import io.micronaut.management.endpoint.env.EnvironmentFilterSpecification; 5 | import jakarta.inject.Singleton; 6 | import jakarta.validation.constraints.NotNull; 7 | 8 | @Singleton 9 | public class LegacyEnvEndpointFilter implements EnvironmentEndpointFilter { 10 | @Override 11 | public void specifyFiltering(@NotNull EnvironmentFilterSpecification specification) { 12 | specification.legacyMasking(); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/example-client/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-client 6 | endpoints: 7 | env: 8 | sensitive: false 9 | enabled: true 10 | health: 11 | details-visible: ANONYMOUS -------------------------------------------------------------------------------- /examples/example-client/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/example-client/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: -1 -------------------------------------------------------------------------------- /examples/example-client/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client-tests]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-informer-java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.client.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.management) 22 | implementation(projects.micronautKubernetesClientOpenapiInformer) 23 | runtimeOnly(mnLogging.logback.classic) 24 | } 25 | 26 | application { 27 | mainClass.set("micronaut.client.Application") 28 | } 29 | 30 | tasks { 31 | dockerBuild { 32 | images = ['micronaut-kubernetes-client-openapi-informer-example'] 33 | } 34 | dockerBuildNative { 35 | images = ['micronaut-kubernetes-client-openapi-informer-example'] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-informer-java/src/main/java/micronaut/client/Application.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-informer-java/src/main/java/micronaut/client/secret/SecretResourceEventHandler.java: -------------------------------------------------------------------------------- 1 | package micronaut.client.secret; 2 | 3 | import io.micronaut.kubernetes.client.openapi.informer.handler.Informer; 4 | import io.micronaut.kubernetes.client.openapi.informer.handler.ResourceEventHandler; 5 | import io.micronaut.kubernetes.client.openapi.model.V1Secret; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | @Informer(apiType = V1Secret.class, namespace = SecretResourceEventHandler.NAMESPACE) // <1> 10 | class SecretResourceEventHandler implements ResourceEventHandler { // <2> 11 | 12 | private static final Logger LOG = LoggerFactory.getLogger(SecretResourceEventHandler.class); 13 | 14 | static final String NAMESPACE = "test-informer-namespace"; 15 | 16 | @Override 17 | public void onAdd(V1Secret obj) { 18 | LOG.info("{} secret added!", obj.getMetadata().getName()); 19 | } 20 | 21 | @Override 22 | public void onUpdate(V1Secret oldObj, V1Secret newObj) { 23 | LOG.info("{} secret updated!", oldObj.getMetadata().getName()); 24 | } 25 | 26 | @Override 27 | public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) { 28 | LOG.info("{} secret deleted!", obj.getMetadata().getName()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-informer-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-kubernetes-client-openapi-informer 6 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-informer-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.client.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.management) 22 | implementation(projects.micronautKubernetesClientOpenapi) 23 | compileOnly(mn.micronaut.http.client) 24 | runtimeOnly(mnLogging.logback.classic) 25 | } 26 | 27 | application { 28 | mainClass.set("micronaut.client.Application") 29 | } 30 | tasks { 31 | dockerBuild { 32 | images = ['micronaut-kubernetes-client-openapi-example'] 33 | } 34 | dockerBuildNative { 35 | images = ['micronaut-kubernetes-client-openapi-example'] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-java/src/main/java/micronaut/client/Application.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-java/src/main/java/micronaut/client/PodController.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.http.annotation.Controller; 4 | import io.micronaut.http.annotation.Get; 5 | import io.micronaut.kubernetes.client.openapi.api.CoreV1Api; 6 | import io.micronaut.kubernetes.client.openapi.model.V1Pod; 7 | import io.micronaut.kubernetes.client.openapi.model.V1PodList; 8 | import io.micronaut.scheduling.TaskExecutors; 9 | import io.micronaut.scheduling.annotation.ExecuteOn; 10 | import jakarta.inject.Inject; 11 | import jakarta.validation.constraints.NotNull; 12 | 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | @Controller("/pods") 17 | @ExecuteOn(TaskExecutors.BLOCKING) 18 | public class PodController { 19 | 20 | @Inject 21 | CoreV1Api coreV1Api; 22 | 23 | @Get("/{namespace}/{name}") 24 | public String getPod(final @NotNull String namespace, final @NotNull String name) { 25 | V1Pod v1Pod = coreV1Api.readNamespacedPod(name, namespace, null); 26 | return v1Pod.getStatus().getPhase(); 27 | } 28 | 29 | @Get("/{namespace}") 30 | public Map getPods(final @NotNull String namespace) { 31 | V1PodList v1PodList = coreV1Api.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null, null, null); 32 | return v1PodList.getItems().stream() 33 | .filter(p -> p.getStatus() != null) 34 | .collect(Collectors.toMap( 35 | p -> p.getMetadata().getName(), 36 | p -> p.getStatus().getPhase())); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-kubernetes-client-openapi 6 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.operator.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.management) 22 | implementation(projects.micronautKubernetesClientOpenapiOperator) 23 | runtimeOnly(mnLogging.logback.classic) 24 | runtimeOnly(mnMicrometer.micronaut.micrometer.core) 25 | } 26 | 27 | application { 28 | mainClass.set("micronaut.operator.Application") 29 | } 30 | 31 | tasks { 32 | dockerBuild { 33 | images = ['micronaut-kubernetes-client-openapi-operator-example'] 34 | } 35 | dockerBuildNative { 36 | images = ['micronaut-kubernetes-client-openapi-operator-example'] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/java/micronaut/operator/Application.java: -------------------------------------------------------------------------------- 1 | package micronaut.operator; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/java/micronaut/operator/OnAddFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.operator; 2 | 3 | import io.micronaut.kubernetes.client.openapi.model.V1ConfigMap; 4 | import jakarta.inject.Singleton; 5 | 6 | import java.util.function.Predicate; 7 | 8 | @Singleton 9 | public class OnAddFilter implements Predicate { 10 | @Override 11 | public boolean test(V1ConfigMap configMap) { 12 | return configMap.getMetadata().getAnnotations() != null 13 | && configMap.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/java/micronaut/operator/OnDeleteFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.operator; 2 | 3 | import io.micronaut.kubernetes.client.openapi.model.V1ConfigMap; 4 | import jakarta.inject.Singleton; 5 | 6 | import java.util.function.BiPredicate; 7 | 8 | @Singleton 9 | public class OnDeleteFilter implements BiPredicate { 10 | @Override 11 | public boolean test(V1ConfigMap configMap, Boolean deletedFinalStateUnknown) { 12 | return configMap.getMetadata().getAnnotations() != null 13 | && configMap.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/java/micronaut/operator/OnUpdateFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.operator; 2 | 3 | import io.micronaut.kubernetes.client.openapi.model.V1ConfigMap; 4 | import jakarta.inject.Singleton; 5 | 6 | import java.util.function.BiPredicate; 7 | 8 | @Singleton 9 | public class OnUpdateFilter implements BiPredicate { 10 | @Override 11 | public boolean test(V1ConfigMap oldConfigMap, V1ConfigMap newConfigMap) { 12 | return newConfigMap.getMetadata().getAnnotations() != null 13 | && newConfigMap.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-kubernetes-client-openapi-operator 6 | 7 | kubernetes: 8 | client: 9 | operator: 10 | leader-election: 11 | lock: 12 | resource-kind: lease 13 | resource-name: lease-lock 14 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-operator-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-reactor-java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.client.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.management) 22 | implementation(projects.micronautKubernetesClientOpenapiReactor) 23 | compileOnly(mn.micronaut.http.client) 24 | runtimeOnly(mnLogging.logback.classic) 25 | } 26 | 27 | application { 28 | mainClass.set("micronaut.client.Application") 29 | } 30 | 31 | tasks { 32 | dockerBuild { 33 | images = ['micronaut-kubernetes-client-openapi-reactor-example'] 34 | } 35 | dockerBuildNative { 36 | images = ['micronaut-kubernetes-client-openapi-reactor-example'] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-reactor-java/src/main/java/micronaut/client/Application.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-reactor-java/src/main/java/micronaut/client/PodController.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.http.annotation.Controller; 4 | import io.micronaut.http.annotation.Get; 5 | import io.micronaut.kubernetes.client.openapi.reactor.api.CoreV1ApiReactor; 6 | import jakarta.inject.Inject; 7 | import jakarta.validation.constraints.NotNull; 8 | import reactor.core.publisher.Mono; 9 | 10 | import java.util.Map; 11 | import java.util.stream.Collectors; 12 | 13 | @Controller("/pods") 14 | public class PodController { 15 | 16 | @Inject 17 | CoreV1ApiReactor coreV1ApiReactor; 18 | 19 | @Get("/{namespace}/{name}") 20 | public Mono getPod(final @NotNull String namespace, final @NotNull String name) { 21 | return coreV1ApiReactor.readNamespacedPod(name, namespace, null) 22 | .map(it -> it.getStatus().getPhase()); 23 | } 24 | 25 | @Get("/{namespace}") 26 | public Mono> getPods(final @NotNull String namespace) { 27 | return coreV1ApiReactor.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null, null, null) 28 | .map(it -> it.getItems().stream() 29 | .filter(p -> p.getStatus() != null) 30 | .collect(Collectors.toMap( 31 | p -> p.getMetadata().getName(), 32 | p -> p.getStatus().getPhase()))); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-reactor-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-kubernetes-client-openapi-reactor 6 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-reactor-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-watcher-java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.client.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mnSerde.micronaut.serde.jackson) 21 | implementation(mn.micronaut.management) 22 | implementation(projects.micronautKubernetesClientOpenapiWatcher) 23 | runtimeOnly(mnLogging.logback.classic) 24 | } 25 | 26 | application { 27 | mainClass.set("micronaut.client.Application") 28 | } 29 | 30 | tasks { 31 | dockerBuild { 32 | images = ['micronaut-kubernetes-client-openapi-watcher-example'] 33 | } 34 | dockerBuildNative { 35 | images = ['micronaut-kubernetes-client-openapi-watcher-example'] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-watcher-java/src/main/java/micronaut/client/Application.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-watcher-java/src/main/java/micronaut/client/SecretController.java: -------------------------------------------------------------------------------- 1 | package micronaut.client; 2 | 3 | import io.micronaut.http.annotation.Controller; 4 | import io.micronaut.http.annotation.Get; 5 | import io.micronaut.kubernetes.client.openapi.watcher.api.CoreV1ApiWatcher; 6 | import jakarta.inject.Inject; 7 | import jakarta.validation.constraints.NotNull; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | @Controller("/secrets") 12 | public class SecretController { 13 | private static final Logger LOG = LoggerFactory.getLogger(SecretController.class); 14 | 15 | @Inject 16 | CoreV1ApiWatcher coreV1ApiWatcher; 17 | 18 | @Get("/{namespace}") 19 | public void startWatchingSecrets(final @NotNull String namespace) { 20 | coreV1ApiWatcher.listNamespacedSecret(namespace, null, null, null, null, null, null, null, null, null, null, true) 21 | .subscribe(event -> LOG.info(event.toString())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-watcher-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: 8082 4 | application: 5 | name: micronaut-kubernetes-client-openapi-watcher 6 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client-openapi-watcher-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-client]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.service.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnValidation.micronaut.validation) 20 | implementation(mn.micronaut.http.client) 21 | implementation(mnSerde.micronaut.serde.jackson) 22 | implementation(mn.micronaut.management) 23 | implementation projects.micronautKubernetesClient 24 | 25 | runtimeOnly(mnLogging.logback.classic) 26 | } 27 | 28 | application { 29 | mainClass.set("micronaut.service.Application") 30 | } 31 | tasks { 32 | dockerBuild { 33 | images = ['micronaut-kubernetes-client-example'] 34 | } 35 | 36 | dockerBuildNative { 37 | images = ['micronaut-kubernetes-client-example'] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true 2 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | profile: service 2 | defaultPackage: micronaut.service 3 | --- 4 | testFramework: junit 5 | sourceLanguage: java -------------------------------------------------------------------------------- /examples/example-kubernetes-client/src/main/java/micronaut/service/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.service; 17 | 18 | import io.micronaut.runtime.Micronaut; 19 | 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | Micronaut.run(Application.class); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client/src/main/java/micronaut/service/LegacyEnvEndpointFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.service; 2 | 3 | import io.micronaut.management.endpoint.env.EnvironmentEndpointFilter; 4 | import io.micronaut.management.endpoint.env.EnvironmentFilterSpecification; 5 | import jakarta.inject.Singleton; 6 | import jakarta.validation.constraints.NotNull; 7 | 8 | @Singleton 9 | public class LegacyEnvEndpointFilter implements EnvironmentEndpointFilter { 10 | @Override 11 | public void specifyFiltering(@NotNull EnvironmentFilterSpecification specification) { 12 | specification.legacyMasking(); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/example-kubernetes-client/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-service 4 | server: 5 | port: 8085 6 | endpoints: 7 | env: 8 | sensitive: false 9 | enabled: true 10 | refresh: 11 | sensitive: false 12 | health: 13 | details-visible: ANONYMOUS -------------------------------------------------------------------------------- /examples/example-kubernetes-client/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-kubernetes-client 4 | kubernetes: 5 | client: 6 | verifySsl: true 7 | -------------------------------------------------------------------------------- /examples/example-kubernetes-client/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("spock2") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.informer.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | implementation(mnValidation.micronaut.validation) 19 | implementation(mn.micronaut.jackson.databind) 20 | compileOnly mn.micronaut.inject.java 21 | implementation(mn.micronaut.http.client) 22 | implementation(mn.micronaut.management) 23 | implementation projects.micronautKubernetesInformer 24 | runtimeOnly(mnLogging.logback.classic) 25 | testImplementation projects.testUtils 26 | } 27 | 28 | application { 29 | mainClass.set("micronaut.informer.Application") 30 | } 31 | 32 | tasks { 33 | dockerBuild { 34 | images = ['micronaut-kubernetes-informer-example'] 35 | } 36 | 37 | dockerBuildNative { 38 | images = ['micronaut-kubernetes-informer-example'] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/main/java/micronaut/informer/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.informer; 17 | 18 | import io.micronaut.runtime.Micronaut; 19 | 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | Micronaut.run(Application.class); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/main/java/micronaut/informer/LegacyEnvEndpointFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.informer; 2 | 3 | import io.micronaut.management.endpoint.env.EnvironmentEndpointFilter; 4 | import io.micronaut.management.endpoint.env.EnvironmentFilterSpecification; 5 | import jakarta.inject.Singleton; 6 | import jakarta.validation.constraints.NotNull; 7 | 8 | @Singleton 9 | public class LegacyEnvEndpointFilter implements EnvironmentEndpointFilter { 10 | @Override 11 | public void specifyFiltering(@NotNull EnvironmentFilterSpecification specification) { 12 | specification.legacyMasking(); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/main/java/micronaut/informer/SecretInformerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.informer; 17 | 18 | import io.kubernetes.client.openapi.models.V1Secret; 19 | import io.micronaut.http.annotation.Controller; 20 | import io.micronaut.http.annotation.Get; 21 | 22 | import java.util.Collection; 23 | 24 | @Controller 25 | public class SecretInformerController { 26 | 27 | private final SecretResourceEventHandler secretResourceEventHandler; 28 | 29 | public SecretInformerController(SecretResourceEventHandler secretResourceEventHandler) { 30 | this.secretResourceEventHandler = secretResourceEventHandler; 31 | } 32 | 33 | @Get("/all") 34 | public Collection all() { 35 | return secretResourceEventHandler.getV1SecretMap().values(); 36 | } 37 | 38 | @Get("/secret/{key}") 39 | public V1Secret secret(String key) { 40 | return secretResourceEventHandler.getV1SecretMap().get(key); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-informer 4 | server: 5 | thread-selection: io 6 | executors: 7 | io: 8 | n-threads: 75 9 | type: fixed 10 | endpoints: 11 | env: 12 | sensitive: false 13 | enabled: true 14 | refresh: 15 | sensitive: false 16 | health: 17 | details-visible: ANONYMOUS -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: -1 -------------------------------------------------------------------------------- /examples/example-kubernetes-informer/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service-tests]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id 'groovy' 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("spock2") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.operator.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | annotationProcessor(mnSerde.micronaut.serde.processor) 19 | implementation(mnSerde.micronaut.serde.jackson) 20 | implementation(mnValidation.micronaut.validation) 21 | implementation(mn.micronaut.http.client) 22 | implementation(mn.micronaut.management) 23 | implementation projects.micronautKubernetesOperator 24 | 25 | runtimeOnly(mnLogging.logback.classic) 26 | 27 | testImplementation projects.testUtils 28 | } 29 | 30 | application { 31 | mainClass.set("micronaut.operator.Application") 32 | } 33 | 34 | tasks { 35 | dockerBuild { 36 | images = ['micronaut-kubernetes-operator-example'] 37 | } 38 | 39 | dockerBuildNative { 40 | images = ['micronaut-kubernetes-operator-example'] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/main/java/micronaut/operator/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.operator; 17 | 18 | import io.micronaut.runtime.Micronaut; 19 | 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | Micronaut.run(Application.class); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/main/java/micronaut/operator/CustomLockIdentityProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.operator; 17 | //tag::lockprovider[] 18 | import io.micronaut.context.annotation.Replaces; 19 | import io.micronaut.kubernetes.client.operator.leaderelection.LockIdentityProvider; 20 | import jakarta.inject.Singleton; 21 | //end::lockprovider[] 22 | 23 | import java.util.Random; 24 | 25 | //tag::lockprovider[] 26 | 27 | @Singleton 28 | @Replaces(LockIdentityProvider.class) 29 | public class CustomLockIdentityProvider implements LockIdentityProvider { 30 | 31 | @Override 32 | public String getIdentity() { 33 | // ... 34 | //end::lockprovider[] 35 | return String.valueOf(new Random().nextInt()); 36 | //tag::lockprovider[] 37 | } 38 | } 39 | //end::lockprovider[] 40 | -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/main/java/micronaut/operator/LegacyEnvEndpointFilter.java: -------------------------------------------------------------------------------- 1 | package micronaut.operator; 2 | 3 | import io.micronaut.management.endpoint.env.EnvironmentEndpointFilter; 4 | import io.micronaut.management.endpoint.env.EnvironmentFilterSpecification; 5 | import jakarta.inject.Singleton; 6 | import jakarta.validation.constraints.NotNull; 7 | 8 | @Singleton 9 | public class LegacyEnvEndpointFilter implements EnvironmentEndpointFilter { 10 | @Override 11 | public void specifyFiltering(@NotNull EnvironmentFilterSpecification specification) { 12 | specification.legacyMasking(); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-operator 4 | server: 5 | thread-selection: io 6 | executors: 7 | io: 8 | n-threads: 75 9 | type: fixed 10 | endpoints: 11 | env: 12 | sensitive: false 13 | enabled: true 14 | refresh: 15 | sensitive: false 16 | health: 17 | details-visible: ANONYMOUS -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: -1 -------------------------------------------------------------------------------- /examples/example-kubernetes-operator/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service-tests]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/example-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-examples' 3 | id("groovy") 4 | } 5 | 6 | micronaut { 7 | version libs.versions.micronaut.platform.get() 8 | runtime("netty") 9 | testRuntime("junit5") 10 | processing { 11 | incremental(true) 12 | annotations("micronaut.service.*") 13 | } 14 | } 15 | 16 | dependencies { 17 | annotationProcessor(mnValidation.micronaut.validation.processor) 18 | implementation(mnValidation.micronaut.validation) 19 | implementation(mn.micronaut.http.client) 20 | implementation(mn.micronaut.jackson.databind) 21 | implementation(mn.micronaut.management) 22 | implementation projects.micronautKubernetesDiscoveryClient 23 | 24 | runtimeOnly(mnLogging.logback.classic) 25 | } 26 | 27 | application { 28 | mainClass.set("micronaut.service.Application") 29 | } 30 | 31 | tasks { 32 | dockerBuild { 33 | images = ['micronaut-kubernetes-example-service'] 34 | } 35 | 36 | dockerBuildNative { 37 | images = ['micronaut-kubernetes-example-service'] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/example-service/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true -------------------------------------------------------------------------------- /examples/example-service/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | profile: service 2 | defaultPackage: micronaut.service 3 | --- 4 | testFramework: junit 5 | sourceLanguage: java -------------------------------------------------------------------------------- /examples/example-service/src/main/java/micronaut/service/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2020 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package micronaut.service; 17 | 18 | import io.micronaut.runtime.Micronaut; 19 | 20 | public class Application { 21 | 22 | public static void main(String[] args) { 23 | Micronaut.run(Application.class); 24 | } 25 | } -------------------------------------------------------------------------------- /examples/example-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-service 4 | server: 5 | port: 8081 6 | thread-selection: io 7 | executors: 8 | io: 9 | n-threads: 75 10 | type: fixed 11 | config-client: 12 | enabled: true 13 | endpoints: 14 | env: 15 | sensitive: false 16 | enabled: true 17 | refresh: 18 | sensitive: false 19 | health: 20 | details-visible: ANONYMOUS -------------------------------------------------------------------------------- /examples/example-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-service 4 | 5 | config-client: 6 | enabled: true 7 | 8 | kubernetes: 9 | client: 10 | secrets: 11 | enabled: true 12 | use-api: true 13 | excludes: mounted-secret 14 | paths: 15 | - /etc/example-service/secrets 16 | config-maps: 17 | use-api: true 18 | excludes: mounted-configmap 19 | paths: 20 | - /etc/example-service/configmap 21 | -------------------------------------------------------------------------------- /examples/example-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/example-service/src/test/java/micronaut/service/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | package micronaut.service; 2 | 3 | import io.micronaut.context.env.Environment; 4 | import io.micronaut.http.HttpRequest; 5 | import io.micronaut.http.MediaType; 6 | import io.micronaut.http.client.HttpClient; 7 | import io.micronaut.runtime.server.EmbeddedServer; 8 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import jakarta.inject.Inject; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertTrue; 14 | 15 | @MicronautTest(environments = Environment.KUBERNETES) 16 | class HelloControllerTest { 17 | 18 | @Inject 19 | EmbeddedServer embeddedServer; 20 | 21 | @Test 22 | void testIndex() throws Exception { 23 | try(HttpClient client = embeddedServer.getApplicationContext().createBean(HttpClient.class, embeddedServer.getURL())) { 24 | HttpRequest request = HttpRequest.GET("/hello/Alvaro").accept(MediaType.TEXT_PLAIN); 25 | assertTrue(client.toBlocking().exchange(request, String.class).body().startsWith("Hello, Alvaro")); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/example-service/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | server: 3 | port: -1 -------------------------------------------------------------------------------- /examples/example-service/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([example-service-tests]) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | projectVersion=7.1.0-SNAPSHOT 2 | 3 | projectGroup=io.micronaut.kubernetes 4 | 5 | title=Micronaut Kubernetes 6 | projectDesc=Integration between Micronaut and Kubernetes 7 | projectUrl=https://micronaut.io 8 | githubSlug=micronaut-projects/micronaut-kubernetes 9 | developers=Alvaro Sanchez-Mariscal, Pavol Gressa 10 | 11 | org.gradle.caching=true 12 | org.gradle.jvmargs=-Xmx2g 13 | 14 | systemProp.maxYamlCodePoints=10485760 15 | -------------------------------------------------------------------------------- /gradle/license.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.hierynomus.license' 2 | 3 | license { 4 | header = rootProject.file('config/HEADER') 5 | strictCheck = true 6 | ignoreFailures = true 7 | mapping { 8 | kt = 'SLASHSTAR_STYLE' 9 | java = 'SLASHSTAR_STYLE' 10 | groovy = 'SLASHSTAR_STYLE' 11 | } 12 | ext.year = '2017-2020' 13 | 14 | exclude "**/transaction/**" 15 | exclude '**/*.txt' 16 | exclude '**/*.html' 17 | exclude '**/*.xml' 18 | exclude '**/*.json' 19 | exclude '**/build-info.properties' 20 | exclude '**/git.properties' 21 | exclude '**/othergit.properties' 22 | } 23 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micronaut-projects/micronaut-kubernetes/d51d18f0acddb84f22ddccb8cfdc336a672dc848/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /k8s-auth.yml: -------------------------------------------------------------------------------- 1 | kind: Role 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: service-discoverer 5 | namespace: micronaut-kubernetes 6 | rules: 7 | - apiGroups: [""] 8 | resources: ["services", "endpoints", "configmaps", "secrets", "pods"] 9 | verbs: ["get", "watch", "list"] 10 | --- 11 | kind: RoleBinding 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | metadata: 14 | name: default-service-discoverer 15 | namespace: micronaut-kubernetes 16 | subjects: 17 | - kind: ServiceAccount 18 | name: default 19 | namespace: micronaut-kubernetes 20 | roleRef: 21 | kind: Role 22 | name: service-discoverer 23 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /kubernetes-bom/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.bom' 3 | } 4 | 5 | micronautBom { 6 | } 7 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/build.gradle: -------------------------------------------------------------------------------- 1 | import io.micronaut.kubernetes.client.openapi.tasks.DownloadSpec 2 | 3 | plugins { 4 | id 'io.micronaut.build.internal.kubernetes-module' 5 | id 'io.micronaut.openapi' version libs.versions.micronaut.gradle.plugin 6 | id 'io.micronaut.kubernetes.client.openapi' 7 | } 8 | 9 | kubernetesClientOpenApi { 10 | specVersion = libs.versions.io.kubernetes.client.java.get() 11 | } 12 | 13 | micronaut { 14 | openapi { 15 | version = libs.versions.micronaut.openapi.get() 16 | client("client", tasks.named("downloadOpenApiSpec", DownloadSpec).flatMap(DownloadSpec::getSpecFile)) { 17 | modelPackageName = "io.micronaut.kubernetes.client.openapi.model" 18 | dateTimeFormat = "OFFSET_DATETIME" 19 | additionalProperties.put("dateTimeFormat", "yyyy-MM-dd'T'HH:mm:ss[.SSSSSS]'Z'") 20 | } 21 | } 22 | } 23 | 24 | generateClientOpenApiApis.enabled = false 25 | 26 | tasks.withType(me.champeau.gradle.japicmp.JapicmpTask) { 27 | packageExcludes = ["io.micronaut.kubernetes.client.openapi.model"] 28 | } 29 | 30 | dependencies { 31 | annotationProcessor(mnValidation.micronaut.validation.processor) 32 | annotationProcessor(mnSerde.micronaut.serde.processor) 33 | annotationProcessor(mn.micronaut.inject.java) 34 | implementation(mnValidation.micronaut.validation) 35 | implementation(mnSerde.micronaut.serde.jackson) 36 | implementation(mn.micronaut.http.client) 37 | implementation(mn.snakeyaml) 38 | compileOnly(platform(mnOpenapi.micronaut.openapi.bom)) 39 | } 40 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/common/KubernetesObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.common; 17 | 18 | import io.micronaut.core.annotation.Internal; 19 | import io.micronaut.kubernetes.client.openapi.model.V1ObjectMeta; 20 | 21 | /** 22 | * Common accessors for kubernetes object. 23 | * 24 | *

25 | * The code has been copied from the official client and modified: 26 | * KubernetesObject 27 | *

28 | */ 29 | @Internal 30 | public interface KubernetesObject extends KubernetesType { 31 | 32 | /** 33 | * Gets metadata. 34 | * 35 | *

ObjectMeta is metadata that all persisted resources must have, which includes all objects 36 | * users must create. 37 | * 38 | * @return the metadata 39 | */ 40 | V1ObjectMeta getMetadata(); 41 | } 42 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/config/KubeConfigLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.config; 17 | 18 | import io.micronaut.core.annotation.Nullable; 19 | 20 | /** 21 | * The loader for kube config file. 22 | */ 23 | public interface KubeConfigLoader { 24 | 25 | /** 26 | * Returns {@link KubeConfig} instance which contains data from the kube config file. The method is 27 | * called multiple times during the application context startup so the {@link KubeConfig} instance 28 | * should be created when the method is called for the first time, cached and then returned by subsequent calls. 29 | * Since it is called only in the context startup, it doesn't require thread synchronization. 30 | * 31 | * @return kube config 32 | */ 33 | @Nullable KubeConfig getKubeConfig(); 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/config/model/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.config.model; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.core.annotation.Nullable; 20 | 21 | /** 22 | * Context is a tuple of references to a cluster, a user and a namespace. 23 | * 24 | * @param cluster the name of the cluster for this context 25 | * @param user the name of the authInfo for this context 26 | * @param namespace the default namespace to use on unspecified requests 27 | */ 28 | public record Context( 29 | @NonNull String cluster, 30 | @NonNull String user, 31 | @Nullable String namespace 32 | ) { 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/config/model/ExecConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.config.model; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.core.annotation.Nullable; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * ExecConfig specifies a command to provide client credentials. 25 | * 26 | * @param apiVersion the preferred input version of the ExecInfo 27 | * @param command the command to execute 28 | * @param args the arguments to pass to the command when executing it 29 | * @param env the additional environment variables to expose to the process 30 | */ 31 | public record ExecConfig( 32 | @NonNull String apiVersion, 33 | @NonNull String command, 34 | @Nullable List args, 35 | @Nullable List env 36 | ) { 37 | } 38 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/config/model/ExecEnvVar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.config.model; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | 20 | /** 21 | * Environment variable used when executing an exec-based credential plugin. 22 | * 23 | * @param name the name of environment variable 24 | * @param value the value of environment variable 25 | */ 26 | public record ExecEnvVar( 27 | @NonNull String name, 28 | @NonNull String value 29 | ) { 30 | } 31 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/credential/KubernetesTokenLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.credential; 17 | 18 | import io.micronaut.core.annotation.Nullable; 19 | 20 | /** 21 | * The loader for bearer token used in kubernetes api service authentication. 22 | */ 23 | public interface KubernetesTokenLoader extends TokenLoader { 24 | 25 | /** 26 | * Gets a bearer token for request authentication. 27 | * 28 | * @return bearer token 29 | */ 30 | @Nullable String getToken(); 31 | } 32 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/credential/ReactiveKubernetesTokenLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.credential; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.core.async.annotation.SingleResult; 20 | import org.reactivestreams.Publisher; 21 | 22 | /** 23 | * The loader for bearer token used in kubernetes api service authentication. 24 | */ 25 | public interface ReactiveKubernetesTokenLoader extends TokenLoader { 26 | 27 | /** 28 | * Gets a bearer token for request authentication. 29 | * 30 | * @return bearer token 31 | */ 32 | @SingleResult 33 | @NonNull Publisher getToken(); 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/credential/TokenLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.credential; 17 | 18 | import io.micronaut.core.annotation.Internal; 19 | import io.micronaut.core.order.Ordered; 20 | 21 | /** 22 | * Interface for blocking and reactive kubernetes token loaders. 23 | */ 24 | @Internal 25 | public interface TokenLoader extends Ordered { 26 | } 27 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/credential/model/ExecCredential.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.credential.model; 17 | 18 | import io.micronaut.core.annotation.Nullable; 19 | import io.micronaut.serde.annotation.Serdeable; 20 | 21 | /** 22 | * ExecCredential is used by exec-based plugins to communicate credentials to HTTP transports. 23 | * 24 | * @param apiVersion the api version 25 | * @param kind the kind of exec credential 26 | * @param status the holder for credentials that should be used to contact the API 27 | */ 28 | @Serdeable.Deserializable 29 | public record ExecCredential( 30 | @Nullable String apiVersion, 31 | @Nullable String kind, 32 | @Nullable ExecCredentialStatus status 33 | ) { 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/resolver/DefaultPodNameResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.resolver; 17 | 18 | import io.micronaut.context.annotation.BootstrapContextCompatible; 19 | import io.micronaut.context.annotation.Requires; 20 | import io.micronaut.kubernetes.client.openapi.config.KubernetesClientConfiguration; 21 | import jakarta.inject.Singleton; 22 | 23 | import java.util.Optional; 24 | 25 | /** 26 | * The default implementation of {@link PodNameResolver}. 27 | */ 28 | @Singleton 29 | @BootstrapContextCompatible 30 | @Requires(beans = KubernetesClientConfiguration.class) 31 | final class DefaultPodNameResolver implements PodNameResolver { 32 | 33 | private static final String HOSTNAME_ENV_VARIABLE = "HOSTNAME"; 34 | 35 | @Override 36 | public Optional getPodName() { 37 | return Optional.ofNullable(System.getenv(HOSTNAME_ENV_VARIABLE)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/resolver/NamespaceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.resolver; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | 20 | /** 21 | * Resolves the Kubernetes namespace for the Micronaut application. 22 | */ 23 | @DefaultImplementation(DefaultNamespaceResolver.class) 24 | public interface NamespaceResolver { 25 | 26 | /** 27 | * Resolves namespace. 28 | * 29 | * @return namespace 30 | */ 31 | String resolveNamespace(); 32 | } 33 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/main/java/io/micronaut/kubernetes/client/openapi/resolver/PodNameResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.resolver; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | 20 | import java.util.Optional; 21 | 22 | /** 23 | * Resolves the Pod name. 24 | */ 25 | @DefaultImplementation(DefaultPodNameResolver.class) 26 | public interface PodNameResolver { 27 | 28 | /** 29 | * Resolves the name of the POD this application is running in. 30 | * 31 | * @return pod name 32 | */ 33 | Optional getPodName(); 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/test/resources/key/pkcs1.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDz2XhYxigM1TVl6+O+nl4lM+uTNs4T8h2n2bUc7GVgjSN3Xj6L 3 | 6cuId+w6o9jKEC90Zgbe2UkWAkxSG3bGzhlTHM6Qh4zi8o9ybg+Yt/fYzR6KhsIt 4 | 2y1D/yiyMC4FCc3oARXh7djhk3qZuS4sbeX/DsqE61Sr9NzWR6RvqgimDwIDAQAB 5 | AoGBAKnZs6MaO3Fc3TnmChePVgJR3OgIx5hLD+8HjMjdvGt5Q9f0dFqeed/PsGLU 6 | F7//cB6Cpox5Cxhid2jFqoEls6q9jnnVGYGDJHDQ7u//xigVfHf9lJzmdxQWId6G 7 | F6VoU0N6Oh2AtG4L/SQqnbacG1JVXZun/8J8bBon6C4PeacZAkEA/YaNeLcLtv22 8 | 992UJaj3Rd9i5Sxs6dH6PDoABvkbipqWtj4osiMt6a5h32Xy/811CYDI1wvcVDDr 9 | 9HAQP1pfPQJBAPY6vcA+JuKdg9KSZzCh77aE5LGXqz62rcMlUHPtRchNfcFo06MC 10 | ehKA+YIBmT5we0GrdyAXsYGIVypK0l8irzsCQEkr43r6wavP8FX7or131d5Zye5A 11 | 8zJNAz8MsmNQ1G0djvAMYqx/UMoIJYFXqFnCD8xtWgoPB0lZUVCcY2QVjjUCQGYk 12 | A+alYZgL400MckXYRwodooiQ8/Z17SrQZclRGet3Sb1bcL9kHaNjYR0u8JTYMCkT 13 | qbzkVzv2hMIEe7P/PVUCQQCxLiT5qDxQawP1/ZFnp4KCHTKTQ1Mvw8cGajEG+DKP 14 | 2GzD8K03HaJU5eN4Z1Uo1TYPQY1tRD3nM+sDH9EcLvqP 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/test/resources/key/pkcs8-ec.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgA+GiZiz2t2c2AS2v 3 | YUgHWsENie4qpXhBUBgFfjJGoAShRANCAARQcGDs68qRKmsCWNBwJylcWez+kw0O 4 | RAlm6iiP3sDTTreKkGtnNt3FNy5VwGMU0kL9OfaR41JA/6b1BtCZB+Yz 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/test/resources/key/pkcs8-rsa.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPPZeFjGKAzVNWXr 3 | 476eXiUz65M2zhPyHafZtRzsZWCNI3dePovpy4h37Dqj2MoQL3RmBt7ZSRYCTFIb 4 | dsbOGVMczpCHjOLyj3JuD5i399jNHoqGwi3bLUP/KLIwLgUJzegBFeHt2OGTepm5 5 | Lixt5f8OyoTrVKv03NZHpG+qCKYPAgMBAAECgYEAqdmzoxo7cVzdOeYKF49WAlHc 6 | 6AjHmEsP7weMyN28a3lD1/R0Wp5538+wYtQXv/9wHoKmjHkLGGJ3aMWqgSWzqr2O 7 | edUZgYMkcNDu7//GKBV8d/2UnOZ3FBYh3oYXpWhTQ3o6HYC0bgv9JCqdtpwbUlVd 8 | m6f/wnxsGifoLg95pxkCQQD9ho14twu2/bb33ZQlqPdF32LlLGzp0fo8OgAG+RuK 9 | mpa2PiiyIy3prmHfZfL/zXUJgMjXC9xUMOv0cBA/Wl89AkEA9jq9wD4m4p2D0pJn 10 | MKHvtoTksZerPratwyVQc+1FyE19wWjTowJ6EoD5ggGZPnB7Qat3IBexgYhXKkrS 11 | XyKvOwJASSvjevrBq8/wVfuivXfV3lnJ7kDzMk0DPwyyY1DUbR2O8AxirH9Qyggl 12 | gVeoWcIPzG1aCg8HSVlRUJxjZBWONQJAZiQD5qVhmAvjTQxyRdhHCh2iiJDz9nXt 13 | KtBlyVEZ63dJvVtwv2Qdo2NhHS7wlNgwKROpvORXO/aEwgR7s/89VQJBALEuJPmo 14 | PFBrA/X9kWengoIdMpNDUy/DxwZqMQb4Mo/YbMPwrTcdolTl43hnVSjVNg9BjW1E 15 | Pecz6wMf0Rwu+o8= 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-common/src/test/resources/key/sec1.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIAPhomYs9rdnNgEtr2FIB1rBDYnuKqV4QVAYBX4yRqAEoAoGCCqGSM49 3 | AwEHoUQDQgAEUHBg7OvKkSprAljQcCcpXFns/pMNDkQJZuooj97A0063ipBrZzbd 4 | xTcuVcBjFNJC/Tn2keNSQP+m9QbQmQfmMw== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | api(projects.micronautKubernetesClientOpenapiInformer) 7 | api(libs.micronaut.discovery.client) 8 | compileOnly(mn.micronaut.management) 9 | 10 | testImplementation(libs.testcontainers.k3s) 11 | } 12 | 13 | project.tasks.withType(Test).configureEach { 14 | environment.put("KUBERNETES_SERVICE_HOST", "localhost") 15 | environment.put("HOSTNAME", "test-pod") 16 | } 17 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/main/java/io/micronaut/kubernetes/client/openapi/configuration/KubernetesConfigMapLabelSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.configuration; 17 | 18 | import io.micronaut.context.annotation.Requires; 19 | import io.micronaut.context.env.Environment; 20 | import io.micronaut.kubernetes.client.openapi.KubernetesConfiguration; 21 | import io.micronaut.kubernetes.client.openapi.reactor.api.CoreV1ApiReactor; 22 | import jakarta.inject.Singleton; 23 | 24 | /** 25 | * Based on configuration dynamically evaluates the label selector for config maps. 26 | */ 27 | @Singleton 28 | @Requires(env = Environment.KUBERNETES) 29 | final class KubernetesConfigMapLabelSupplier extends AbstractKubernetesConfigLabelSupplier { 30 | 31 | KubernetesConfigMapLabelSupplier(CoreV1ApiReactor coreV1ApiReactor, KubernetesConfiguration configuration) { 32 | super(coreV1ApiReactor, configuration, configuration.getConfigMaps()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/main/java/io/micronaut/kubernetes/client/openapi/configuration/KubernetesConfigMapWatcherCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.configuration; 17 | 18 | import io.micronaut.context.condition.ConditionContext; 19 | import io.micronaut.kubernetes.client.openapi.KubernetesConfiguration; 20 | 21 | /** 22 | * Condition evaluates when the {@link KubernetesConfigMapWatcherCondition} is enabled. 23 | * 24 | * @author Pavol Gressa 25 | */ 26 | final class KubernetesConfigMapWatcherCondition extends AbstractKubernetesConfigWatcherCondition { 27 | 28 | @Override 29 | KubernetesConfiguration.AbstractConfigConfiguration getConfig(ConditionContext context) { 30 | return context.getBean(KubernetesConfiguration.KubernetesConfigMapsConfiguration.class); 31 | } 32 | 33 | @Override 34 | String getPropertyPrefix() { 35 | return KubernetesConfiguration.KubernetesConfigMapsConfiguration.PREFIX; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/main/java/io/micronaut/kubernetes/client/openapi/configuration/KubernetesSecretLabelSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.configuration; 17 | 18 | import io.micronaut.context.annotation.Requires; 19 | import io.micronaut.context.env.Environment; 20 | import io.micronaut.kubernetes.client.openapi.KubernetesConfiguration; 21 | import io.micronaut.kubernetes.client.openapi.reactor.api.CoreV1ApiReactor; 22 | import jakarta.inject.Singleton; 23 | 24 | /** 25 | * Based on configuration dynamically evaluates the label selector for secrets. 26 | */ 27 | @Singleton 28 | @Requires(env = Environment.KUBERNETES) 29 | final class KubernetesSecretLabelSupplier extends AbstractKubernetesConfigLabelSupplier { 30 | 31 | KubernetesSecretLabelSupplier(CoreV1ApiReactor coreV1ApiReactor, KubernetesConfiguration configuration) { 32 | super(coreV1ApiReactor, configuration, configuration.getSecrets()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/main/java/io/micronaut/kubernetes/client/openapi/configuration/KubernetesSecretWatcherCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.configuration; 17 | 18 | import io.micronaut.context.condition.ConditionContext; 19 | import io.micronaut.kubernetes.client.openapi.KubernetesConfiguration; 20 | 21 | /** 22 | * Condition evaluates when the {@link KubernetesSecretWatcherCondition} is enabled. 23 | * 24 | * @author Pavol Gressa 25 | */ 26 | final class KubernetesSecretWatcherCondition extends AbstractKubernetesConfigWatcherCondition { 27 | 28 | @Override 29 | KubernetesConfiguration.AbstractConfigConfiguration getConfig(ConditionContext context) { 30 | return context.getBean(KubernetesConfiguration.KubernetesSecretsConfiguration.class); 31 | } 32 | 33 | @Override 34 | String getPropertyPrefix() { 35 | return KubernetesConfiguration.KubernetesSecretsConfiguration.PREFIX; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/test/resources/kubernetes/config-maps/mounted.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo2": "bar2" 3 | } 4 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/test/resources/kubernetes/config-maps/mounted.yml: -------------------------------------------------------------------------------- 1 | mounted: 2 | foo1: bar1 3 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/test/resources/kubernetes/secrets/foo: -------------------------------------------------------------------------------- 1 | bar -------------------------------------------------------------------------------- /kubernetes-client-openapi-discovery/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-informer/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | api(projects.micronautKubernetesClientOpenapiReactor) 7 | api(projects.micronautKubernetesClientOpenapiWatcher) 8 | implementation(mn.micronaut.http.client) 9 | 10 | testImplementation(libs.testcontainers.k3s) 11 | } 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-informer/src/main/java/io/micronaut/kubernetes/client/openapi/informer/handler/EmptyLabelSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.informer.handler; 17 | 18 | import io.micronaut.core.util.StringUtils; 19 | 20 | import java.util.function.Supplier; 21 | 22 | /** 23 | * Default label supplier for the {@link Informer#labelSelectorSupplier()} that returns empty string. 24 | */ 25 | final class EmptyLabelSupplier implements Supplier { 26 | @Override 27 | public String get() { 28 | return StringUtils.EMPTY_STRING; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-informer/src/main/java/io/micronaut/kubernetes/client/openapi/informer/handler/EmptyNamespacesSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.informer.handler; 17 | 18 | import io.micronaut.core.util.StringUtils; 19 | 20 | import java.util.function.Supplier; 21 | 22 | /** 23 | * Default namespaces supplier for the {@link Informer#namespacesSupplier()} that returns empty array. 24 | */ 25 | final class EmptyNamespacesSupplier implements Supplier { 26 | @Override 27 | public String[] get() { 28 | return StringUtils.EMPTY_STRING_ARRAY; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-informer/src/main/java/io/micronaut/kubernetes/client/openapi/informer/handler/InformerNamespaceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.informer.handler; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | import io.micronaut.core.annotation.AnnotationValue; 20 | import io.micronaut.core.annotation.Internal; 21 | import io.micronaut.core.annotation.NonNull; 22 | 23 | import java.util.Set; 24 | 25 | /** 26 | * Informer namespace resolver. 27 | */ 28 | @Internal 29 | @DefaultImplementation(DefaultInformerNamespaceResolver.class) 30 | public interface InformerNamespaceResolver { 31 | 32 | /** 33 | * Resolves the namespaces for the informer's watched resources. 34 | * 35 | * @param annotationValue the informer annotation value 36 | * @return set of namespaces 37 | */ 38 | @NonNull 39 | Set resolveInformerNamespaces(@NonNull AnnotationValue annotationValue); 40 | } 41 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-informer/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | micronautBuild { 6 | binaryCompatibility { 7 | enabledAfter('7.1.0') 8 | } 9 | } 10 | 11 | dependencies { 12 | annotationProcessor(mnSerde.micronaut.serde.processor) 13 | 14 | api(projects.micronautKubernetesClientOpenapi) 15 | api(projects.micronautKubernetesClientOpenapiInformer) 16 | implementation(mnSerde.micronaut.serde.jackson) 17 | implementation(mn.micronaut.http.client.core) 18 | implementation(libs.bucket4j) 19 | 20 | compileOnly(mn.micronaut.management) 21 | compileOnly(mnMicrometer.micronaut.micrometer.core) 22 | 23 | testImplementation(libs.testcontainers.k3s) 24 | testImplementation(mnMicrometer.micronaut.micrometer.core) 25 | } 26 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/controller/Controller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.controller; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | 20 | /** 21 | * The interface for operating a controller. 22 | * 23 | *

24 | * The code has been copied from the official client and modified: 25 | * Controller 26 | *

27 | */ 28 | public interface Controller extends Runnable { 29 | 30 | /** 31 | * Get controller name. 32 | * 33 | * @return controller name 34 | */ 35 | @NonNull String getName(); 36 | 37 | /** 38 | * Shutdown the controller. 39 | */ 40 | void shutdown(); 41 | } 42 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/controller/reconciler/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.controller.reconciler; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.core.annotation.Nullable; 20 | 21 | /** 22 | * Contains information necessary to uniquely identify the resource object. 23 | * 24 | * @param name the name of the resource object. 25 | * @param namespace the namespace 26 | */ 27 | public record Request( 28 | @NonNull String name, 29 | @Nullable String namespace 30 | ) { 31 | } 32 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/controller/reconciler/Result.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.controller.reconciler; 17 | 18 | import io.micronaut.core.annotation.Nullable; 19 | 20 | import java.time.Duration; 21 | 22 | /** 23 | * Contains the result of a reconciler invocation. 24 | * 25 | * @param requeue the info which determines whether the processing request should be returned to the queue 26 | * @param requeueAfter the info which determines when the processing request should be returned to the queue 27 | */ 28 | public record Result( 29 | boolean requeue, 30 | @Nullable Duration requeueAfter 31 | ) { 32 | public Result(boolean requeue) { 33 | this(requeue, null); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/leaderelection/LockIdentityProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.leaderelection; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | import io.micronaut.core.annotation.NonNull; 20 | 21 | /** 22 | * Provides the lock identity which is used to uniquely identifies the application for the leader 23 | * election process. Every replica of the application needs to have unique identity. 24 | */ 25 | @DefaultImplementation(DefaultLockIdentityProvider.class) 26 | public interface LockIdentityProvider { 27 | 28 | /** 29 | * Get the lock identity. 30 | * 31 | * @return the lock identity. 32 | */ 33 | @NonNull String getIdentity(); 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/leaderelection/event/LeaderChangedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.leaderelection.event; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.kubernetes.client.openapi.operator.leaderelection.LeaderElectionRecord; 20 | 21 | /** 22 | * Event fired when a leader has changed. 23 | * 24 | * @param leaderElectionRecord the leader election record 25 | */ 26 | public record LeaderChangedEvent(@NonNull LeaderElectionRecord leaderElectionRecord) { 27 | } 28 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/leaderelection/event/LeaseAcquiredEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.leaderelection.event; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.kubernetes.client.openapi.operator.leaderelection.LeaderElectionRecord; 20 | 21 | /** 22 | * Event fired when this service instance has become a leader. 23 | * 24 | * @param leaderElectionRecord the leader election record 25 | */ 26 | public record LeaseAcquiredEvent(@NonNull LeaderElectionRecord leaderElectionRecord) { 27 | } 28 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/main/java/io/micronaut/kubernetes/client/openapi/operator/leaderelection/event/LeaseLostEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.operator.leaderelection.event; 17 | 18 | import io.micronaut.core.annotation.Nullable; 19 | import io.micronaut.kubernetes.client.openapi.operator.leaderelection.LeaderElectionRecord; 20 | 21 | /** 22 | * Event fired when this service instance has lost the leader lease. 23 | * 24 | * @param leaderElectionRecord the leader election record 25 | */ 26 | public record LeaseLostEvent(@Nullable LeaderElectionRecord leaderElectionRecord) { 27 | } 28 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/test/groovy/io/micronaut/kubernetes/client/openapi/operator/util/NamespaceOperation.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.openapi.operator.util 2 | 3 | import io.micronaut.kubernetes.client.openapi.api.CoreV1Api 4 | import io.micronaut.kubernetes.client.openapi.model.V1Namespace 5 | import io.micronaut.kubernetes.client.openapi.model.V1ObjectMeta 6 | 7 | class NamespaceOperation { 8 | 9 | private final CoreV1Api api 10 | 11 | NamespaceOperation(CoreV1Api api) { 12 | this.api = api 13 | } 14 | 15 | V1Namespace createNamespace(String namespaceName) { 16 | V1Namespace namespace = new V1Namespace() 17 | namespace.kind('Namespace') 18 | namespace.apiVersion('v1') 19 | V1ObjectMeta objectMeta = new V1ObjectMeta() 20 | objectMeta.name(namespaceName) 21 | namespace.metadata(objectMeta) 22 | return api.createNamespace(namespace, null, null, null, null) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/test/groovy/io/micronaut/kubernetes/client/openapi/operator/workqueue/ratelimiter/BucketRateLimiterSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.openapi.operator.workqueue.ratelimiter 2 | 3 | import spock.lang.Specification 4 | 5 | import java.time.Duration 6 | 7 | class BucketRateLimiterSpec extends Specification { 8 | 9 | def 'test delay repeated'() { 10 | given: 11 | def rateLimiter = new BucketRateLimiter(2, 2, Duration.ofSeconds(1)) 12 | 13 | when: 14 | Duration delay = rateLimiter.when('item1') 15 | 16 | then: 17 | delay == Duration.ZERO 18 | 19 | when: 20 | delay = rateLimiter.when('item1') 21 | 22 | then: 23 | delay == Duration.ZERO 24 | 25 | when: 26 | delay = rateLimiter.when('item1') 27 | 28 | then: 29 | delay.toMillis() > 0 30 | 31 | when: 32 | Thread.sleep(1000) 33 | delay = rateLimiter.when('item1') 34 | 35 | then: 36 | delay == Duration.ZERO 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-operator/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-reactor/src/main/java/io/micronaut/kubernetes/client/openapi/reactor/annotation/KubernetesClientApiReactor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.reactor.annotation; 17 | 18 | import io.micronaut.core.annotation.Internal; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.Target; 23 | 24 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 25 | 26 | /** 27 | * Internal annotation used for finding kubernetes client api reactor beans. 28 | */ 29 | @Internal 30 | @Retention(RUNTIME) 31 | @Target(ElementType.TYPE) 32 | public @interface KubernetesClientApiReactor { 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-reactor/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-watcher/src/main/java/io/micronaut/kubernetes/client/openapi/watcher/WatchEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.watcher; 17 | 18 | import io.micronaut.core.annotation.NonNull; 19 | import io.micronaut.core.annotation.Nullable; 20 | import io.micronaut.kubernetes.client.openapi.model.V1Status; 21 | import io.micronaut.serde.annotation.Serdeable; 22 | 23 | /** 24 | * Holder for deserialized kubernetes streamed event. 25 | * 26 | * @param type the type of event (ADDED, MODIFIED, DELETED, ERROR, BOOKMARK) 27 | * @param object the object 28 | * @param status the instance of V1Status 29 | * @param the object type 30 | */ 31 | // tag::class[] 32 | @Serdeable 33 | public record WatchEvent( 34 | @NonNull String type, 35 | @Nullable T object, 36 | @Nullable V1Status status 37 | ) { 38 | } 39 | // end::class[] 40 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-watcher/src/main/java/io/micronaut/kubernetes/client/openapi/watcher/annotation/KubernetesClientApiWatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.openapi.watcher.annotation; 17 | 18 | import io.micronaut.core.annotation.Internal; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.Target; 23 | 24 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 25 | 26 | /** 27 | * Internal annotation used for finding kubernetes client api watcher beans. 28 | */ 29 | @Internal 30 | @Retention(RUNTIME) 31 | @Target(ElementType.TYPE) 32 | public @interface KubernetesClientApiWatcher { 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-client-openapi-watcher/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-openapi/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-processor/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | implementation libs.javapoet 7 | implementation mn.micronaut.inject.java 8 | } 9 | 10 | micronautBuild { 11 | binaryCompatibility { 12 | enabled = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /kubernetes-client-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | io.micronaut.kubernetes.client.processor.KubernetesApisProcessor -------------------------------------------------------------------------------- /kubernetes-client-reactor/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor projects.micronautKubernetesClientProcessor 7 | api projects.micronautKubernetesClient 8 | api mnReactor.micronaut.reactor 9 | 10 | testImplementation projects.testUtils 11 | } 12 | 13 | tasks.withType(me.champeau.gradle.japicmp.JapicmpTask) { 14 | packageExcludes = ["io.micronaut.kubernetes.client.reactor"] 15 | } 16 | -------------------------------------------------------------------------------- /kubernetes-client-reactor/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-rxjava2/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor projects.micronautKubernetesClientProcessor 7 | 8 | api projects.micronautKubernetesClient 9 | implementation libs.rxjava2 10 | 11 | testImplementation projects.testUtils 12 | } 13 | 14 | tasks.withType(me.champeau.gradle.japicmp.JapicmpTask) { 15 | packageExcludes = ["io.micronaut.kubernetes.client.rxjava2"] 16 | } 17 | -------------------------------------------------------------------------------- /kubernetes-client-rxjava2/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client-rxjava3/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor projects.micronautKubernetesClientProcessor 7 | 8 | api projects.micronautKubernetesClient 9 | implementation libs.rxjava3 10 | 11 | testImplementation projects.testUtils 12 | } 13 | 14 | tasks.withType(me.champeau.gradle.japicmp.JapicmpTask) { 15 | packageExcludes = ["io.micronaut.kubernetes.client.rxjava3"] 16 | } 17 | -------------------------------------------------------------------------------- /kubernetes-client-rxjava3/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kubernetes-client/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor mn.micronaut.graal 7 | annotationProcessor projects.micronautKubernetesClientProcessor 8 | 9 | api mn.micronaut.inject.java 10 | api libs.io.kubernetes.client.java 11 | 12 | implementation mn.micronaut.runtime 13 | compileOnly libs.graal.svm 14 | 15 | testAnnotationProcessor mn.micronaut.inject.java 16 | 17 | testImplementation mnSerde.micronaut.serde.jackson 18 | testImplementation projects.testUtils 19 | testRuntimeOnly mn.snakeyaml 20 | } 21 | 22 | tasks.withType(me.champeau.gradle.japicmp.JapicmpTask) { 23 | packageExcludes = ["io.micronaut.kubernetes.client"] 24 | } 25 | -------------------------------------------------------------------------------- /kubernetes-client/src/main/java/io/micronaut/kubernetes/client/ApisAutomaticFeatureMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client; 17 | 18 | import io.micronaut.core.annotation.Internal; 19 | 20 | /** 21 | * Causes the Kubernetes apis beans will be generated. 22 | * 23 | * @author Pavol Gressa 24 | * @since 2.2 25 | */ 26 | @Apis(kind = Apis.Kind.ASYNC) 27 | @Internal 28 | final class ApisAutomaticFeatureMetadata { 29 | } 30 | -------------------------------------------------------------------------------- /kubernetes-client/src/main/java/io/micronaut/kubernetes/client/DefaultPodNameResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client; 17 | 18 | import jakarta.inject.Singleton; 19 | 20 | import java.util.Optional; 21 | 22 | /** 23 | * The default implementation of {@link PodNameResolver}. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.3 27 | */ 28 | @Singleton 29 | public class DefaultPodNameResolver implements PodNameResolver { 30 | 31 | private static final String HOSTNAME_ENV_VARIABLE = "HOSTNAME"; 32 | 33 | @Override 34 | public Optional getPodName() { 35 | return Optional.ofNullable(System.getenv(HOSTNAME_ENV_VARIABLE)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kubernetes-client/src/main/java/io/micronaut/kubernetes/client/NamespaceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client; 17 | 18 | 19 | import io.micronaut.context.annotation.DefaultImplementation; 20 | 21 | /** 22 | * Resolves the Kubernetes namespace for the Micronaut application. 23 | * 24 | * @see DefaultNamespaceResolver 25 | * @author Pavol Gressa 26 | * @since 3.1 27 | */ 28 | @DefaultImplementation(DefaultNamespaceResolver.class) 29 | public interface NamespaceResolver { 30 | 31 | /** 32 | * Resolves namespace. 33 | * @return namespace name 34 | */ 35 | String resolveNamespace(); 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-client/src/main/java/io/micronaut/kubernetes/client/PodNameResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | 20 | import java.util.Optional; 21 | 22 | /** 23 | * Resolves the Pod name. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.3 27 | */ 28 | @DefaultImplementation(DefaultPodNameResolver.class) 29 | public interface PodNameResolver { 30 | 31 | /** 32 | * Resolves the name of the POD this application is running in. 33 | * @return pod name 34 | */ 35 | Optional getPodName(); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /kubernetes-client/src/main/resources/META-INF/native-image/io.micronaut.kubernetes/micronaut-kubernetes-client/native-image.properties: -------------------------------------------------------------------------------- 1 | Args = --features=io.micronaut.kubernetes.client.graalvm.KubernetesClientFeature -------------------------------------------------------------------------------- /kubernetes-client/src/test/groovy/io/micronaut/kubernetes/client/ApisSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client 2 | 3 | import io.kubernetes.client.openapi.ApiClient 4 | import io.kubernetes.client.openapi.apis.CoreV1Api 5 | import io.kubernetes.client.openapi.apis.NodeV1Api 6 | import io.micronaut.context.ApplicationContext 7 | import io.micronaut.context.annotation.Requires 8 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 9 | import jakarta.inject.Inject 10 | import spock.lang.Specification 11 | 12 | @MicronautTest 13 | @Requires(beans = ApiClient.class) 14 | class ApisSpec extends Specification { 15 | 16 | @Inject 17 | ApplicationContext context 18 | 19 | def "it creates core api"(){ 20 | expect: 21 | context.containsBean(CoreV1Api) 22 | } 23 | 24 | def "it creates node api"(){ 25 | expect: 26 | context.containsBean(NodeV1Api) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kubernetes-client/src/test/groovy/io/micronaut/kubernetes/client/DiscoveryFactorySpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client 2 | 3 | import io.micronaut.context.ApplicationContext 4 | import io.micronaut.context.exceptions.NoSuchBeanException 5 | import spock.lang.Specification 6 | 7 | class DiscoveryFactorySpec extends Specification { 8 | 9 | def "it resolves factory"() { 10 | given: 11 | ApplicationContext applicationContext = ApplicationContext.run() 12 | 13 | expect: 14 | applicationContext.getBean(DiscoveryFactory) 15 | 16 | cleanup: 17 | applicationContext.close() 18 | } 19 | 20 | def "it fails to resolve factory when it is disabled"() { 21 | given: 22 | ApplicationContext applicationContext = ApplicationContext.run(["kubernetes.client.api-discovery.enabled": false]) 23 | 24 | when: 25 | applicationContext.getBean(DiscoveryFactory) 26 | 27 | then: 28 | thrown(NoSuchBeanException) 29 | 30 | cleanup: 31 | applicationContext.close() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-client/src/test/groovy/io/micronaut/kubernetes/client/ModelMapperSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client 2 | 3 | import io.kubernetes.client.openapi.models.V1ClusterRole 4 | import io.kubernetes.client.openapi.models.V1ConfigMap 5 | import spock.lang.Specification 6 | 7 | class ModelMapperSpec extends Specification { 8 | 9 | ModelMapper mapper = new ModelMapper() 10 | 11 | def "it resolves core model"() { 12 | expect: 13 | with(mapper.getGroupVersionKindByClass(V1ConfigMap)) { 14 | it.version == "v1" 15 | it.group == "" 16 | it.kind == "ConfigMap" 17 | } 18 | } 19 | 20 | def "it resolves rbac model"() { 21 | expect: 22 | with(mapper.getGroupVersionKindByClass(V1ClusterRole)) { 23 | it.version == "v1" 24 | it.group == "" 25 | it.kind == "ClusterRole" 26 | } 27 | } 28 | 29 | def "it resolves custom api versions"() { 30 | expect: 31 | with(mapper.getGroupVersionKindByClass(V3CustomResource)) { 32 | it.version == "v3" 33 | it.group == "" 34 | it.kind == "CustomResource" 35 | } 36 | } 37 | 38 | static class V3CustomResource{} 39 | } 40 | -------------------------------------------------------------------------------- /kubernetes-client/src/test/java/io/micronaut/kubernetes/client/ApiClientListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client; 17 | 18 | import io.kubernetes.client.openapi.ApiClient; 19 | import io.micronaut.context.event.BeanCreatedEvent; 20 | import io.micronaut.context.event.BeanCreatedEventListener; 21 | import jakarta.inject.Singleton; 22 | import okhttp3.OkHttpClient; 23 | 24 | import java.util.concurrent.TimeUnit; 25 | 26 | //tag::listener[] 27 | @Singleton 28 | public class ApiClientListener implements BeanCreatedEventListener { 29 | 30 | @Override 31 | public ApiClient onCreated(BeanCreatedEvent event) { 32 | ApiClient apiClient = event.getBean(); 33 | OkHttpClient okHttpClient = apiClient.getHttpClient().newBuilder() 34 | .readTimeout(5345, TimeUnit.MILLISECONDS) 35 | .build(); 36 | apiClient.setHttpClient(okHttpClient); 37 | return apiClient; 38 | } 39 | } 40 | //end::listener[] 41 | -------------------------------------------------------------------------------- /kubernetes-client/src/test/resources/k8s/kubernetes-client-example-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: kubernetes-client-example 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: kubernetes-client-example 9 | template: 10 | metadata: 11 | labels: 12 | app: kubernetes-client-example 13 | spec: 14 | containers: 15 | - name: kubernetes-client-example 16 | image: micronaut-kubernetes-client-example 17 | imagePullPolicy: "Never" 18 | ports: 19 | - name: http 20 | containerPort: 8085 21 | livenessProbe: 22 | httpGet: 23 | port: 8085 24 | path: /health/liveness 25 | initialDelaySeconds: 2 26 | periodSeconds: 3 27 | failureThreshold: 10 28 | readinessProbe: 29 | httpGet: 30 | port: 8085 31 | path: /health/readiness 32 | initialDelaySeconds: 2 33 | periodSeconds: 3 34 | failureThreshold: 10 35 | -------------------------------------------------------------------------------- /kubernetes-client/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor mn.micronaut.graal 7 | 8 | compileOnly mn.micronaut.inject.java 9 | compileOnly mn.micronaut.management 10 | compileOnly libs.graal.svm 11 | 12 | api projects.micronautKubernetesClientReactor 13 | api projects.micronautKubernetesInformer 14 | api libs.io.kubernetes.client.java.extended 15 | api libs.micronaut.discovery.client 16 | 17 | implementation mn.micronaut.runtime 18 | implementation mn.micronaut.jackson.databind 19 | 20 | testImplementation libs.micronaut.discovery.client 21 | testImplementation libs.system.lambda 22 | testImplementation(projects.testUtils) 23 | 24 | testRuntimeOnly mn.snakeyaml 25 | } 26 | 27 | tasks.withType(Test).configureEach { 28 | // for system lambda 29 | jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") 30 | } 31 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/src/main/java/io/micronaut/kubernetes/configuration/KubernetesConfigMapWatcherCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.configuration; 17 | 18 | import io.micronaut.context.condition.ConditionContext; 19 | import io.micronaut.core.annotation.Internal; 20 | import io.micronaut.kubernetes.KubernetesConfiguration; 21 | 22 | /** 23 | * Condition evaluates when the {@link KubernetesConfigMapWatcherCondition} is enabled. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.1 27 | */ 28 | @Internal 29 | public class KubernetesConfigMapWatcherCondition extends AbstractKubernetesConfigWatcherCondition { 30 | @Override 31 | KubernetesConfiguration.AbstractConfigConfiguration getConfig(ConditionContext context) { 32 | return context.getBean(KubernetesConfiguration.KubernetesConfigMapsConfiguration.class); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/src/main/java/io/micronaut/kubernetes/configuration/KubernetesSecretWatcherCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.configuration; 17 | 18 | import io.micronaut.context.condition.ConditionContext; 19 | import io.micronaut.core.annotation.Internal; 20 | import io.micronaut.kubernetes.KubernetesConfiguration; 21 | 22 | /** 23 | * Condition evaluates when the {@link KubernetesSecretWatcherCondition} is enabled. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.1 27 | */ 28 | @Internal 29 | public class KubernetesSecretWatcherCondition extends AbstractKubernetesConfigWatcherCondition { 30 | @Override 31 | KubernetesConfiguration.AbstractConfigConfiguration getConfig(ConditionContext context) { 32 | return context.getBean(KubernetesConfiguration.KubernetesSecretsConfiguration.class); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/src/test/groovy/io/micronaut/kubernetes/KubernetesConfigurationSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes 2 | 3 | import io.micronaut.context.ApplicationContext 4 | import io.micronaut.context.env.Environment 5 | import io.micronaut.kubernetes.KubernetesConfiguration 6 | import io.micronaut.kubernetes.client.DefaultNamespaceResolver 7 | import io.micronaut.kubernetes.test.TestUtils 8 | import spock.lang.Requires 9 | import spock.lang.Specification 10 | 11 | @Requires({ TestUtils.kubernetesApiAvailable() }) 12 | class KubernetesConfigurationSpec extends Specification { 13 | 14 | void "the namespace can be set via configuration"() { 15 | given: 16 | ApplicationContext applicationContext = ApplicationContext.run(["kubernetes.client.namespace": "other-namespace"], Environment.KUBERNETES) 17 | 18 | when: 19 | String namespace = applicationContext.getBean(KubernetesConfiguration).namespace 20 | 21 | then: 22 | namespace == "other-namespace" 23 | } 24 | 25 | void "when not set, namespace is default"() { 26 | given: 27 | ApplicationContext applicationContext = ApplicationContext.builder() 28 | .deduceEnvironment(false) 29 | .environments(Environment.KUBERNETES) 30 | .build() 31 | .start() 32 | 33 | when: 34 | String namespace = applicationContext.getBean(KubernetesConfiguration).namespace 35 | 36 | then: 37 | namespace == DefaultNamespaceResolver.DEFAULT_NAMESPACE; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | config-client: 3 | enabled: true 4 | http: 5 | services: 6 | kubernetes: 7 | path: /api/v1 8 | --- 9 | kubernetes: 10 | client: 11 | namespace: micronaut-kubernetes 12 | host: localhost 13 | port: 8001 14 | secure: false 15 | -------------------------------------------------------------------------------- /kubernetes-discovery-client/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /kubernetes-informer/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | 7 | annotationProcessor mn.micronaut.graal 8 | 9 | compileOnly mn.micronaut.inject.java 10 | compileOnly libs.graal.svm 11 | 12 | api projects.micronautKubernetesClient 13 | implementation mn.micronaut.runtime 14 | api mn.micronaut.context 15 | 16 | testAnnotationProcessor mn.micronaut.inject.java 17 | testImplementation projects.testUtils 18 | } 19 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/EmptyLabelSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer; 17 | 18 | import java.util.function.Supplier; 19 | 20 | /** 21 | * Default label supplier for the {@link Informer#labelSelectorSupplier()} that returns empty string. 22 | * 23 | * @author Pavol Gressa 24 | * @since 3.1 25 | */ 26 | public class EmptyLabelSupplier implements Supplier { 27 | @Override 28 | public String get() { 29 | return ""; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/EmptyNamespacesSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer; 17 | 18 | import java.util.function.Supplier; 19 | 20 | /** 21 | * Default namespaces supplier for the {@link Informer#namespacesSupplier()} ()} that returns empty array. 22 | * 23 | * @author Pavol Gressa 24 | * @since 3.1 25 | */ 26 | public class EmptyNamespacesSupplier implements Supplier { 27 | @Override 28 | public String[] get() { 29 | return new String[0]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2022 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * Contains classes specific to Kubernetes informer. 18 | * 19 | * @author Nemanja Mikic 20 | * @since 3.4.1 21 | */ 22 | 23 | @Configuration 24 | @Requires(env = Environment.KUBERNETES) 25 | package io.micronaut.kubernetes.client.informer; 26 | 27 | import io.micronaut.context.annotation.Configuration; 28 | import io.micronaut.context.annotation.Requires; 29 | import io.micronaut.context.env.Environment; 30 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/resolvers/InformerApiGroupResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer.resolvers; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | import io.micronaut.core.annotation.AnnotationValue; 20 | import io.micronaut.core.annotation.NonNull; 21 | import io.micronaut.kubernetes.client.informer.Informer; 22 | 23 | /** 24 | * The informer's resource api group. 25 | * 26 | * @author Pavol Gressa 27 | * @since 3.3 28 | */ 29 | @DefaultImplementation(DefaultInformerApiGroupResolver.class) 30 | public interface InformerApiGroupResolver { 31 | 32 | /** 33 | * Resolves the informer's watched resources api group. 34 | * 35 | * @param informer the informer 36 | * @return resource api group 37 | */ 38 | @NonNull 39 | String resolveInformerApiGroup(@NonNull AnnotationValue informer); 40 | } 41 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/resolvers/InformerNamespaceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer.resolvers; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | import io.micronaut.core.annotation.AnnotationValue; 20 | import io.micronaut.core.annotation.NonNull; 21 | import io.micronaut.kubernetes.client.informer.Informer; 22 | 23 | import java.util.Set; 24 | 25 | /** 26 | * Informer namespace resolver. 27 | * 28 | * @author Pavol Gressa 29 | * @since 3.3 30 | */ 31 | @DefaultImplementation(DefaultInformerNamespaceResolver.class) 32 | public interface InformerNamespaceResolver { 33 | 34 | /** 35 | * Resolves the namespaces for the informer's watched resources. 36 | * 37 | * @param informer the informer 38 | * @return namespaces to watch 39 | */ 40 | @NonNull 41 | Set resolveInformerNamespaces(@NonNull AnnotationValue informer); 42 | } 43 | -------------------------------------------------------------------------------- /kubernetes-informer/src/main/java/io/micronaut/kubernetes/client/informer/resolvers/InformerResourcePluralResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer.resolvers; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | import io.micronaut.core.annotation.AnnotationValue; 20 | import io.micronaut.core.annotation.NonNull; 21 | import io.micronaut.kubernetes.client.informer.Informer; 22 | 23 | /** 24 | * Resolves the k8s resource plural. 25 | * 26 | * @author Pavol Gressa 27 | * @since 3.3 28 | */ 29 | @DefaultImplementation(DefaultInformerResourcePluralResolver.class) 30 | public interface InformerResourcePluralResolver { 31 | 32 | @NonNull 33 | String resolveInformerResourcePlural(@NonNull AnnotationValue informer); 34 | } 35 | -------------------------------------------------------------------------------- /kubernetes-informer/src/test/groovy/io/micronaut/kubernetes/client/informer/InformerSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.informer 2 | 3 | import io.kubernetes.client.informer.SharedInformerFactory 4 | import io.micronaut.context.ApplicationContext 5 | import io.micronaut.context.env.Environment 6 | import spock.lang.Specification 7 | 8 | class InformerSpec extends Specification { 9 | 10 | def "factory is created"() { 11 | given: 12 | ApplicationContext applicationContext = ApplicationContext.run(Environment.KUBERNETES) 13 | 14 | expect: 15 | applicationContext.getBean(SharedInformerFactory) 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kubernetes-informer/src/test/java/io/micronaut/kubernetes/client/informer/LabelSelectorSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.informer; 17 | 18 | import io.micronaut.context.ApplicationContext; 19 | import io.micronaut.context.annotation.Requires; 20 | import jakarta.inject.Singleton; 21 | 22 | import java.util.function.Supplier; 23 | 24 | @Singleton 25 | @Requires(property = "spec.name", value = "ConfigMapLabelSelectorInformerSpec") 26 | public class LabelSelectorSupplier implements Supplier { 27 | 28 | private final ApplicationContext applicationContext; 29 | 30 | public LabelSelectorSupplier(ApplicationContext applicationContext) { 31 | this.applicationContext = applicationContext; 32 | } 33 | 34 | @Override 35 | public String get() { 36 | return "environment=test"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kubernetes-informer/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /kubernetes-operator/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'io.micronaut.build.internal.kubernetes-module' 3 | } 4 | 5 | dependencies { 6 | annotationProcessor mn.micronaut.graal 7 | 8 | compileOnly mn.micronaut.inject.java 9 | compileOnly libs.graal.svm 10 | 11 | api projects.micronautKubernetesInformer 12 | api libs.io.kubernetes.client.java.extended 13 | implementation mn.micronaut.runtime 14 | 15 | testAnnotationProcessor mn.micronaut.inject.java 16 | testImplementation projects.testUtils 17 | 18 | testRuntimeOnly mn.snakeyaml 19 | } 20 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/event/LeaseAcquiredEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.event; 17 | 18 | import io.kubernetes.client.extended.controller.ControllerManager; 19 | import io.micronaut.kubernetes.client.operator.ControllerConfiguration; 20 | 21 | /** 22 | * Event fired when the controller created from the {@link AbstracLeaderElectingControllerEvent#getOperatorConfiguration()} 23 | * has become a leader. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.3 27 | */ 28 | public class LeaseAcquiredEvent extends AbstracLeaderElectingControllerEvent { 29 | 30 | /** 31 | * Create the event. 32 | * 33 | * @param controllerConfiguration operator configuration 34 | * @param source controller manager 35 | */ 36 | public LeaseAcquiredEvent(ControllerConfiguration controllerConfiguration, ControllerManager source) { 37 | super(controllerConfiguration, source); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/event/LeaseLostEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.event; 17 | 18 | import io.kubernetes.client.extended.controller.ControllerManager; 19 | import io.micronaut.kubernetes.client.operator.ControllerConfiguration; 20 | 21 | /** 22 | * Event fired when the controller created from the {@link AbstracLeaderElectingControllerEvent#getOperatorConfiguration()} 23 | * has lost the leader lease. 24 | * 25 | * @author Pavol Gressa 26 | * @since 3.3 27 | */ 28 | public class LeaseLostEvent extends AbstracLeaderElectingControllerEvent { 29 | 30 | public LeaseLostEvent(ControllerConfiguration controllerConfiguration, ControllerManager source) { 31 | super(controllerConfiguration, source); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/filter/DefaultAddFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.filter; 17 | 18 | import io.kubernetes.client.common.KubernetesObject; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.Predicate; 22 | 23 | /** 24 | * Default filter for added resources. 25 | * 26 | * @author Pavol Gressa 27 | * @since 3.3 28 | */ 29 | @Singleton 30 | public class DefaultAddFilter implements Predicate { 31 | 32 | @Override 33 | public boolean test(KubernetesObject kubernetesObject) { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/filter/DefaultDeleteFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.filter; 17 | 18 | import io.kubernetes.client.common.KubernetesObject; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.BiPredicate; 22 | 23 | /** 24 | * Default filter for deleted resources. 25 | * 26 | * @author Pavol Gressa 27 | * @since 3.3 28 | */ 29 | @Singleton 30 | public class DefaultDeleteFilter implements BiPredicate { 31 | 32 | @Override 33 | public boolean test(KubernetesObject kubernetesObject, Boolean aBoolean) { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/filter/DefaultUpdateFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.filter; 17 | 18 | import io.kubernetes.client.common.KubernetesObject; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.BiPredicate; 22 | 23 | /** 24 | * Default filter for updated resources. 25 | * 26 | * @author Pavol Gressa 27 | * @since 3.3 28 | */ 29 | @Singleton 30 | public class DefaultUpdateFilter implements BiPredicate { 31 | 32 | @Override 33 | public boolean test(KubernetesObject kubernetesObject, KubernetesObject kubernetesObject2) { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/leaderelection/LockIdentityProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.leaderelection; 17 | 18 | import io.micronaut.context.annotation.DefaultImplementation; 19 | 20 | /** 21 | * The lock identity provider. The lock identity is used to uniquely identity the application for the leader election 22 | * process. Every replica of the application needs to have unique identity. 23 | * 24 | * @author Pavol Gressa 25 | * @since 3.3 26 | */ 27 | @DefaultImplementation(DefaultLockIdentityProvider.class) 28 | public interface LockIdentityProvider { 29 | 30 | /** 31 | * Get the lock identity. 32 | * 33 | * @return the lock identity. 34 | */ 35 | String getIdentity(); 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/main/java/io/micronaut/kubernetes/client/operator/queue/RateLimitingQueueFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator.queue; 17 | 18 | import io.kubernetes.client.extended.workqueue.DefaultRateLimitingQueue; 19 | import io.kubernetes.client.extended.workqueue.RateLimitingQueue; 20 | import io.micronaut.context.annotation.Factory; 21 | import jakarta.inject.Singleton; 22 | 23 | import java.util.concurrent.Executors; 24 | 25 | /** 26 | * The factory for {@link RateLimitingQueue}. 27 | * 28 | * @author Pavol Gressa 29 | * @since 3.3 30 | */ 31 | @Factory 32 | public class RateLimitingQueueFactory { 33 | 34 | /** 35 | * Creates {@link RateLimitingQueue}. 36 | * @return rate limiting queue 37 | */ 38 | @SuppressWarnings("rawtypes") 39 | @Singleton 40 | public RateLimitingQueue rateLimitingQueue() { 41 | return new DefaultRateLimitingQueue<>(Executors.newSingleThreadExecutor()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/groovy/io/micronaut/kubernetes/client/operator/controller/DefaultControllerManagerBuilderSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.operator.controller 2 | 3 | import io.kubernetes.client.extended.controller.Controller 4 | import io.micronaut.context.env.Environment 5 | import io.micronaut.kubernetes.client.operator.ControllerConfiguration 6 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 7 | import jakarta.inject.Inject 8 | import spock.lang.Specification 9 | 10 | @MicronautTest(environments = [Environment.KUBERNETES]) 11 | class DefaultControllerManagerBuilderSpec extends Specification{ 12 | 13 | @Inject 14 | DefaultControllerManagerBuilder builder; 15 | 16 | def "it builds manager builder"(){ 17 | given: 18 | ControllerConfiguration operator = Stub() 19 | Controller controller1 = Mock(Controller) 20 | Controller controller2 = Mock(Controller) 21 | 22 | when: 23 | def controllerManager = builder.build(operator, [controller1, controller2]) 24 | 25 | then: 26 | controllerManager 27 | 28 | when: 29 | controllerManager.run() 30 | 31 | then: 32 | 1 * controller1.run() 33 | 1 * controller2.run() 34 | 35 | when: 36 | controllerManager.shutdown() 37 | 38 | then: 39 | 1 * controller1.shutdown() 40 | 1 * controller2.shutdown() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/groovy/io/micronaut/kubernetes/client/operator/controller/DefaultControllerWatchBuilderSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.operator.controller 2 | 3 | import io.kubernetes.client.extended.controller.reconciler.Request 4 | import io.kubernetes.client.extended.workqueue.DefaultRateLimitingQueue 5 | import io.kubernetes.client.extended.workqueue.WorkQueue 6 | import io.kubernetes.client.openapi.models.V1ConfigMap 7 | import io.micronaut.context.env.Environment 8 | import io.micronaut.kubernetes.client.operator.ControllerConfiguration 9 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 10 | import jakarta.inject.Inject 11 | import spock.lang.Specification 12 | 13 | import java.time.Duration 14 | 15 | @MicronautTest(environments = [Environment.KUBERNETES]) 16 | class DefaultControllerWatchBuilderSpec extends Specification { 17 | 18 | @Inject 19 | DefaultControllerWatchBuilder builder 20 | 21 | def "it creates controller watch"(){ 22 | given: 23 | ControllerConfiguration operator = Stub(ControllerConfiguration.class) 24 | operator.getApiType() >> V1ConfigMap 25 | operator.getResyncCheckPeriod() >> 2000L 26 | 27 | WorkQueue queue = new DefaultRateLimitingQueue<>() 28 | 29 | when: 30 | def controllerWatch = builder.buildControllerWatch(operator, queue) 31 | 32 | then: 33 | controllerWatch.getResourceClass() == V1ConfigMap 34 | controllerWatch.getResyncPeriod() == Duration.ofMillis(2000) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/groovy/io/micronaut/kubernetes/client/operator/leaderelection/DefaultLockIdentityProviderSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.operator.leaderelection 2 | 3 | import io.micronaut.context.env.Environment 4 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 5 | import jakarta.inject.Inject 6 | import spock.lang.Specification 7 | 8 | @MicronautTest(environments = [Environment.KUBERNETES]) 9 | class DefaultLockIdentityProviderSpec extends Specification { 10 | 11 | @Inject 12 | LockIdentityProvider provider; 13 | 14 | def "it resolves the provider from env variable"() { 15 | expect: 16 | provider.getIdentity() == "test" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/groovy/io/micronaut/kubernetes/client/operator/queue/RateLimitingQueueFactorySpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.client.operator.queue 2 | 3 | import io.kubernetes.client.extended.workqueue.RateLimitingQueue 4 | import io.micronaut.context.ApplicationContext 5 | import io.micronaut.context.env.Environment 6 | import io.micronaut.inject.qualifiers.Qualifiers 7 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 8 | import jakarta.inject.Inject 9 | import spock.lang.Specification 10 | 11 | @MicronautTest(environments = [Environment.KUBERNETES]) 12 | class RateLimitingQueueFactorySpec extends Specification { 13 | 14 | @Inject 15 | ApplicationContext applicationContext 16 | 17 | def "it creates queue for every name"() { 18 | when: 19 | 20 | def q1 = applicationContext.createBean(RateLimitingQueue) 21 | def q3 = applicationContext.createBean(RateLimitingQueue) 22 | 23 | applicationContext.registerSingleton(RateLimitingQueue.class, q1, Qualifiers.byName("q1"), true) 24 | applicationContext.registerSingleton(RateLimitingQueue.class, q3, Qualifiers.byName("q3")) 25 | 26 | then: 27 | noExceptionThrown() 28 | 29 | when: 30 | def q2 = applicationContext.getBean(RateLimitingQueue, Qualifiers.byName("q1")) 31 | 32 | then: 33 | q1 == q2 34 | q1 != q3 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/java/io/micronaut/kubernetes/client/operator/OnAddFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator; 17 | //tag::reconciler[] 18 | import io.kubernetes.client.openapi.models.V1ConfigMap; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.Predicate; 22 | 23 | @Singleton 24 | public class OnAddFilter implements Predicate { 25 | 26 | @Override 27 | public boolean test(V1ConfigMap v1ConfigMap) { 28 | if (v1ConfigMap.getMetadata().getAnnotations() != null) { 29 | return v1ConfigMap.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 30 | } 31 | return false; 32 | } 33 | } 34 | //end::reconciler[] 35 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/java/io/micronaut/kubernetes/client/operator/OnDeleteFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator; 17 | //tag::reconciler[] 18 | import io.kubernetes.client.openapi.models.V1ConfigMap; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.BiPredicate; 22 | 23 | @Singleton 24 | public class OnDeleteFilter implements BiPredicate { 25 | 26 | @Override 27 | public boolean test(V1ConfigMap v1ConfigMap, Boolean deletedFinalStateUnknown) { 28 | if (v1ConfigMap.getMetadata().getAnnotations() != null) { 29 | return v1ConfigMap.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 30 | } 31 | return false; 32 | } 33 | } 34 | //end::reconciler[] 35 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/java/io/micronaut/kubernetes/client/operator/OnUpdateFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator; 17 | //tag::reconciler[] 18 | import io.kubernetes.client.openapi.models.V1ConfigMap; 19 | import jakarta.inject.Singleton; 20 | 21 | import java.util.function.BiPredicate; 22 | 23 | @Singleton 24 | public class OnUpdateFilter implements BiPredicate { 25 | 26 | @Override 27 | public boolean test(V1ConfigMap oldObj, V1ConfigMap newObj) { 28 | if (newObj.getMetadata().getAnnotations() != null) { 29 | return newObj.getMetadata().getAnnotations().containsKey("io.micronaut.operator"); 30 | } 31 | return false; 32 | } 33 | } 34 | //end::reconciler[] 35 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/java/io/micronaut/kubernetes/client/operator/TestPodNamespaceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 original authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.micronaut.kubernetes.client.operator; 17 | 18 | 19 | import io.micronaut.context.annotation.Replaces; 20 | import io.micronaut.kubernetes.client.PodNameResolver; 21 | import jakarta.inject.Singleton; 22 | 23 | import java.util.Optional; 24 | 25 | @Singleton 26 | @Replaces(PodNameResolver.class) 27 | public class TestPodNamespaceResolver implements PodNameResolver { 28 | 29 | @Override 30 | public Optional getPodName() { 31 | return Optional.of("test"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kubernetes-operator/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: micronaut-operator-test 4 | server: 5 | thread-selection: io 6 | executors: 7 | io: 8 | n-threads: 75 9 | type: fixed -------------------------------------------------------------------------------- /kubernetes-operator/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /redeploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -e 3 | 4 | ./gradlew jibDockerBuild 5 | for NS in micronaut-kubernetes micronaut-kubernetes-a; do 6 | kubectl -n $NS patch deployment example-service -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(date +'%s')\"}}}}}" 7 | kubectl -n $NS patch deployment example-client -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(date +'%s')\"}}}}}" 8 | done -------------------------------------------------------------------------------- /setup-kubernetes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | ###################################### 3 | # Setup script for local developemnt # 4 | ###################################### 5 | set -ex 6 | 7 | while getopts c:t: flag; do 8 | case "${flag}" in 9 | c) CLUSTER_OPTION=${OPTARG} ;; 10 | t) TYPE_OPTION=${OPTARG} ;; 11 | *) ;; 12 | esac 13 | done 14 | 15 | CLUSTER_NAME=${CLUSTER_OPTION:-kind} 16 | TYPE=${TYPE_OPTION:-java} 17 | 18 | if [ "$TYPE" = "java" ]; then 19 | TYPE_CMD="dockerBuild" 20 | elif [ "$TYPE" = "native" ]; then 21 | TYPE_CMD="dockerBuildNative" 22 | fi 23 | 24 | kind get clusters 25 | 26 | ./gradlew clean $TYPE_CMD --refresh-dependencies 27 | kind --name "$CLUSTER_NAME" load docker-image micronaut-kubernetes-example-service:latest 28 | kind --name "$CLUSTER_NAME" load docker-image micronaut-kubernetes-example-client:latest 29 | kind --name "$CLUSTER_NAME" load docker-image micronaut-kubernetes-client-example:latest 30 | kind --name "$CLUSTER_NAME" load docker-image micronaut-kubernetes-informer-example:latest 31 | kind --name "$CLUSTER_NAME" load docker-image micronaut-kubernetes-operator-example:latest 32 | 33 | # 34 | # Run Kubernetes API proxy 35 | pkill -9 kubectl || true 36 | kubectl proxy & 37 | -------------------------------------------------------------------------------- /src/main/docs/guide/breaking.adoc: -------------------------------------------------------------------------------- 1 | ## Micronaut Kubernetes 7.x 2 | 3 | Micronaut Kubernetes 7.0.0 updates the official Kubernetes Client from v19 to v22. 4 | 5 | Starting from Kubernetes Client v20 the client api was refactored to use the builder pattern when creating client requests which caused breaking changes in all micronaut modules which are using 6 | the official kubernetes client. To support the builder pattern, the reactive client micronaut modules (Reactor, RxJava2 and RxJava3) are recreated and will also cause breaking changes. 7 | 8 | ## Micronaut Kubernetes 4.x 9 | 10 | Micronaut Kubernetes 4.0.0 updates to Kubernetes Client v18 (major). This major upgrade of the Kubernetes Client addresses several security CVEs. 11 | 12 | ## Micronaut Kubernetes 3.x 13 | 14 | This section documents breaking changes between Micronaut Kubernetes 2.x and Micronaut Kubernetes 3.x: 15 | 16 | ### In-house Kubernetes client removed 17 | 18 | The in-house Kubernetes client `io.micronaut.kubernetes.client.v1.*` was deprecated and removed. Instead use the new module `micronaut-kubernetes-client` or the reactive alternatives `micronaut-client-reactor` or `micronaut-client-rxjava2` that extends the client API classes by the reactive support of respective reactive framework. 19 | 20 | -------------------------------------------------------------------------------- /src/main/docs/guide/introduction.adoc: -------------------------------------------------------------------------------- 1 | This project eases https://kubernetes.io[Kubernetes] integration with Micronaut by providing the following two different implementation of kubernetes client: 2 | 3 | * `micronaut-kubernetes-client` module provides an implementation which integrates with the official https://github.com/kubernetes-client/java[Kubernetes Java SDK] client 4 | * `micronaut-kubernetes-client-openapi` module provides an in-house client implementation which uses Micronaut Netty HTTP Client and generated apis and modules from the Kubernetes Java SDK https://github.com/kubernetes-client/java/blob/master/kubernetes/api/openapi.yaml[OpenApi Spec] 5 | 6 | The project adds support for the following features: 7 | 8 | * Service Discovery 9 | * Configuration client for config maps and secrets 10 | * Kubernetes blocking and non-blocking clients 11 | 12 | To use the `BUILD-SNAPSHOT` version of this library, check the 13 | https://docs.micronaut.io/latest/guide/index.html#usingsnapshots[documentation to use snapshots]. 14 | 15 | ## Namespace configuration 16 | 17 | When a Micronaut application with this module is running within a Pod in a Kubernetes cluster, it will 18 | infer automatically the namespace it's running from by reading it from the service account secret (which will be 19 | provisioned at `/var/run/secrets/kubernetes.io/serviceaccount/namespace`). 20 | 21 | However, the namespace can still be overridden via configuration in bootstrap configuration files: 22 | 23 | [configuration] 24 | ---- 25 | kubernetes: 26 | client: 27 | namespace: other-namespace 28 | ---- 29 | -------------------------------------------------------------------------------- /src/main/docs/guide/kubernetes-client-openapi/kubernetes-client-openapi-watcher.adoc: -------------------------------------------------------------------------------- 1 | The Micronaut Kubernetes Client OpenApi Watcher implements streaming of Kubernetes events using the Micronaut Kubernetes Client OpenApi client. 2 | 3 | First you need to add a dependency on the `micronaut-kubernetes-client-openapi-watcher` module: 4 | 5 | dependency:io.micronaut.kubernetes:micronaut-kubernetes-client-openapi-watcher[] 6 | 7 | Then you can simply use Micronaut injection to get configured apis object from package `io.micronaut.kubernetes.client.openapi.watcher.api`: 8 | 9 | snippet::micronaut.client.SecretController[project-base="examples/example-kubernetes-client-openapi-watcher", source="main"] 10 | 11 | [IMPORTANT] 12 | The streaming will work only if the `watch` parameter is set to `true`. 13 | 14 | The Kubernetes streamed events are deserialized into the link:{api}/io/micronaut/kubernetes/client/openapi/watcher/WatchEvent.html[WatchEvent] class: 15 | 16 | [source, java] 17 | ---- 18 | include::kubernetes-client-openapi-watcher/src/main/java/io/micronaut/kubernetes/client/openapi/watcher/WatchEvent.java[tags=class, indent=0] 19 | ---- 20 | 21 | [cols="1,5"] 22 | |======= 23 | |*Name* |*Description* 24 | |type |The type of the streamed event. At the moment the type can be one of the following values: ADDED, MODIFIED, DELETED, ERROR, BOOKMARK 25 | |object |The data for the watched object (V1Namespace, V1Pod etc.). The value will be empty only if the event type is `ERROR` 26 | |status |The instance of V1Status which won't be empty only if the event type is `ERROR` 27 | |======= 28 | -------------------------------------------------------------------------------- /src/main/docs/guide/kubernetesGuides.adoc: -------------------------------------------------------------------------------- 1 | See the following list of guides to learn more about working with Kubernetes in the Micronaut Framework: 2 | 3 | https://guides.micronaut.io/latest/tag-kubernetes.html 4 | -------------------------------------------------------------------------------- /src/main/docs/guide/logging.adoc: -------------------------------------------------------------------------------- 1 | If you need to debug the Micronaut Kubernetes module, you need to set the `io.micronaut.kubernetes` logger level 2 | to `DEBUG`: 3 | 4 | [source,xml] 5 | ---- 6 | 7 | ---- 8 | 9 | By configuring the logger level to `TRACE`, the module will produce detailed responses from the Kubernetes API. 10 | 11 | [source,xml] 12 | ---- 13 | 14 | ---- 15 | 16 | Other package that might produce relevant logging is `io.micronaut.discovery`, which belongs to Micronaut Core. 17 | 18 | In addition to that, another source of information is 19 | https://docs.micronaut.io/latest/guide/index.html#environmentEndpoint[the Environment Endpoint], which outputs all 20 | the resolved ``PropertySource``s from ``ConfigMap``s, and their corresponding properties. -------------------------------------------------------------------------------- /src/main/docs/guide/releaseHistory.adoc: -------------------------------------------------------------------------------- 1 | For this project, you can find a list of releases (with release notes) here: 2 | 3 | https://github.com/{githubSlug}/releases[https://github.com/{githubSlug}/releases] -------------------------------------------------------------------------------- /src/main/docs/guide/repository.adoc: -------------------------------------------------------------------------------- 1 | You can find the source code of this project in this repository: 2 | 3 | https://github.com/{githubSlug}[https://github.com/{githubSlug}] -------------------------------------------------------------------------------- /src/main/docs/guide/toc.yml: -------------------------------------------------------------------------------- 1 | introduction: Introduction 2 | whatsNew: What's New? 3 | releaseHistory: Release History 4 | kubernetes-client: 5 | title: Kubernetes Client 6 | service-discovery: Service Discovery 7 | config-client: Configuration Client 8 | health-checks: Health Checks 9 | kubernetes-informer: Kubernetes Informer 10 | kubernetes-operator: Kubernetes Operator 11 | kubernetes-client-openapi: 12 | title: Kubernetes Client OpenAPI 13 | kubernetes-client-openapi-service-discovery: Service Discovery 14 | kubernetes-client-openapi-config-client: Configuration Client 15 | kubernetes-client-openapi-health-checks: Health Checks 16 | kubernetes-client-openapi-watcher: Kubernetes Watcher 17 | kubernetes-client-openapi-informer: Kubernetes Informer 18 | kubernetes-client-openapi-operator: Kubernetes Operator 19 | logging: Logging and debugging 20 | breaking: Breaking Changes 21 | kubernetesGuides: Guides 22 | repository: Repository 23 | -------------------------------------------------------------------------------- /src/main/docs/guide/whatsNew.adoc: -------------------------------------------------------------------------------- 1 | === Micronaut Kubernetes 7.1.0 2 | - Kubernetes Operator support for Micronaut Kubernetes Client OpenApi 3 | 4 | === Micronaut Kubernetes 7.0.0 5 | - Kubernetes Watcher support for Micronaut Kubernetes Client OpenApi 6 | - Kubernetes Informer support for Micronaut Kubernetes Client OpenApi 7 | - Kubernetes Service Discovery and Configuration Client support for Micronaut Kubernetes Client OpenApi 8 | 9 | === Micronaut Kubernetes 6.2.1 10 | - Reactive support for Micronaut Kubernetes Client OpenApi 11 | 12 | === Micronaut Kubernetes 6.2.0 13 | - Implementation of in-house kubernetes client: Micronaut Kubernetes Client OpenApi 14 | 15 | === Micronaut Kubernetes 3.0.0 16 | - Official K8s JAVA SDK client with reactive support 17 | -------------------------------------------------------------------------------- /teardown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | # 5 | # Defaults 6 | K8S_DEFAULT_VERSION="1.19" 7 | 8 | # 9 | # Resolve K8s version 10 | K8S_VERSION=${K8S_VERSION:=$K8S_DEFAULT_VERSION} 11 | echo "K8S_VERSION = $K8S_VERSION" 12 | 13 | # 14 | # Create a cluster 15 | KIND_CLUSTER=$(echo $K8S_VERSION | tr -cd '[:alnum:]') 16 | KIND_CLUSTER_NAME="k8s${KIND_CLUSTER}java${JAVA_VERSION}" 17 | ./kind delete cluster --name ${KIND_CLUSTER_NAME} || true 18 | 19 | # 20 | # Stop kubernetes API proxy 21 | pkill -9 kubectl || true -------------------------------------------------------------------------------- /test-utils/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'groovy' 4 | id("io.micronaut.build.internal.common") 5 | id 'io.micronaut.build.internal.kubernetes-tests' 6 | } 7 | 8 | dependencies { 9 | annotationProcessor mn.micronaut.inject.groovy 10 | annotationProcessor mn.micronaut.inject.java 11 | api mn.micronaut.inject.groovy 12 | api mn.micronaut.inject.java 13 | api mn.micronaut.http.client 14 | api libs.io.fabric8.kubernetes.client 15 | api mnTest.micronaut.test.spock 16 | api mnLogging.logback.classic 17 | api libs.testcontainers.k3s 18 | } 19 | -------------------------------------------------------------------------------- /test-utils/gradle.properties: -------------------------------------------------------------------------------- 1 | skipDocumentation=true -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/example-client-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: example-client 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: example-client 9 | template: 10 | metadata: 11 | labels: 12 | app: example-client 13 | spec: 14 | containers: 15 | - name: example-client 16 | image: micronaut-kubernetes-example-client 17 | imagePullPolicy: "Never" 18 | env: 19 | - name: JAVA_TOOL_OPTIONS 20 | value: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" 21 | ports: 22 | - name: http 23 | containerPort: 8082 24 | - name: "jvm-debug" 25 | containerPort: 5005 26 | livenessProbe: 27 | httpGet: 28 | port: 8082 29 | path: /health/liveness 30 | initialDelaySeconds: 2 31 | periodSeconds: 3 32 | failureThreshold: 10 33 | readinessProbe: 34 | httpGet: 35 | port: 8082 36 | path: /health/readiness 37 | initialDelaySeconds: 2 38 | periodSeconds: 3 39 | failureThreshold: 10 40 | -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/game.json: -------------------------------------------------------------------------------- 1 | { 2 | "lives": 7, 3 | "enemies": "monsters", 4 | "enemies.cheat": true, 5 | "secret": { 6 | "code": { 7 | "passphrase": "UUDDLRLRBABAS", 8 | "allowed": true, 9 | "lives": 30 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/game.properties: -------------------------------------------------------------------------------- 1 | enemies=zombies 2 | lives=5 3 | enemies.cheat=true 4 | enemies.cheat.level=noGoodRotten 5 | secret.code.passphrase=UUDDLRLRBABAS 6 | secret.code.allowed=true 7 | secret.code.lives=30 8 | -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/game.yml: -------------------------------------------------------------------------------- 1 | --- 2 | lives: 3 3 | enemies: aliens 4 | enemies.cheat: true 5 | --- 6 | enemies: 7 | cheat: 8 | level: noGoodRotten 9 | --- 10 | secret: 11 | code: 12 | passphrase: UUDDLRLRBABAS 13 | allowed: true 14 | lives: 30 15 | -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/mounted.yml: -------------------------------------------------------------------------------- 1 | mounted: 2 | foo: bar -------------------------------------------------------------------------------- /test-utils/src/main/resources/k8s/secure-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: secure-deployment 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: secure-deployment 9 | replicas: 1 10 | template: 11 | metadata: 12 | labels: 13 | app: secure-deployment 14 | spec: 15 | containers: 16 | - name: secure-deployment 17 | image: nginx 18 | ports: 19 | - containerPort: 80 20 | -------------------------------------------------------------------------------- /test-utils/src/test/groovy/io/micronaut/kubernetes/test/KubernetesSpecificationSpec.groovy: -------------------------------------------------------------------------------- 1 | package io.micronaut.kubernetes.test 2 | 3 | import io.micronaut.context.annotation.Property 4 | import io.micronaut.context.env.Environment 5 | import io.micronaut.test.extensions.spock.annotation.MicronautTest 6 | import spock.lang.Requires 7 | 8 | @MicronautTest(environments = [Environment.KUBERNETES]) 9 | @Requires({ TestUtils.kubernetesApiAvailable() }) 10 | class KubernetesSpecificationSpec extends KubernetesSpecification{ 11 | 12 | def "it created example service"(){ 13 | expect: 14 | def deployment = operations.getDeployment("example-service", namespace) 15 | deployment.status.availableReplicas == 2 16 | } 17 | 18 | def "it created example client"(){ 19 | expect: 20 | def deployment = operations.getDeployment("example-client", namespace) 21 | deployment.status.availableReplicas == 1 22 | } 23 | 24 | def "it created secure deployment"(){ 25 | expect: 26 | def deployment = operations.getDeployment("secure-deployment", namespace) 27 | deployment.status.availableReplicas == 1 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test-utils/src/test/resources/k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: example-client 5 | namespace: test-namespace 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: example-client 10 | template: 11 | metadata: 12 | labels: 13 | app: example-client 14 | spec: 15 | containers: 16 | - name: example-client 17 | image: nginx 18 | env: 19 | - name: JAVA_TOOL_OPTIONS 20 | value: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" 21 | ports: 22 | - name: http 23 | containerPort: 8082 24 | - name: "jvm-debug" 25 | containerPort: 5005 26 | -------------------------------------------------------------------------------- /test-utils/src/test/resources/k8s/game.yml: -------------------------------------------------------------------------------- 1 | --- 2 | lives: 3 3 | enemies: aliens 4 | enemies.cheat: true 5 | --- 6 | enemies: 7 | cheat: 8 | level: noGoodRotten 9 | --- 10 | secret: 11 | code: 12 | passphrase: UUDDLRLRBABAS 13 | allowed: true 14 | lives: 30 15 | -------------------------------------------------------------------------------- /test-utils/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} %gray([core]) [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | 25 | --------------------------------------------------------------------------------