Patch through Kuberentes rest API - kubernetes

I am trying to patch horizontal pod autoscaler by setting minimum replica through kubernetes api
Here is the curl which I am using
curl -k \
--request PATCH \
--header "Authorization: Bearer $KUBE_TOKEN" \
--header "Content-Type: application/strategic-merge-patch+json" \
--data '{
"apiVersion": "autoscaling/v1",
"kind": "HorizontalPodAutoscaler",
"metadata": {
"labels": {
"app.kubernetes.io/instance": "test"
},
"name": "test",
"namespace": "default"
},
"spec": {
"maxReplicas": 2,
"minReplicas": 1,
"scaleTargetRef": {
"apiVersion": "apps/v1",
"kind": "Deployment",
"name": "test"
},
"targetCPUUtilizationPercentage": 60
}
}' \
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers
I receive following response
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "the server does not allow this method on the requested resource",
"reason": "MethodNotAllowed",
"details": {
},
"code": 405
}
Can anyone know where am I missing?
Thanks

The URL path must contain the name:
/apis/autoscaling/v1/namespaces/{namespace}/horizontalpodautoscalers/{name}
Its documented on this page https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#horizontalpodautoscaler-v1-autoscaling

Related

I cannot send southbound commands via the context broker (Orion-LD)

Service group provisioning:
curl -iX POST 'http://localhost:4041/iot/services' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-H 'Content-Type: application/json' \
--data-raw '{
"services": [
{
"apikey": "4jggokgpepnvsb2uv4s40d59ov",
"entity_type": "LightFixture",
"resource": ""
}
]
}'
Actuator provisioning:
curl -L -X POST 'http://localhost:4041/iot/devices' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-H 'Content-Type: application/json' \
--data-raw '{
"devices": [
{
"device_id": "LightFixture00",
"entity_name": "urn:ngsi-ld:LightFixture:00",
"entity_type": "LightFixture",
"protocol": "PDI-IoTA-JSON",
"transport": "MQTT",
"commands": [
{
"name": "on",
"type": "command"
},
{
"name": "off",
"type": "command"
}
],
"static_attributes": [
{
"name": "refPole",
"type": "Relationship",
"value": "urn:ngsi-ld:Pole:0"
}
]
}
]
}'
Sending the command through the IoT agent (works correctly):
curl -L -X PATCH 'http://localhost:4041/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00/attrs/on' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-H 'Content-Type: application/json' \
--data-raw '{
"type": "Property",
"value": ""
}'
Sending the command to the context broker (Orion-LD):
curl -L -X PATCH 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00/attrs/on' \
-H 'NGSILD-Tenant: openiot' \
-H 'Content-Type: application/json' \
--data-raw '{
"type": "Property",
"value": ""
}'
This does not work:
msg=***** ERROR Entity/Attribute not found: Entity 'urn:ngsi-ld:LightFixture:00', Attribute 'on'
When I make the following request:
curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00' \
-H 'NGSILD-Tenant: openiot' \
-H 'Accept: application/json'
Contrary to what appears in this tutorial, I don't have the "on" and "off" commands and I suspect this is the reason for the above error:
{
"id": "urn:ngsi-ld:LightFixture:00",
"type": "LightFixture",
"refPole": {
"object": "urn:ngsi-ld:Pole:0",
"type": "Relationship",
"observedAt": "2022-08-15T01:44:00.605Z"
},
"on_status": {
"value": {
"#type": "commandStatus",
"#value": "OK"
},
"type": "Property",
"observedAt": "2022-08-15T01:24:07.900Z"
},
"on_info": {
"value": {
"#type": "commandResult",
"#value": ""
},
"type": "Property",
"observedAt": "2022-08-15T01:24:07.900Z"
},
"off_status": {
"value": {
"#type": "commandStatus",
"#value": "OK"
},
"type": "Property",
"observedAt": "2022-08-15T01:44:00.605Z"
},
"off_info": {
"value": {
"#type": "commandResult",
"#value": ""
},
"type": "Property",
"observedAt": "2022-08-15T01:44:00.605Z"
}
}
Context sources (curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/csourceRegistrations' -H 'NGSILD-Tenant: openiot'):
[
{
"id": "urn:ngsi-ld:ContextSourceRegistration:...",
"type": "ContextSourceRegistration",
"endpoint": "http://iot-agent:4041",
"information": [
{
"entities": [
{
"id": "urn:ngsi-ld:LightFixture:00",
"type": "LightFixture"
}
],
"properties": [
"on",
"off"
]
}
]
}
]
Edit
After updating the IoT agent to the latest version ("1.24.0"), the request curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00' -H 'NGSILD-Tenant: openiot now returns the on and off commands:
{
"id": "urn:ngsi-ld:LightFixture:00",
"type": "LightFixture",
"refPole": {
"type": "Relationship",
"object": "urn:ngsi-ld:Pole:0",
},
"on_status": {
"type": "Property",
"value": {
"#type": "commandStatus",
"#value": "UNKNOWN"
}
},
"on_info": {
"type": "Property",
"value": {
"#type": "commandResult",
"#value": " "
}
},
"off_status": {
"type": "Property",
"value": {
"#type": "commandStatus",
"#value": "UNKNOWN"
}
},
"off_info": {
"type": "Property",
"value": {
"#type": "commandResult",
"#value": " "
}
},
"on": {
"type": "Property",
"value": {
"#type": "command",
"#value": ""
}
},
"off": {
"type": "Property",
"value": {
"#type": "command",
"#value": ""
}
}
}
But I still get the same error:
msg=***** ERROR Entity/Attribute not found: Entity 'urn:ngsi-ld:LightFixture:00', Attribute 'on' (https://uri=etsi=org/ngsi-ld/default-context/on) (status code: 404)
One thing that may be relevant - GET request output:
In this tutorial:
"on": {
"type": "command",
"value": ""
},
"off": {
"type": "command",
"value": ""
}
Mine:
"on": {
"type": "Property",
"value": {
"#type": "command",
"#value": ""
}
},
"off": {
"type": "Property",
"value": {
"#type": "command",
"#value": ""
}
}
This appears to be #context related. Internally an NGSI-LD context broker holds all its attributes as expanded URIs. With a GET these are usually reduced to short names using a compaction operation, so you see short attribute names, however when you PATCH you must be careful to supply the correct user #context as they payload is expanded prior to processing.
If you do curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00' and don't supply a user #context then the entity returned will expand all attributes.
As a check, you probably want to GET with and without your user context:
curl -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00' \
-H ''NGSILD-Tenant: openiot' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
This should return all attributes using short names.
curl -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:LightFixture:00' \
-H ''NGSILD-Tenant: openiot'
This should return all attributes using long URIs.
It could be the case that "on" has been previously been defined in your user #context. Now if you do a PATCH and don't supply the user #context, only the core NGSI-LD #context is processed. This contains the final line:
"#vocab": "https://uri.etsi.org/ngsi-ld/default-context/"
Which means that all unknown attributes are placed under default-context/. However, I assume that the term "on" has registered using a different URI, so that https://uri=etsi=org/ngsi-ld/default-context/on is not recognised as an attribute.
You can check the registrations using:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/csourceRegistrations/' \
-H 'Accept: application/ld+json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-d 'type=LightFixture'
When running an IoT Agent in NGSI-LD mode, you must supply a user #context - this is usually a Docker Environment variable:
- "IOTA_JSON_LD_CONTEXT=http://context/ngsi-context.jsonld"
That is the user #context used to expand the entity attribute URIs, and is supplied with the registration of the command.
Obviously if you omit the Link header you can also check the expanded attributes:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/csourceRegistrations/' \
-H 'Accept: application/ld+json' \
-d 'type=http://whatever/my/uri-is/LightFixture'
If something doesn't expand (like Property) is defined in core. If an attribute doesn't expand, it has fallen into the default context.

I get Bad Authentication data when I try to send a DM via REST request

After running
curl --request POST
--url https://api.twitter.com/1.1/direct_messages/events/new.json
--header 'authorization: OAuth oauth_consumer_key="YOUR_CONSUMER_KEY", oauth_nonce="AUTO_GENERATED_NONCE", oauth_signature="AUTO_GENERATED_SIGNATURE", oauth_signature_method="HMAC-SHA1", oauth_timestamp="AUTO_GENERATED_TIMESTAMP", oauth_token="USERS_ACCESS_TOKEN", oauth_version="1.0"'
--header 'content-type: application/json'
--data '{"event": {"type": "message_create", "message_create": {"target": {"recipient_id": "RECIPIENT_USER_ID"}, "message_data": {"text": "Hello World!"}}}}'
I got this error:
{"errors":[{"code":215,"message":"Bad Authentication data."}]} back.
Where do you set your access token & access token secret? And how do you add Quick Replies?
Oh got it! YES!
curl --request POST \
--url https://api.twitter.com/1.1/direct_messages/events/new.json \
--header 'authorization: OAuth oauth_callback="CALLBACK_URL", oauth_consumer_key="KEY", oauth_nonce="auto generated", oauth_signature="autogenerated", oauth_signature_method="HMAC-SHA1", oauth_timestamp="current time stamp", oauth_token="TOKEN", oauth_version="1.0"' \
--header 'content-type: application/json' \
--cookie 'personalization_id=SOME COOKIE; guest_id=SOME ID; lang=en' \
--data '{
"event": {
"type": "message_create",
"message_create": {
"target": {
"recipient_id": "ID"
},
"message_data": {
"text": "What'\''s your favorite type of bird?",
"quick_reply": {
"type": "options",
"options": [
{
"label": "Red Bird",
"description": "A description about the red bird.",
"metadata": "external_id_1"
},
{
"label": "Blue Bird",
"description": "A description about the blue bird.",
"metadata": "external_id_2"
},
{
"label": "Black Bird",
"description": "A description about the black bird.",
"metadata": "external_id_3"
},
{
"label": "White Bird",
"description": "A description about the white bird.",
"metadata": "external_id_4"
}
]
}
}
}
}
}'```

Add pod annotation through Kubernetes REST API

I can add labels to a pod as described here
But no luck to create annotations likewise
$ KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)
$ cat > patch.json <<EOF
]
{
"op": "add", "path": "/metadata/annotations/test", "value": "world"
}
]
EOF
$ curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" --request PATCH --data "$(cat patch.json)" -H "Content-Type:application/json-patch+json" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/$POD_NAMESPACE/pods/$POD_NAME
the response is:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "jsonpatch add operation does not apply: doc is missing path: /metadata/annotations/test",
"code": 500
}
The error is related to non-existing path.
[
{
"op": "add", "path": "/metadata/annotations/", "value": { "test" : "world" }
}
]
Check out https://www.rfc-editor.org/rfc/rfc6902#section-4.1
AFAIR, you cannot add new annotations on existing resources. You can only update existing ones.

Kubernetes API : add label to pod

With command, I can add label as below
kubectl label pod POD_NAME KEY1=VALUE1
How could I do that from kubernetes API?
I guess it can be done by PATCH /api/v1/namespaces/{namespace}/pods/{name}
Here is pod.json
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"labels": {
"key1": "value1"
}
}
}
I tried with following command
KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)
curl --request PATCH --insecure \
--header "Authorization: Bearer $KUBE_TOKEN" \
--data "$(cat pod.json)" \
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/$POD_NAMESPACE/pods/$POD_NAME
And it returns
{
"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
}
Set content-type to application/json-patch+json and specify the patch in http://jsonpatch.org format.
$ cat > patch.json <<EOF
[
{
"op": "add", "path": "/metadata/labels/hello", "value": "world"
}
]
EOF
$ curl --request PATCH --data "$(cat patch.json)" -H "Content-Type:application/json-patch+json" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/$POD_NAMESPACE/pods/$POD_NAME
In order to use JSON Patch properly, you have to set content type to application/json-patch+json as defined in RFC6902. Works for me.

Orion doesn't notify Cygnus

I followed the official documentation about cygnus and orion. All generic enablers are deployed correctly, without errors in their log files. But something strange happens, Orion never notifies Cygnus.
To test this mechanism I followed the example with Car entity provided in the official documentation.
My entity creation bash script:
(curl $1:1026/v1/updateContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' -d #- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Car",
"isPattern": "false",
"id": "Car1",
"attributes": [
{
"name": "speed",
"type": "integer",
"value": "75"
},
{
"name": "fuel",
"type": "float",
"value": "12.5"
}
]
}
],
"updateAction": "APPEND"
}
EOF
My entity subscription bash script:
(curl $1:1026/v1/subscribeContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Fiware-Service: vehicles' --header 'Fiware-ServicePath: /4wheels' -d #- | python -mjson.tool) <<EOF
{
"entities": [
{
"type": "Car",
"isPattern": "false",
"id": "Car1"
}
],
"attributes": [
"speed",
"oil_level"
],
"reference": "http://$2:5050/notify",
"duration": "P1M",
"notifyConditions": [
{
"type": "ONCHANGE",
"condValues": [
"speed"
]
}
],
"throttling": "PT1S"
}
EOF
My entity update bash script:
(curl $1:1026/v1/updateContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' -d #- | python -mjson.tool) <<EOF
{
"contextElements": [
{
"type": "Car",
"isPattern": "false",
"id": "Car1",
"attributes": [
{
"name": "speed",
"type": "integer",
"value": $2
}
]
}
],
"updateAction": "UPDATE"
}
EOF
Note: Orion responds to all requests.
After executing these scripts, cygnus must receive reported information from orion and save it in the database, but nothing happens.
Neither in /var/log/cygnus/cygnus.log file or in /var/log/contextBroker/contextBroker.log file are reported any information about orion notification.
Note: If I use the notify.sh script provided in the official documentation, Cygnus works well and saves all data in the database.
Note: I read in other questions problems about open ports but those don't apply to mine.
EDIT 1
After I subscribe the orion, the response is:
{
"subscribeResponse": {
"duration": "P1M",
"subscriptionId": "563e12b4f4d8334d599753e0",
"throttling": "PT1S"
}
}
And when I update anentity, orion returns it:
{
"contextResponses": [
{
"contextElement": {
"attributes": [
{
"name": "speed",
"type": "integer",
"value": ""
}
],
"id": "Car1",
"isPattern": "false",
"type": "Car"
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
To GET entity from orion I used the following script:
(curl $1:1026/v1/queryContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d #- | python -mjson.tool) <<EOF
{
"entities": [
{
"type": "Car",
"isPattern": "false",
"id": "Car1"
}
]
}
EOF
Response:
{
"contextResponses": [
{
"contextElement": {
"attributes": [
{
"name": "fuel",
"type": "float",
"value": "12.5"
},
{
"name": "speed",
"type": "integer",
"value": "123"
}
],
"id": "Car1",
"isPattern": "false",
"type": "Car"
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
Note The speed value was updated with success.
Taking into account the Fiware-Service and Fiware-ServicePath headers in subscription request, it has been performeed in the "/4wheels" service path of the service "vehicles". However, entity creation request doesn't use such headers, so it is created in the default service path ("/") of the default service. Thus, the subscription is not "covering" the entity, so updates in the entity are not triggering notifications.
One solution to the problem would be to create the entity in the same service and service path of the subscription, i.e. "/4wheels" service path of the service "vehicles".
Please, check Orion official documentation about service and service path concepts.