mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-11 05:57:08 +08:00
update github.com/compose-spec/compose-go to v1.9.0
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
6
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
6
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
@ -160,8 +160,8 @@ services:
|
||||
# somehost: "162.242.195.82"
|
||||
# otherhost: "50.31.209.229"
|
||||
extra_hosts:
|
||||
- "somehost:162.242.195.82"
|
||||
- "otherhost:50.31.209.229"
|
||||
- "somehost:162.242.195.82"
|
||||
|
||||
hostname: foo
|
||||
|
||||
@ -182,6 +182,8 @@ services:
|
||||
|
||||
ipc: host
|
||||
|
||||
uts: host
|
||||
|
||||
# Mapping or list
|
||||
# Mapping values can be strings, numbers or null
|
||||
labels:
|
||||
@ -428,6 +430,8 @@ secrets:
|
||||
environment: BAR
|
||||
x-bar: baz
|
||||
x-foo: bar
|
||||
secret5:
|
||||
file: /abs/secret_data
|
||||
x-bar: baz
|
||||
x-foo: bar
|
||||
x-nested:
|
||||
|
142
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
142
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
@ -17,9 +17,7 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
paths "path"
|
||||
"path/filepath"
|
||||
@ -30,7 +28,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/consts"
|
||||
"github.com/compose-spec/compose-go/dotenv"
|
||||
interp "github.com/compose-spec/compose-go/interpolation"
|
||||
"github.com/compose-spec/compose-go/schema"
|
||||
"github.com/compose-spec/compose-go/template"
|
||||
@ -67,6 +64,8 @@ type Options struct {
|
||||
projectName string
|
||||
// Indicates when the projectName was imperatively set or guessed from path
|
||||
projectNameImperativelySet bool
|
||||
// Profiles set profiles to enable
|
||||
Profiles []string
|
||||
}
|
||||
|
||||
func (o *Options) SetProjectName(name string, imperativelySet bool) {
|
||||
@ -125,6 +124,13 @@ func WithSkipValidation(opts *Options) {
|
||||
opts.SkipValidation = true
|
||||
}
|
||||
|
||||
// WithProfiles sets profiles to be activated
|
||||
func WithProfiles(profiles []string) func(*Options) {
|
||||
return func(opts *Options) {
|
||||
opts.Profiles = profiles
|
||||
}
|
||||
}
|
||||
|
||||
// ParseYAML reads the bytes from a file, parses the bytes into a mapping
|
||||
// structure, and returns it.
|
||||
func ParseYAML(source []byte) (map[string]interface{}, error) {
|
||||
@ -161,12 +167,22 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
op(opts)
|
||||
}
|
||||
|
||||
projectName := projectName(configDetails, opts)
|
||||
projectName, err := projectName(configDetails, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var configs []*types.Config
|
||||
for i, file := range configDetails.ConfigFiles {
|
||||
configDict := file.Config
|
||||
if configDict == nil {
|
||||
if len(file.Content) == 0 {
|
||||
content, err := os.ReadFile(file.Filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file.Content = content
|
||||
}
|
||||
dict, err := parseConfig(file.Content, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -188,12 +204,6 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.discardEnvFiles {
|
||||
for i := range cfg.Services {
|
||||
cfg.Services[i].EnvFile = nil
|
||||
}
|
||||
}
|
||||
|
||||
configs = append(configs, cfg)
|
||||
}
|
||||
|
||||
@ -236,22 +246,35 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
}
|
||||
|
||||
return project, nil
|
||||
if len(opts.Profiles) > 0 {
|
||||
project.ApplyProfiles(opts.Profiles)
|
||||
}
|
||||
|
||||
err = project.ResolveServicesEnvironment(opts.discardEnvFiles)
|
||||
|
||||
return project, err
|
||||
}
|
||||
|
||||
func projectName(details types.ConfigDetails, opts *Options) string {
|
||||
func projectName(details types.ConfigDetails, opts *Options) (string, error) {
|
||||
projectName, projectNameImperativelySet := opts.GetProjectName()
|
||||
var pjNameFromConfigFile string
|
||||
|
||||
for _, configFile := range details.ConfigFiles {
|
||||
yml, err := ParseYAML(configFile.Content)
|
||||
if err != nil {
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
if val, ok := yml["name"]; ok && val != "" {
|
||||
pjNameFromConfigFile = yml["name"].(string)
|
||||
}
|
||||
}
|
||||
if !opts.SkipInterpolation {
|
||||
interpolated, err := interp.Interpolate(map[string]interface{}{"name": pjNameFromConfigFile}, *opts.Interpolate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pjNameFromConfigFile = interpolated["name"].(string)
|
||||
}
|
||||
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
|
||||
if !projectNameImperativelySet && pjNameFromConfigFile != "" {
|
||||
projectName = pjNameFromConfigFile
|
||||
@ -260,7 +283,7 @@ func projectName(details types.ConfigDetails, opts *Options) string {
|
||||
if _, ok := details.Environment[consts.ComposeProjectName]; !ok && projectName != "" {
|
||||
details.Environment[consts.ComposeProjectName] = projectName
|
||||
}
|
||||
return projectName
|
||||
return projectName, nil
|
||||
}
|
||||
|
||||
func NormalizeProjectName(s string) string {
|
||||
@ -508,6 +531,10 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
return nil, fmt.Errorf("cannot extend service %q in %s: service not found", name, filename)
|
||||
}
|
||||
|
||||
if target == nil {
|
||||
target = map[string]interface{}{}
|
||||
}
|
||||
|
||||
serviceConfig, err := LoadService(name, target.(map[string]interface{}), workingDir, lookupEnv, opts.ResolvePaths, opts.ConvertWindowsPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -547,16 +574,14 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
// absolute path.
|
||||
baseFileParent := filepath.Dir(*file)
|
||||
if baseService.Build != nil {
|
||||
// Note that the Dockerfile is always defined relative to the
|
||||
// build context, so there's no need to update the Dockerfile field.
|
||||
baseService.Build.Context = absPath(baseFileParent, baseService.Build.Context)
|
||||
baseService.Build.Context = resolveBuildContextPath(baseFileParent, baseService.Build.Context)
|
||||
}
|
||||
|
||||
for i, vol := range baseService.Volumes {
|
||||
if vol.Type != types.VolumeTypeBind {
|
||||
continue
|
||||
}
|
||||
baseService.Volumes[i].Source = absPath(baseFileParent, vol.Source)
|
||||
baseService.Volumes[i].Source = resolveMaybeUnixPath(vol.Source, baseFileParent, lookupEnv)
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,6 +594,19 @@ 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) {
|
||||
@ -580,10 +618,6 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str
|
||||
}
|
||||
serviceConfig.Name = name
|
||||
|
||||
if err := resolveEnvironment(serviceConfig, workingDir, lookupEnv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, volume := range serviceConfig.Volumes {
|
||||
if volume.Type != types.VolumeTypeBind {
|
||||
continue
|
||||
@ -620,48 +654,8 @@ func convertVolumePath(volume types.ServiceVolumeConfig) types.ServiceVolumeConf
|
||||
return volume
|
||||
}
|
||||
|
||||
func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string, lookupEnv template.Mapping) error {
|
||||
environment := types.MappingWithEquals{}
|
||||
|
||||
if len(serviceConfig.EnvFile) > 0 {
|
||||
if serviceConfig.Environment == nil {
|
||||
serviceConfig.Environment = types.MappingWithEquals{}
|
||||
}
|
||||
for _, envFile := range serviceConfig.EnvFile {
|
||||
filePath := absPath(workingDir, envFile)
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Do not defer to avoid it inside a loop
|
||||
file.Close() //nolint:errcheck
|
||||
|
||||
fileVars, err := dotenv.ParseWithLookup(bytes.NewBuffer(b), dotenv.LookupFn(lookupEnv))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env := types.MappingWithEquals{}
|
||||
for k, v := range fileVars {
|
||||
v := v
|
||||
env[k] = &v
|
||||
}
|
||||
environment.OverrideBy(env.Resolve(lookupEnv).RemoveEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
environment.OverrideBy(serviceConfig.Environment.Resolve(lookupEnv))
|
||||
serviceConfig.Environment = environment
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveVolumePath(volume types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) types.ServiceVolumeConfig {
|
||||
filePath := expandUser(volume.Source, lookupEnv)
|
||||
func resolveMaybeUnixPath(path string, workingDir string, lookupEnv template.Mapping) string {
|
||||
filePath := expandUser(path, lookupEnv)
|
||||
// Check if source is an absolute path (either Unix or Windows), to
|
||||
// handle a Windows client with a Unix daemon or vice-versa.
|
||||
//
|
||||
@ -671,10 +665,21 @@ func resolveVolumePath(volume types.ServiceVolumeConfig, workingDir string, look
|
||||
if !paths.IsAbs(filePath) && !isAbs(filePath) {
|
||||
filePath = absPath(workingDir, filePath)
|
||||
}
|
||||
volume.Source = filePath
|
||||
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 {
|
||||
if strings.HasPrefix(path, "~") {
|
||||
@ -723,7 +728,7 @@ func LoadNetworks(source map[string]interface{}) (map[string]types.NetworkConfig
|
||||
if network.Name != "" {
|
||||
return nil, errors.Errorf("network %s: network.external.name and network.name conflict; only use network.name", name)
|
||||
}
|
||||
logrus.Warnf("network %s: network.external.name is deprecated in favor of network.name", name)
|
||||
logrus.Warnf("network %s: network.external.name is deprecated. Please set network.name with external: true", name)
|
||||
network.Name = network.External.Name
|
||||
network.External.Name = ""
|
||||
case network.Name == "":
|
||||
@ -782,11 +787,14 @@ func LoadSecrets(source map[string]interface{}, details types.ConfigDetails, res
|
||||
return secrets, err
|
||||
}
|
||||
for name, secret := range secrets {
|
||||
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret), details, resolvePaths)
|
||||
obj, err := loadFileObjectConfig(name, "secret", types.FileObjectConfig(secret), details, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
secretConfig := types.SecretConfig(obj)
|
||||
if resolvePaths {
|
||||
secretConfig = resolveSecretsPath(secretConfig, details.WorkingDir, details.LookupEnv)
|
||||
}
|
||||
secrets[name] = secretConfig
|
||||
}
|
||||
return secrets, nil
|
||||
|
51
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
51
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
@ -38,11 +38,19 @@ var serviceSpecials = &specials{
|
||||
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
|
||||
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
|
||||
reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig,
|
||||
reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig,
|
||||
},
|
||||
}
|
||||
|
||||
func (s *specials) Transformer(t reflect.Type) func(dst, src reflect.Value) error {
|
||||
// TODO this is a workaround waiting for imdario/mergo#131
|
||||
if t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Bool {
|
||||
return func(dst, src reflect.Value) error {
|
||||
if dst.CanSet() && !src.IsNil() {
|
||||
dst.Set(src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if fn, ok := s.m[t]; ok {
|
||||
return fn
|
||||
}
|
||||
@ -113,12 +121,18 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
|
||||
}
|
||||
|
||||
func _merge(baseService *types.ServiceConfig, overrideService *types.ServiceConfig) (*types.ServiceConfig, error) {
|
||||
if err := mergo.Merge(baseService, overrideService, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(serviceSpecials)); err != nil {
|
||||
if err := mergo.Merge(baseService, overrideService,
|
||||
mergo.WithAppendSlice,
|
||||
mergo.WithOverride,
|
||||
mergo.WithTransformers(serviceSpecials)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if overrideService.Command != nil {
|
||||
baseService.Command = overrideService.Command
|
||||
}
|
||||
if overrideService.HealthCheck != nil {
|
||||
baseService.HealthCheck.Test = overrideService.HealthCheck.Test
|
||||
}
|
||||
if overrideService.Entrypoint != nil {
|
||||
baseService.Entrypoint = overrideService.Entrypoint
|
||||
}
|
||||
@ -127,9 +141,26 @@ func _merge(baseService *types.ServiceConfig, overrideService *types.ServiceConf
|
||||
} else {
|
||||
baseService.Environment = overrideService.Environment
|
||||
}
|
||||
baseService.Expose = unique(baseService.Expose)
|
||||
return baseService, nil
|
||||
}
|
||||
|
||||
func unique(slice []string) []string {
|
||||
if slice == nil {
|
||||
return nil
|
||||
}
|
||||
uniqMap := make(map[string]struct{})
|
||||
for _, v := range slice {
|
||||
uniqMap[v] = struct{}{}
|
||||
}
|
||||
|
||||
uniqSlice := make([]string, 0, len(uniqMap))
|
||||
for v := range uniqMap {
|
||||
uniqSlice = append(uniqSlice, v)
|
||||
}
|
||||
return uniqSlice
|
||||
}
|
||||
|
||||
func toServiceSecretConfigsMap(s interface{}) (map[interface{}]interface{}, error) {
|
||||
secrets, ok := s.([]types.ServiceSecretConfig)
|
||||
if !ok {
|
||||
@ -299,7 +330,7 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint: unparam
|
||||
// nolint: unparam
|
||||
func mergeUlimitsConfig(dst, src reflect.Value) error {
|
||||
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
|
||||
dst.Elem().Set(src.Elem())
|
||||
@ -307,20 +338,6 @@ func mergeUlimitsConfig(dst, src reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint: unparam
|
||||
func mergeServiceNetworkConfig(dst, src reflect.Value) error {
|
||||
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
|
||||
dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases"))
|
||||
if ipv4 := src.Elem().FieldByName("Ipv4Address").Interface().(string); ipv4 != "" {
|
||||
dst.Elem().FieldByName("Ipv4Address").SetString(ipv4)
|
||||
}
|
||||
if ipv6 := src.Elem().FieldByName("Ipv6Address").Interface().(string); ipv6 != "" {
|
||||
dst.Elem().FieldByName("Ipv6Address").SetString(ipv6)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLoggingDriver(v reflect.Value) string {
|
||||
return v.FieldByName("Driver").String()
|
||||
}
|
||||
|
11
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
@ -85,6 +85,9 @@ func normalize(project *types.Project, resolvePaths bool) error {
|
||||
}
|
||||
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)
|
||||
|
||||
err := relocateLogDriver(&s)
|
||||
@ -110,6 +113,14 @@ 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
|
||||
|
14
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
14
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
@ -38,6 +38,14 @@ func checkConsistency(project *types.Project) error {
|
||||
}
|
||||
}
|
||||
|
||||
if s.HealthCheck != nil && len(s.HealthCheck.Test) > 0 {
|
||||
switch s.HealthCheck.Test[0] {
|
||||
case "CMD", "CMD-SHELL", "NONE":
|
||||
default:
|
||||
return errors.New(`healthcheck.test must start either by "CMD", "CMD-SHELL" or "NONE"`)
|
||||
}
|
||||
}
|
||||
|
||||
for dependedService := range s.DependsOn {
|
||||
if _, err := project.GetService(dependedService); err != nil {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %q depends on undefined service %s", s.Name, dependedService))
|
||||
@ -70,6 +78,12 @@ func checkConsistency(project *types.Project) error {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %q refers to undefined config %s", s.Name, config.Source))
|
||||
}
|
||||
}
|
||||
|
||||
for _, secret := range s.Secrets {
|
||||
if _, ok := project.Secrets[secret.Source]; !ok {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %q refers to undefined secret %s", s.Name, secret.Source))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for name, secret := range project.Secrets {
|
||||
|
Reference in New Issue
Block a user