Merge pull request #1244 from vdemeester/expose-compose-transform

Exposes compose `loader.Transform` function…
This commit is contained in:
Sebastiaan van Stijn 2018-07-31 09:43:13 +02:00 committed by GitHub
commit 70d5cb0dd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 8 deletions

View File

@ -265,11 +265,13 @@ func getServices(configDict map[string]interface{}) map[string]interface{} {
return 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{} data := mapstructure.Metadata{}
config := &mapstructure.DecoderConfig{ config := &mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc( DecodeHook: mapstructure.ComposeDecodeHookFunc(
createTransformHook(), createTransformHook(additionalTransformers...),
mapstructure.StringToTimeDurationHookFunc()), mapstructure.StringToTimeDurationHookFunc()),
Result: target, Result: target,
Metadata: &data, Metadata: &data,
@ -281,7 +283,13 @@ func transform(source map[string]interface{}, target interface{}) error {
return decoder.Decode(source) 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){ transforms := map[reflect.Type]func(interface{}) (interface{}, error){
reflect.TypeOf(types.External{}): transformExternal, reflect.TypeOf(types.External{}): transformExternal,
reflect.TypeOf(types.HealthCheckTest{}): transformHealthCheckTest, reflect.TypeOf(types.HealthCheckTest{}): transformHealthCheckTest,
@ -303,6 +311,10 @@ func createTransformHook() mapstructure.DecodeHookFuncType {
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig, 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) { return func(_ reflect.Type, target reflect.Type, data interface{}) (interface{}, error) {
transform, ok := transforms[target] transform, ok := transforms[target]
if !ok { if !ok {
@ -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 // 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) { func LoadService(name string, serviceDict map[string]interface{}, workingDir string, lookupEnv template.Mapping) (*types.ServiceConfig, error) {
serviceConfig := &types.ServiceConfig{} serviceConfig := &types.ServiceConfig{}
if err := transform(serviceDict, serviceConfig); err != nil { if err := Transform(serviceDict, serviceConfig); err != nil {
return nil, err return nil, err
} }
serviceConfig.Name = name serviceConfig.Name = name
@ -509,7 +521,7 @@ func transformUlimits(data interface{}) (interface{}, error) {
// the source Dict is not validated if directly used. Use Load() to enable validation // 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) { func LoadNetworks(source map[string]interface{}, version string) (map[string]types.NetworkConfig, error) {
networks := make(map[string]types.NetworkConfig) networks := make(map[string]types.NetworkConfig)
err := transform(source, &networks) err := Transform(source, &networks)
if err != nil { if err != nil {
return networks, err return networks, err
} }
@ -546,7 +558,7 @@ func externalVolumeError(volume, key string) error {
// the source Dict is not validated if directly used. Use Load() to enable validation // 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) { func LoadVolumes(source map[string]interface{}, version string) (map[string]types.VolumeConfig, error) {
volumes := make(map[string]types.VolumeConfig) volumes := make(map[string]types.VolumeConfig)
if err := transform(source, &volumes); err != nil { if err := Transform(source, &volumes); err != nil {
return volumes, err return volumes, err
} }
@ -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 // 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) { func LoadSecrets(source map[string]interface{}, details types.ConfigDetails) (map[string]types.SecretConfig, error) {
secrets := make(map[string]types.SecretConfig) secrets := make(map[string]types.SecretConfig)
if err := transform(source, &secrets); err != nil { if err := Transform(source, &secrets); err != nil {
return secrets, err return secrets, err
} }
for name, secret := range secrets { for name, secret := range secrets {
@ -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 // 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) { func LoadConfigObjs(source map[string]interface{}, details types.ConfigDetails) (map[string]types.ConfigObjConfig, error) {
configs := make(map[string]types.ConfigObjConfig) configs := make(map[string]types.ConfigObjConfig)
if err := transform(source, &configs); err != nil { if err := Transform(source, &configs); err != nil {
return configs, err return configs, err
} }
for name, config := range configs { for name, config := range configs {