k8sのPHPクライアントライブラリのエラーを修正した
先日の課題が解決です。
tl;dr
mergeしてもらったプルリクエストです。
振り返り
k8sのAPIクライアントは各言語向けに公式のものが用意されていますが、PHPは公式ではなく有志のものが紹介されています。
2つ紹介されていますが、私が使わせてもらったのはこちら。
※ネコ好きだからとかでは決してない!
で使ってる時にエラーが出てたので調べました。
調べる
エラーメッセージ
前回曖昧にしてたので、改めてエラーメッセージはこんな感じ。
"Deployment in version \"v1\" cannot be handled as a Deployment: v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Volumes: v1.Volume: v1.Volume.VolumeSource: EmptyDir: readObjectStart: expect { or n, but found [, error found in #10 byte of ...|ptyDir\": \n |..., bigger context ...|\": \"shared\",\n \"emptyDir\": []\n }\n ]\n |...
expect { or n, but found [
がポイントっぽい。
マニフェストファイル
処理としては.ymlファイルを読み込ませてarrayに変換し、ライブラリのpods()->createメソッド呼んでるだけ。 先に.ymlの確認。
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
実際のファイルでは無いですが、これで十分なので公式で公開されているマニフェストを参考にします。
emptyDir: {}
とあるのがエラーメッセージとかなり関係してそう。
ちなみにこのファイルで kubectl apply -f pod.yml とかすると正常にPodができます。
ソースコード
さてついにソースコードです。 create()の中を追っていきます。
Repository.phpという抽象クラスに集約されています。
抜粋)
/** * Send a request. * * @param string $method * @param string $uri * @param array $query * @param mixed $body * @param boolean $namespace * @return array */ protected function sendRequest($method, $uri, $query = [], $body = [], $namespace = true) { $apiVersion = $this->getApiVersion(); if ($apiVersion == 'v1') { $apiVersion = null; } return $this->client->sendRequest($method, $uri, $query, $body, $namespace, $apiVersion); } ... /** * Create a new model. * * @param \Maclof\Kubernetes\Models\Model $model * @return array */ public function create(Model $model) { return $this->sendRequest('POST', '/' . $this->uri, null, $model->getSchema(), $this->namespace); }
$modelに読み込んだマニフェストのarrayを渡しています。
呼び出し先はClient.php
public function sendRequest($method, $uri, $query = [], $body = [], $namespace = true, $apiVersion = null) { $baseUri = $apiVersion ? 'apis/' . $apiVersion : 'api/' . $this->apiVersion; if ($namespace) { $baseUri .= '/namespaces/' . $this->namespace; } $requestUri = $baseUri . $uri; $requestOptions = []; if (is_array($query) && !empty($query)) { $requestOptions['query'] = $query; } if ($body !== null) { $requestOptions['body'] = is_array($body) ? json_encode($body) : $body; } ... }
ここの$bodyが渡された$model->getSchema()です。json_encodeしている。ここでしょう。
結論
expect { or n, but found [
ということなので、空の配列として認識されてるっぽい。
json_encodeにはオプションが指定できるらしい。使えそうなのを見つける。
JSON_FORCE_OBJECT (integer)
非連想配列を使用した場合に、配列ではなくオブジェクトを出力します。 出力を受け取る側がオブジェクトを期待しており、配列が空っぽである場合などに特に便利です。 この定数は PHP 5.3.0 以降で使用可能です。
これかな?
というわけで修正して実行!成功です!
あとは先の通りプルリクエスト出して、数時間後に無事マージしていただきました。
感想
オープンソースにコミットするのが初めてでしたが、ゲームやってるみたいで楽しいですね。
これからもっとやっていきます。