diff --git a/engine/hatchery/kubernetes/helper_test.go b/engine/hatchery/kubernetes/helper_test.go index c0b15ab328..4d6673057e 100644 --- a/engine/hatchery/kubernetes/helper_test.go +++ b/engine/hatchery/kubernetes/helper_test.go @@ -20,8 +20,8 @@ func NewHatcheryKubernetesTest(t *testing.T) *HatcheryKubernetes { clientSet, errCl := kubernetes.NewForConfig(&rest.Config{Host: "http://lolcat.kube"}) require.NoError(t, errCl) - h.k8sClient = clientSet - gock.InterceptClient(h.k8sClient.CoreV1().RESTClient().(*rest.RESTClient).Client) + h.kubeClient = &kubernetesClient{clientSet} + gock.InterceptClient(clientSet.CoreV1().RESTClient().(*rest.RESTClient).Client) h.Config.Name = "kyubi" h.Config.Namespace = "hachibi" diff --git a/engine/hatchery/kubernetes/kill_workers.go b/engine/hatchery/kubernetes/kill_workers.go index 8b7d169fc2..d645000ea7 100644 --- a/engine/hatchery/kubernetes/kill_workers.go +++ b/engine/hatchery/kubernetes/kill_workers.go @@ -17,7 +17,7 @@ import ( ) func (h *HatcheryKubernetes) killAwolWorkers(ctx context.Context) error { - pods, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: LABEL_WORKER}) + pods, err := h.kubeClient.PodList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: LABEL_WORKER}) if err != nil { return err } @@ -35,7 +35,7 @@ func (h *HatcheryKubernetes) killAwolWorkers(ctx context.Context) error { } // If no job identifiers, no services on pod - jobIdentifiers := h.getJobIdentiers(labels) + jobIdentifiers := getJobIdentiers(labels) if jobIdentifiers != nil { // Browse container to send end log for each service servicesLogs := make([]cdslog.Message, 0) @@ -97,9 +97,8 @@ func (h *HatcheryKubernetes) killAwolWorkers(ctx context.Context) error { log.Error(ctx, "killAndRemove> error on call client.WorkerModelSpawnError on worker model %s for register: %s", modelPath, err) } } - } - if err := h.k8sClient.CoreV1().Pods(pod.Namespace).Delete(pod.Name, nil); err != nil { + if err := h.kubeClient.PodDelete(ctx, pod.Namespace, pod.Name, nil); err != nil { globalErr = err log.Error(ctx, "hatchery:kubernetes> killAwolWorkers> Cannot delete pod %s (%s)", pod.Name, err) } diff --git a/engine/hatchery/kubernetes/kubernetes.go b/engine/hatchery/kubernetes/kubernetes.go index 6310180218..ead505d2af 100644 --- a/engine/hatchery/kubernetes/kubernetes.go +++ b/engine/hatchery/kubernetes/kubernetes.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "html/template" - "os" "strconv" "strings" "time" @@ -14,14 +13,11 @@ import ( "github.com/gorilla/mux" "github.com/rockbears/log" "github.com/sirupsen/logrus" + apiv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "github.com/ovh/cds/engine/api" "github.com/ovh/cds/engine/service" @@ -80,71 +76,16 @@ func (h *HatcheryKubernetes) ApplyConfiguration(cfg interface{}) error { return fmt.Errorf("Invalid configuration") } - var errCl error - var clientSet *kubernetes.Clientset - k8sTimeout := time.Second * 10 - - if h.Config.KubernetesConfigFile != "" { - cfg, err := clientcmd.BuildConfigFromFlags(h.Config.KubernetesMasterURL, h.Config.KubernetesConfigFile) - if err != nil { - return sdk.WrapError(err, "Cannot build config from flags") - } - cfg.Timeout = k8sTimeout - - clientSet, errCl = kubernetes.NewForConfig(cfg) - if errCl != nil { - return sdk.WrapError(errCl, "Cannot create client with newForConfig") - } - } else if h.Config.KubernetesMasterURL != "" { - configK8s, err := clientcmd.BuildConfigFromKubeconfigGetter(h.Config.KubernetesMasterURL, h.getStartingConfig) - if err != nil { - return sdk.WrapError(err, "Cannot build config from config getter") - } - configK8s.Timeout = k8sTimeout - - if h.Config.KubernetesCertAuthData != "" { - configK8s.TLSClientConfig = rest.TLSClientConfig{ - CAData: []byte(h.Config.KubernetesCertAuthData), - CertData: []byte(h.Config.KubernetesClientCertData), - KeyData: []byte(h.Config.KubernetesClientKeyData), - } - } - - // creates the clientset - clientSet, errCl = kubernetes.NewForConfig(configK8s) - if errCl != nil { - return sdk.WrapError(errCl, "Cannot create new config") - } - } else { - config, err := rest.InClusterConfig() - if err != nil { - return sdk.WrapError(err, "Unable to configure k8s InClusterConfig") - } - - clientSet, errCl = kubernetes.NewForConfig(config) - if errCl != nil { - return sdk.WrapError(errCl, "Unable to configure k8s client with InClusterConfig") - } - - } - - h.k8sClient = clientSet - - if h.Config.Namespace != apiv1.NamespaceDefault { - if _, err := clientSet.CoreV1().Namespaces().Get(h.Config.Namespace, metav1.GetOptions{}); err != nil { - ns := apiv1.Namespace{} - ns.SetName(h.Config.Namespace) - if _, errC := clientSet.CoreV1().Namespaces().Create(&ns); errC != nil { - return sdk.WrapError(errC, "Cannot create namespace %s in kubernetes", h.Config.Namespace) - } - } + var err error + h.kubeClient, err = initKubeClient(h.Config) + if err != nil { + return err } h.Common.Common.ServiceName = h.Config.Name h.Common.Common.ServiceType = sdk.TypeHatchery h.HTTPURL = h.Config.URL h.MaxHeartbeatFailures = h.Config.API.MaxHeartbeatFailures - var err error h.Common.Common.PrivateKey, err = jwt.ParseRSAPrivateKeyFromPEM([]byte(h.Config.RSAPrivateKey)) if err != nil { return fmt.Errorf("unable to parse RSA private Key: %v", err) @@ -161,42 +102,19 @@ func (h *HatcheryKubernetes) Status(ctx context.Context) *sdk.MonitoringStatus { return m } -// getStartingConfig implements ConfigAccess -func (h *HatcheryKubernetes) getStartingConfig() (*clientcmdapi.Config, error) { - defaultClientConfigRules := clientcmd.NewDefaultClientConfigLoadingRules() - overrideCfg := clientcmd.ConfigOverrides{ - AuthInfo: clientcmdapi.AuthInfo{ - Username: h.Config.KubernetesUsername, - Password: h.Config.KubernetesPassword, - Token: h.Config.KubernetesToken, - }, - } - - clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(defaultClientConfigRules, &overrideCfg) - rawConfig, err := clientConfig.RawConfig() - if os.IsNotExist(err) { - return clientcmdapi.NewConfig(), nil - } - if err != nil { - return nil, err - } - - return &rawConfig, nil -} - // CheckConfiguration checks the validity of the configuration object func (h *HatcheryKubernetes) CheckConfiguration(cfg interface{}) error { hconfig, ok := cfg.(HatcheryConfiguration) if !ok { - return fmt.Errorf("Invalid hatchery kubernetes configuration") + return sdk.WithStack(fmt.Errorf("invalid hatchery kubernetes configuration")) } if err := hconfig.Check(); err != nil { - return fmt.Errorf("Invalid hatchery kubernetes configuration: %v", err) + return sdk.WithStack(fmt.Errorf("invalid hatchery kubernetes configuration: %v", err)) } if hconfig.Namespace == "" { - return fmt.Errorf("please enter a valid kubernetes namespace") + return sdk.WithStack(fmt.Errorf("missing valid kubernetes namespace")) } return nil @@ -391,7 +309,7 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery // Check here to add secret if needed secretName := "cds-credreg-" + spawnArgs.Model.Name if spawnArgs.Model.ModelDocker.Private { - if err := h.createSecret(secretName, *spawnArgs.Model); err != nil { + if err := h.createSecret(ctx, secretName, *spawnArgs.Model); err != nil { return sdk.WrapError(err, "cannot create secret for model %s", spawnArgs.Model.Path()) } podSchema.Spec.ImagePullSecrets = []apiv1.LocalObjectReference{{Name: secretName}} @@ -447,10 +365,8 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery podSchema.Spec.HostAliases[0].Hostnames[i+1] = strings.ToLower(serv.Name) } - _, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).Create(&podSchema) - + _, err := h.kubeClient.PodCreate(ctx, h.Config.Namespace, &podSchema) log.Debug(ctx, "hatchery> kubernetes> SpawnWorker> %s > Pod created", spawnArgs.WorkerName) - return err } @@ -461,7 +377,7 @@ func (h *HatcheryKubernetes) GetLogger() *logrus.Logger { // WorkersStarted returns the number of instances started but // not necessarily register on CDS yet func (h *HatcheryKubernetes) WorkersStarted(ctx context.Context) []string { - list, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: LABEL_HATCHERY_NAME}) + list, err := h.kubeClient.PodList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: LABEL_HATCHERY_NAME}) if err != nil { log.Warn(ctx, "WorkersStarted> unable to list pods on namespace %s", h.Config.Namespace) return nil @@ -479,7 +395,7 @@ func (h *HatcheryKubernetes) WorkersStarted(ctx context.Context) []string { // WorkersStartedByModel returns the number of instances of given model started but // not necessarily register on CDS yet func (h *HatcheryKubernetes) WorkersStartedByModel(ctx context.Context, model *sdk.Model) int { - list, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: LABEL_WORKER_MODEL}) + list, err := h.kubeClient.PodList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: LABEL_WORKER_MODEL}) if err != nil { log.Error(ctx, "WorkersStartedByModel> Cannot get list of workers started (%s)", err) return 0 diff --git a/engine/hatchery/kubernetes/kubernetes_client.go b/engine/hatchery/kubernetes/kubernetes_client.go new file mode 100644 index 0000000000..01189cf0b9 --- /dev/null +++ b/engine/hatchery/kubernetes/kubernetes_client.go @@ -0,0 +1,174 @@ +package kubernetes + +import ( + "context" + "os" + "time" + + "github.com/ovh/cds/sdk" + "github.com/rockbears/log" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +const ( + logNS = log.Field("k8s_ns") + logPod = log.Field("k8s_pod") +) + +func init() { + log.RegisterField(logNS, logPod) +} + +func initKubeClient(config HatcheryConfiguration) (KubernetesClient, error) { + k8sTimeout := time.Second * 10 + + if config.KubernetesConfigFile != "" { + cfg, err := clientcmd.BuildConfigFromFlags(config.KubernetesMasterURL, config.KubernetesConfigFile) + if err != nil { + return nil, sdk.WrapError(err, "Cannot build config from flags") + } + cfg.Timeout = k8sTimeout + + clientSet, err := kubernetes.NewForConfig(cfg) + if err != nil { + return nil, sdk.WrapError(err, "Cannot create client with newForConfig") + } + return &kubernetesClient{clientSet}, nil + } + + if config.KubernetesMasterURL != "" { + configK8s, err := clientcmd.BuildConfigFromKubeconfigGetter(config.KubernetesMasterURL, getStartingConfig(config)) + if err != nil { + return nil, sdk.WrapError(err, "Cannot build config from config getter") + } + configK8s.Timeout = k8sTimeout + + if config.KubernetesCertAuthData != "" { + configK8s.TLSClientConfig = rest.TLSClientConfig{ + CAData: []byte(config.KubernetesCertAuthData), + CertData: []byte(config.KubernetesClientCertData), + KeyData: []byte(config.KubernetesClientKeyData), + } + } + + // creates the clientset + clientSet, err := kubernetes.NewForConfig(configK8s) + if err != nil { + return nil, sdk.WrapError(err, "Cannot create new config") + } + + return &kubernetesClient{clientSet}, nil + } + + cfg, err := rest.InClusterConfig() + if err != nil { + return nil, sdk.WrapError(err, "Unable to configure k8s InClusterConfig") + } + + clientSet, err := kubernetes.NewForConfig(cfg) + if err != nil { + return nil, sdk.WrapError(err, "Unable to configure k8s client with InClusterConfig") + } + + return &kubernetesClient{clientSet}, nil +} + +// getStartingConfig implements ConfigAccess +func getStartingConfig(config HatcheryConfiguration) func() (*clientcmdapi.Config, error) { + return func() (*clientcmdapi.Config, error) { + defaultClientConfigRules := clientcmd.NewDefaultClientConfigLoadingRules() + overrideCfg := clientcmd.ConfigOverrides{ + AuthInfo: clientcmdapi.AuthInfo{ + Username: config.KubernetesUsername, + Password: config.KubernetesPassword, + Token: config.KubernetesToken, + }, + } + + clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(defaultClientConfigRules, &overrideCfg) + rawConfig, err := clientConfig.RawConfig() + if os.IsNotExist(err) { + return clientcmdapi.NewConfig(), nil + } + if err != nil { + return nil, err + } + + return &rawConfig, nil + } +} + +type KubernetesClient interface { + PodCreate(ctx context.Context, ns string, spec *corev1.Pod) (*corev1.Pod, error) + PodDelete(ctx context.Context, ns string, name string, options *metav1.DeleteOptions) error + PodGetRawLogs(ctx context.Context, ns string, name string, options *corev1.PodLogOptions) ([]byte, error) + PodList(ctx context.Context, ns string, options metav1.ListOptions) (*corev1.PodList, error) + SecretCreate(ctx context.Context, ns string, spec *corev1.Secret) (*corev1.Secret, error) + SecretDelete(ctx context.Context, ns string, name string, options *metav1.DeleteOptions) error + SecretGet(ctx context.Context, ns string, name string, options *metav1.GetOptions) (*corev1.Secret, error) + SecretList(ctx context.Context, ns string, options metav1.ListOptions) (*corev1.SecretList, error) +} + +type kubernetesClient struct { + client *kubernetes.Clientset +} + +var ( + _ KubernetesClient = new(kubernetesClient) +) + +func (k *kubernetesClient) PodCreate(ctx context.Context, ns string, spec *corev1.Pod) (*corev1.Pod, error) { + ctx = context.WithValue(ctx, logNS, ns) + ctx = context.WithValue(ctx, logPod, spec.Name) + log.Info(ctx, "creating pod %s", spec.Name) + pod, err := k.client.CoreV1().Pods(ns).Create(spec) + return pod, sdk.WrapError(err, "unable to create pod %s", spec.Name) +} + +func (k *kubernetesClient) PodDelete(ctx context.Context, ns string, name string, options *metav1.DeleteOptions) error { + ctx = context.WithValue(ctx, logNS, ns) + ctx = context.WithValue(ctx, logPod, name) + log.Info(ctx, "deleting pod %s", name) + err := k.client.CoreV1().Pods(ns).Delete(name, options) + return sdk.WrapError(err, "unable to delete pod %s", name) +} + +func (k *kubernetesClient) PodList(ctx context.Context, ns string, opts metav1.ListOptions) (*corev1.PodList, error) { + ctx = context.WithValue(ctx, logNS, ns) + log.Info(ctx, "listing pod") + pods, err := k.client.CoreV1().Pods(ns).List(opts) + return pods, sdk.WrapError(err, "unable to list pods in namespace %s", ns) +} + +func (k *kubernetesClient) SecretCreate(ctx context.Context, ns string, spec *corev1.Secret) (*corev1.Secret, error) { + secret, err := k.client.CoreV1().Secrets(ns).Create(spec) + return secret, sdk.WrapError(err, "unable to create secret %s", spec.Name) +} + +func (k *kubernetesClient) SecretDelete(ctx context.Context, ns string, name string, options *metav1.DeleteOptions) error { + err := k.client.CoreV1().Secrets(ns).Delete(name, options) + return sdk.WrapError(err, "unable to delete secret %s", name) +} + +func (k *kubernetesClient) SecretGet(ctx context.Context, ns string, name string, options *metav1.GetOptions) (*corev1.Secret, error) { + secret, err := k.client.CoreV1().Secrets(ns).Get(name, *options) + return secret, sdk.WrapError(err, "unable to get secret %s", name) +} + +func (k *kubernetesClient) SecretList(ctx context.Context, ns string, options metav1.ListOptions) (*corev1.SecretList, error) { + secrets, err := k.client.CoreV1().Secrets(ns).List(options) + return secrets, sdk.WrapError(err, "unable to list secrets in namespace %s", ns) +} + +func (k *kubernetesClient) PodGetRawLogs(ctx context.Context, ns string, name string, options *corev1.PodLogOptions) ([]byte, error) { + ctx = context.WithValue(ctx, logNS, ns) + ctx = context.WithValue(ctx, logPod, name) + log.Debug(ctx, "get logs for pod %s", name) + logs, err := k.client.CoreV1().Pods(ns).GetLogs(name, options).DoRaw() + return logs, sdk.WrapError(err, "unable to get pod %s raw logs", name) +} diff --git a/engine/hatchery/kubernetes/secrets.go b/engine/hatchery/kubernetes/secrets.go index e11ff74b72..310e4ed4b2 100644 --- a/engine/hatchery/kubernetes/secrets.go +++ b/engine/hatchery/kubernetes/secrets.go @@ -12,12 +12,13 @@ import ( ) func (h *HatcheryKubernetes) deleteSecrets(ctx context.Context) error { - pods, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: LABEL_SECRET}) + pods, err := h.kubeClient.PodList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: LABEL_SECRET}) if err != nil { return sdk.WrapError(err, "cannot get pods with secret") } - secrets, errS := h.k8sClient.CoreV1().Secrets(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: LABEL_SECRET}) - if errS != nil { + + secrets, err := h.kubeClient.SecretList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: LABEL_SECRET}) + if err != nil { return sdk.WrapError(err, "cannot get secrets") } @@ -31,7 +32,7 @@ func (h *HatcheryKubernetes) deleteSecrets(ctx context.Context) error { } } if !found { - if err := h.k8sClient.CoreV1().Secrets(h.Config.Namespace).Delete(secret.Name, nil); err != nil { + if err := h.kubeClient.SecretDelete(ctx, h.Config.Namespace, secret.Name, nil); err != nil { log.Error(ctx, "deleteSecrets> Cannot delete secret %s : %v", secret.Name, err) } } @@ -40,10 +41,8 @@ func (h *HatcheryKubernetes) deleteSecrets(ctx context.Context) error { return nil } -func (h *HatcheryKubernetes) createSecret(secretName string, model sdk.Model) error { - h.k8sClient.CoreV1().Secrets(h.Config.Namespace) - _, err := h.k8sClient.CoreV1().Secrets(h.Config.Namespace).Get(secretName, metav1.GetOptions{}) - if err != nil { +func (h *HatcheryKubernetes) createSecret(ctx context.Context, secretName string, model sdk.Model) error { + if _, err := h.kubeClient.SecretGet(ctx, h.Config.Namespace, secretName, &metav1.GetOptions{}); err != nil { registry := "https://index.docker.io/v1/" if model.ModelDocker.Registry != "" { registry = model.ModelDocker.Registry @@ -62,9 +61,8 @@ func (h *HatcheryKubernetes) createSecret(secretName string, model sdk.Model) er apiv1.DockerConfigJsonKey: dockerCfg, }, } - _, errCreate := h.k8sClient.CoreV1().Secrets(h.Config.Namespace).Create(&wmSecret) - if errCreate != nil { - return sdk.WrapError(errCreate, "Cannot create secret %s", secretName) + if _, err := h.kubeClient.SecretCreate(ctx, h.Config.Namespace, &wmSecret); err != nil { + return sdk.WrapError(err, "Cannot create secret %s", secretName) } } diff --git a/engine/hatchery/kubernetes/services.go b/engine/hatchery/kubernetes/services.go index 37ecb7593e..6a7a034a3a 100644 --- a/engine/hatchery/kubernetes/services.go +++ b/engine/hatchery/kubernetes/services.go @@ -2,23 +2,24 @@ package kubernetes import ( "context" - "github.com/ovh/cds/sdk/cdn" "strconv" "strings" "time" "github.com/rockbears/log" "github.com/sirupsen/logrus" + apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/ovh/cds/sdk" + "github.com/ovh/cds/sdk/cdn" "github.com/ovh/cds/sdk/hatchery" cdslog "github.com/ovh/cds/sdk/log" ) func (h *HatcheryKubernetes) getServicesLogs(ctx context.Context) error { - pods, err := h.k8sClient.CoreV1().Pods(h.Config.Namespace).List(metav1.ListOptions{LabelSelector: hatchery.LabelServiceJobID}) + pods, err := h.kubeClient.PodList(ctx, h.Config.Namespace, metav1.ListOptions{LabelSelector: hatchery.LabelServiceJobID}) if err != nil { return err } @@ -33,7 +34,7 @@ func (h *HatcheryKubernetes) getServicesLogs(ctx context.Context) error { } // If no job identifier, no service on the pod - jobIdentifiers := h.getJobIdentiers(labels) + jobIdentifiers := getJobIdentiers(labels) if jobIdentifiers == nil { continue } @@ -49,9 +50,10 @@ func (h *HatcheryKubernetes) getServicesLogs(ctx context.Context) error { continue } logsOpts := apiv1.PodLogOptions{SinceSeconds: &sinceSeconds, Container: container.Name, Timestamps: true} - logs, errLogs := h.k8sClient.CoreV1().Pods(h.Config.Namespace).GetLogs(podName, &logsOpts).DoRaw() - if errLogs != nil { - log.Error(ctx, "getServicesLogs> cannot get logs for container %s in pod %s, err : %v", container.Name, podName, errLogs) + + logs, err := h.kubeClient.PodGetRawLogs(ctx, h.Config.Namespace, podName, &logsOpts) + if err != nil { + log.Error(ctx, "getServicesLogs> cannot get logs for container %s in pod %s, err : %v", container.Name, podName, err) continue } // No check on error thanks to the regexp @@ -99,9 +101,9 @@ func (h *HatcheryKubernetes) getServicesLogs(ctx context.Context) error { return nil } -func (h *HatcheryKubernetes) getJobIdentiers(labels map[string]string) *hatchery.JobIdentifiers { - serviceJobID, errPj := strconv.ParseInt(labels[hatchery.LabelServiceJobID], 10, 64) - if errPj != nil { +func getJobIdentiers(labels map[string]string) *hatchery.JobIdentifiers { + serviceJobID, err := strconv.ParseInt(labels[hatchery.LabelServiceJobID], 10, 64) + if err != nil { return nil } diff --git a/engine/hatchery/kubernetes/types.go b/engine/hatchery/kubernetes/types.go index 5cdcf1fd67..ee9c92b47d 100644 --- a/engine/hatchery/kubernetes/types.go +++ b/engine/hatchery/kubernetes/types.go @@ -1,17 +1,11 @@ package kubernetes import ( - "os/exec" "regexp" - "sync" - "time" "github.com/ovh/cds/engine/service" hatcheryCommon "github.com/ovh/cds/engine/hatchery" - "github.com/ovh/cds/sdk/cdsclient" - - "k8s.io/client-go/kubernetes" ) const ( @@ -53,16 +47,6 @@ type HatcheryConfiguration struct { // HatcheryKubernetes implements HatcheryMode interface for local usage type HatcheryKubernetes struct { hatcheryCommon.Common - Config HatcheryConfiguration - sync.Mutex - workers map[string]workerCmd - client cdsclient.Interface - os string - arch string - k8sClient *kubernetes.Clientset -} - -type workerCmd struct { - cmd *exec.Cmd - created time.Time + Config HatcheryConfiguration + kubeClient KubernetesClient }