kubernetes-clientを経由してpatch

## 何がしたかった？
[全ての Pod を一発でリロードさせる方法](https://qiita.com/dtan4/items/9e0ab5dbe8c64ed6dd21)
↑をJavaから[kubernetes-client/java](https://github.com/kubernetes-client/java)を使ってやりたかった。
これができるとpodリロードをAPI化してwebから蹴ったりできるのでは？と画策。

## 壁
[Example](https://github.com/kubernetes-client/java/blob/master/kubernetes/docs/AppsV1beta1Api.md#patchNamespacedDeployment)がExampleじゃない気がするんだ。
めっちゃ500とか400で怒られるけど全然わからなくて泣いた。bodyがなってねえんだよとひたすら言われた。

## 壁崩壊
て思ったらなんかいつの間にかUPDATEされたExampleがあったので、あの夜の私の汗と涙を返してほしい。嘘ですメンテありがとう。
できることなら君と一ヶ月前に会いたかった。
:tada: \\\ [PatchExample.java](https://github.com/kubernetes-client/java/blob/da58401c5bc38bdeaa28a6f66d25481af4d6e994/examples/src/main/java/io/kubernetes/client/examples/PatchExample.java) // :tada: 
もうこの記事書く意味なくなったけど悔しいので備忘録兼日記的に残します。

## 環境
* SpringBoot2.0.2

### 準備
ライブラリをbuild.gradeleに追加

```
compile('io.kubernetes:client-java:4.0.0')
```

### 実行前

```deployment.yaml
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: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
```
これにpatchを実行します。


### おれおれコード
```java
@RequiredArgsConstructor
public class SampleClient {

    private final AppsV1Api appsV1Api;

        public V1Deployment patchDeploymentSample() throws ApiException {
        
            String namespace = "namespace";
            String name = "deployment_name";
        
            ArrayList<JsonObject> body = new ArrayList<>();
            String jsonStr = "{"
                            + "\"op\":\"add\", "
                            + "\"path\":\"/spec/template/spec/sample/reload\","
                            + "\"value\":\"update-test-20190624\""
                            + "}";
            body.add(((JsonElement) this.deserialize(jsonStr, JsonElement.class)).getAsJsonObject());
        
            return appsV1Api.patchNamespacedDeployment(name, namespace, body, true, null);
        }
        
        private Object deserialize(String jsonStr, Class<?> targetClass) {
            return (new Gson()).fromJson(jsonStr, targetClass);
        }
}
```

### 実行後

上記コードを実行すると以下のdeploymentに変わっていました。
bodyで指定した項目が追加されています！
valueを変えて再度実行すると、keyはそのままでvalueだけ更新されています。
もちろんpodも再起動がかかっています。

```deployment.yaml
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: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
      sample:
        reload: update-test-20190624

```

### JSON Patch
Json Patchなるものは[この記事](https://qiita.com/taknuki/items/76d2fda912443b6854a4)がとてもわかり易かったのでどうぞ。
自分はoperationにaddではなくreplaceを指定していますが、

* add -> 指定の項目追加。既にあれば置き換える。
* remove -> 指定の項目削除。項目がなければエラー。
* replace -> remove + add。つまり置き換える項目がなければエラー。

という仕様なので、今回の用途ならaddです。なければinsert、あればupdateという動きをします。
むしろreplaceを使いたいのってどういうときでしょうか :thinking:

### 公式ドキュメントとの違い
DI部分とかはさておき、自分でdeserializeしてJsonElementのObjectを渡しているところがV1Patchというものに入れて渡してますね。
PatchExampleの更新と[ソース](https://github.com/kubernetes-client/java/blob/da58401c5bc38bdeaa28a6f66d25481af4d6e994/kubernetes/src/main/java/io/kubernetes/client/models/V1Patch.java)の更新日が同じなので新しく追加されたObjectなのかも。
[V1Patchのドキュメント](https://github.com/kubernetes-client/java/blob/da58401c5bc38bdeaa28a6f66d25481af4d6e994/kubernetes/docs/V1Patch.md)も空。
> Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.

JsonのStringを渡すとPATCHのための具体的な名前と型に落とし込んでくれるものらしい。
こっち使った方が良いですね。便利って大事。

### 気になる
`patchNamespacedDeployment`の第4引数の`pretty`がよくわかっていません。  
> If true, then the output is pretty printed. (optional)

……何を？  ログとかエラー？ :thinking::thinking:

## 多謝
* [PatchExample.java](https://github.com/kubernetes-client/java/blob/da58401c5bc38bdeaa28a6f66d25481af4d6e994/examples/src/main/java/io/kubernetes/client/examples/PatchExample.java)
* [kubernetes-client/java](https://github.com/kubernetes-client/java)
* [全ての Pod を一発でリロードさせる方法](https://qiita.com/dtan4/items/9e0ab5dbe8c64ed6dd21)
* [JSON PointerとJSON Patch](https://qiita.com/taknuki/items/76d2fda912443b6854a4)
* [JavaScript Object Notation (JSON) Patch](https://datatracker.ietf.org/doc/rfc6902/)