kubernetes-client / java

Official Java client library for kubernetes
http://kubernetes.io/
Apache License 2.0
3.57k stars 1.9k forks source link

How to create custom object with a provided yaml spec? #995

Closed dbrat43 closed 3 years ago

dbrat43 commented 4 years ago

Hi,

I am trying to dynamically create a namespaced custom object using the documentation provided here: https://github.com/kubernetes-client/java/blob/master/kubernetes/docs/CustomObjectsApi.md#createNamespacedCustomObject

When attempting to pass in my json body as a String into the method, I get the following json parse error:

{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"the object provided is unrecognized (must be of type NetworkPolicy): couldn't get version/kind; json parse error: json: cannot unmarshal string into Go value of type struct { APIVersion string \"json:\\\"apiVersion,omitempty\\\"\"; Kind string \"json:\\\"kind,omitempty\\\"\" } (227b5c6e20205c2261706956657273696f6e5c223a205c2270726f6a6563 ...)","reason":"BadRequest","code":400}

This is my helper method that I'm using to call the CustomObjectsApi:

public Object createKubernetesCustomObject(final String group, final String version, final String namespace, final String plural, final String resourceYaml) throws KubernetesClientException {

    log.info("Received request for namespace: {}, and resource yaml: {} for create kubernetes custom object", namespace, resourceYaml);
    try {

        Object customObject = customObjectsApi.createNamespacedCustomObject(group, version, namespace, plural, resourceYaml, null, null, null);
        return customObject;

    } catch (ApiException e) {

        log.error("Kubernetes ApiException while creating service with code: {}, response body: {}, response headers: {}. Possible error: {}",
                e.getCode(), e.getResponseBody(), e.getResponseHeaders(), K8S_API_ERROR_MESSAGE, e);
        throw new KubernetesClientException(CREATE_SERVICE_FAILURE);
    } catch (Exception e) {

        log.error("Exception while creating a service. Possible error: {}", K8S_RESOURCE_ERROR_MESSAGE, e);
        throw new KubernetesClientException(CREATE_SERVICE_FAILURE);
    }
}

This is the sample json that I'm attempting to create an object with:

{
  "apiVersion": "projectcalico.org/v3",
  "kind": "NetworkPolicy",
  "metadata": {
    "name": "default.spark-shared-network-policy",
    "namespace": "my-namespace"
  },
  "spec": {
    "tier": "default",
    "selector": "fleet == 'spark-cluster'",
    "types": [
      "Egress"
    ],
    "egress": [
    {
      "action": "Allow",
      "protocol": "TCP",
      "destination": {
        "nets": [
          "9.9.9.9/32"
        ],
        "ports": [
          50070,
          50470
        ]
      }
    }
    ]
  }
}

I also attempted to pass in the below yaml itself, however I got the same error as above:

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: default.spark-shared-network-policy
  namespace: my-namespace
spec:
  tier: default
  selector:
    fleet == 'spark-cluster'
  types:
    - Egress
  egress:
    - action: Allow 
      protocol: TCP
      destination:
        nets:
          - 9.9.9.9/32
        ports:
          - 50070
          - 50470

We are using the Kubernetes client library to generate Kube-native objects in the same class without any issues and I am confident that my json does not have any syntax issues, so I have the following questions:

yue9944882 commented 4 years ago

Am I calling the createNamespacedCustomObject() method correctly?

i think so

Am I passing in my String json body into the object body correctly, or should I be using a different object to make it work?

no need to cast the resource to json content before calling createNamespacedCustomObject, just passing the object as parameter will work.

dbrat43 commented 4 years ago

I would also like to point out that I was able to manually apply the above yaml to my Kubernetes cluster which supports the Calico NetworkPolicy custom resource, validating that the yaml does not have any syntactical issues itself. Here is an example of what a Calico NetworkPolicy should look like: https://docs.projectcalico.org/reference/resources/networkpolicy

My basic understanding of the Go error listed above is that the custom yaml I am providing is being parsed into a struct, however since I am specifying NetworkPolicy as the kind, it is attempting to parse it into the kube-native network policy which has a different structure from the custom Calico policy object I am trying to create, thus failing, however please correct me if I'm wrong.

If it looks like I'm doing things correctly on my end, is there an end-to-end example (code, sample yaml / json) of the steps that need to be taken to dynamically create a custom object in Java to help me identify the deltas? And if there is no end-to-end example, can you please advise what my next steps should be to ensure that I can create this custom object?

brendandburns commented 4 years ago

You need to either write the custom object yourself just like any other Java class, or if Calico provides an openapi spec for their objects you can use the instructions here:

https://github.com/kubernetes-client/java/blob/master/docs/generate-model-from-third-party-resources.md

To create the CRD objects.

But it's probably just easier to hand-code the Java object corresponding to the calico network policy.

dbrat43 commented 4 years ago

Will try it out. Thanks!

mattsanta commented 4 years ago

@brendanburns, what if you don't know the structure of the CRD so you can't create a POJO for it beforehand?

Is there something similar to the CustomResource Typeless API in the fabric8io kubernetes client?

fejta-bot commented 3 years ago

Issues go stale after 90d of inactivity. Mark the issue as fresh with /remove-lifecycle stale. Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle stale

brendandburns commented 3 years ago

@mattsanta sorry, I missed this from a long time ago! There is the GenericAPI which can use for this.

fejta-bot commented 3 years ago

Stale issues rot after 30d of inactivity. Mark the issue as fresh with /remove-lifecycle rotten. Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle rotten

fejta-bot commented 3 years ago

Rotten issues close after 30d of inactivity. Reopen the issue with /reopen. Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /close

k8s-ci-robot commented 3 years ago

@fejta-bot: Closing this issue.

In response to [this](https://github.com/kubernetes-client/java/issues/995#issuecomment-754141388): >Rotten issues close after 30d of inactivity. >Reopen the issue with `/reopen`. >Mark the issue as fresh with `/remove-lifecycle rotten`. > >Send feedback to sig-testing, kubernetes/test-infra and/or [fejta](https://github.com/fejta). >/close Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.