func GenerateDeamonsetManifestFromConfig(c *Config, imageVersion string, inCluster, taint bool) string {
	podSpec := generatePodSpec(c, imageVersion, inCluster).Spec
	newManifest := &appv1.DaemonSet{
		TypeMeta: metav1.TypeMeta{
			Kind:       "DaemonSet",
			APIVersion: "apps/v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "kube-vip-ds",
			Namespace: "kube-system",
		},
		Spec: appv1.DaemonSetSpec{
			Selector: &metav1.LabelSelector{
				MatchLabels: map[string]string{
					"name": "kube-vip-ds",
				},
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{
						"name": "kube-vip-ds",
					},
				},
				Spec: podSpec,
			},
		},
	}
	if taint {
		newManifest.Spec.Template.Spec.Tolerations = []corev1.Toleration{
			{
				Effect:   corev1.TaintEffectNoSchedule,
				Operator: corev1.TolerationOpExists,
			},
			{
				Effect:   corev1.TaintEffectNoExecute,
				Operator: corev1.TolerationOpExists,
			},
		}
		newManifest.Spec.Template.Spec.Affinity = &corev1.Affinity{
			NodeAffinity: &corev1.NodeAffinity{
				RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
					NodeSelectorTerms: []corev1.NodeSelectorTerm{
						{
							MatchExpressions: []corev1.NodeSelectorRequirement{
								{
									Key:      "node-role.kubernetes.io/master",
									Operator: corev1.NodeSelectorOpExists,
								},
							},
						},
						{
							MatchExpressions: []corev1.NodeSelectorRequirement{
								{
									Key:      "node-role.kubernetes.io/control-plane",
									Operator: corev1.NodeSelectorOpExists,
								},
							},
						},
					},
				},
			},
		}
	}
	b, _ := yaml.Marshal(newManifest)
	return string(b)
}
GenerateDeamonsetManifestFromConfig will take a kube-vip config and generate a manifest
package kubevip
import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"github.com/ghodss/yaml"
	"github.com/kube-vip/kube-vip/pkg/bgp"
	"github.com/kube-vip/kube-vip/pkg/detector"
	log "github.com/sirupsen/logrus"
	appv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func ParseEnvironment(c *Config) error {
	env := os.Getenv(vipLogLevel)
	if env != "" {
		logLevel, err := strconv.Atoi(env)
		if err != nil {
			panic("Unable to parse environment variable [vip_loglevel], should be int")
		}
		log.SetLevel(log.Level(logLevel))
	}
	env = os.Getenv(vipInterface)
	if env != "" {
		c.Interface = env
	}
	env = os.Getenv(vipServicesInterface)
	if env != "" {
		c.ServicesInterface = env
	}
	env = os.Getenv(providerConfig)
	if env != "" {
		c.ProviderConfig = env
	}
	env = os.Getenv(vipLeaderElection)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableLeaderElection = b
	}
	env = os.Getenv(vipLeaseDuration)
	if env != "" {
		i, err := strconv.ParseInt(env, 10, 32)
		if err != nil {
			return err
		}
		c.LeaseDuration = int(i)
	}
	env = os.Getenv(vipRenewDeadline)
	if env != "" {
		i, err := strconv.ParseInt(env, 10, 32)
		if err != nil {
			return err
		}
		c.RenewDeadline = int(i)
	}
	env = os.Getenv(vipRetryPeriod)
	if env != "" {
		i, err := strconv.ParseInt(env, 10, 32)
		if err != nil {
			return err
		}
		c.RetryPeriod = int(i)
	}
	env = os.Getenv(vipAddress)
	if env != "" {
		c.VIP = env
	}
	env = os.Getenv(address)
	if env != "" {
		c.Address = env
	}
	env = os.Getenv(port)
	if env != "" {
		i, err := strconv.ParseInt(env, 10, 32)
		if err != nil {
			return err
		}
		c.Port = int(i)
	}
	env = os.Getenv(vipDdns)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.DDNS = b
	}
	env = os.Getenv(cpNamespace)
	if env != "" {
		c.Namespace = env
	}
	env = os.Getenv(cpNamespace)
	if env != "" {
		c.Namespace = env
	}
	env = os.Getenv(cpEnable)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableControlPane = b
	}
	env = os.Getenv(svcEnable)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableServices = b
	}
	env = os.Getenv(vipCidr)
	if env != "" {
		c.VIPCIDR = env
	}
	env = os.Getenv(vipSingleNode)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.SingleNode = b
	}
	env = os.Getenv(annotations)
	if env != "" {
		c.Annotations = env
	}
	env = os.Getenv(vipStartLeader)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.StartAsLeader = b
	}
	env = os.Getenv(vipArp)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableARP = b
	}
	env = os.Getenv(vipLocalPeer)
	if env != "" {
		peer, err := ParsePeerConfig(env)
		if err != nil {
			return err
		}
		c.LocalPeer = *peer
	}
	env = os.Getenv(vipPeers)
	if env != "" {
		c.RemotePeers = []RaftPeer{}
		s := strings.Split(env, ",")
		if len(s) == 0 {
			return fmt.Errorf("The Remote Peer List [%s] is unable to be parsed, should be in comma separated format <id>:<address>:<port>", env)
		}
		for x := range s {
			peer, err := ParsePeerConfig(s[x])
			if err != nil {
				return err
			}
			c.RemotePeers = append(c.RemotePeers, *peer)
		}
	}
	env = os.Getenv(vipAddPeersToLB)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.AddPeersAsBackends = b
	}
	env = os.Getenv(bgpEnable)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableBGP = b
	}
	env = os.Getenv(bgpRouterInterface)
	if env != "" {
		_, address, err := detector.FindIPAddress(env)
		if err != nil {
			return err
		}
		c.BGPConfig.RouterID = address
	}
	env = os.Getenv(bgpRouterID)
	if env != "" {
		c.BGPConfig.RouterID = env
	}
	env = os.Getenv(bgpRouterAS)
	if env != "" {
		u64, err := strconv.ParseUint(env, 10, 32)
		if err != nil {
			return err
		}
		c.BGPConfig.AS = uint32(u64)
	}
	env = os.Getenv(bgpPeerAS)
	if env != "" {
		u64, err := strconv.ParseUint(env, 10, 32)
		if err != nil {
			return err
		}
		c.BGPPeerConfig.AS = uint32(u64)
	}
	env = os.Getenv(bgpPeers)
	if env != "" {
		peers, err := bgp.ParseBGPPeerConfig(env)
		if err != nil {
			return err
		}
		c.BGPConfig.Peers = peers
	}
	env = os.Getenv(bgpMultiHop)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.BGPPeerConfig.MultiHop = b
	}
	env = os.Getenv(bgpPeerPassword)
	if env != "" {
		c.BGPPeerConfig.Password = env
	}
	env = os.Getenv(bgpSourceIF)
	if env != "" {
		c.BGPConfig.SourceIF = env
	}
	env = os.Getenv(bgpSourceIP)
	if env != "" {
		c.BGPConfig.SourceIP = env
	}
	env = os.Getenv(bgpPeerAddress)
	if env != "" {
		c.BGPPeerConfig.Address = env
		c.BGPConfig.Peers = append(c.BGPConfig.Peers, c.BGPPeerConfig)
	}
	env = os.Getenv(vipPacket)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableMetal = b
	}
	env = os.Getenv(vipPacketProject)
	if env != "" {
		c.MetalProject = env
	}
	env = os.Getenv(vipPacketProjectID)
	if env != "" {
		c.MetalProjectID = env
	}
	env = os.Getenv(lbEnable)
	if env != "" {
		b, err := strconv.ParseBool(env)
		if err != nil {
			return err
		}
		c.EnableLoadBalancer = b
	}
	env = os.Getenv(lbPort)
	if env != "" {
		i, err := strconv.ParseInt(env, 10, 32)
		if err != nil {
			return err
		}
		c.LoadBalancerPort = int(i)
	}
	return nil
}
func generatePodSpec(c *Config, imageVersion string, inCluster bool) *corev1.Pod {
	command := "manager"
	newEnvironment := []corev1.EnvVar{
		{
			Name:  vipArp,
			Value: strconv.FormatBool(c.EnableARP),
		},
		{
			Name:  port,
			Value: fmt.Sprintf("%d", c.Port),
		},
	}
	if c.Interface != "" {
		iface := []corev1.EnvVar{
			{
				Name:  vipInterface,
				Value: c.Interface,
			},
		}
		newEnvironment = append(newEnvironment, iface...)
	}
	if c.ServicesInterface != "" {
		svcInterface := []corev1.EnvVar{
			{
				Name:  vipServicesInterface,
				Value: c.ServicesInterface,
			},
		}
		newEnvironment = append(newEnvironment, svcInterface...)
	}
	if c.VIPCIDR != "" {
		cidr := []corev1.EnvVar{
			{
				Name:  vipCidr,
				Value: c.VIPCIDR,
			},
		}
		newEnvironment = append(newEnvironment, cidr...)
	}
	if c.EnableControlPane {
		cp := []corev1.EnvVar{
			{
				Name:  cpEnable,
				Value: strconv.FormatBool(c.EnableControlPane),
			},
			{
				Name:  cpNamespace,
				Value: c.Namespace,
			},
			{
				Name:  vipDdns,
				Value: strconv.FormatBool(c.DDNS),
			},
		}
		newEnvironment = append(newEnvironment, cp...)
	}
	if c.EnableServices {
		cp := []corev1.EnvVar{
			{
				Name:  svcEnable,
				Value: strconv.FormatBool(c.EnableServices),
			},
		}
		newEnvironment = append(newEnvironment, cp...)
	}
	if c.EnableLeaderElection {
		leaderElection := []corev1.EnvVar{
			{
				Name:  vipLeaderElection,
				Value: strconv.FormatBool(c.EnableLeaderElection),
			},
			{
				Name:  vipLeaseDuration,
				Value: fmt.Sprintf("%d", c.LeaseDuration),
			},
			{
				Name:  vipRenewDeadline,
				Value: fmt.Sprintf("%d", c.RenewDeadline),
			},
			{
				Name:  vipRetryPeriod,
				Value: fmt.Sprintf("%d", c.RetryPeriod),
			},
		}
		if c.LeaseDuration == 0 {
			c.LeaseDuration = 15
		}
		if c.RenewDeadline == 0 {
			c.RenewDeadline = 10
		}
		if c.RetryPeriod == 0 {
			c.RetryPeriod = 2
		}
		newEnvironment = append(newEnvironment, leaderElection...)
	} else {
		raft := []corev1.EnvVar{
			{
				Name:  vipStartLeader,
				Value: strconv.FormatBool(c.StartAsLeader),
			},
			{
				Name:  vipAddPeersToLB,
				Value: strconv.FormatBool(c.AddPeersAsBackends),
			},
			{
				Name:  vipLocalPeer,
				Value: fmt.Sprintf("%s:%s:%d", c.LocalPeer.ID, c.LocalPeer.Address, c.LocalPeer.Port),
			},
		}
		newEnvironment = append(newEnvironment, raft...)
	}
	if c.Annotations != "" {
		annotations := []corev1.EnvVar{
			{
				Name:  annotations,
				Value: c.Annotations,
			},
		}
		newEnvironment = append(newEnvironment, annotations...)
	}
	if c.ProviderConfig != "" {
		provider := []corev1.EnvVar{
			{
				Name:  providerConfig,
				Value: c.ProviderConfig,
			},
		}
		newEnvironment = append(newEnvironment, provider...)
	}
	if c.EnableMetal {
		packet := []corev1.EnvVar{
			{
				Name:  vipPacket,
				Value: strconv.FormatBool(c.EnableMetal),
			},
			{
				Name:  vipPacketProject,
				Value: c.MetalProject,
			},
			{
				Name:  vipPacketProjectID,
				Value: c.MetalProjectID,
			},
			{
				Name:  "PACKET_AUTH_TOKEN",
				Value: c.MetalAPIKey,
			},
		}
		newEnvironment = append(newEnvironment, packet...)
	}
	if c.EnableBGP {
		bgp := []corev1.EnvVar{
			{
				Name:  bgpEnable,
				Value: strconv.FormatBool(c.EnableBGP),
			},
		}
		newEnvironment = append(newEnvironment, bgp...)
	}
	if c.EnableBGP && !c.EnableMetal {
		bgpConfig := []corev1.EnvVar{
			{
				Name:  bgpRouterID,
				Value: c.BGPConfig.RouterID,
			},
			{
				Name:  bgpRouterAS,
				Value: fmt.Sprintf("%d", c.BGPConfig.AS),
			},
			{
				Name:  bgpPeerAddress,
				Value: c.BGPPeerConfig.Address,
			},
			{
				Name:  bgpPeerPassword,
				Value: c.BGPPeerConfig.Password,
			},
			{
				Name:  bgpPeerAS,
				Value: fmt.Sprintf("%d", c.BGPPeerConfig.AS),
			},
		}
		if c.BGPConfig.SourceIF != "" {
			bgpConfig = append(bgpConfig, corev1.EnvVar{
				Name:  bgpSourceIF,
				Value: c.BGPConfig.SourceIF,
			},
			)
		}
		if c.BGPConfig.SourceIP != "" {
			bgpConfig = append(bgpConfig, corev1.EnvVar{
				Name:  bgpSourceIP,
				Value: c.BGPConfig.SourceIP,
			},
			)
		}
		var peers string
		if len(c.BGPPeers) != 0 {
			for x := range c.BGPPeers {
				if x != 0 {
					peers = fmt.Sprintf("%s,%s", peers, c.BGPPeers[x])
				} else {
					peers = c.BGPPeers[x]
				}
			}
			bgpConfig = append(bgpConfig, corev1.EnvVar{
				Name:  bgpPeers,
				Value: peers,
			},
			)
		}
		newEnvironment = append(newEnvironment, bgpConfig...)
	}
	if c.EnableLoadBalancer {
		lb := []corev1.EnvVar{
			{
				Name:  lbEnable,
				Value: strconv.FormatBool(c.EnableLoadBalancer),
			},
			{
				Name:  lbPort,
				Value: fmt.Sprintf("%d", c.LoadBalancerPort),
			},
		}
		newEnvironment = append(newEnvironment, lb...)
	}
	if c.Address != "" {
		newEnvironment = append(newEnvironment, corev1.EnvVar{
			Name:  address,
			Value: c.Address,
		})
	} else {
		newEnvironment = append(newEnvironment, corev1.EnvVar{
			Name:  vipAddress,
			Value: c.VIP,
		})
	}
	if len(c.RemotePeers) != 0 {
		var peers string
		for x := range c.RemotePeers {
			if x != 0 {
				peers = fmt.Sprintf("%s,%s:%s:%d", peers, c.RemotePeers[x].ID, c.RemotePeers[x].Address, c.RemotePeers[x].Port)
			} else {
				peers = fmt.Sprintf("%s:%s:%d", c.RemotePeers[x].ID, c.RemotePeers[x].Address, c.RemotePeers[x].Port)
			}
		}
		peerEnvirontment := corev1.EnvVar{
			Name:  vipPeers,
			Value: peers,
		}
		newEnvironment = append(newEnvironment, peerEnvirontment)
	}
	newManifest := &corev1.Pod{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Pod",
			APIVersion: "v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "kube-vip",
			Namespace: "kube-system",
		},
		Spec: corev1.PodSpec{
			Containers: []corev1.Container{
				{
					Name:            "kube-vip",
					Image:           fmt.Sprintf("ghcr.io/kube-vip/kube-vip:%s", imageVersion),
					ImagePullPolicy: corev1.PullAlways,
					SecurityContext: &corev1.SecurityContext{
						Capabilities: &corev1.Capabilities{
							Add: []corev1.Capability{
								"NET_ADMIN",
								"NET_RAW",
								"SYS_TIME",
							},
						},
					},
					Args: []string{
						command,
					},
					Env: newEnvironment,
				},
			},
			HostNetwork: true,
		},
	}
	if inCluster {
		newManifest.Spec.ServiceAccountName = "kube-vip"
	} else {
		adminConfMount := corev1.VolumeMount{
			Name:      "kubeconfig",
			MountPath: "/etc/kubernetes/admin.conf",
		}
		newManifest.Spec.Containers[0].VolumeMounts = append(newManifest.Spec.Containers[0].VolumeMounts, adminConfMount)
		adminConfVolume := corev1.Volume{
			Name: "kubeconfig",
			VolumeSource: corev1.VolumeSource{
				HostPath: &corev1.HostPathVolumeSource{
					Path: "/etc/kubernetes/admin.conf",
				},
			},
		}
		newManifest.Spec.Volumes = append(newManifest.Spec.Volumes, adminConfVolume)
		hostAlias := corev1.HostAlias{
			IP:        "127.0.0.1",
			Hostnames: []string{"kubernetes"},
		}
		newManifest.Spec.HostAliases = append(newManifest.Spec.HostAliases, hostAlias)
	}
	if c.ProviderConfig != "" {
		providerConfigMount := corev1.VolumeMount{
			Name:      "cloud-sa-volume",
			MountPath: "/etc/cloud-sa",
			ReadOnly:  true,
		}
		newManifest.Spec.Containers[0].VolumeMounts = append(newManifest.Spec.Containers[0].VolumeMounts, providerConfigMount)
		providerConfigVolume := corev1.Volume{
			Name: "cloud-sa-volume",
			VolumeSource: corev1.VolumeSource{
				Secret: &corev1.SecretVolumeSource{
					SecretName: "metal-cloud-config",
				},
			},
		}
		newManifest.Spec.Volumes = append(newManifest.Spec.Volumes, providerConfigVolume)
	}
	return newManifest
}
func GeneratePodManifestFromConfig(c *Config, imageVersion string, inCluster bool) string {
	newManifest := generatePodSpec(c, imageVersion, inCluster)
	b, _ := yaml.Marshal(newManifest)
	return string(b)
}