Having trouble to patch a job in kubernetes using postman - kubernetes

Created a job in kubernetes using post method using postman, now trying to patch the same job using patch method using postman and i am getting 400 bad request.
Headers for post: Content-type application/yaml
post method body:
---
apiVersion: batch/v1
kind: Job
metadata:
name: pi
labels:
app: dev
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
Headers for patch : Content-type application/strategic-merge-patch+json
Content-Type in Headers
patch request body:
{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": {
"name": "pi"
},
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "pi",
"image": "perl",
"command": [
"perl",
"-Mbignum=bpi",
"-wle",
"print bpi(2000)"
]
}
],
"restartPolicy": "Never"
}
},
"backoffLimit": 5
}
}
Changed body please check the link.
body of the patch request
Modification i did was changed backofflimit to 5.
I was able to post and patch other resources like services and deployments but i am stuck at patching a job, I followed exactly same steps for others as well.
error i am getting error

With 'strategic-merge-patch+json' type you should use in the Request body just this json patch:
{"spec":{"backoffLimit": 7}}
As your intent is to merge/replace existing object's value based on backoffLimit key.
Check documentation for example usage of strategic-merge-patch to update resources.
Update
Please try yourself with curl:
Start local Kubernetes proxy server: kubectl proxy
curl -k -v -XPATCH -H "Content-Type: application/strategic-merge-patch+json" --data '{"spe":{"backoffLimit": 9}}' http://localhost:8001/apis/batch/v1/namespaces/default/jobs/pi
Output:
< HTTP/1.1 200 OK <-patch succeeded
< Audit-Id: 02d97d05-2bfb-4500-ac34-c8eb04ff8503
< Content-Length: 1795
< Content-Type: application/json
< Date: Fri, 12 Jul 2019 13:54:37 GMT
<
{
"kind": "Job",
"apiVersion": "batch/v1",
"metadata": {
"name": "pi",
"namespace": "default",
"selfLink": "/apis/batch/v1/namespaces/default/jobs/pi",
"uid": "5ac61d6d-a4a0-11e9-abc7-42010a80012c",
"resourceVersion": "4339038",
"creationTimestamp": "2019-07-12T12:27:03Z",
"labels": {
"app": "dev"
}
},
"spec": {
"parallelism": 1,
"completions": 1,
"backoffLimit": 9 <-patch succeeded
,

With Content-Type as application/strategic-merge-patch+json
and with body
{ "spec": { "backoffLimit": 7 }}
I have recreated the request and it worked fine.
Things that went wrong first time is that even though "content-type" is mentioned in headers correctly as "application/strategic-merge-patch+json" postman is taking a wrong Content-type, so i deleted the request and recreated the patch request with same body and headers it worked perfectly.

Related

oc / kubernetes: deployment returns "unrecognized type: string" while adding environment variables

We are deploying with Ansible scripts to Openshift 3 using oc apply. When we change template to add more environment variables, we receive a very vague error: "unrecognized type: string" and status code 500.
Setting --loglevel 10 leads to no more details:
$ /usr/local/bin/oc_v3.11.715 apply -f \"/tmp/ansible.YtEqVm_deploy/app.yml.json\" -n test-env --loglevel 10 2&> log.log
(several GET to get secret, deploymentconfigs, etc.)
...
I0127 11:49:05.455217 605 request.go:897] Request Body: {xxxxxxxx}
I0127 11:49:05.455280 605 round_trippers.go:386] curl -k -v -XPATCH -H "User-Agent: oc_v3.11.715/v1.11.0+d4cacc0 (linux/amd64) kubernetes/d4cacc0" -H "Authorization: Bearer xxxxxx" -H "Accept: application/json" -H "Content-Type: application/strategic-merge-patch+json" 'https://test-env:8443/apis/apps.openshift.io/v1/namespaces/test-app/deploymentconfigs/app'
I0127 11:49:05.466278 605 round_trippers.go:405] PATCH https://test-env:8443/apis/apps.openshift.io/v1/namespaces/test-env-app/deploymentconfigs/app 500 Internal Server Error in 10 milliseconds
I0127 11:49:05.466287 605 round_trippers.go:411] Response Headers:
I0127 11:49:05.466291 605 round_trippers.go:414] Content-Length: 118
I0127 11:49:05.466294 605 round_trippers.go:414] Date: Fri, 27 Jan 2023 09:49:05 GMT
I0127 11:49:05.466297 605 round_trippers.go:414] Audit-Id: 1d3f3398-14fc-4bfa-854b-6faf9b105680
I0127 11:49:05.466302 605 round_trippers.go:414] Cache-Control: no-store
I0127 11:49:05.466307 605 round_trippers.go:414] Content-Type: application/json
I0127 11:49:05.466321 605 request.go:897] Response Body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"unrecognized type: string","code":500}
I0127 11:49:05.466603 605 helpers.go:201] server response object: [{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "unrecognized type: string",
"code": 500
}]
F0127 11:49:05.466618 605 helpers.go:119] Error from server: unrecognized type: string
The request body is like:
{
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
},
"spec": {
"template": {
"spec": {
"$setElementOrder/containers": [{
"name": "app"
}],
"containers": [{
"$setElementOrder/env": [{
"name": "OLD_VAR_1"
}, {
"name": "OLD_VAR_2"
}, {
"name": "OLD_VAR_3"
}, {
"name": "OLD_VAR_4"
}, {
"name": "NEW_VAR_1"
}, {
"name": "NEW_VAR_2"
}, {
"name": "NEW_VAR_3"
}],
"dnsPolicy": "ClusterFirst",
"env": [{
"name": "OLD_VAR_4",
"value": false
}, {
"name": "NEW_VAR_1",
"value": 10
}, {
"name": "NEW_VAR_2",
"value": 20
}, {
"name": "NEW_VAR_3",
"value": 6
}],
"name": "app",
"restartPolicy": "Always",
"terminationGracePeriodSeconds": 300
}]
}
}
}
}
OLD_VAR_x are old environment variables; we want to add NEW_VAR_[1-3]. Notice strangely that not all old vars are in env, only OLD_VAR_4, but all new vars are in env.
This also happens when we use oc patch with the same request body. Same error response.
What is wrong?
A workaround is first, deployment, fail, and add new vars in Openshift manually, and deploy in Openshift webconsole on top of the last, failed deployment. It works.
Solved by quoting the var values in the template, like:
- name: NEW_VAR_X
value: "${NEW_VAR_VALUE_X}"
No errors ever since.

PUT k8s deployment returns 404

According to the Replacement section of Kubernetes API reference v1.24 I should be able to create a deployment with a PUT /apis/apps/v1/namespaces/{namespace}/deployments/{name} HTTP request. The success response here is 201 Created. However, when I try the following, I get a 404 Not Found which is of course correct but unwanted: PUT requests should be treated as Create statements if the resource does not yet exist as documented. Updating a deployment does work (and returns the expected 200 OK HTTP response). Is there any documentation regarding this? Or is the request somehow incorrect? Ty.
➜ ~ curl --request PUT \
--url http://localhost:8080/apis/apps/v1/namespaces/ns/deployments/nginx-deployment \
--header 'content-type: application/json' \
--data '{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec": {
"replicas" : 3,
"selector": {
"matchLabels" : {
"app":"nginx"
}
},
"template" : {
"metadata" : {
"labels" : {
"app":"nginx"
}
},
"spec":{
"containers":[
{
"name":"ngnix",
"image":"nginx:1.7.9",
"ports":[
{
"containerPort": 80
}
]
}
]
}
}
}
}'
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "deployments.apps \"nginx-deployment\" not found",
"reason": "NotFound",
"details": {
"name": "nginx-deployment",
"group": "apps",
"kind": "deployments"
},
"code": 404
}%
According to the documentation you provided,
PUT /apis/apps/v1/namespaces/{namespace}/deployments/{name}
is meant to "replace the specified Deployment", while a Deployment is created with a POST:
create a Deployment
HTTP Request
POST /apis/apps/v1/namespaces/{namespace}/deployments
You are correct that the documentation also states:
For PUT requests, Kubernetes internally classifies these as either create or update based on the state of the existing object
so there seems to be a contradiction, but the Deployment API spec states that POST should be used to create a deployment and PUT to update it.

Kubernetes API server filtering by field - in request time

I'm trying to get all the secrets in the cluster of type helm.sh/release.v1:
$ curl -X GET $APISERVER/api/v1/secrets --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "SecretList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/secrets",
"resourceVersion": "442181"
},
"items": [
{
"metadata": {
...
},
"data": {
...
},
"type": "helm.sh/release.v1"
},
{
"metadata": {
...
},
"data": {
...
},
"type": "kubernetes.io/service-account-token"
},
{
"metadata": {
...
},
"data": {
...
},
"type": "kubernetes.io/service-account-token"
},
...
}
I can use the command above and then filter by myself (jq or whatever) but I wonder if there's an option to filter in the API by adding query parameters or something, for example (didn't work):
curl -X GET $APISERVER/api/v1/secrets?type=<value>
any idea how to filter by specific field? (type) can I also request specific fields in the response (if I don't care about the data for instance)?
I'm going to use HTTP requests from my application (python) that runs
within a pod in the cluster. I am trying to be more efficient and ask
only for what I need (only specific type and not all secrets in the
cluster)
If your application is written in Python, maybe it's a good idea to use Kubernetes Python Client library to get the secrets ?
If you want to get all the secrets in the cluster of type helm.sh/release.v1, you can do it with the following Python code:
from kubernetes import client , config
config.load_kube_config()
v1 = client.CoreV1Api()
list_secrets = v1.list_secret_for_all_namespaces(field_selector='type=helm.sh/release.v1')
If you also want to count them, use:
print(len(list_secrets.items))
to print secret's name use:
print(list_secrets.items[0].metadata.name)
to retrieve it's data:
print(list_secrets.items[0].data)
and so on...
More details, including arguments that can be used with this method, you can find here (just search for list_secret_for_all_namespaces):
# **list_secret_for_all_namespaces**
> V1SecretList list_secret_for_all_namespaces(allow_watch_bookmarks=allow_watch_bookmarks, _continue=_continue, field_selector=field_selector, label_selector=label_selector, limit=limit, pretty=pretty, resource_version=resource_version, timeout_seconds=timeout_seconds, watch=watch)

How to update secret with "kubectl patch --type='json'"

I created a secret like this:
kubectl create secret generic test --from-literal=username=testuser --from-literal=password=12345
I want to update the username to testuser2 but I want to do it only with kubectl patch --type='json'.
This is how I tried to do it:
kubectl patch secret test --type='json' -p='[{"data":{"username": "testuser 2"}}]' -v=1
But I received:
The "" is invalid
Remember, I want to do it with the option of --type='json', no other workarounds.
I found how to do it after I read here that referred me to this great article.
This is the JSON secret:
{
"apiVersion": "v1",
"data": {
"password": "aWx1dnRlc3Rz",
"username": "dGVzdHVzZXI="
},
"kind": "Secret",
"metadata": {
"creationTimestamp": "2019-04-18T11:37:09Z",
"name": "test",
"namespace": "default",
"resourceVersion": "3017",
"selfLink": "/api/v1/namespaces/default/secrets/test",
"uid": "4d0a763e-61ce-11e9-92b6-0242ac110015"
},
"type": "Opaque"
}
Therefore, to update the user's field I needed to create the JSON Patch format:
[
{
"op" : "replace" ,
"path" : "/data/username" ,
"value" : "dGVzdHVzZXIy" # testuser2 in base64
}
]
Notice that the value should be in base64.
The result is:
kubectl patch secret test --type='json' -p='[{"op" : "replace" ,"path" : "/data/username" ,"value" : "dGVzdHVzZXIy"}]'
This is what I do in order to replace the secret:
kubectl patch secret my-secret --patch="{\"data\": { \"NEW_PASSWORD\": \"$(echo -n mypassword |base64 -w0)\" }}" -oyaml
This command solved my issue on version 1.24.x:
kubectl patch secret app-sec --patch="{\"data\": { \"license-id\": \"TEST\" }}" -oyaml

How can I set a node to unschedulable status via the Kubernetes api?

I am attempting to emulate the behavior of kubectl patch. I'm sending an HTTP PATCH with a json payload of the following:
{
"apiVersion": "v1",
"kind": "Node",
"metadata": {
"name": "my-node-hostname"
},
"spec": {
"unschedulable": true
}
}
However, no matter how I seem to tweak this JSON, I keep getting a 415 and the following JSON status back:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "the server responded with the status code 415 but did not return more information",
"details": {},
"code": 415
}
Even with debug on kube-apiserver set to 1000, I get no feedback about why the payload is wrong!
Is there a particular format that one should use in the JSON payload sent via PATCH to enable this to work?
After a helpful member of the Kubernetes Slack channel mentioned I could get the payload from kubectl patch via the --verbose flag, it turns out that Kubernetes expects to get "Content-Type: application/strategic-merge-patch+json" when you are sending the PATCH payload.