Skip to content

Instantly share code, notes, and snippets.

@pytimer
Created August 19, 2020 08:34
Show Gist options
  • Save pytimer/0ad436972a073bb37b8b6b8b474520fc to your computer and use it in GitHub Desktop.
Save pytimer/0ad436972a073bb37b8b6b8b474520fc to your computer and use it in GitHub Desktop.

Revisions

  1. pytimer created this gist Aug 19, 2020.
    152 changes: 152 additions & 0 deletions client-go-parse-yaml.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,152 @@
    Parse the kubernetes manifest in yaml or json, don't care a manifest type.

    Examples:

    ```go
    package main

    import (
    "bytes"
    "context"
    "flag"
    "io"
    "io/ioutil"
    "log"

    "k8s.io/apimachinery/pkg/api/meta"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
    yamlutil "k8s.io/apimachinery/pkg/util/yaml"
    "k8s.io/client-go/dynamic"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/restmapper"
    "k8s.io/client-go/tools/clientcmd"
    )

    var (
    kubeconfig string
    filename string
    )

    func main() {
    flag.StringVar(&kubeconfig, "kubeconfig", "", "")
    flag.StringVar(&filename, "f", "", "")
    flag.Parse()

    b, err := ioutil.ReadFile(filename)
    if err != nil {
    log.Fatal(err)
    }
    log.Printf("%q \n", string(b))

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
    log.Fatal(err)
    }

    c, err := kubernetes.NewForConfig(config)
    if err != nil {
    log.Fatal(err)
    }

    dd, err := dynamic.NewForConfig(config)
    if err != nil {
    log.Fatal(err)
    }

    decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader(b), 100)
    for {
    var rawObj runtime.RawExtension
    if err = decoder.Decode(&rawObj); err != nil {
    break
    }

    obj, gvk, err := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme).Decode(rawObj.Raw, nil, nil)
    unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
    if err != nil {
    log.Fatal(err)
    }

    unstructuredObj := &unstructured.Unstructured{Object: unstructuredMap}

    gr, err := restmapper.GetAPIGroupResources(c.Discovery())
    if err != nil {
    log.Fatal(err)
    }

    mapper := restmapper.NewDiscoveryRESTMapper(gr)
    mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
    if err != nil {
    log.Fatal(err)
    }

    var dri dynamic.ResourceInterface
    if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
    if unstructuredObj.GetNamespace() == "" {
    unstructuredObj.SetNamespace("default")
    }
    dri = dd.Resource(mapping.Resource).Namespace(unstructuredObj.GetNamespace())
    } else {
    dri = dd.Resource(mapping.Resource)
    }

    if _, err := dri.Create(context.Background(), unstructuredObj, metav1.CreateOptions{}); err != nil {
    log.Fatal(err)
    }
    }
    if err != io.EOF {
    log.Fatal("eof ", err)
    }
    }
    ```

    Usage:

    app.yaml:

    ```yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: nginx
    name: nginx
    namespace: default
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: nginx
    strategy:
    rollingUpdate:
    maxSurge: 25%
    maxUnavailable: 25%
    type: RollingUpdate
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - image: nginx
    name: nginx
    ---
    apiVersion: v1
    kind: Service
    metadata:
    labels:
    app: demo
    name: demo
    namespace: default
    spec:
    ports:
    - name: web
    port: 80
    selector:
    app: demo
    type: ClusterIP
    ```
    `go run demo.go -kubeconfig ~/.kube/config -f app.yaml`