abra/pkg/compose/compose.go

159 lines
4.0 KiB
Go
Raw Normal View History

2021-09-05 23:15:59 +00:00
package compose
import (
"fmt"
"io/ioutil"
"path"
2021-09-05 23:15:59 +00:00
"path/filepath"
"strings"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/upstream/stack"
loader "coopcloud.tech/abra/pkg/upstream/stack"
2021-09-05 23:15:59 +00:00
composetypes "github.com/docker/cli/cli/compose/types"
"github.com/docker/distribution/reference"
"github.com/sirupsen/logrus"
)
// UpdateTag updates an image tag in-place on file system local compose files.
func UpdateTag(pattern, image, tag, recipeName string) (bool, error) {
2021-09-05 23:15:59 +00:00
composeFiles, err := filepath.Glob(pattern)
if err != nil {
return false, err
2021-09-05 23:15:59 +00:00
}
2021-12-25 01:03:09 +00:00
logrus.Debugf("considering %s config(s) for tag update", strings.Join(composeFiles, ", "))
2021-09-05 23:15:59 +00:00
for _, composeFile := range composeFiles {
opts := stack.Deploy{Composefiles: []string{composeFile}}
2021-12-25 13:04:07 +00:00
envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample")
sampleEnv, err := config.ReadEnv(envSamplePath)
if err != nil {
return false, err
}
compose, err := loader.LoadComposefile(opts, sampleEnv)
2021-09-05 23:15:59 +00:00
if err != nil {
return false, err
2021-09-05 23:15:59 +00:00
}
for _, service := range compose.Services {
if service.Image == "" {
continue // may be a compose.$optional.yml file
}
img, _ := reference.ParseNormalizedNamed(service.Image)
if err != nil {
return false, err
2021-09-05 23:15:59 +00:00
}
var composeTag string
switch img.(type) {
case reference.NamedTagged:
composeTag = img.(reference.NamedTagged).Tag()
default:
// unable to parse, typically image missing tag
return false, nil
2021-09-05 23:15:59 +00:00
}
composeImage := formatter.StripTagMeta(reference.Path(img))
2021-09-05 23:15:59 +00:00
2021-12-25 01:03:09 +00:00
logrus.Debugf("parsed %s from %s", composeTag, service.Image)
2021-09-05 23:15:59 +00:00
if image == composeImage {
bytes, err := ioutil.ReadFile(composeFile)
if err != nil {
return false, err
2021-09-05 23:15:59 +00:00
}
old := fmt.Sprintf("%s:%s", composeImage, composeTag)
new := fmt.Sprintf("%s:%s", composeImage, tag)
replacedBytes := strings.Replace(string(bytes), old, new, -1)
2021-12-25 01:03:09 +00:00
logrus.Debugf("updating %s to %s in %s", old, new, compose.Filename)
if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil {
return false, err
2021-09-05 23:15:59 +00:00
}
}
}
}
return false, nil
2021-09-05 23:15:59 +00:00
}
// UpdateLabel updates a label in-place on file system local compose files.
func UpdateLabel(pattern, serviceName, label, recipeName string) error {
2021-09-05 23:15:59 +00:00
composeFiles, err := filepath.Glob(pattern)
if err != nil {
return err
}
2021-12-20 00:05:51 +00:00
logrus.Debugf("considering %s config(s) for label update", strings.Join(composeFiles, ", "))
2021-09-05 23:15:59 +00:00
for _, composeFile := range composeFiles {
opts := stack.Deploy{Composefiles: []string{composeFile}}
2021-12-25 13:04:07 +00:00
envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample")
sampleEnv, err := config.ReadEnv(envSamplePath)
if err != nil {
return err
}
compose, err := loader.LoadComposefile(opts, sampleEnv)
2021-09-05 23:15:59 +00:00
if err != nil {
return err
}
serviceExists := false
var service composetypes.ServiceConfig
for _, s := range compose.Services {
if s.Name == serviceName {
service = s
serviceExists = true
}
}
if !serviceExists {
continue
}
discovered := false
2021-09-05 23:15:59 +00:00
for oldLabel, value := range service.Deploy.Labels {
if strings.HasPrefix(oldLabel, "coop-cloud") {
discovered = true
2021-09-05 23:15:59 +00:00
bytes, err := ioutil.ReadFile(composeFile)
if err != nil {
return err
}
old := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", value)
2021-09-05 23:15:59 +00:00
replacedBytes := strings.Replace(string(bytes), old, label, -1)
2021-12-21 00:48:37 +00:00
if old == label {
logrus.Warnf("%s is already set, nothing to do?", label)
return nil
}
logrus.Debugf("updating %s to %s in %s", old, label, compose.Filename)
if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil {
2021-09-05 23:15:59 +00:00
return err
}
2021-12-21 00:48:37 +00:00
logrus.Infof("synced label %s to service %s", label, serviceName)
2021-09-05 23:15:59 +00:00
}
}
if !discovered {
2021-12-23 01:10:57 +00:00
logrus.Warn("no existing label found, automagic insertion not supported yet")
2021-12-27 17:06:46 +00:00
logrus.Fatalf("add '- \"%s\"' manually to the 'app' service in %s", label, composeFile)
}
2021-09-05 23:15:59 +00:00
}
return nil
}