events.action: opened
events.author: palourde
events.masked_author: username_0
events.text: ### Description
  We will introduce support for a new HTTP verb, `PATCH`, in 6.1. For now, it will be available exclusively via the REST API (sensuctl won't be able to use that yet). It's also available to "configuration" resources:
  
  - apikeys
  - checks
  - clusterrolebindings
  - clusterroles
  - filters
  - hooks
  - mutators
  - namespaces
  - rolebindings
  - roles
  
  It's also available to entities, but only to the **configuration** attributes; behind the scenes, entities are now stored into two distinct resources, an [`EntityConfig`](https://github.com/sensu/sensu-go/blob/fe06dac0a08176a87f65bb1934613879d928b7ac/api/core/v3/entity_config.pb.go#L29) and an [`EntityState`](https://github.com/sensu/sensu-go/blob/fe06dac0a08176a87f65bb1934613879d928b7ac/api/core/v3/entity_state.pb.go#L31). Therefore, users will be able to PATCH entities attributes that belong to the `EntityConfig`.
  
  The two notable exceptions in terms of resources are `silenced` entries and `users`. We might tackle those in a subsequent release.
  
  For the moment, we only support `JSON Merge Patches`, as defined by the [RFC7396](https://tools.ietf.org/html/rfc7396), therefore users will have to explicitly set the `Content-Type` header to `application/merge-patch+json`.
  
  Also, users won't be able to alter the `name` or the `namespace` of a resource via a PATCH request.
  
  One important thing to note is that all GET and PATCH requests will now return an [`Etag`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) response header, which identifies a specific version of a resource.
  
  Using that `Etag` value, users will be able to conditionally execute a PATCH request using the [`If-Match`]() and [`If-None-Match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) headers. When a PATCH request cannot be executed because one of the condition failed, we will return the response status code `412 Precondition Failed`.
  
  Here are some useful examples:
  
  ### A user can add a label
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -d '{
    "metadata": {
      "labels": {
        "what_magic": "is this"
      }
    }
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/assets/sensu-go-hello-world
  
  HTTP/1.1 200 OK
  Content-Type: application/json
  Etag: "deeb157828631797"
  Date: Mon, 28 Sep 2020 13:56:43 GMT
  Content-Length: 465
  
  {"filters":["entity.system.os == linux"],"builds":[{"url":"https://self-signed.badssl.com/sensu-go-hello-world-0.0.1.tar.gz","sha512":"06665fea5b7c7ee15e7822820aa7ddb791cc6338e38444e976e601bc7d7970592e806a7b88733690a238b7325437d31f85e98ae2fe47b008ca09c86530da9600","filters":null,"headers":null}],"metadata":{"name":"sensu-go-hello-world","namespace":"default","labels":{"sensu.io/managed_by":"sensuctl","what_magic":"is this"},"created_by":"admin"},"headers":null}
  ```
  
  ### A user can replace an array
  One of the caveat of JSON merge patches is that it's not possible to add elements to an array, you can only replace it.
  
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -d '{
    "subscriptions": ["tootsie_roll"]
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/entities/gin
  
  HTTP/1.1 200 OK
  Content-Type: application/json
  Etag: "655cde6ef9f86805"
  Date: Mon, 28 Sep 2020 13:58:48 GMT
  Content-Length: 302
  
  {"metadata":{"name":"gin","namespace":"default","labels":{"what_magic":"is this"}},"entity_class":"agent","user":"agent","subscriptions":["tootsie_roll"],"deregister":false,"deregistration":{},"redact":["password","passwd","pass","api_key","api_token","access_key","secret_key","private_key","secret"]}
  ```
  
  ### A user cannot alter the namespace or the name of a resource
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'Content-Type:' \
  -d '{
    "metadata": {
      "namespace": "dev"
    }
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/checks/check-asset
  
  HTTP/1.1 400 Bad Request
  X-Content-Type-Options: nosniff
  Date: Mon, 28 Sep 2020 13:52:31 GMT
  Content-Length: 108
  Content-Type: text/plain; charset=utf-8
  
  {"message":"the namespace of the resource (dev) does not match the namespace in the URI (default)","code":1}
  ```
  
  
  ### A PATCH request can only be issued if the stored resource matches the provided Etag in `If-Match`
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'If-Match: "deeb157828631797"' \
  -d '{
    "metadata": {
      "labels": {
        "what_magic": "is this"
      }
    }
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/assets/sensu-go-hello-world
  
  HTTP/1.1 200 OK
  Content-Type: application/json
  Etag: "deeb157828631797"
  Date: Mon, 28 Sep 2020 14:01:18 GMT
  Content-Length: 465
  
  {"filters":["entity.system.os == linux"],"builds":[{"url":"https://self-signed.badssl.com/sensu-go-hello-world-0.0.1.tar.gz","sha512":"06665fea5b7c7ee15e7822820aa7ddb791cc6338e38444e976e601bc7d7970592e806a7b88733690a238b7325437d31f85e98ae2fe47b008ca09c86530da9600","filters":null,"headers":null}],"metadata":{"name":"sensu-go-hello-world","namespace":"default","labels":{"sensu.io/managed_by":"sensuctl","what_magic":"is this"},"created_by":"admin"},"headers":null}
  ```
  
  ### A PATCH request can only be issued if the stored resource does not match any of the provided Etag in `If-Match`
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'If-None-Match: "2459df058c399716", "67ab43"' \
  -d '{
    "metadata": {
      "labels": {
        "what_magic": "is this"
      }
    }
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/entities/gin
  HTTP/1.1 200 OK
  Content-Type: application/json
  Etag: "655cde6ef9f86805"
  Date: Mon, 28 Sep 2020 14:02:05 GMT
  Content-Length: 302
  
  {"metadata":{"name":"gin","namespace":"default","labels":{"what_magic":"is this"}},"entity_class":"agent","user":"agent","subscriptions":["tootsie_roll"],"deregister":false,"deregistration":{},"redact":["password","passwd","pass","api_key","api_token","access_key","secret_key","private_key","secret"]}
  ```
  
  ### A 412 Precondition Failed error is returned if the request cannot be fulfilled because of the condition
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -H 'If-Match: "54ed21"' \
  -d '{
    "metadata": {
      "labels": {
        "what_magic": "is this"
      }
    }
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/assets/sensu-go-hello-world
  
  HTTP/1.1 412 Precondition Failed
  X-Content-Type-Options: nosniff
  Date: Mon, 28 Sep 2020 14:04:21 GMT
  Content-Length: 110
  Content-Type: text/plain; charset=utf-8
  
  {"message":"at least one condition failed for the key /sensu.io/assets/default/sensu-go-hello-world","code":7}
  ```
  
  ### Only the entity configuration attributes can be PATCHED
  See the returned response body, which only returns configuration attributes.
  ```
  $ curl -i -X PATCH \
  -H "Authorization: Key $SENSU_API_KEY" \
  -H 'Content-Type: application/merge-patch+json' \
  -d '{
    "deregister": true
  }' \
  http://127.0.0.1:8080/api/core/v2/namespaces/default/entities/gin
  
  HTTP/1.1 200 OK
  Content-Type: application/json
  Etag: "655cde6ef9f86805"
  Date: Mon, 28 Sep 2020 14:05:25 GMT
  Content-Length: 302
  
  {"metadata":{"name":"gin","namespace":"default","labels":{"what_magic":"is this"}},"entity_class":"agent","user":"agent","subscriptions":["tootsie_roll"],"deregister":false,"deregistration":{},"redact":["password","passwd","pass","api_key","api_token","access_key","secret_key","private_key","secret"]}
  ```
  
  ### Category
  
  This is an issue with:
  
  - [ ] errata (error in doc content)
  - [x] new doc (requires a completely new doc)
  - [ ] update (add missing or refresh existing content)
  - [ ] improvement (improve docs content or format)
  
  
  Please let me know if you have any question or you would like some specific examples.
  
  Thanks!
events.title: Document PATCH method for the REST API
events.type: issue
events.action: closed
events.author: hillaryfraley
events.masked_author: username_1
events.type: issue