mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
   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
 | 
						|
}
 |