package daemons import ( "context" "encoding/base64" "fmt" "oc-schedulerd/conf" oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/models/common/enum" "github.com/rs/zerolog" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" ) type ContainerMonitor struct { Monitor LocalMonitor KubeCA string KubeCert string KubeData string KubeHost string KubePort string KubeNamespace string KubeImage string } func NewContainerMonitor(UUID string, peerId string, duration int) Executor { return &ContainerMonitor{ Monitor: LocalMonitor{ ExecutionID: UUID, PeerID: peerId, Duration: duration, LokiUrl: oclib.GetConfig().LokiUrl, MongoUrl: oclib.GetConfig().MongoUrl, DBName: oclib.GetConfig().MongoDatabase, }, KubeCA: conf.GetConfig().KubeCA, KubeCert: conf.GetConfig().KubeCert, KubeData: conf.GetConfig().KubeData, KubeHost: conf.GetConfig().KubeHost, KubePort: conf.GetConfig().KubePort, KubeNamespace: conf.GetConfig().KubeNamespace, KubeImage: conf.GetConfig().KubeImage, } } func (cm *ContainerMonitor) PrepareMonitorExec() []string { args := []string{ "-e", cm.Monitor.ExecutionID, "-p", cm.Monitor.PeerID, "-u", cm.Monitor.LokiUrl, "-m", cm.Monitor.MongoUrl, "-d", cm.Monitor.DBName, "-M", "kubernetes", "-H", cm.KubeHost, "-P", cm.KubePort, "-C", cm.KubeCert, "-D", cm.KubeData, "-c", cm.KubeCA, } if cm.Monitor.Duration > 0 { args = append(args, "-t", fmt.Sprintf("%d", cm.Monitor.Duration)) } return args } func (cm *ContainerMonitor) failExec(execID string, l zerolog.Logger, msg string) { l.Error().Msg(msg) oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKFLOW_EXECUTION), nil).UpdateOne(map[string]interface{}{ "state": enum.FAILURE.EnumIndex(), }, execID) } func (cm *ContainerMonitor) LaunchMonitor(args []string, execID string, l zerolog.Logger) { ca, err := base64.StdEncoding.DecodeString(cm.KubeCA) if err != nil { cm.failExec(execID, l, "Failed to decode KubeCA: "+err.Error()) return } cert, err := base64.StdEncoding.DecodeString(cm.KubeCert) if err != nil { cm.failExec(execID, l, "Failed to decode KubeCert: "+err.Error()) return } key, err := base64.StdEncoding.DecodeString(cm.KubeData) if err != nil { cm.failExec(execID, l, "Failed to decode KubeData: "+err.Error()) return } cfg := &rest.Config{ Host: "https://" + cm.KubeHost + ":" + cm.KubePort, TLSClientConfig: rest.TLSClientConfig{ CAData: ca, CertData: cert, KeyData: key, }, } clientset, err := kubernetes.NewForConfig(cfg) if err != nil { cm.failExec(execID, l, "Failed to build Kubernetes client: "+err.Error()) return } backoffLimit := int32(0) job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: "oc-monitord-" + execID, Namespace: cm.KubeNamespace, }, Spec: batchv1.JobSpec{ BackoffLimit: &backoffLimit, Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, Containers: []corev1.Container{ { Name: "oc-monitord", Image: cm.KubeImage, Args: args, }, }, }, }, }, } _, err = clientset.BatchV1().Jobs(cm.KubeNamespace).Create(context.Background(), job, metav1.CreateOptions{}) if err != nil { cm.failExec(execID, l, "Failed to create Kubernetes Job: "+err.Error()) return } l.Info().Msg("Started Kubernetes Job oc-monitord-" + execID) }