func ListPersistentVolume(clientSet kubernetes.Interface) (*v1.PersistentVolumeList, error) {
	return clientSet.CoreV1().PersistentVolumes().List(requestContext(), metav1.ListOptions{})
}
ListPersistentVolume lists persistent volumes.
package installbase
import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"github.com/megaease/easemeshctl/cmd/common"
	admissionregv1 "k8s.io/api/admissionregistration/v1"
	appsV1 "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	"k8s.io/apimachinery/pkg/api/errors"
	"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"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)
var (
	scheme         = runtime.NewScheme()
	codecs         = serializer.NewCodecFactory(scheme)
	parameterCodec = runtime.NewParameterCodec(scheme)
	encoder = unstructured.NewJSONFallbackEncoder(codecs.LegacyCodec(scheme.PrioritizedVersionsAllGroups()...))
	metadataAccessor = meta.NewAccessor()
)
type (
	createResourceFunc func() error
	getResourceRunc    func() (runtime.Object, error)
	updateResourceFunc func() error
	PredictFunc func(interface{}) bool
	PodStatus struct {
		Name            string
		ReadyContainer  int
		ExpectContainer int
		Status          string
		Restarts        int
	}
	deleteResourceFunc func(kubernetes.Interface, string, string, string) error
	ListPodFunc func(kubernetes.Interface, string) []PodStatus
)
func NewKubernetesClient() (kubernetes.Interface, error) {
	config, err := clientcmd.BuildConfigFromFlags("", DefaultKubernetesConfigPath)
	if err != nil {
		return nil, err
	}
	kubeClient, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, err
	}
	return kubeClient, nil
}
func NewKubernetesAPIExtensionsClient() (apiextensions.Interface, error) {
	config, err := clientcmd.BuildConfigFromFlags("", DefaultKubernetesConfigPath)
	if err != nil {
		return nil, err
	}
	clientset, err := apiextensions.NewForConfig(config)
	if err != nil {
		return nil, err
	}
	return clientset, nil
}
func requestContext() context.Context     { return context.TODO() }
func createOptions() metav1.CreateOptions { return metav1.CreateOptions{} }
func getOptions() metav1.GetOptions       { return metav1.GetOptions{} }
func updateOptions() metav1.UpdateOptions { return metav1.UpdateOptions{} }
func adaptReplaceObject(old, new runtime.Object) error {
	oldAnnots, err := metadataAccessor.Annotations(old)
	if err != nil {
		return err
	}
	delete(oldAnnots, v1.LastAppliedConfigAnnotation)
	metadataAccessor.SetAnnotations(old, oldAnnots)
	lastConfig, err := json.Marshal(old)
	if err != nil {
		return err
	}
	newAnnots, err := metadataAccessor.Annotations(new)
	if err != nil {
		return err
	}
	if newAnnots == nil {
		newAnnots = make(map[string]string)
	}
	newAnnots[v1.LastAppliedConfigAnnotation] = string(lastConfig)
	err = metadataAccessor.SetAnnotations(new, newAnnots)
	if err != nil {
		return err
	}
	oldResourceVersion, err := metadataAccessor.ResourceVersion(old)
	if err == nil {
		metadataAccessor.SetResourceVersion(new, oldResourceVersion)
	}
	return nil
}
func deployResource(createFn createResourceFunc, updateFn updateResourceFunc) error {
	err := createFn()
	if err == nil {
		return nil
	}
	if !errors.IsAlreadyExists(err) {
		return err
	}
	return updateFn()
}
func DeployNamespace(namespace *v1.Namespace, clientSet kubernetes.Interface) error {
	createFn := func() error {
		_, err := clientSet.CoreV1().Namespaces().
			Create(requestContext(), namespace, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.CoreV1().Namespaces().
			Get(requestContext(), namespace.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, namespace)
		if err != nil {
			return err
		}
		_, err = clientSet.CoreV1().Namespaces().
			Update(requestContext(), namespace, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeployDeployment(deployment *appsV1.Deployment, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.AppsV1().Deployments(namespace).
			Create(requestContext(), deployment, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.AppsV1().Deployments(namespace).
			Get(requestContext(), deployment.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, deployment)
		if err != nil {
			return err
		}
		_, err = clientSet.AppsV1().Deployments(namespace).
			Update(requestContext(), deployment, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeployStatefulset(statefulset *appsV1.StatefulSet, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.AppsV1().StatefulSets(namespace).
			Create(requestContext(), statefulset, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.AppsV1().StatefulSets(namespace).
			Get(requestContext(), statefulset.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, statefulset)
		if err != nil {
			return err
		}
		_, err = clientSet.AppsV1().StatefulSets(namespace).
			Update(requestContext(), statefulset, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeployService(service *v1.Service, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.CoreV1().Services(namespace).
			Create(requestContext(), service, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.CoreV1().Services(namespace).
			Get(requestContext(), service.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, service)
		if err != nil {
			return err
		}
		service.Spec.ClusterIP = oldObject.Spec.ClusterIP
		service.Spec.ClusterIPs = oldObject.Spec.ClusterIPs
		_, err = clientSet.CoreV1().Services(namespace).
			Update(requestContext(), service, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeployConfigMap(configMap *v1.ConfigMap, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.CoreV1().ConfigMaps(namespace).
			Create(requestContext(), configMap, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.CoreV1().ConfigMaps(namespace).
			Get(requestContext(), configMap.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, configMap)
		if err != nil {
			return err
		}
		_, err = clientSet.CoreV1().ConfigMaps(namespace).
			Update(requestContext(), configMap, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeploySecret(secret *v1.Secret, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.CoreV1().Secrets(namespace).
			Create(requestContext(), secret, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.CoreV1().Secrets(namespace).
			Get(requestContext(), secret.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, secret)
		if err != nil {
			return err
		}
		_, err = clientSet.CoreV1().Secrets(namespace).
			Update(requestContext(), secret, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}
func DeployMutatingWebhookConfig(mutatingWebhookConfig *admissionregv1.MutatingWebhookConfiguration, clientSet kubernetes.Interface, namespace string) error {
	createFn := func() error {
		_, err := clientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().
			Create(requestContext(), mutatingWebhookConfig, createOptions())
		return err
	}
	updateFn := func() error {
		oldObject, err := clientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().
			Get(requestContext(), mutatingWebhookConfig.Name, getOptions())
		if err != nil {
			return err
		}
		err = adaptReplaceObject(oldObject, mutatingWebhookConfig)
		if err != nil {
			return err
		}
		_, err = clientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().
			Update(requestContext(), mutatingWebhookConfig, updateOptions())
		return err
	}
	return deployResource(createFn, updateFn)
}