forked from toolshed/abra
.gitea
cli
cmd
pkg
app
autocomplete
client
compose
compose.go
config
container
context
dns
formatter
git
integration
limit
lint
recipe
secret
server
service
ssh
test
upstream
web
scripts
tests
.drone.yml
.e2e.env.sample
.envrc.sample
.gitignore
.goreleaser.yml
AUTHORS.md
LICENSE
Makefile
README.md
go.mod
go.sum
renovate.json
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
|
|
}
|