Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sample For Dynamic Admission Controller with that uses a Custom Resource #95

Closed
csviri opened this issue Apr 7, 2023 · 7 comments
Closed

Comments

@csviri
Copy link
Contributor

csviri commented Apr 7, 2023

No description provided.

@sflandergan
Copy link

sflandergan commented Apr 26, 2023

Not sure if this is the right way but this is how I got the REST endpoint working:

import com.fasterxml.jackson.databind.ObjectMapper
import io.fabric8.kubernetes.api.model.GenericKubernetesResource
import io.fabric8.kubernetes.api.model.Namespaced
import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview
import io.fabric8.kubernetes.client.CustomResource
import io.fabric8.kubernetes.model.annotation.Group
import io.fabric8.kubernetes.model.annotation.Kind
import io.fabric8.kubernetes.model.annotation.Version
import io.javaoperatorsdk.webhook.admission.AdmissionController
import io.javaoperatorsdk.webhook.admission.validation.Validator
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.web.bind.annotation.RestController


@Group("mygroup")
@Kind("Sample")
@Version("v1")
class SampleCustomResource: CustomResource<Sample, SampleStatus>(), Namespaced

data class Sample(val field: String)

data class SampleStatus(val field: String)


@RestController
class SampleCustomResourceWebhookEndpoint(private val admissionController: AdmissionController<GenericKubernetesResource>) {
    @PostMapping("/validate")
    @ResponseBody
    fun validate(@RequestBody admissionReview: AdmissionReview): AdmissionReview =
            admissionController.handle(admissionReview)

}

@Configuration
class SampleCustomResourceWebHookConfiguration {

    @Bean
    fun admissionController(objectMapper: ObjectMapper): AdmissionController<GenericKubernetesResource> {
        return AdmissionController<GenericKubernetesResource>(Validator { resource: GenericKubernetesResource, _ ->
            val sampleResource = objectMapper.convertValue(resource.additionalProperties, SampleCustomResource::class.java)
            // do your validation here
        })
    }
}

When I send this http request:

{
    "request": {
        "name": "sample",
        "namespace": "default",
        "object": {
            "apiVersion": "mygroup/v1",
            "kind": "Sample",
            "spec": {
                "field": "hello"
            }
        },
        "operation": "CREATE"
    }
}

I get a proper response:

{
    "apiVersion": "admission.k8s.io/v1",
    "kind": "AdmissionReview",
    "response": {
        "allowed": true
    }
}

If I don't go via the GenericKubernetesResource I get a ClassCastException:

java.lang.ClassCastException: class io.fabric8.kubernetes.api.model.GenericKubernetesResource cannot be cast to class com.deviceinsight.sample.SampleCustomResource (io.fabric8.kubernetes.api.model.GenericKubernetesResource and com.deviceinsight.sample.SampleCustomResource are in unnamed module of loader 'app')

Would be great if the framework could handle the conversion from GenericKubernetesResource to the CustomResource itself

@csviri
Copy link
Contributor Author

csviri commented Apr 26, 2023

@sflandergan AFAIk GenericKubernetesResource serves a different purpose, it is intended to represent any resource in a generic way in fabric8 client. It's not meant to be a generic super class.
What you are probably searching for is HasMetadata instead.

@sflandergan
Copy link

@csviri not really.
With HasMetadata I wouldn't be able to access the CustomResource's spec.
That is stored within the additionalProperties field.

AdmissionReview.request.object is serialized as GenericKubernetesResource internally by the kubernetes-webhooks-framework.

@csviri
Copy link
Contributor Author

csviri commented Apr 26, 2023

AdmissionReview.request.object is serialized as GenericKubernetesResource internally by the kubernetes-webhooks-framework.

Just if it cannot serialize to a proper resource. Because your resources is not registered for serialization.

If you are dealing just with custom resource you can use CustomResource as base class to access spec

@csviri
Copy link
Contributor Author

csviri commented Apr 26, 2023

see: https://github.com/java-operator-sdk/kubernetes-webooks-framework/tree/main/docs#using-custom-resources-in-the-api

@sflandergan
Copy link

Thanks for the input @csviri
Unfortunately that does not work for me java.lang.ClassCastException: class com.deviceinsight.sample.SampleCustomResource cannot be cast to class com.deviceinsight.sample.SampleCustomResource

Maybe this is related to fabric8io/kubernetes-client#5034

@sflandergan
Copy link

Just found out this comes from spring-boot-devtools.
When I remove the dependency it works :).
Thanks a lot!

@csviri csviri closed this as completed Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants