GoでKubernetesまわりのツールを作るときにYAMLを読んでKubernetesオブジェクトにしたいということがあったので調べました。
コードはGistにアップしました。 https://gist.github.com/nownabe/4345d9b68f323ba30905c9dfe3460006
KubernetesのオブジェクトというのはKubernetesのソースで定義されているstructのことです。こんなやつ。
// A namespace provides a scope for Names.
// Use of multiple namespaces is optional
type Namespace struct {
metav1.TypeMeta
// +optional
metav1.ObjectMeta
// Spec defines the behavior of the Namespace.
// +optional
Spec NamespaceSpec
// Status describes the current status of a Namespace
// +optional
Status NamespaceStatus
}
https://godoc.org/k8s.io/api/core/v1#Namespace
YAMLはこんなやつですね。
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
このYAMLを上のNamespace
structによろしくDeserializeする方法です。
まずはDeserializerを手に入れます。
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)
func main() {
// SerializeとDeserializeの方法を定義するやつ
// https://godoc.org/k8s.io/apimachinery/pkg/runtime#Scheme
scheme := runtime.NewScheme()
// Deserializerとかをくれるやつ
// https://godoc.org/k8s.io/apimachinery/pkg/runtime/serializer#CodecFactory
codecFactory := serializer.NewCodecFactory(scheme)
// Deserializer
// https://godoc.org/k8s.io/apimachinery/pkg/runtime#Decoder
deserializer := codecFactory.UniversalDeserializer()
}
UniversalDeserializer()
はJSONとかYAMLとかを自動で認識してDeserializeしてくれるやつをくれます。これを使っておけば問題ないと思いますが、それぞれのシリアライズ形式専用のDeserializerも簡単に手に入ります。1
いずれにしてもruntime.Decoder
というinterfaceのインスタンスが得られます。
type Decoder interface {
Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error)
}
https://godoc.org/k8s.io/apimachinery/pkg/runtime#Decoder
Decode
メソッドでDeserializeするわけですが、それぞれの引数はこんな感じになってます。
data []byte
: Deserializeしたいデータ。YAMLとかdefaults *schema.GroupVersionKind
:nil
でよい。よくわからないときに使われるデフォルト値。Group、Version、Kindそれぞれの文字列が入る構造体into Object
: Deserializeしたいオブジェクト。Namespace
とかのstructのポインタがこのinterfaceを実装している。
例えばNamespaceのYAMLをNamespace
structにDeserializeするのはこんな感じになります。
package main
import (
"fmt"
"io/ioutil"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)
func main() {
scheme := runtime.NewScheme()
codecFactory := serializer.NewCodecFactory(scheme)
deserializer := codecFactory.UniversalDeserializer()
yaml, err := ioutil.ReadFile("namespace.yaml")
if err != nil {
panic(err)
}
object, _, err := deserializer.Decode(yaml, nil, &corev1.Namespace{})
if err != nil {
panic(err)
}
namespace := object.(*corev1.Namespace)
fmt.Printf("Name: %s\n", namespace.ObjectMeta.GetName())
}
他のオブジェクトも同様にできます。GistのコードにはDeploymentのサンプルもあります。
オブジェクトについてはk8s.io/apiのgodocにあります。