Parse the kubernetes manifest in yaml or json, don't care a manifest type.
Examples:
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:
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
Thanks @pytimer for sharing the code.
I was able to apply YAML using this, but when I re-tried again, it reported error that the resource already exists, even though I deleted it manually. Does it cache somewhere? I thought it would update it even if it is there. Could you please share the complete code as well incorporating the update part? or, let me know how to do it. That’s why it ‘d be great if you could also elaborate this comment. Thanks in advance!