package compose import ( "fmt" "io/ioutil" "path/filepath" "strings" "coopcloud.tech/abra/pkg/client/stack" loader "coopcloud.tech/abra/pkg/client/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 string) error { composeFiles, err := filepath.Glob(pattern) if err != nil { return err } for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} emptyEnv := make(map[string]string) compose, err := loader.LoadComposefile(opts, emptyEnv) if err != nil { return 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 { logrus.Fatal(err) } composeImage := reference.Path(img) if strings.Contains(composeImage, "library") { // ParseNormalizedNamed prepends 'library' to images like nginx:, // postgres:, i.e. images which do not have a username in the // first position of the string composeImage = strings.Split(composeImage, "/")[1] } composeTag := img.(reference.NamedTagged).Tag() if image == composeImage { bytes, err := ioutil.ReadFile(composeFile) if err != nil { logrus.Fatal(err) } old := fmt.Sprintf("%s:%s", composeImage, composeTag) new := fmt.Sprintf("%s:%s", composeImage, tag) replacedBytes := strings.Replace(string(bytes), old, new, -1) if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0644); err != nil { return err } } } } return nil } // UpdateLabel updates a label in-place on file system local compose files. func UpdateLabel(pattern, serviceName, label string) error { composeFiles, err := filepath.Glob(pattern) if err != nil { return err } for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} emptyEnv := make(map[string]string) compose, err := loader.LoadComposefile(opts, emptyEnv) 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 } for oldLabel, value := range service.Deploy.Labels { if strings.HasPrefix(oldLabel, "coop-cloud") { bytes, err := ioutil.ReadFile(composeFile) if err != nil { return err } old := fmt.Sprintf("coop-cloud.${STACK_NAME}.%s.version=%s", service.Name, value) replacedBytes := strings.Replace(string(bytes), old, label, -1) if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0644); err != nil { return err } } } } return nil }