func (k *Kubernetes) prepareKubernetes() error {
	ctx := context.TODO()
	if _, err := k.k8sclient.CoreV1().Namespaces().Get(ctx, k.config.Namespace, metav1.GetOptions{}); err != nil {
		if errors.IsNotFound(err) {
			ns := &corev1.Namespace{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{
						"created-by": "ancientt",
					},
					Name: k.config.Namespace,
				},
			}
			k.logger.Info("trying to create namespace")
			ctx := context.TODO()
			if _, err := k.k8sclient.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}); err != nil {
				return fmt.Errorf("failed to create namespace %s. %+v", k.config.Namespace, err)
			}
			k.logger.Info("created namespace")
		} else {
			return fmt.Errorf("error while getting namespace %s. %+v", k.config.Namespace, err)
		}
	}
	return nil
}
prepareKubernetes prepares Kubernetes by creating the namespace if it does not exist
package kubernetes
import (
	"context"
	"fmt"
	"sync"
	"time"
	"github.com/cloudical-io/ancientt/parsers"
	"github.com/cloudical-io/ancientt/pkg/cmdtemplate"
	"github.com/cloudical-io/ancientt/pkg/config"
	"github.com/cloudical-io/ancientt/pkg/hostsfilter"
	"github.com/cloudical-io/ancientt/pkg/k8sutil"
	"github.com/cloudical-io/ancientt/pkg/util"
	"github.com/cloudical-io/ancientt/runners"
	"github.com/cloudical-io/ancientt/testers"
	"github.com/sirupsen/logrus"
	log "github.com/sirupsen/logrus"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)
const Name = "kubernetes"
func init() {
	runners.Factories[Name] = NewRunner
}
type Kubernetes struct {
	runners.Runner
	logger     *log.Entry
	config     *config.RunnerKubernetes
	k8sclient  kubernetes.Interface
	runOptions config.RunOptions
}
func NewRunner(cfg *config.Config) (runners.Runner, error) {
	conf := cfg.Runner.Kubernetes
	clientset, err := k8sutil.NewClient(cfg.Runner.Kubernetes.InClusterConfig, cfg.Runner.Kubernetes.Kubeconfig)
	if err != nil {
		return nil, err
	}
	return &Kubernetes{
		logger:    log.WithFields(logrus.Fields{"runner": Name, "namespace": cfg.Runner.Kubernetes.Namespace}),
		config:    conf,
		k8sclient: clientset,
	}, nil
}
func (k *Kubernetes) GetHostsForTest(test *config.Test) (*testers.Hosts, error) {
	hosts := &testers.Hosts{
		Clients: map[string]*testers.Host{},
		Servers: map[string]*testers.Host{},
	}
	k8sNodes, err := k.k8sNodesToHosts()
	if err != nil {
		return nil, err
	}
	for _, servers := range test.Hosts.Servers {
		filtered, err := hostsfilter.FilterHostsList(k8sNodes, servers)
		if err != nil {
			return nil, err
		}
		for _, host := range filtered {
			if _, ok := hosts.Servers[host.Name]; !ok {
				hosts.Servers[host.Name] = host
			}
		}
	}
	for _, clients := range test.Hosts.Clients {
		filtered, err := hostsfilter.FilterHostsList(k8sNodes, clients)
		if err != nil {
			return nil, err
		}
		for _, host := range filtered {
			if _, ok := hosts.Clients[host.Name]; !ok {
				hosts.Clients[host.Name] = host
			}
		}
	}
	k.logger.Debug("returning Kubernetes hosts list")
	return hosts, nil
}
func (k *Kubernetes) k8sNodesToHosts() ([]*testers.Host, error) {
	hosts := []*testers.Host{}
	ctx := context.TODO()
	nodes, err := k.k8sclient.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, node := range nodes.Items {
		if (k.config.Hosts != nil && *k.config.Hosts.IgnoreSchedulingDisabled) && node.Spec.Unschedulable {
			k.logger.WithFields(logrus.Fields{"node": node.ObjectMeta.Name}).Debug("skipping unschedulable node")
			continue
		}
		tolerations := []corev1.Toleration{}
		if k.config.Hosts != nil {
			tolerations = k.config.Hosts.Tolerations
		}
		if !k8sutil.NodeIsTolerable(node, tolerations) {
			continue
		}
		hosts = append(hosts, &testers.Host{
			Labels: node.ObjectMeta.Labels,
			Name:   node.ObjectMeta.Name,
		})
	}
	return hosts, nil
}
func (k *Kubernetes) Prepare(runOpts config.RunOptions, plan *testers.Plan) error {
	k.runOptions = runOpts
	if err := k.prepareKubernetes(); err != nil {
		return err
	}
	return nil
}
func (k *Kubernetes) Execute(plan *testers.Plan, parser chan<- parsers.Input) error {
	for round, tasks := range plan.Commands {
		k.logger.Infof("running commands round %d of %d", round+1, len(plan.Commands))
		for i, task := range tasks {
			if task.Sleep != 0 {
				k.logger.Infof("waiting %s to pass before continuing next round", task.Sleep.String())
				time.Sleep(task.Sleep)
				continue
			}
			k.logger.Infof("running task round %d of %d", i+1, len(tasks))
			if err := k.createPodsForTasks(round, task, plan, parser); err != nil {
				if !*plan.RunOptions.ContinueOnError {
					return err
				}
				k.logger.Warnf("continuing after err. %+v", err)
			}
		}
	}
	return nil
}