forked from toolshed/abra
.gitea
cli
cmd
pkg
app
catalogue
client
compose
config
context
dns
git
limit
recipe
secret
server
ssh
upstream
commandconn
container
convert
stack
loader.go
options.go
remove.go
stack.go
web
scripts
tests
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
Makefile
README.md
go.mod
go.sum
renovate.json
136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
package stack // https://github.com/docker/cli/blob/master/cli/command/stack/loader/loader.go
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/docker/cli/cli/compose/loader"
|
|
"github.com/docker/cli/cli/compose/schema"
|
|
composetypes "github.com/docker/cli/cli/compose/types"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// DontSkipValidation ensures validation is done for compose file loading
|
|
func DontSkipValidation(opts *loader.Options) {
|
|
opts.SkipValidation = false
|
|
}
|
|
|
|
// LoadComposefile parse the composefile specified in the cli and returns its Config and version.
|
|
func LoadComposefile(opts Deploy, appEnv map[string]string) (*composetypes.Config, error) {
|
|
configDetails, err := getConfigDetails(opts.Composefiles, appEnv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dicts := getDictsFrom(configDetails.ConfigFiles)
|
|
config, err := loader.Load(configDetails, DontSkipValidation)
|
|
if err != nil {
|
|
if fpe, ok := err.(*loader.ForbiddenPropertiesError); ok {
|
|
return nil, fmt.Errorf("compose file contains unsupported options:\n\n%s",
|
|
propertyWarnings(fpe.Properties))
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
unsupportedProperties := loader.GetUnsupportedProperties(dicts...)
|
|
if len(unsupportedProperties) > 0 {
|
|
logrus.Warnf("Ignoring unsupported options: %s\n\n",
|
|
strings.Join(unsupportedProperties, ", "))
|
|
}
|
|
|
|
deprecatedProperties := loader.GetDeprecatedProperties(dicts...)
|
|
if len(deprecatedProperties) > 0 {
|
|
logrus.Warnf("Ignoring deprecated options:\n\n%s\n\n",
|
|
propertyWarnings(deprecatedProperties))
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func getDictsFrom(configFiles []composetypes.ConfigFile) []map[string]interface{} {
|
|
dicts := []map[string]interface{}{}
|
|
|
|
for _, configFile := range configFiles {
|
|
dicts = append(dicts, configFile.Config)
|
|
}
|
|
|
|
return dicts
|
|
}
|
|
|
|
func propertyWarnings(properties map[string]string) string {
|
|
var msgs []string
|
|
for name, description := range properties {
|
|
msgs = append(msgs, fmt.Sprintf("%s: %s", name, description))
|
|
}
|
|
sort.Strings(msgs)
|
|
return strings.Join(msgs, "\n\n")
|
|
}
|
|
|
|
func getConfigDetails(composefiles []string, appEnv map[string]string) (composetypes.ConfigDetails, error) {
|
|
var details composetypes.ConfigDetails
|
|
|
|
absPath, err := filepath.Abs(composefiles[0])
|
|
if err != nil {
|
|
return details, err
|
|
}
|
|
details.WorkingDir = filepath.Dir(absPath)
|
|
|
|
details.ConfigFiles, err = loadConfigFiles(composefiles)
|
|
if err != nil {
|
|
return details, err
|
|
}
|
|
// Take the first file version (2 files can't have different version)
|
|
details.Version = schema.Version(details.ConfigFiles[0].Config)
|
|
details.Environment = appEnv
|
|
return details, err
|
|
}
|
|
|
|
func buildEnvironment(env []string) (map[string]string, error) {
|
|
result := make(map[string]string, len(env))
|
|
for _, s := range env {
|
|
// if value is empty, s is like "K=", not "K".
|
|
if !strings.Contains(s, "=") {
|
|
return result, fmt.Errorf("unexpected environment %q", s)
|
|
}
|
|
kv := strings.SplitN(s, "=", 2)
|
|
result[kv[0]] = kv[1]
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func loadConfigFiles(filenames []string) ([]composetypes.ConfigFile, error) {
|
|
var configFiles []composetypes.ConfigFile
|
|
|
|
for _, filename := range filenames {
|
|
configFile, err := loadConfigFile(filename)
|
|
if err != nil {
|
|
return configFiles, err
|
|
}
|
|
configFiles = append(configFiles, *configFile)
|
|
}
|
|
|
|
return configFiles, nil
|
|
}
|
|
|
|
func loadConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
|
var bytes []byte
|
|
var err error
|
|
|
|
bytes, err = ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
config, err := loader.ParseYAML(bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &composetypes.ConfigFile{
|
|
Filename: filename,
|
|
Config: config,
|
|
}, nil
|
|
}
|