159 lines
4.0 KiB
Go
159 lines
4.0 KiB
Go
package compose
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path"
|
|
"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"
|
|
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) {
|
|
composeFiles, err := filepath.Glob(pattern)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
logrus.Debugf("considering %s config(s) for tag update", strings.Join(composeFiles, ", "))
|
|
|
|
for _, composeFile := range composeFiles {
|
|
opts := stack.Deploy{Composefiles: []string{composeFile}}
|
|
|
|
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)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
var composeTag string
|
|
switch img.(type) {
|
|
case reference.NamedTagged:
|
|
composeTag = img.(reference.NamedTagged).Tag()
|
|
default:
|
|
logrus.Debugf("unable to parse %s, skipping", img)
|
|
continue
|
|
}
|
|
|
|
composeImage := formatter.StripTagMeta(reference.Path(img))
|
|
|
|
logrus.Debugf("parsed %s from %s", composeTag, service.Image)
|
|
|
|
if image == composeImage {
|
|
bytes, err := ioutil.ReadFile(composeFile)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
old := fmt.Sprintf("%s:%s", composeImage, composeTag)
|
|
new := fmt.Sprintf("%s:%s", composeImage, tag)
|
|
replacedBytes := strings.Replace(string(bytes), old, new, -1)
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// UpdateLabel updates a label in-place on file system local compose files.
|
|
func UpdateLabel(pattern, serviceName, label, recipeName string) error {
|
|
composeFiles, err := filepath.Glob(pattern)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logrus.Debugf("considering %s config(s) for label update", strings.Join(composeFiles, ", "))
|
|
|
|
for _, composeFile := range composeFiles {
|
|
opts := stack.Deploy{Composefiles: []string{composeFile}}
|
|
|
|
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)
|
|
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
|
|
for oldLabel, value := range service.Deploy.Labels {
|
|
if strings.HasPrefix(oldLabel, "coop-cloud") {
|
|
discovered = true
|
|
|
|
bytes, err := ioutil.ReadFile(composeFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
old := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", value)
|
|
replacedBytes := strings.Replace(string(bytes), old, label, -1)
|
|
|
|
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 {
|
|
return err
|
|
}
|
|
|
|
logrus.Infof("synced label %s to service %s", label, serviceName)
|
|
}
|
|
}
|
|
|
|
if !discovered {
|
|
logrus.Warn("no existing label found, automagic insertion not supported yet")
|
|
logrus.Fatalf("add '- \"%s\"' manually to the 'app' service in %s", label, composeFile)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|