the equivalent way of doing 'kubectl apply' in Golang

3/3/2020

It's simple to apply complicate yaml config using kubectl, for example, installing the kong-ingress-controller is simply one line using kubectl:

kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/master/deploy/single/all-in-one-dbless.yaml

what is the equivalent way of doing this in Golang?

-- DiveInto
controller
go
kubectl
kubernetes

1 Answer

3/4/2020

figured out by checking out this issue: https://github.com/kubernetes/client-go/issues/193#issuecomment-363318588

I'm using kubebuilder, simple turn yamls into runtime.Objects using UniversalDeserializer, then create the object using Reconciler's Create method:

// ref: https://github.com/kubernetes/client-go/issues/193#issuecomment-363318588
func parseK8sYaml(fileR []byte) []runtime.Object {

    acceptedK8sTypes := regexp.MustCompile(`(Namespace|Role|ClusterRole|RoleBinding|ClusterRoleBinding|ServiceAccount)`)
    fileAsString := string(fileR[:])
    sepYamlfiles := strings.Split(fileAsString, "---")
    retVal := make([]runtime.Object, 0, len(sepYamlfiles))
    for _, f := range sepYamlfiles {
        if f == "\n" || f == "" {
            // ignore empty cases
            continue
        }

        decode := scheme.Codecs.UniversalDeserializer().Decode
        obj, groupVersionKind, err := decode([]byte(f), nil, nil)

        if err != nil {
            log.Println(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err))
            continue
        }

        if !acceptedK8sTypes.MatchString(groupVersionKind.Kind) {
            log.Printf("The custom-roles configMap contained K8s object types which are not supported! Skipping object with type: %s", groupVersionKind.Kind)
        } else {
            retVal = append(retVal, obj)
        }

    }
    return retVal
}

func (r *MyReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
    ctx := context.Background()
    log := r.Log.WithValues("MyReconciler", req.NamespacedName)

    // your logic here
    log.Info("reconciling")

    yaml := `
apiVersion: v1
kind: Namespace
metadata:
  name: test-ns`
    obj := parseK8sYaml([]byte(yaml))
    if err := r.Create(ctx, obj[0]); err != nil {
        log.Error(err, "failed when creating obj")
    }

    ...

}
-- DiveInto
Source: StackOverflow