-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Unable to update status on Custom Resources #1548
Comments
@kolorful : Have u tried our raw custom resource api? It's somewhat less typed and allows you to get, delete, create and edit custom resources without pojos. Here is an example: Lines 36 to 50 in c78cc4d
|
Are you facing problems with creating Custom Resource Definition or Custom Resource? |
I haven't tried creating the CRD using this client, I created the CRD via kubectl with a yaml file I wrote. |
So you're facing problems with creating custom resource. Would you like to try this new raw custom resource api which was added recently and see if it helps. It's available in v4.2.2 |
I'm able to create the custom resource, but cannot update its status via patch. I'll give the new API a try |
I tried the latest endpoint and I converted my pojo to string using json:
But I got an error when trying to create the CR, and it didn't give much details
Hmm, I tried Cronjob instead of my CR, looks like it doesn't work either. I went back and checked client-go and it seems linke only the UpdateStatus endpoint works.
|
We didn't have problems with setting status on our CR using the typed API. Status isn't a special thing in the Kubernetes API so the same rules should apply to it than any other field. I do see that our classes look quite different from your CR mapping classes:
|
@adam-sandor thanks for your input. I tried that and doesn't work either. I then did a round of tests and I think the problem lies in my CRD yaml file. The only difference appear to be the working one doesn't have:
Once I have this set, my status patching no longer works. This seems to be an expected behavior, because |
If I can add to this. According to https://blog.openshift.com/kubernetes-custom-resources-grow-up-in-v1-10/, one of the key benefits of defining the status property as the standard '/status' subresource is that updates to the status won't increment the metadata.generation property. This property will only get updated when the spec gets updated. This is extremely useful for cases where the custom controller needs to update the status without triggering an unintended sync. @adam-sandor I would therefor say that perhaps the /status subresource, as well as the /scale subresource is something special in K8S, and from the above document it would seem that they even have their own resource URL's where they can be updated, e.g. "/apis/example.com/v1/namespaces/default/databases/mysql/status". From what I can see it would seem that the Fabric8 Java client doesn't support PUTs to the url of the subresource. |
#417 seems related, i'm also looking for this :) |
This issue has been automatically marked as stale because it has not had any activity since 90 days. It will be closed if no further activity occurs within 7 days. Thank you for your contributions! |
this is still relevant, is it not? there still is no proper subresource support |
i am currently using a quick and dirty workaround for this: final String statusUri = URLUtils.join(client.getMasterUrl().toString(), "apis", "myclass.com", "v1", "namespaces",
namespace, "my-objects", name, "status");
infoClass.setStatus(status);
final RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), mapper.writeValueAsBytes(infoClass));
baseClient.getHttpClient().newCall(new Request.Builder()
.method("PUT", requestBody)
.url(statusUri)
.build())
.execute()
.close(); and then ignoring watcher |
Hmm, I see. Let me try to prioritize this. |
Thank you! |
Trying to use this feature. |
@novakov-alexey I believe updating the Status of an CR or in general updating a subresouce of any type of resources won't trigger a Modify event in watcher, because the whole point is not needing to update the generation of the resource. |
@kolorful it corresponds to my understanding as well. However, I am getting Modify event on live Kubernetes (not mock server) with the same generation number, when I am updating the CR Status, which is strange. 😞 I will try to prepare abstract reproducible code example. |
While implementation i just followed https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#subresources i would check for the modify event and report back |
@rohanKanojia There is an example where I get Modified event, which I would like to not have: import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import io.fabric8.kubernetes.api.model.apiextensions.{CustomResourceDefinition, CustomResourceDefinitionBuilder}
import io.fabric8.kubernetes.api.model.{HasMetadata, ObjectMetaBuilder}
import io.fabric8.kubernetes.client._
import io.fabric8.kubernetes.client.dsl.{NonNamespaceOperation, Resource}
import io.fabric8.kubernetes.client.utils.Serialization
import io.fabric8.kubernetes.internal.KubernetesDeserializer
import io.fabric8.kubernetes.api.builder.Function
import io.fabric8.kubernetes.client.CustomResourceDoneable
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.fabric8.kubernetes.client.CustomResourceList
import io.fabric8.kubernetes.client.CustomResource
class AnyCrDoneable(val resource: AnyCustomResource, val f: Function[AnyCustomResource, AnyCustomResource])
extends CustomResourceDoneable[AnyCustomResource](resource, f)
@JsonDeserialize(using = classOf[KubernetesDeserializer]) class AnyCrList
extends CustomResourceList[AnyCustomResource]
class AnyCustomResource extends CustomResource {
private var spec: AnyRef = _
private var status: AnyRef = _
def getSpec: AnyRef = spec
def setSpec(spec: AnyRef): Unit =
this.spec = spec
def getStatus: AnyRef = status
def setStatus(status: AnyRef): Unit =
this.status = status
override def toString: String =
super.toString + s", spec: $spec, status: $status"
}
def createWatch(
kerbClient: NonNamespaceOperation[
AnyCustomResource,
AnyCrList,
AnyCrDoneable,
Resource[AnyCustomResource, AnyCrDoneable]
]
): Watch = {
kerbClient.watch(new Watcher[AnyCustomResource]() {
override def eventReceived(action: Watcher.Action, resource: AnyCustomResource): Unit =
println(s"received: $action for $resource")
override def onClose(cause: KubernetesClientException): Unit =
println(s"watch is closed, $cause")
})
}
private def newCr(crd: CustomResourceDefinition, spec: AnyRef) = {
val anyCr = new AnyCustomResource
anyCr.setKind(crd.getSpec.getNames.getKind)
anyCr.setApiVersion(s"${crd.getSpec.getGroup}/${crd.getSpec.getVersion}")
anyCr.setMetadata(
new ObjectMetaBuilder()
.withName("test-kerb")
.build()
)
anyCr.setSpec(spec)
anyCr
}
Serialization.jsonMapper().registerModule(DefaultScalaModule)
Serialization.jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
val prefix = "io.github.novakov-alexey"
val version = "v1"
val apiVersion = prefix + "/" + version
val kind = classOf[Kerb].getSimpleName
val plural = "kerbs"
KubernetesDeserializer.registerCustomKind(apiVersion, kind, classOf[AnyCustomResource])
KubernetesDeserializer.registerCustomKind(apiVersion, s"${kind}List", classOf[CustomResourceList[_ <: HasMetadata]])
val client = new DefaultKubernetesClient
val crd = new CustomResourceDefinitionBuilder()
.withApiVersion("apiextensions.k8s.io/v1beta1")
.withNewMetadata
.withName(plural + "." + prefix)
.endMetadata
.withNewSpec
.withNewNames
.withKind(kind)
.withPlural(plural)
.endNames
.withGroup(prefix)
.withVersion(version)
.withScope("Namespaced")
.withPreserveUnknownFields(false)
.endSpec()
.build()
val kerbClient = client
.customResource(crd, classOf[AnyCustomResource], classOf[AnyCrList], classOf[AnyCrDoneable])
.inNamespace("test")
val watch = createWatch(kerbClient)
val kerb = Kerb("test.realm", Nil, failInTest = true)
val anyCr = newCr(crd, kerb.asInstanceOf[AnyRef])
kerbClient.delete(anyCr)
Thread.sleep(1000)
val cr = kerbClient.createOrReplace(anyCr)
Thread.sleep(1000)
anyCr.setStatus(Status(true).asInstanceOf[AnyRef])
anyCr.getMetadata.setResourceVersion(cr.getMetadata.getResourceVersion)
kerbClient.updateStatus(anyCr)
Thread.sleep(1000)
watch.close() Result in the watcher:
|
@rohanKanojia do you think you could help with above question? |
@novakov-alexey: Hi, I also tested this locally on my minikube instance with Kubernetes 1.17.0 and looks like you're right. I'm also seeing Modified event being triggered when I do status update. I think this is something handled by kubernetes and Fabric8 client doesn't play any role in it. We just hit k8s server with |
@rohanKanojia thank you for confirmation. I see that even your Kubernetes version is newer. I also tend to think that this behaviour is up to Kubernetes. |
Hello, I was recently work on a CRD, but I was not able to set the Status on the CR. I've tried a couple of things and this is what I find:
I'm clueless right now, and any help would be awesome, thanks!
Anacron.java
AnacronList.java
AnacronSpec.java
AnacronStatus.java
DoneableAnacron.java
Client Initialization
The text was updated successfully, but these errors were encountered: