forked from buildpacks/pack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig_reader.go
110 lines (89 loc) · 3.12 KB
/
config_reader.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
105
106
107
108
109
110
package buildpackage
import (
"path/filepath"
"github.com/BurntSushi/toml"
"github.com/pkg/errors"
"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/internal/dist"
"github.com/buildpacks/pack/internal/paths"
"github.com/buildpacks/pack/internal/style"
)
const defaultOS = "linux"
// Config encapsulates the possible configuration options for buildpackage creation.
type Config struct {
Buildpack dist.BuildpackURI `toml:"buildpack"`
Dependencies []dist.ImageOrURI `toml:"dependencies"`
Platform dist.Platform `toml:"platform"`
}
func DefaultConfig() Config {
return Config{
Buildpack: dist.BuildpackURI{
URI: ".",
},
Platform: dist.Platform{
OS: defaultOS,
},
}
}
// NewConfigReader returns an instance of ConfigReader. It does not take any parameters.
func NewConfigReader() *ConfigReader {
return &ConfigReader{}
}
// ConfigReader implements a Read method for buildpackage configuration which parses and validates buildpackage
// configuration from a toml file.
type ConfigReader struct{}
// Read reads and validates a buildpackage configuration from the file path provided and returns the
// configuration and any error that occurred during reading or validation.
func (r *ConfigReader) Read(path string) (Config, error) {
packageConfig := Config{}
tomlMetadata, err := toml.DecodeFile(path, &packageConfig)
if err != nil {
return packageConfig, errors.Wrap(err, "decoding toml")
}
undecodedKeys := tomlMetadata.Undecoded()
if len(undecodedKeys) > 0 {
unknownElementsMsg := config.FormatUndecodedKeys(undecodedKeys)
return packageConfig, errors.Errorf("%s in %s",
unknownElementsMsg,
style.Symbol(path),
)
}
if packageConfig.Buildpack.URI == "" {
return packageConfig, errors.Errorf("missing %s configuration", style.Symbol("buildpack.uri"))
}
if packageConfig.Platform.OS == "" {
packageConfig.Platform.OS = defaultOS
}
if packageConfig.Platform.OS != "linux" && packageConfig.Platform.OS != "windows" {
return packageConfig, errors.Errorf("invalid %s configuration: only [%s, %s] is permitted, found %s",
style.Symbol("platform.os"), style.Symbol("linux"), style.Symbol("windows"), style.Symbol(packageConfig.Platform.OS))
}
configDir, err := filepath.Abs(filepath.Dir(path))
if err != nil {
return packageConfig, err
}
absPath, err := paths.ToAbsolute(packageConfig.Buildpack.URI, configDir)
if err != nil {
return packageConfig, errors.Wrapf(err, "getting absolute path for %s", style.Symbol(packageConfig.Buildpack.URI))
}
packageConfig.Buildpack.URI = absPath
for i := range packageConfig.Dependencies {
uri := packageConfig.Dependencies[i].URI
if uri != "" {
absPath, err := paths.ToAbsolute(uri, configDir)
if err != nil {
return packageConfig, errors.Wrapf(err, "getting absolute path for %s", style.Symbol(uri))
}
packageConfig.Dependencies[i].URI = absPath
}
dep := packageConfig.Dependencies[i]
if dep.URI != "" && dep.ImageName != "" {
return packageConfig, errors.Errorf(
"dependency configured with both %s and %s",
style.Symbol("uri"),
style.Symbol("image"),
)
}
}
return packageConfig, nil
}