func (k *KubeAPIServer) Validate() error {
	var errors util.ValidateErrors
	v := validator{
		Common: k.Common,
		Host:   k.Host,
		YAML:   k,
	}
	if err := v.validate(false); err != nil {
		errors = append(errors, err)
	}
	if len(k.EtcdServers) == 0 {
		errors = append(errors, fmt.Errorf("at least one etcd server must be defined"))
	}
	return errors.Return()
}
Validate validates KubeAPIServer struct.

TODO: Add validation of certificates if specified.
package controlplane
import (
	"fmt"
	"path"
	"strings"
	"github.com/flexkube/libflexkube/internal/util"
	"github.com/flexkube/libflexkube/pkg/container"
	"github.com/flexkube/libflexkube/pkg/container/runtime/docker"
	containertypes "github.com/flexkube/libflexkube/pkg/container/types"
	"github.com/flexkube/libflexkube/pkg/defaults"
	"github.com/flexkube/libflexkube/pkg/host"
	"github.com/flexkube/libflexkube/pkg/types"
)
type KubeAPIServer struct {
	Common *Common `json:"common,omitempty"`
	Host *host.Host `json:"host,omitempty"`
	APIServerCertificate types.Certificate `json:"apiServerCertificate"`
	APIServerKey types.PrivateKey `json:"apiServerKey"`
	ServiceAccountPrivateKey string `json:"serviceAccountPrivateKey"`
	BindAddress string `json:"bindAddress"`
	AdvertiseAddress string `json:"advertiseAddress"`
	EtcdServers []string `json:"etcdServers"`
	ServiceCIDR string `json:"serviceCIDR"`
	SecurePort int `json:"securePort"`
	FrontProxyCertificate types.Certificate `json:"frontProxyCertificate"`
	FrontProxyKey types.PrivateKey `json:"frontProxyKey"`
	KubeletClientCertificate types.Certificate `json:"kubeletClientCertificate"`
	KubeletClientKey types.PrivateKey `json:"kubeletClientKey"`
	EtcdCACertificate types.Certificate `json:"etcdCACertificate"`
	EtcdClientCertificate types.Certificate `json:"etcdClientCertificate"`
	EtcdClientKey types.PrivateKey `json:"etcdClientKey"`
}
type kubeAPIServer struct {
	common                   Common
	host                     host.Host
	apiServerCertificate     string
	apiServerKey             string
	serviceAccountPrivateKey string
	bindAddress              string
	advertiseAddress         string
	etcdServers              []string
	serviceCIDR              string
	securePort               int
	frontProxyCertificate    string
	frontProxyKey            string
	kubeletClientCertificate string
	kubeletClientKey         string
	etcdCACertificate        string
	etcdClientCertificate    string
	etcdClientKey            string
}
const (
	hostConfigPath      = "/etc/kubernetes/kube-apiserver/pki"
	containerConfigPath = "/etc/kubernetes/pki"
	containerName       = "kube-apiserver"
	clientCAFile                 = "ca.crt"
	tlsCertFile                  = "apiserver.crt"
	tlsPrivateKeyFile            = "apiserver.key"
	serviceAccountPrivateKeyFile = "service-account.key"
	requestheaderClientCAFile    = "front-proxy-ca.crt"
	proxyClientCertFile          = "front-proxy-client.crt"
	proxyClientKeyFile           = "front-proxy-client.key"
	kubeletClientCertificate     = "apiserver-kubelet-client.crt"
	kubeletClientKey             = "apiserver-kubelet-client.key"
	etcdCAFile                   = "etcd/ca.crt"
	etcdCertificate              = "apiserver-etcd-client.crt"
	etcdKeyfile                  = "apiserver-etcd-client.key"
)
func (k *kubeAPIServer) configFiles() map[string]string {
	m := map[string]string{
		clientCAFile:                 string(k.common.KubernetesCACertificate),
		tlsCertFile:                  k.apiServerCertificate,
		tlsPrivateKeyFile:            k.apiServerKey,
		serviceAccountPrivateKeyFile: k.serviceAccountPrivateKey,
		requestheaderClientCAFile:    string(k.common.FrontProxyCACertificate),
		proxyClientCertFile:          k.frontProxyCertificate,
		proxyClientKeyFile:           k.frontProxyKey,
		kubeletClientCertificate:     k.kubeletClientCertificate,
		kubeletClientKey:             k.kubeletClientKey,
		etcdCAFile:                   k.etcdCACertificate,
		etcdCertificate:              k.etcdClientCertificate,
		etcdKeyfile:                  k.etcdClientKey,
	}
	r := map[string]string{}
	for k, v := range m {
		r[path.Join(hostConfigPath, k)] = v
	}
	return r
}
func (k *kubeAPIServer) args() []string {
	return []string{
		"kube-apiserver",
		fmt.Sprintf("--etcd-servers=%s", strings.Join(k.etcdServers, ",")),
		fmt.Sprintf("--client-ca-file=%s", path.Join(containerConfigPath, clientCAFile)),
		fmt.Sprintf("--tls-cert-file=%s", path.Join(containerConfigPath, tlsCertFile)),
		fmt.Sprintf("--tls-private-key-file=%s", path.Join(containerConfigPath, tlsPrivateKeyFile)),
		"--enable-bootstrap-token-auth=true",
		fmt.Sprintf("--service-cluster-ip-range=%s", k.serviceCIDR),
		"--insecure-port=0",
		"--allow-privileged=true",
		"--authorization-mode=RBAC,Node",
		fmt.Sprintf("--service-account-key-file=%s", path.Join(containerConfigPath, serviceAccountPrivateKeyFile)),
		fmt.Sprintf("--advertise-address=%s", k.advertiseAddress),
		fmt.Sprintf("--secure-port=%d", k.securePort),
		"--kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP",
		fmt.Sprintf("--requestheader-client-ca-file=%s", path.Join(containerConfigPath, requestheaderClientCAFile)),
		fmt.Sprintf("--proxy-client-cert-file=%s", path.Join(containerConfigPath, proxyClientCertFile)),
		fmt.Sprintf("--proxy-client-key-file=%s", path.Join(containerConfigPath, proxyClientKeyFile)),
		"--requestheader-allowed-names=",
		"--requestheader-extra-headers-prefix=X-Remote-Extra-",
		"--requestheader-group-headers=X-Remote-Group",
		"--requestheader-username-headers=X-Remote-User",
		fmt.Sprintf("--kubelet-client-certificate=%s", path.Join(containerConfigPath, kubeletClientCertificate)),
		fmt.Sprintf("--kubelet-client-key=%s", path.Join(containerConfigPath, kubeletClientKey)),
		fmt.Sprintf("--kubelet-certificate-authority=%s", path.Join(containerConfigPath, clientCAFile)),
		fmt.Sprintf("--etcd-cafile=%s", path.Join(containerConfigPath, etcdCAFile)),
		fmt.Sprintf("--etcd-certfile=%s", path.Join(containerConfigPath, etcdCertificate)),
		fmt.Sprintf("--etcd-keyfile=%s", path.Join(containerConfigPath, etcdKeyfile)),
		"--enable-admission-plugins=NodeRestriction,PodSecurityPolicy",
		"--target-ram-mb=512",
		"--permit-port-sharing=true",
		"--service-account-issuer=https://kubernetes.default.svc",
		fmt.Sprintf("--service-account-signing-key-file=%s", path.Join(containerConfigPath, serviceAccountPrivateKeyFile)),
	}
}
func (k *kubeAPIServer) ToHostConfiguredContainer() (*container.HostConfiguredContainer, error) {
	return &container.HostConfiguredContainer{
		Host:        k.host,
		ConfigFiles: k.configFiles(),
		Container: container.Container{
			Runtime: container.RuntimeConfig{
				Docker: docker.DefaultConfig(),
			},
			Config: containertypes.ContainerConfig{
				Name:        containerName,
				Image:       util.PickString(k.common.Image, defaults.KubeAPIServerImage),
				NetworkMode: "host",
				Mounts: []containertypes.Mount{
					{
						Source: hostConfigPath,
						Target: containerConfigPath,
					},
				},
				Args: k.args(),
			},
		},
	}, nil
}
func (k *KubeAPIServer) New() (container.ResourceInstance, error) {
	if k.Common == nil {
		k.Common = &Common{}
	}
	if k.Host == nil {
		k.Host = &host.Host{}
	}
	if err := k.Validate(); err != nil {
		return nil, fmt.Errorf("validating Kubernetes API server configuration: %w", err)
	}
	return &kubeAPIServer{
		common:                   *k.Common,
		host:                     *k.Host,
		apiServerCertificate:     string(k.APIServerCertificate),
		apiServerKey:             string(k.APIServerKey),
		serviceAccountPrivateKey: k.ServiceAccountPrivateKey,
		bindAddress:              k.BindAddress,
		advertiseAddress:         k.AdvertiseAddress,
		etcdServers:              k.EtcdServers,
		serviceCIDR:              k.ServiceCIDR,
		securePort:               k.SecurePort,
		frontProxyCertificate:    string(k.FrontProxyCertificate),
		frontProxyKey:            string(k.FrontProxyKey),
		kubeletClientCertificate: string(k.KubeletClientCertificate),
		kubeletClientKey:         string(k.KubeletClientKey),
		etcdCACertificate:        string(k.EtcdCACertificate),
		etcdClientCertificate:    string(k.EtcdClientCertificate),
		etcdClientKey:            string(k.EtcdClientKey),
	}, nil
}