func newDynamicClient(kubeConfigPath string) (dynamic.Interface, error) {
	kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
	if err != nil {
		return nil, err
	}
	return dynamic.NewForConfig(kubeConfig)
}
newDynamicClient returns a dyamnic kubernetes interface
package export
import (
	"context"
	"errors"
	"fmt"
	"html/template"
	"os"
	"path/filepath"
	"strings"
	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/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/kubectl/pkg/scheme"
)
var FuncMap = template.FuncMap{
	"Myfp": Myfp,
}
func ExportClusterYaml(capicfg string, repodir string) (bool, error) {
	client, err := newClient(capicfg)
	if err != nil {
		return false, err
	}
	dynamicClient, err := newDynamicClient(capicfg)
	if err != nil {
		return false, err
	}
	e := json.NewYAMLSerializer(json.DefaultMetaFactory, nil, nil)
	isNamespaced := false
	clusterApiResouces, err := getApiResources(client, isNamespaced)
	if err != nil {
		return false, err
	}
	for _, car := range clusterApiResouces {
		if car.APIResource.Name == "componentstatuses" ||
			car.APIResource.Name == "namespaces" ||
			car.APIResource.Name == "certificatesigningrequests" ||
			car.APIResource.Name == "tokenreviews" ||
			car.APIResource.Name == "selfsubjectaccessreviews" ||
			car.APIResource.Name == "selfsubjectrulesreviews" ||
			car.APIResource.Name == "subjectaccessreviews" ||
			car.APIResource.Name == "ipamblocks" ||
			car.APIResource.Name == "ipamhandles" ||
			car.APIResource.Name == "ipamconfigs" ||
			car.APIResource.Name == "podsecuritypolicies" {
			continue
		}
		_, err = exportClusterScopedYaml(dynamicClient, car, e, repodir+"/cluster"+"/core/cluster", "NOT-NAMESPACED")
		if err != nil {
			return false, err
		}
	}
	dirGlob := repodir + "/cluster" + "/core/cluster/*.yaml"
	clusterScopedYamlFiles, err := filepath.Glob(dirGlob)
	if err != nil {
		return false, err
	}
	if len(clusterScopedYamlFiles) == 0 {
		return false, errors.New("no YAML Files found at: " + dirGlob)
	}
	cskf := struct {
		ClusterScopedYamls []string
	}{
		ClusterScopedYamls: clusterScopedYamlFiles,
	}
	_, err = WriteTemplateWithFunc(ClusterScopedKustomizeFile, repodir+"/cluster/core/cluster/kustomization.yaml", cskf, FuncMap)
	if err != nil {
		return false, err
	}
	isItNamespaced := true
	namespacedApis, err := getApiResources(client, isItNamespaced)
	if err != nil {
		return false, err
	}
	namespaces, err := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		return false, err
	}
	for _, ns := range namespaces.Items {
		outdir := repodir + "/cluster/core/" + ns.Name
		for _, nc := range namespacedApis {
			thens, err := client.CoreV1().Namespaces().Get(context.TODO(), ns.Name, metav1.GetOptions{})
			if err != nil {
				return false, err
			}
			thens.SetResourceVersion("")
			thens.SetUID("")
			thens.SetAnnotations(map[string]string{})
			thens.CreationTimestamp.Reset()
			thens.SetSelfLink("")
			thens.SetManagedFields([]metav1.ManagedFieldsEntry{})
			thens.SetFinalizers([]string{})
			thens.SetOwnerReferences([]metav1.OwnerReference{})
			thens.SetGeneration(0)
			thens.Status.Reset()
			addTypeInformationToObject(thens)
			encodeNs := json.NewYAMLSerializer(json.DefaultMetaFactory, nil, nil)
			if nc.APIResource.Name == "bindings" ||
				nc.APIResource.Name == "pods" ||
				nc.APIResource.Name == "endpoints" ||
				nc.APIResource.Name == "replicasets" ||
				nc.APIResource.Name == "localsubjectaccessreviews" ||
				nc.APIResource.Name == "selfsubjectrulesreviews" ||
				nc.APIResource.Name == "events" ||
				nc.APIResource.Name == "endpointslices" {
				continue
			}
			_, err = exportClusterScopedYaml(dynamicClient, nc, e, outdir, ns.Name)
			if err != nil {
				return false, err
			}
			tnf, err := os.Create(outdir + "/namespace-" + ns.Name + ".yaml")
			if err != nil {
				return false, err
			}
			err = encodeNs.Encode(thens, tnf)
			if err != nil {
				return false, err
			}
			tnf.Close()
		}
		dirGlob := repodir + "/cluster" + "/core/" + ns.Name + "/*.yaml"
		nsScopedYamlFiles, err := filepath.Glob(dirGlob)
		if err != nil {
			return false, err
		}
		if len(nsScopedYamlFiles) == 0 {
			return false, errors.New("no YAML Files found at: " + dirGlob)
		}
		nskf := struct {
			NsScopedYamls []string
		}{
			NsScopedYamls: nsScopedYamlFiles,
		}
		_, err = WriteTemplateWithFunc(NameSpacedScopedKustomizeFile, repodir+"/cluster/core/"+ns.Name+"/kustomization.yaml", nskf, FuncMap)
		if err != nil {
			return false, err
		}
	}
	return true, nil
}
func exportClusterScopedYaml(client dynamic.Interface, gr GroupResource, e *json.Serializer, dir string, ns string) (bool, error) {
	var list *unstructured.UnstructuredList
	var err error
	if ns == "NOT-NAMESPACED" {
		list, err = client.Resource(schema.GroupVersionResource{Group: gr.APIGroup, Resource: gr.APIResource.Name, Version: gr.APIVersion}).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			return false, err
		}
	} else {
		list, err = client.Resource(schema.GroupVersionResource{Group: gr.APIGroup, Resource: gr.APIResource.Name, Version: gr.APIVersion}).List(context.TODO(), metav1.ListOptions{FieldSelector: "metadata.namespace=" + ns})
		if err != nil {
			return false, err
		}
	}
	os.MkdirAll(dir, 0755)
	for _, listItem := range list.Items {
		listItem.SetGroupVersionKind(schema.GroupVersionKind{Group: gr.APIResource.Group, Kind: gr.APIResource.Kind, Version: gr.APIGroupVersion})
		metadata := listItem.Object["metadata"].(map[string]interface{})
		itemName := listItem.GetName()
		if strings.Contains(itemName, "bootstrap-token") ||
			itemName == "cluster-info" ||
			itemName == "calico-config" {
			continue
		}
		delete(metadata, "resourceVersion")
		delete(metadata, "uid")
		delete(metadata, "annotations")
		delete(metadata, "creationTimestamp")
		delete(metadata, "selfLink")
		delete(metadata, "managedFields")
		delete(metadata, "finalizers")
		delete(metadata, "ownerReferences")
		delete(metadata, "generation")
		delete(listItem.Object, "status")
		obj := listItem.DeepCopyObject()
		fileName := fmt.Sprintf("%s-%s", strings.ReplaceAll(strings.ToLower(listItem.GetKind()), ":", "-"), strings.ReplaceAll(strings.ToLower(listItem.GetName()), ":", "-"))
		y, err := os.Create(dir + "/" + fileName + ".yaml")
		if err != nil {
			return false, err
		}
		defer y.Close()
		err = addTypeInformationToObject(obj)
		if err != nil {
			return false, err
		}
		err = e.Encode(obj, y)
		if err != nil {
			return false, err
		}
	}
	return true, nil
}
func addTypeInformationToObject(obj runtime.Object) error {
	gvks, _, err := scheme.Scheme.ObjectKinds(obj)
	if err != nil {
		return fmt.Errorf("missing apiVersion or kind and cannot assign it; %w", err)
	}
	for _, gvk := range gvks {
		if len(gvk.Kind) == 0 {
			continue
		}
		if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
			continue
		}
		obj.GetObjectKind().SetGroupVersionKind(gvk)
		break
	}
	return nil
}
func newClient(kubeConfigPath string) (kubernetes.Interface, error) {
	kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
	if err != nil {
		return nil, err
	}
	return kubernetes.NewForConfig(kubeConfig)
}