Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposes compose loader.Transform function… #1244

Merged
merged 1 commit into from
Jul 31, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions cli/compose/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,13 @@ func getServices(configDict map[string]interface{}) map[string]interface{} {
return map[string]interface{}{}
}

func transform(source map[string]interface{}, target interface{}) error {
// Transform converts the source map into the target struct with compose types transformer
// and the specified transformers if any.
func Transform(source map[string]interface{}, target interface{}, additionalTransformers ...Transformer) error {
data := mapstructure.Metadata{}
config := &mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc(
createTransformHook(),
createTransformHook(additionalTransformers...),
mapstructure.StringToTimeDurationHookFunc()),
Result: target,
Metadata: &data,
Expand All @@ -281,7 +283,13 @@ func transform(source map[string]interface{}, target interface{}) error {
return decoder.Decode(source)
}

func createTransformHook() mapstructure.DecodeHookFuncType {
// Transformer defines a map to type transformer
type Transformer struct {
TypeOf reflect.Type
Func func(interface{}) (interface{}, error)
}

func createTransformHook(additionalTransformers ...Transformer) mapstructure.DecodeHookFuncType {
transforms := map[reflect.Type]func(interface{}) (interface{}, error){
reflect.TypeOf(types.External{}): transformExternal,
reflect.TypeOf(types.HealthCheckTest{}): transformHealthCheckTest,
Expand All @@ -303,6 +311,10 @@ func createTransformHook() mapstructure.DecodeHookFuncType {
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig,
}

for _, transformer := range additionalTransformers {
transforms[transformer.TypeOf] = transformer.Func
}

return func(_ reflect.Type, target reflect.Type, data interface{}) (interface{}, error) {
transform, ok := transforms[target]
if !ok {
Expand Down Expand Up @@ -380,7 +392,7 @@ func LoadServices(servicesDict map[string]interface{}, workingDir string, lookup
// 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) (*types.ServiceConfig, error) {
serviceConfig := &types.ServiceConfig{}
if err := transform(serviceDict, serviceConfig); err != nil {
if err := Transform(serviceDict, serviceConfig); err != nil {
return nil, err
}
serviceConfig.Name = name
Expand Down Expand Up @@ -509,7 +521,7 @@ func transformUlimits(data interface{}) (interface{}, error) {
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadNetworks(source map[string]interface{}, version string) (map[string]types.NetworkConfig, error) {
networks := make(map[string]types.NetworkConfig)
err := transform(source, &networks)
err := Transform(source, &networks)
if err != nil {
return networks, err
}
Expand Down Expand Up @@ -546,7 +558,7 @@ func externalVolumeError(volume, key string) error {
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadVolumes(source map[string]interface{}, version string) (map[string]types.VolumeConfig, error) {
volumes := make(map[string]types.VolumeConfig)
if err := transform(source, &volumes); err != nil {
if err := Transform(source, &volumes); err != nil {
return volumes, err
}

Expand Down Expand Up @@ -583,7 +595,7 @@ func LoadVolumes(source map[string]interface{}, version string) (map[string]type
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadSecrets(source map[string]interface{}, details types.ConfigDetails) (map[string]types.SecretConfig, error) {
secrets := make(map[string]types.SecretConfig)
if err := transform(source, &secrets); err != nil {
if err := Transform(source, &secrets); err != nil {
return secrets, err
}
for name, secret := range secrets {
Expand All @@ -602,7 +614,7 @@ func LoadSecrets(source map[string]interface{}, details types.ConfigDetails) (ma
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails) (map[string]types.ConfigObjConfig, error) {
configs := make(map[string]types.ConfigObjConfig)
if err := transform(source, &configs); err != nil {
if err := Transform(source, &configs); err != nil {
return configs, err
}
for name, config := range configs {
Expand Down