package daemons import ( "bytes" "encoding/json" "fmt" "io" "net/http" "oc-schedulerd/conf" oclib "cloud.o-forge.io/core/oc-lib" "github.com/rs/zerolog" ) type ContainerMonitor struct { Monitor LocalMonitor KubeCA string KubeCert string KubeData string KubeHost string KubePort 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, } } 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 } // Contact the docker's API at the KubeHost's URL to : // - Check if the image exists // - Create the container // - Start the container func (cm *ContainerMonitor) LaunchMonitor(args []string, l zerolog.Logger) { var containerID string imageName := "oc-monitord" url := "http://" + cm.KubeHost + ":2375" resp, err := http.Get(url + "/images/" + imageName + "/json") if err != nil { l.Fatal().Msg("Error when contacting the docker API on " + url + ": " + err.Error()) } if resp.StatusCode != http.StatusOK { d, _ := io.ReadAll(resp.Body) l.Fatal().Msg("Couldn't find the oc-monitord image : " + string(d)) } dataCreation := map[string]interface{}{"Image": imageName, "Cmd": args} byteData, err := json.Marshal(dataCreation) if err != nil { l.Fatal().Msg("Error when contacting the creating request body : " + err.Error()) } r, _ := http.NewRequest("POST", url+"/containers/create", bytes.NewBuffer(byteData)) r.Header.Add("Content-Type", "application/json") resp, err = http.DefaultClient.Do(r) if err != nil { l.Fatal().Msg("Error when contacting the docker API on " + url + ": " + err.Error()) } if resp.StatusCode == 201 { var d map[string]interface{} b, err := io.ReadAll(resp.Body) if err != nil { l.Fatal().Msg(err.Error()) } err = json.Unmarshal(b, &d) if err != nil { l.Fatal().Msg(err.Error()) } containerID = d["Id"].(string) } else { d, _ := io.ReadAll(resp.Body) l.Fatal().Msg("Error when creating the container on " + url + "\n " + string(d)) } networkName := "oc" dataNetwork, _ := json.Marshal(map[string]string{"Container": containerID}) r, _ = http.NewRequest("POST", url+"/networks/"+networkName+"/connect", bytes.NewBuffer(dataNetwork)) r.Header.Add("Content-Type", "application/json") resp, err = http.DefaultClient.Do(r) if err != nil { l.Fatal().Msg("Error when contacting the docker API on " + url + ": " + err.Error()) } if resp.StatusCode != 200 { d, _ := io.ReadAll(resp.Body) l.Error().Msg("Error when adding container to the network : " + string(d)) return } resp, err = http.Post(url+"/containers/"+containerID+"/start", "", nil) if err != nil { l.Fatal().Msg("Error when contacting the docker API on " + url + ": " + err.Error()) } if resp.StatusCode >= 300 { d, _ := io.ReadAll(resp.Body) l.Fatal().Msg("Error when starting the container on " + url + "\n " + string(d)) } l.Info().Msg("Started container " + containerID) // we can add logging with GET /containers/id/logs?stdout=true&follow=true // logExecution(stdoutMonitord, l) }