This repository has been archived by the owner on Jun 13, 2021. It is now read-only.
/
types.go
104 lines (90 loc) · 2.7 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package build
import (
"fmt"
"reflect"
"strings"
"github.com/docker/cli/cli/compose/loader"
compose "github.com/docker/cli/cli/compose/types"
"github.com/pkg/errors"
)
// A minimal subset of github.com/docker/cli/cli/compose/types/types.go for the purpose of loading the build configuration
type ServiceConfig struct {
Name string `yaml:"-" json:"-"`
Build *ImageBuildConfig
Image *string
}
type ImageBuildConfig struct {
Context string `yaml:",omitempty" json:"context,omitempty"`
Dockerfile string `yaml:",omitempty" json:"dockerfile,omitempty"`
Args compose.MappingWithEquals `yaml:",omitempty" json:"args,omitempty"`
}
func load(dict map[string]interface{}, buildArgs []string) ([]ServiceConfig, error) {
section, ok := dict["services"]
if !ok {
return nil, fmt.Errorf("Compose file doesn't declare any service")
}
services, ok := section.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("Invalid Compose file: 'services' should be a map")
}
return loadServices(services, buildArgs)
}
func loadServices(servicesDict map[string]interface{}, buildArgs []string) ([]ServiceConfig, error) {
var services []ServiceConfig
for name, serviceDef := range servicesDict {
serviceConfig, err := loadService(name, serviceDef.(map[string]interface{}), buildArgs)
if err != nil {
return nil, err
}
services = append(services, *serviceConfig)
}
return services, nil
}
func loadService(name string, serviceDict map[string]interface{}, buildArgs []string) (*ServiceConfig, error) {
serviceConfig := &ServiceConfig{Name: name}
args := buildArgsToMap(buildArgs)
if err := loader.Transform(serviceDict, serviceConfig, loader.Transformer{
TypeOf: reflect.TypeOf(ImageBuildConfig{}),
Func: transformBuildConfig,
}); err != nil {
return nil, err
}
if serviceConfig.Build != nil {
serviceConfig.Build.mergeArgs(args)
}
return serviceConfig, nil
}
func transformBuildConfig(data interface{}) (interface{}, error) {
switch value := data.(type) {
case string:
return map[string]interface{}{"context": value}, nil
case map[string]interface{}:
return data, nil
default:
return data, errors.Errorf("invalid type %T for service build", value)
}
}
func buildArgsToMap(array []string) map[string]string {
result := make(map[string]string)
for _, value := range array {
parts := strings.SplitN(value, "=", 2)
key := parts[0]
if len(parts) == 1 {
result[key] = ""
} else {
result[key] = parts[1]
}
}
return result
}
func (m ImageBuildConfig) mergeArgs(mapToMerge map[string]string) {
for key := range m.Args {
if val, ok := mapToMerge[key]; ok {
if val == "" {
m.Args[key] = nil
} else {
m.Args[key] = &val
}
}
}
}