|
|
@@ -4,6 +4,7 @@ import (
|
|
|
"context"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
+ "goseg/config"
|
|
|
"goseg/structs"
|
|
|
"log/slog"
|
|
|
"os"
|
|
|
@@ -102,3 +103,128 @@ func GetContainerStats(containerName string) (structs.ContainerStats, error) {
|
|
|
DiskUsage: diskUsage,
|
|
|
}, nil
|
|
|
}
|
|
|
+
|
|
|
+// start a container by name + tag
|
|
|
+// not for booting new ships
|
|
|
+func StartContainer(containerName, containerType string) error {
|
|
|
+ ctx := context.Background()
|
|
|
+ cli, err := client.NewClientWithOpts(client.FromEnv)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ // Placeholder: Get the desired tag and hash from your config
|
|
|
+ containerInfo, err := getCurrentContainerInfo()
|
|
|
+ if err != nil {
|
|
|
+ errMsg := fmt.Errorf("Couldn't get %s container info: %v", containerName, err)
|
|
|
+ logger.Error(errMsg)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ desiredTag := containerInfo["tag"]
|
|
|
+ desiredHash := containerInfo["hash"]
|
|
|
+ desiredRepo := containerInfo["repo"]
|
|
|
+ if desiredTag == "" || desiredHash == "" {
|
|
|
+ err = fmt.Errorf("Version info has not been retrieved!")
|
|
|
+ logger.Error(err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ // Check if the desired image is available locally
|
|
|
+ images, err := cli.ImageList(ctx, types.ImageListOptions{})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ imageExistsLocally := false
|
|
|
+ for _, img := range images {
|
|
|
+ for _, tag := range img.RepoTags {
|
|
|
+ if tag == containerType+":"+desiredTag && img.ID == desiredHash {
|
|
|
+ imageExistsLocally = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if imageExistsLocally {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if !imageExistsLocally {
|
|
|
+ // pull the image if it doesn't exist locally
|
|
|
+ _, err = cli.ImagePull(ctx, desiredRepo+":"+desiredTag, types.ImagePullOptions{})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ switch {
|
|
|
+ case existingContainer == nil:
|
|
|
+ // if the container does not exist, create and start it
|
|
|
+ _, err := cli.ContainerCreate(ctx, &container.Config{
|
|
|
+ Image: containerType + ":" + containerTag,
|
|
|
+ }, nil, nil, nil, containerName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ err = cli.ContainerStart(ctx, containerName, types.ContainerStartOptions{})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ msg := fmt.Sprintf("%s started with image %s:%s", containerName, containerType, containerTag)
|
|
|
+ logger.Info(msg)
|
|
|
+ case existingContainer.State == "exited":
|
|
|
+ // if the container exists but is stopped, start it
|
|
|
+ err := cli.ContainerStart(ctx, containerName, types.ContainerStartOptions{})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ msg := fmt.Sprintf("Started stopped container %s", containerName)
|
|
|
+ logger.Info(msg)
|
|
|
+ default:
|
|
|
+ // if container is running, check the image tag
|
|
|
+ currentImage := existingContainer.Image
|
|
|
+ currentTag := strings.Split(currentImage, ":")[1]
|
|
|
+ if currentTag != containerTag {
|
|
|
+ // if the tags don't match, recreate the container with the new tag
|
|
|
+ err := cli.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{Force: true})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ _, err = cli.ContainerCreate(ctx, &container.Config{
|
|
|
+ Image: containerType + ":" + containerTag,
|
|
|
+ }, nil, nil, nil, containerName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ err = cli.ContainerStart(ctx, containerName, types.ContainerStartOptions{})
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ msg := fmt.Sprintf("Restarted %s with image %s:%s", containerName, containerType, containerTag)
|
|
|
+ logger.Info(msg)
|
|
|
+ } else {
|
|
|
+ msg := fmt.Sprintf("%s is already running with the correct tag: %s", containerName, containerTag)
|
|
|
+ logger.Info(msg)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// convert the version info back into json then a map lol
|
|
|
+// so we can easily get the correct repo/release channel/tag/hash
|
|
|
+func getCurrentContainerInfo(containerType string) (map[string]string, error) {
|
|
|
+ var res map[string]string
|
|
|
+ conf := config.Conf()
|
|
|
+ releaseChannel := conf.UpdateBranch
|
|
|
+ arch := config.Architecture
|
|
|
+ hashLabel := arch + "_sha256"
|
|
|
+ versionInfo := config.VersionInfo
|
|
|
+ jsonData, err := json.Marshal(VersionInfo)
|
|
|
+ if err != nil {
|
|
|
+ return res, err
|
|
|
+ }
|
|
|
+ // Convert JSON to map
|
|
|
+ var m map[string]interface{}
|
|
|
+ err = json.Unmarshal(jsonData, &m)
|
|
|
+ if err != nil {
|
|
|
+ return res, err
|
|
|
+ }
|
|
|
+ res["tag"] = m["groundseg"][releaseChannel][containerType]["tag"]
|
|
|
+ res["hash"] = m["groundseg"][releaseChannel][containerType][hashLabel]
|
|
|
+ res["repo"] = m["groundseg"][releaseChannel][containerType]["repo"]
|
|
|
+ return res, nil
|
|
|
+}
|