mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-12 14:37:08 +08:00
bump compose-go version to v1.17.0 to fix issue with depends_on
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:

committed by
CrazyMax

parent
50fbdd86f9
commit
f3775c0046
3
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
3
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
@ -24,7 +24,7 @@ services:
|
||||
- bar
|
||||
labels: [FOO=BAR]
|
||||
additional_contexts:
|
||||
foo: /bar
|
||||
foo: ./bar
|
||||
secrets:
|
||||
- secret1
|
||||
- source: secret2
|
||||
@ -181,6 +181,7 @@ services:
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
start_period: 15s
|
||||
start_interval: 5s
|
||||
|
||||
# Any valid image reference - repo, tag, id, sha
|
||||
image: redis
|
||||
|
120
vendor/github.com/compose-spec/compose-go/loader/include.go
generated
vendored
Normal file
120
vendor/github.com/compose-spec/compose-go/loader/include.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2020 The Compose Specification Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/compose-spec/compose-go/dotenv"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// LoadIncludeConfig parse the require config from raw yaml
|
||||
func LoadIncludeConfig(source []interface{}) ([]types.IncludeConfig, error) {
|
||||
var requires []types.IncludeConfig
|
||||
err := Transform(source, &requires)
|
||||
return requires, err
|
||||
}
|
||||
|
||||
var transformIncludeConfig TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case string:
|
||||
return map[string]interface{}{"path": value}, nil
|
||||
case map[string]interface{}:
|
||||
return value, nil
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for `include` configuration", value)
|
||||
}
|
||||
}
|
||||
|
||||
func loadInclude(configDetails types.ConfigDetails, model *types.Config, options *Options, loaded []string) (*types.Config, error) {
|
||||
for _, r := range model.Include {
|
||||
for i, p := range r.Path {
|
||||
if !filepath.IsAbs(p) {
|
||||
r.Path[i] = filepath.Join(configDetails.WorkingDir, p)
|
||||
}
|
||||
}
|
||||
if r.ProjectDirectory == "" {
|
||||
r.ProjectDirectory = filepath.Dir(r.Path[0])
|
||||
}
|
||||
|
||||
loadOptions := options.clone()
|
||||
loadOptions.SetProjectName(model.Name, true)
|
||||
loadOptions.ResolvePaths = true
|
||||
loadOptions.SkipNormalization = true
|
||||
loadOptions.SkipConsistencyCheck = true
|
||||
|
||||
env, err := dotenv.GetEnvFromFile(configDetails.Environment, r.ProjectDirectory, r.EnvFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imported, err := load(types.ConfigDetails{
|
||||
WorkingDir: r.ProjectDirectory,
|
||||
ConfigFiles: types.ToConfigFiles(r.Path),
|
||||
Environment: env,
|
||||
}, loadOptions, loaded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = importResources(model, imported, r.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
model.Include = nil
|
||||
return model, nil
|
||||
}
|
||||
|
||||
// importResources import into model all resources defined by imported, and report error on conflict
|
||||
func importResources(model *types.Config, imported *types.Project, path []string) error {
|
||||
services := mapByName(model.Services)
|
||||
for _, service := range imported.Services {
|
||||
if _, ok := services[service.Name]; ok {
|
||||
return fmt.Errorf("imported compose file %s defines conflicting service %s", path, service.Name)
|
||||
}
|
||||
model.Services = append(model.Services, service)
|
||||
}
|
||||
for n, network := range imported.Networks {
|
||||
if _, ok := model.Networks[n]; ok {
|
||||
return fmt.Errorf("imported compose file %s defines conflicting network %s", path, n)
|
||||
}
|
||||
model.Networks[n] = network
|
||||
}
|
||||
for n, volume := range imported.Volumes {
|
||||
if _, ok := model.Volumes[n]; ok {
|
||||
return fmt.Errorf("imported compose file %s defines conflicting volume %s", path, n)
|
||||
}
|
||||
model.Volumes[n] = volume
|
||||
}
|
||||
for n, secret := range imported.Secrets {
|
||||
if _, ok := model.Secrets[n]; ok {
|
||||
return fmt.Errorf("imported compose file %s defines conflicting secret %s", path, n)
|
||||
}
|
||||
model.Secrets[n] = secret
|
||||
}
|
||||
for n, config := range imported.Configs {
|
||||
if _, ok := model.Configs[n]; ok {
|
||||
return fmt.Errorf("imported compose file %s defines conflicting config %s", path, n)
|
||||
}
|
||||
model.Configs[n] = config
|
||||
}
|
||||
return nil
|
||||
}
|
203
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
203
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
@ -56,6 +56,8 @@ type Options struct {
|
||||
SkipConsistencyCheck bool
|
||||
// Skip extends
|
||||
SkipExtends bool
|
||||
// SkipInclude will ignore `include` and only load model from file(s) set by ConfigDetails
|
||||
SkipInclude bool
|
||||
// Interpolation options
|
||||
Interpolate *interp.Options
|
||||
// Discard 'env_file' entries after resolving to 'environment' section
|
||||
@ -68,6 +70,24 @@ type Options struct {
|
||||
Profiles []string
|
||||
}
|
||||
|
||||
func (o *Options) clone() *Options {
|
||||
return &Options{
|
||||
SkipValidation: o.SkipValidation,
|
||||
SkipInterpolation: o.SkipInterpolation,
|
||||
SkipNormalization: o.SkipNormalization,
|
||||
ResolvePaths: o.ResolvePaths,
|
||||
ConvertWindowsPaths: o.ConvertWindowsPaths,
|
||||
SkipConsistencyCheck: o.SkipConsistencyCheck,
|
||||
SkipExtends: o.SkipExtends,
|
||||
SkipInclude: o.SkipInclude,
|
||||
Interpolate: o.Interpolate,
|
||||
discardEnvFiles: o.discardEnvFiles,
|
||||
projectName: o.projectName,
|
||||
projectNameImperativelySet: o.projectNameImperativelySet,
|
||||
Profiles: o.Profiles,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Options) SetProjectName(name string, imperativelySet bool) {
|
||||
o.projectName = name
|
||||
o.projectNameImperativelySet = imperativelySet
|
||||
@ -185,6 +205,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
LookupValue: configDetails.LookupEnv,
|
||||
TypeCastMapping: interpolateTypeCastMapping,
|
||||
},
|
||||
ResolvePaths: true,
|
||||
}
|
||||
|
||||
for _, op := range options {
|
||||
@ -195,8 +216,22 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.projectName = projectName
|
||||
return load(configDetails, opts, nil)
|
||||
}
|
||||
|
||||
func load(configDetails types.ConfigDetails, opts *Options, loaded []string) (*types.Project, error) {
|
||||
var model *types.Config
|
||||
|
||||
mainFile := configDetails.ConfigFiles[0].Filename
|
||||
for _, f := range loaded {
|
||||
if f == mainFile {
|
||||
loaded = append(loaded, mainFile)
|
||||
return nil, errors.Errorf("include cycle detected:\n%s\n include %s", loaded[0], strings.Join(loaded[1:], "\n include "))
|
||||
}
|
||||
}
|
||||
loaded = append(loaded, mainFile)
|
||||
|
||||
for i, file := range configDetails.ConfigFiles {
|
||||
var postProcessor PostProcessor
|
||||
configDict := file.Config
|
||||
@ -231,10 +266,18 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !opts.SkipInclude {
|
||||
cfg, err = loadInclude(configDetails, cfg, opts, loaded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
model = cfg
|
||||
continue
|
||||
}
|
||||
|
||||
merged, err := merge([]*types.Config{model, cfg})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -248,16 +291,8 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
model = merged
|
||||
}
|
||||
|
||||
for _, s := range model.Services {
|
||||
var newEnvFiles types.StringList
|
||||
for _, ef := range s.EnvFile {
|
||||
newEnvFiles = append(newEnvFiles, absPath(configDetails.WorkingDir, ef))
|
||||
}
|
||||
s.EnvFile = newEnvFiles
|
||||
}
|
||||
|
||||
project := &types.Project{
|
||||
Name: projectName,
|
||||
Name: opts.projectName,
|
||||
WorkingDir: configDetails.WorkingDir,
|
||||
Services: model.Services,
|
||||
Networks: model.Networks,
|
||||
@ -269,14 +304,30 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
|
||||
if !opts.SkipNormalization {
|
||||
err = Normalize(project, opts.ResolvePaths)
|
||||
err := Normalize(project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.ResolvePaths {
|
||||
err := ResolveRelativePaths(project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.ConvertWindowsPaths {
|
||||
for i, service := range project.Services {
|
||||
for j, volume := range service.Volumes {
|
||||
service.Volumes[j] = convertVolumePath(volume)
|
||||
}
|
||||
project.Services[i] = service
|
||||
}
|
||||
}
|
||||
|
||||
if !opts.SkipConsistencyCheck {
|
||||
err = checkConsistency(project)
|
||||
err := checkConsistency(project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -287,7 +338,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
project.ApplyProfiles(opts.Profiles)
|
||||
|
||||
err = project.ResolveServicesEnvironment(opts.discardEnvFiles)
|
||||
err := project.ResolveServicesEnvironment(opts.discardEnvFiles)
|
||||
|
||||
return project, err
|
||||
}
|
||||
@ -419,7 +470,6 @@ func loadSections(filename string, config map[string]interface{}, configDetails
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.Networks, err = LoadNetworks(getSection(config, "networks"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -428,11 +478,15 @@ func loadSections(filename string, config map[string]interface{}, configDetails
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Secrets, err = LoadSecrets(getSection(config, "secrets"), configDetails, opts.ResolvePaths)
|
||||
cfg.Secrets, err = LoadSecrets(getSection(config, "secrets"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Configs, err = LoadConfigObjs(getSection(config, "configs"), configDetails, opts.ResolvePaths)
|
||||
cfg.Configs, err = LoadConfigObjs(getSection(config, "configs"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Include, err = LoadIncludeConfig(getSequence(config, "include"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -451,6 +505,14 @@ func getSection(config map[string]interface{}, key string) map[string]interface{
|
||||
return section.(map[string]interface{})
|
||||
}
|
||||
|
||||
func getSequence(config map[string]interface{}, key string) []interface{} {
|
||||
section, ok := config[key]
|
||||
if !ok {
|
||||
return make([]interface{}, 0)
|
||||
}
|
||||
return section.([]interface{})
|
||||
}
|
||||
|
||||
// ForbiddenPropertiesError is returned when there are properties in the Compose
|
||||
// file that are forbidden.
|
||||
type ForbiddenPropertiesError struct {
|
||||
@ -515,6 +577,7 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec
|
||||
reflect.TypeOf(types.ExtendsConfig{}): transformExtendsConfig,
|
||||
reflect.TypeOf(types.DeviceRequest{}): transformServiceDeviceRequest,
|
||||
reflect.TypeOf(types.SSHConfig{}): transformSSHConfig,
|
||||
reflect.TypeOf(types.IncludeConfig{}): transformIncludeConfig,
|
||||
}
|
||||
|
||||
for _, transformer := range additionalTransformers {
|
||||
@ -605,6 +668,7 @@ func LoadServices(filename string, servicesDict map[string]interface{}, workingD
|
||||
for k, v := range x.(map[string]interface{}) {
|
||||
servicesDict[k] = v
|
||||
}
|
||||
delete(servicesDict, extensions)
|
||||
}
|
||||
|
||||
for name := range servicesDict {
|
||||
@ -633,7 +697,7 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
target = map[string]interface{}{}
|
||||
}
|
||||
|
||||
serviceConfig, err := LoadService(name, target.(map[string]interface{}), workingDir, lookupEnv, opts.ResolvePaths, opts.ConvertWindowsPaths)
|
||||
serviceConfig, err := LoadService(name, target.(map[string]interface{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -671,21 +735,9 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
// make the paths relative to `file` rather than `baseFilePath` so
|
||||
// that the resulting paths won't be absolute if `file` isn't an
|
||||
// absolute path.
|
||||
|
||||
baseFileParent := filepath.Dir(file)
|
||||
if baseService.Build != nil {
|
||||
baseService.Build.Context = resolveBuildContextPath(baseFileParent, baseService.Build.Context)
|
||||
}
|
||||
|
||||
for i, vol := range baseService.Volumes {
|
||||
if vol.Type != types.VolumeTypeBind {
|
||||
continue
|
||||
}
|
||||
baseService.Volumes[i].Source = resolveMaybeUnixPath(vol.Source, baseFileParent, lookupEnv)
|
||||
}
|
||||
|
||||
for i, envFile := range baseService.EnvFile {
|
||||
baseService.EnvFile[i] = resolveMaybeUnixPath(envFile, baseFileParent, lookupEnv)
|
||||
}
|
||||
ResolveServiceRelativePaths(baseFileParent, baseService)
|
||||
}
|
||||
|
||||
serviceConfig, err = _merge(baseService, serviceConfig)
|
||||
@ -698,22 +750,9 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
return serviceConfig, nil
|
||||
}
|
||||
|
||||
func resolveBuildContextPath(baseFileParent string, context string) string {
|
||||
// Checks if the context is an HTTP(S) URL or a remote git repository URL
|
||||
for _, prefix := range []string{"https://", "http://", "git://", "github.com/", "git@"} {
|
||||
if strings.HasPrefix(context, prefix) {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
// Note that the Dockerfile is always defined relative to the
|
||||
// build context, so there's no need to update the Dockerfile field.
|
||||
return absPath(baseFileParent, context)
|
||||
}
|
||||
|
||||
// LoadService produces a single ServiceConfig from a compose file Dict
|
||||
// the serviceDict is not validated if directly used. Use Load() to enable validation
|
||||
func LoadService(name string, serviceDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, resolvePaths bool, convertPaths bool) (*types.ServiceConfig, error) {
|
||||
func LoadService(name string, serviceDict map[string]interface{}) (*types.ServiceConfig, error) {
|
||||
serviceConfig := &types.ServiceConfig{
|
||||
Scale: 1,
|
||||
}
|
||||
@ -730,13 +769,6 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str
|
||||
return nil, errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
||||
}
|
||||
|
||||
if resolvePaths || convertPaths {
|
||||
volume = resolveVolumePath(volume, workingDir, lookupEnv)
|
||||
}
|
||||
|
||||
if convertPaths {
|
||||
volume = convertVolumePath(volume)
|
||||
}
|
||||
serviceConfig.Volumes[i] = volume
|
||||
}
|
||||
|
||||
@ -758,8 +790,8 @@ func convertVolumePath(volume types.ServiceVolumeConfig) types.ServiceVolumeConf
|
||||
return volume
|
||||
}
|
||||
|
||||
func resolveMaybeUnixPath(path string, workingDir string, lookupEnv template.Mapping) string {
|
||||
filePath := expandUser(path, lookupEnv)
|
||||
func resolveMaybeUnixPath(workingDir string, path string) string {
|
||||
filePath := expandUser(path)
|
||||
// Check if source is an absolute path (either Unix or Windows), to
|
||||
// handle a Windows client with a Unix daemon or vice-versa.
|
||||
//
|
||||
@ -772,20 +804,8 @@ func resolveMaybeUnixPath(path string, workingDir string, lookupEnv template.Map
|
||||
return filePath
|
||||
}
|
||||
|
||||
func resolveVolumePath(volume types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) types.ServiceVolumeConfig {
|
||||
volume.Source = resolveMaybeUnixPath(volume.Source, workingDir, lookupEnv)
|
||||
return volume
|
||||
}
|
||||
|
||||
func resolveSecretsPath(secret types.SecretConfig, workingDir string, lookupEnv template.Mapping) types.SecretConfig {
|
||||
if !secret.External.External && secret.File != "" {
|
||||
secret.File = resolveMaybeUnixPath(secret.File, workingDir, lookupEnv)
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
||||
// TODO: make this more robust
|
||||
func expandUser(path string, lookupEnv template.Mapping) string {
|
||||
func expandUser(path string) string {
|
||||
if strings.HasPrefix(path, "~") {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
@ -885,44 +905,39 @@ func LoadVolumes(source map[string]interface{}) (map[string]types.VolumeConfig,
|
||||
|
||||
// LoadSecrets produces a SecretConfig map from a compose file Dict
|
||||
// the source Dict is not validated if directly used. Use Load() to enable validation
|
||||
func LoadSecrets(source map[string]interface{}, details types.ConfigDetails, resolvePaths bool) (map[string]types.SecretConfig, error) {
|
||||
func LoadSecrets(source map[string]interface{}) (map[string]types.SecretConfig, error) {
|
||||
secrets := make(map[string]types.SecretConfig)
|
||||
if err := Transform(source, &secrets); err != nil {
|
||||
return secrets, err
|
||||
}
|
||||
for name, secret := range secrets {
|
||||
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret), details, false)
|
||||
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
secretConfig := types.SecretConfig(obj)
|
||||
if resolvePaths {
|
||||
secretConfig = resolveSecretsPath(secretConfig, details.WorkingDir, details.LookupEnv)
|
||||
}
|
||||
secrets[name] = secretConfig
|
||||
secrets[name] = types.SecretConfig(obj)
|
||||
}
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
// LoadConfigObjs produces a ConfigObjConfig map from a compose file Dict
|
||||
// the source Dict is not validated if directly used. Use Load() to enable validation
|
||||
func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails, resolvePaths bool) (map[string]types.ConfigObjConfig, error) {
|
||||
func LoadConfigObjs(source map[string]interface{}) (map[string]types.ConfigObjConfig, error) {
|
||||
configs := make(map[string]types.ConfigObjConfig)
|
||||
if err := Transform(source, &configs); err != nil {
|
||||
return configs, err
|
||||
}
|
||||
for name, config := range configs {
|
||||
obj, err := loadFileObjectConfig(name, "config", types.FileObjectConfig(config), details, resolvePaths)
|
||||
obj, err := loadFileObjectConfig(name, "config", types.FileObjectConfig(config))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configConfig := types.ConfigObjConfig(obj)
|
||||
configs[name] = configConfig
|
||||
configs[name] = types.ConfigObjConfig(obj)
|
||||
}
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfig, details types.ConfigDetails, resolvePaths bool) (types.FileObjectConfig, error) {
|
||||
func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfig) (types.FileObjectConfig, error) {
|
||||
// if "external: true"
|
||||
switch {
|
||||
case obj.External.External:
|
||||
@ -942,26 +957,11 @@ func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfi
|
||||
if obj.File != "" {
|
||||
return obj, errors.Errorf("%[1]s %[2]s: %[1]s.driver and %[1]s.file conflict; only use %[1]s.driver", objType, name)
|
||||
}
|
||||
default:
|
||||
if obj.File != "" && resolvePaths {
|
||||
obj.File = absPath(details.WorkingDir, obj.File)
|
||||
}
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func absPath(workingDir string, filePath string) string {
|
||||
if strings.HasPrefix(filePath, "~") {
|
||||
home, _ := os.UserHomeDir()
|
||||
return filepath.Join(home, filePath[1:])
|
||||
}
|
||||
if filepath.IsAbs(filePath) {
|
||||
return filePath
|
||||
}
|
||||
return filepath.Join(workingDir, filePath)
|
||||
}
|
||||
|
||||
var transformMapStringString TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case map[string]interface{}:
|
||||
@ -1088,13 +1088,24 @@ var transformDependsOnConfig TransformerFunc = func(data interface{}) (interface
|
||||
for _, serviceIntf := range value {
|
||||
service, ok := serviceIntf.(string)
|
||||
if !ok {
|
||||
return data, errors.Errorf("invalid type %T for service depends_on elementn, expected string", value)
|
||||
return data, errors.Errorf("invalid type %T for service depends_on element, expected string", value)
|
||||
}
|
||||
transformed[service] = map[string]interface{}{"condition": types.ServiceConditionStarted}
|
||||
transformed[service] = map[string]interface{}{"condition": types.ServiceConditionStarted, "required": true}
|
||||
}
|
||||
return transformed, nil
|
||||
case map[string]interface{}:
|
||||
return groupXFieldsIntoExtensions(data.(map[string]interface{})), nil
|
||||
transformed := map[string]interface{}{}
|
||||
for service, val := range value {
|
||||
dependsConfigIntf, ok := val.(map[string]interface{})
|
||||
if !ok {
|
||||
return data, errors.Errorf("invalid type %T for service depends_on element", value)
|
||||
}
|
||||
if _, ok := dependsConfigIntf["required"]; !ok {
|
||||
dependsConfigIntf["required"] = true
|
||||
}
|
||||
transformed[service] = dependsConfigIntf
|
||||
}
|
||||
return groupXFieldsIntoExtensions(transformed), nil
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for service depends_on", value)
|
||||
}
|
||||
|
11
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
@ -150,13 +150,12 @@ func unique(slice []string) []string {
|
||||
return nil
|
||||
}
|
||||
uniqMap := make(map[string]struct{})
|
||||
var uniqSlice []string
|
||||
for _, v := range slice {
|
||||
uniqMap[v] = struct{}{}
|
||||
}
|
||||
|
||||
uniqSlice := make([]string, 0, len(uniqMap))
|
||||
for v := range uniqMap {
|
||||
uniqSlice = append(uniqSlice, v)
|
||||
if _, ok := uniqMap[v]; !ok {
|
||||
uniqSlice = append(uniqSlice, v)
|
||||
uniqMap[v] = struct{}{}
|
||||
}
|
||||
}
|
||||
return uniqSlice
|
||||
}
|
||||
|
71
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
71
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
@ -18,8 +18,6 @@ package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/errdefs"
|
||||
@ -29,19 +27,7 @@ import (
|
||||
)
|
||||
|
||||
// Normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
|
||||
func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
absWorkingDir, err := filepath.Abs(project.WorkingDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
project.WorkingDir = absWorkingDir
|
||||
|
||||
absComposeFiles, err := absComposeFiles(project.ComposeFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
project.ComposeFiles = absComposeFiles
|
||||
|
||||
func Normalize(project *types.Project) error {
|
||||
if project.Networks == nil {
|
||||
project.Networks = make(map[string]types.NetworkConfig)
|
||||
}
|
||||
@ -51,8 +37,7 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
project.Networks["default"] = types.NetworkConfig{}
|
||||
}
|
||||
|
||||
err = relocateExternalName(project)
|
||||
if err != nil {
|
||||
if err := relocateExternalName(project); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -72,38 +57,16 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
}
|
||||
|
||||
if s.Build != nil {
|
||||
if s.Build.Context == "" {
|
||||
s.Build.Context = "."
|
||||
}
|
||||
if s.Build.Dockerfile == "" && s.Build.DockerfileInline == "" {
|
||||
s.Build.Dockerfile = "Dockerfile"
|
||||
}
|
||||
if resolvePaths {
|
||||
// Build context might be a remote http/git context. Unfortunately supported "remote"
|
||||
// syntax is highly ambiguous in moby/moby and not defined by compose-spec,
|
||||
// so let's assume runtime will check
|
||||
localContext := absPath(project.WorkingDir, s.Build.Context)
|
||||
if _, err := os.Stat(localContext); err == nil {
|
||||
s.Build.Context = localContext
|
||||
}
|
||||
for name, path := range s.Build.AdditionalContexts {
|
||||
if strings.Contains(path, "://") { // `docker-image://` or any builder specific context type
|
||||
continue
|
||||
}
|
||||
path = absPath(project.WorkingDir, path)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
s.Build.AdditionalContexts[name] = path
|
||||
}
|
||||
}
|
||||
}
|
||||
s.Build.Args = s.Build.Args.Resolve(fn)
|
||||
}
|
||||
for j, f := range s.EnvFile {
|
||||
s.EnvFile[j] = absPath(project.WorkingDir, f)
|
||||
}
|
||||
s.Environment = s.Environment.Resolve(fn)
|
||||
|
||||
if s.Extends != nil && s.Extends.File != "" {
|
||||
s.Extends.File = absPath(project.WorkingDir, s.Extends.File)
|
||||
}
|
||||
|
||||
for _, link := range s.Links {
|
||||
parts := strings.Split(link, ":")
|
||||
if len(parts) == 2 {
|
||||
@ -112,6 +75,7 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
s.DependsOn = setIfMissing(s.DependsOn, link, types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: true,
|
||||
Required: true,
|
||||
})
|
||||
}
|
||||
|
||||
@ -121,6 +85,7 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
s.DependsOn = setIfMissing(s.DependsOn, name, types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: true,
|
||||
Required: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -131,6 +96,7 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
s.DependsOn = setIfMissing(s.DependsOn, spec[0], types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: false,
|
||||
Required: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -160,14 +126,6 @@ func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
project.Services[i] = s
|
||||
}
|
||||
|
||||
for name, config := range project.Volumes {
|
||||
if config.Driver == "local" && config.DriverOpts["o"] == "bind" {
|
||||
// This is actually a bind mount
|
||||
config.DriverOpts["device"] = absPath(project.WorkingDir, config.DriverOpts["device"])
|
||||
project.Volumes[name] = config
|
||||
}
|
||||
}
|
||||
|
||||
setNameFromKey(project)
|
||||
|
||||
return nil
|
||||
@ -223,6 +181,7 @@ func inferImplicitDependencies(service *types.ServiceConfig) {
|
||||
if _, ok := service.DependsOn[d]; !ok {
|
||||
service.DependsOn[d] = types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Required: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,18 +213,6 @@ func relocateScale(s *types.ServiceConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func absComposeFiles(composeFiles []string) ([]string, error) {
|
||||
absComposeFiles := make([]string, len(composeFiles))
|
||||
for i, composeFile := range composeFiles {
|
||||
absComposefile, err := filepath.Abs(composeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
absComposeFiles[i] = absComposefile
|
||||
}
|
||||
return absComposeFiles, nil
|
||||
}
|
||||
|
||||
// Resources with no explicit name are actually named by their key in map
|
||||
func setNameFromKey(project *types.Project) {
|
||||
for i, n := range project.Networks {
|
||||
|
135
vendor/github.com/compose-spec/compose-go/loader/paths.go
generated
vendored
Normal file
135
vendor/github.com/compose-spec/compose-go/loader/paths.go
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
Copyright 2020 The Compose Specification Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
)
|
||||
|
||||
// ResolveRelativePaths resolves relative paths based on project WorkingDirectory
|
||||
func ResolveRelativePaths(project *types.Project) error {
|
||||
absWorkingDir, err := filepath.Abs(project.WorkingDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
project.WorkingDir = absWorkingDir
|
||||
|
||||
absComposeFiles, err := absComposeFiles(project.ComposeFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
project.ComposeFiles = absComposeFiles
|
||||
|
||||
for i, s := range project.Services {
|
||||
ResolveServiceRelativePaths(project.WorkingDir, &s)
|
||||
project.Services[i] = s
|
||||
}
|
||||
|
||||
for i, obj := range project.Configs {
|
||||
if obj.File != "" {
|
||||
obj.File = absPath(project.WorkingDir, obj.File)
|
||||
project.Configs[i] = obj
|
||||
}
|
||||
}
|
||||
|
||||
for i, obj := range project.Secrets {
|
||||
if obj.File != "" {
|
||||
obj.File = resolveMaybeUnixPath(project.WorkingDir, obj.File)
|
||||
project.Secrets[i] = obj
|
||||
}
|
||||
}
|
||||
|
||||
for name, config := range project.Volumes {
|
||||
if config.Driver == "local" && config.DriverOpts["o"] == "bind" {
|
||||
// This is actually a bind mount
|
||||
config.DriverOpts["device"] = resolveMaybeUnixPath(project.WorkingDir, config.DriverOpts["device"])
|
||||
project.Volumes[name] = config
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResolveServiceRelativePaths(workingDir string, s *types.ServiceConfig) {
|
||||
if s.Build != nil {
|
||||
if !isRemoteContext(s.Build.Context) {
|
||||
s.Build.Context = absPath(workingDir, s.Build.Context)
|
||||
}
|
||||
for name, path := range s.Build.AdditionalContexts {
|
||||
if strings.Contains(path, "://") { // `docker-image://` or any builder specific context type
|
||||
continue
|
||||
}
|
||||
if isRemoteContext(path) {
|
||||
continue
|
||||
}
|
||||
s.Build.AdditionalContexts[name] = absPath(workingDir, path)
|
||||
}
|
||||
}
|
||||
for j, f := range s.EnvFile {
|
||||
s.EnvFile[j] = absPath(workingDir, f)
|
||||
}
|
||||
|
||||
if s.Extends != nil && s.Extends.File != "" {
|
||||
s.Extends.File = absPath(workingDir, s.Extends.File)
|
||||
}
|
||||
|
||||
for i, vol := range s.Volumes {
|
||||
if vol.Type != types.VolumeTypeBind {
|
||||
continue
|
||||
}
|
||||
s.Volumes[i].Source = resolveMaybeUnixPath(workingDir, vol.Source)
|
||||
}
|
||||
}
|
||||
|
||||
func absPath(workingDir string, filePath string) string {
|
||||
if strings.HasPrefix(filePath, "~") {
|
||||
home, _ := os.UserHomeDir()
|
||||
return filepath.Join(home, filePath[1:])
|
||||
}
|
||||
if filepath.IsAbs(filePath) {
|
||||
return filePath
|
||||
}
|
||||
return filepath.Join(workingDir, filePath)
|
||||
}
|
||||
|
||||
func absComposeFiles(composeFiles []string) ([]string, error) {
|
||||
for i, composeFile := range composeFiles {
|
||||
absComposefile, err := filepath.Abs(composeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
composeFiles[i] = absComposefile
|
||||
}
|
||||
return composeFiles, nil
|
||||
}
|
||||
|
||||
// isRemoteContext returns true if the value is a Git reference or HTTP(S) URL.
|
||||
//
|
||||
// Any other value is assumed to be a local filesystem path and returns false.
|
||||
//
|
||||
// See: https://github.com/moby/buildkit/blob/18fc875d9bfd6e065cd8211abc639434ba65aa56/frontend/dockerui/context.go#L76-L79
|
||||
func isRemoteContext(maybeURL string) bool {
|
||||
for _, prefix := range []string{"https://", "http://", "git://", "ssh://", "github.com/", "git@"} {
|
||||
if strings.HasPrefix(maybeURL, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Reference in New Issue
Block a user