Error while applying JSON Patch to Kubernetes Custom Resource - kubernetes

I have an instance of a Kubernetes Custom Resource that I want to patch via the Kubernetes API using a JSON patch.
This is my PATCH request:
PATCH /apis/example.com/v1alpha1/namespaces/default/mycrd/test HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json
[other headers omitted for brevity...]
[
{"op": "replace", "path": "/status/foo", value: "bar"}
]
I'm fairly certain that my request body is a valid JSON patch, and I've previously already successfully updated core (non-CRD) API resources using similar API calls. The CRD has a openAPIV3Schema defined that explicitly allows .status.foo to exist and to be of type string.
The request above is declined by the Kubernetes API server with the following response:
HTTP/1.1 422 Unprocessable Entity
Conent-Type: application/json
[other headers omitted for brevity...]
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "the server rejected our request due to an error in our request",
"reason": "Invalid",
"details": {},
"code": 422
}
According to the CRD documentation, CRDs should support PATCH request with the application/json-patch+json content type. But for some reason, the request appears to be invalid without Kubernetes bothering to tell me why. The API server pod did not have any relevant messages in its log stream, either.
The same error also occurs when using kubectl patch on the command line:
$ kubectl patch mycrd.example.com test --type=json -p '[{"op": "replace", "path": "/status/foo", "value": "bar"}]'
The "" is invalid
What are possible reasons for this error to occur? What options to I have for further debugging?

Found the (or at least, a partial) answer while still typing the question...
The Kubernetes API server will not recursively create nested objects for a JSON patch input. This behaviour is consistent with the JSON Patch specification in RFC 6902, section A.12:
A.12. Adding to a Nonexistent Target
An example target JSON document:
{ "foo": "bar" }
A JSON Patch document:
[
{ "op": "add", "path": "/baz/bat", "value": "qux" }
]
This JSON Patch document, applied to the target JSON document above,
would result in an error (therefore, it would not be applied),
because the "add" operation's target location that references neither
the root of the document, nor a member of an existing object, nor a
member of an existing array.
This is why the original request fails, when the Custom Resources does not have a .status property to begin with. The following two subsequent calls (the second one being the original one) will complete successfully:
$ kubectl patch mycrd.example.com test --type=json \
-p '[{"op": "replace", "path": "/status", "value": {}}]'
mycrd.example.com/test patched
$ kubectl patch mycrd.example.com test --type=json \
-p '[{"op": "replace", "path": "/status/foo", "value": "bar"}]'
mycrd.example.com/test patched
Obviously, replaceing the entire .status property with {} is not a good idea if that property already contains data that you want to keep.
A suitable alternative to a JSON patch in this scenario is a JSON Merge Patch:
PATCH /apis/example.com/v1alpha1/namespaces/default/mycrd/test HTTP/1.1
Accept: application/json
Content-Type: application/merge-patch+json
[other headers omitted for brevity...]
{
"status": {
"foo": "bar"
}
}
Or, alternatively, using kubectl:
$ kubectl patch mycrd.example.com test --type=merge \
-p '{"status": {"foo": "bar"}}'
mycrd.example.com/test patched

Related

wso2api manager 4.0 with Post Request Error: Not Found

I want to secure .net core api with wso2 api manager ,for that i have enabled swagger on the api and able to get post response . I have created Api with swagger defination
http://localhost:5000/swagger/v1/swagger.json
and given endpoint http://localhost:5000/api/BigData which will get response in swagger ui
now i am trying to test with api working with token for that wso2api showing error
curl request from wso2-am
curl reuqest semding from wso2-am ```curl -X 'POST' \
'http://localhost:8280/api/v1/api/BigData' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Internal-Key: eyJraWQiOiJnYXRld2F5X2NlcnRpZmljYXRlX2FsaWFzIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbkBjYXJib24uc3VwZXIiLCJpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvdG9rZW4iLCJrZXl0eXBlIjoiUFJPRFVDVElPTiIsInN1YnNjcmliZWRBUElzIjpbeyJzdWJzY3JpYmVyVGVuYW50RG9tYWluIjpudWxsLCJuYW1lIjoiQmlnRGF0YUFQSSIsImNvbnRleHQiOiJcL2FwaVwvdjEiLCJwdWJsaXNoZXIiOiJhZG1pbiIsInZlcnNpb24iOiJ2MSIsInN1YnNjcmlwdGlvblRpZXIiOm51bGx9XSwiZXhwIjoxNjI0OTIyMzg3LCJ0b2tlbl90eXBlIjoiSW50ZXJuYWxLZXkiLCJpYXQiOjE2MjQ4NjIzODcsImp0aSI6ImZiYjQ2OGQ0LWUyOTItNGEyZC1hZmEzLTdhNzFlODUxNTlhNCJ9.Xkz9jigCPs3I65kI40rigE6L8mA-w4kks3n7Cabahg1dMVEo8AVs64PXuKBshucuT_vk5ms-7wFiIiI0pdXrL1ymOlEacBtW2r1F-WvV7o9SVw6lpF4EQNsIFi96Exe5Gg0k2wSaG1iErJ2P8boOQGI66fudGfjC-Gt1RJxfE-ZwQ_aS7fNur4G7HFAbBOdSq3yNDWjsMiv9k4IBlQ-IkJj88zSM6eXnHbtiAJKB84bAkFX7PDxXzjdItGkTKBx2oW11SO27xvqlrlJCHh6dcvEKb1_XZIjyrrvQjTGTX0cTgUlL0HQFOL9RwavrDwXh_fsP51zhGbbLozuUbhUKWg' \
-d '{
"messageID": "string",
"tenantName": "string",
"tenantID": "string",
"entityID": "string",
"entityType": "string",
"dataType": "string",
"messageKind": "string",
"routing": "string",
"payload": "string",
"type": "string",
"clientID": "string",
"userID": "string",
"isAdmin": true,
"fabric": "string",
"capabilityId": "string",
"sourceSystem": "string",
"applicationName": "string"
}'```
when i check the endpoint again its showing method not allowed
As with the shared information, I believe that you have configured an API resource as /api/BigData. If that is the case, update the Production and Sandbox endpoints as http://localhost:5000 and not with the complete URL of the actual endpoint to overcome the 404 errors.
The API Manager uses and appends the API Resources that are defined at the end of the Production/Sandbox endpoints. So, when you are configuring an API and exposing that, you have to be sure of choosing the correct endpoints.
For example:
If you have an actual Backend server with the following endpoint https://backendserver/api/v1/get and https://backendserver/api/v1/post then you have to configure an API in the API Manager as following
Create an API with the following two resources
/get
/post
Configure the Production / Sandbox endpoints as https://backendserver/api/v1
Then, if you invoke the API with the API Manager endpoint (https://apimanager:8243/your-api/v1/get), the /get resource will get appended to the configured endpoint and the request will be served as https://backendserver/api/v1/get.
Hope this explains and gives you a brief understanding of the URL mappings in API Manager.

Send file using Axios Assyst REST API

Working in Blue Prism .Net environment utilising the HTTP utility to make calls to Axios Assyst (an IT service desk 3rd party software).
My HTTP request is as per below:
POST /assystREST/v2/site/10/attachments/binary HTTP/1.1
Host: <myserver>:<myport>
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary<base64 encode here>
Accept: application/json
Authorization: Basic <base64 encoded key>
{
"eventId": 10010045,
"fileName": "C:\Users\Me\Desktop\MyFile.msg",
"attachment": "data:;base64,<base64 encoded file>
"onBehalfOfUser": "MR ROBOT",
"custom": {},
"attachedByUserId": <my ID>,
"name": "C:\Users\Me\Desktop\MyFile.msg",
"event":{
"assystRESTType": "event",
"assystRESTXMLType": "eventDto",
"id": 10010045
},
"attachedByUser":{
"assystRESTType": "assystUser",
"assystRESTXMLType": "assystUserDto",
"name": "Mr Robot - Test",
"id": <my ID>,
"shortCode": "MR ROBOT"
}
}
I can create and close my tickets but unable to send/save files to my newly created tickets. I get a HTTP STATUS CODE 410-GONE and the below exception JSON response:
{
"type": "NotFoundException",
"message": "The requested resource is not available.",
"messageKey": "rest.exceptions.NotFoundException",
"diagnostic": "Could not find resource for relative : /site/10/attachments/binary of full path: http://server:port/assystREST/v2/site/10/attachments/binary"
}
I'm following the instructions and guidelines noted in the official Axios Assyst Web Service wiki(per the below link), i.e. I'm using multipart/form-data while sending the file, a .msg file, and the binary of said file (yes I know this adds 33% more to the file size): https://wiki.axiossystems.com/assyst10SP75Wiki/index.php/Integrations:assystREST#Attachments
My issue is that 400 status codes would denote an issue on the client side but I've checked internally re firewall/port being used and nothing is being blocked.
I've reasearched 410 status codes and it would seem that the issue is server side but one that the server is not willing to elaborate on.
For testing I'm using Postman as it allows for greater flexibility rather than using Blue Prism, the JSON response is the same.
Looking for some guidance re status code 410 and possible solutions, note I've limited scope re options due to Blue Prisms .net vbo's.

Retrieve custom `custom.metrics.k8s.io` value using curl

I can list all the custom.metrics available, but I don't know how to query an individual value. For example I have tried:
curl http://localhost:8001/apis/custom.metrics.k8s.io/v1beta1/ | jq .
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "deployments.apps/aws_sqs_approximate_number_of_messages_visible_average",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
But if I try this:
curl http://localhost:8001/apis/custom.metrics.k8s.io/v1beta1/deployments.apps/aws_sqs_approximate_number_of_messages_visible_average | jq .
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "the server could not find the requested resource",
"reason": "NotFound",
"details": {
},
"code": 404
}
I get a 404. I've seen this issue which shows how to get a namespaced metric, but mine does not have a namespace? Is there a definition for how to use this API?
Just like Resource Metrics, Custom Metrics are bound to Kubernetes objects too.
What you're missing in your URL is the resource you want the metric to relate to.
For example the Pod the custom metric is related to, but the same is true for Deployments.
Try to adjust this url to your needs:
kubectl get --raw \
'/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pod/podinfo-67c9fd95d-fqk4g/http_requests_per_second' \
| jq .
Here are the slides for the talk we gave at FOSDEM 2019 on the Prometheus Adapter: https://speakerdeck.com/metalmatze/kubernetes-metrics-api?slide=26
I'll update this answer, once the video is available too.
Since I'm using DirectXMan12/k8s-prometheus-adapter there are a few things to know:
I think it can only work with namespaced metrics.
If a query does not return a metric for a particular time period in prometheus k8s-prometheus-adapter will report it as non-existent.
This is my actual problem.
Using the custom metrics API is very simple:
kubectl proxy to open a proxy to your kubernetes API
curl http://localhost:8001/apis/custom.metrics.k8s.io/v1beta1/ to list all custom metrics available.
For example you may see:
{
"name": "deployments.extensions/kube_deployment_status_replicas_available",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
We know it is namespaced from namespaced: true and beneath the namespace we can select via deployment from the name field.
So we would build our query like so:
curl http://localhost:8001/apis/custom.metrics.k8s.io/v1beta1/namespace/$NAMESPACE/deployments.extensions/$DEPLOYMENT/kube_deployment_status_replicas_available
At least I think that's how it should work, although if you do the same query without deployments.extensions section it will show the value for the namespace:
curl http://localhost:8001/apis/custom.metrics.k8s.io/v1beta1/namespace/$NAMESPACE/kube_deployment_status_replicas_available
Perhaps this is due to how the query executes in prometheus.

How to apply HTTP Patch in my REST API where the underlying resource is a custom properties file

I recently found out that JSON PATCH is only for applying PATCH where the underlying resource is JSON and the request body is something like this
{ "op": "replace", "path": "/a/b/c", "value": 42 } for replace.
Can I have something similar to this when the resource is a custom properties file instead of JSON? or is there any specification for general PATCH. The RFC for HTTP Patch just tells [description of changes] in the body like this.
PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100
[description of changes]

Map viewer retrieve POI from context Broker Instance

I can not get any data from a context BrokerInstance to display it in a Map viewer mashup. The context Broker is deployed in Fi-Ware cloud and the mashups are installed in the mashups section as recommended.
Here my entity (with the related curl request than you can roll out to check it that it responses properly):
curl 130.206.85.114:1026/ngsi10/contextEntities/Madrid -X GET -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' \
> --header "X-Auth-Token: $AUTH_TOKEN" | python -mjson.tool
{
"contextElement": {
"attributes": [
{
"metadatas": [
{
"name": "location",
"type": "string",
"value": "WGS84"
}
],
"name": "position",
"type": "coords",
"value": "40.418889, -3.691944"
}
],
"id": "Madrid",
"isPattern": "false",
"type": "City"
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
Here my mashup configuration:
NGSI Source:
NGSI server URL: http://130.206.85.114:1026
NGSI proxy URL: http://ngsiproxy.lab.fi-ware.org
Use the FIWARE credentials of the user: yes
NGSI entity types: City Monitored NGSI Attributes: position
NGSI entity to POI
Coordinates attribute: position
Map viewer:
Initial Location: Madrid
This questions related How to show an entity from in the Wirecloud MapViewer widget did not help me as long I have not any HTTPS server and I am using the recommended proxy.
Finally, point out that I tried "changing Use the FIWARE credentials of the user" to "No" and changing the "NGSI proxy URL" to other recommended configurations like http://ngsiproxy.lab.fiware.org (no score) with the same (negative) result..
Thanks for your help
I've tried what you said and I've managed to view the POI of Madrid you mention. I guess you don't see it for the security constraints on modern browsers. Have you noticed the security issue regarding access to insecure websites from HTTPS-based ones? Firefox and Chrome show a "shield" icon on the address bar, and you must acknowledge unsecure content for it to work.
For the future, using an HTTPS version of the NGSI proxy is recommended, though it will imply deploying RUSH together with the Context Broker for enablin HTTPS on Orion, or waiting for an upcoming version with HTTPS embedded.
Best regards