mirror of https://github.com/docker/cli.git
Exposes compose `loader.Transform` function…
This should make it easier for people to write custom composefile parser without duplicating too much code. It takes the default transformers and any additional number of transformer for any types. That way it's possible to transform a `cli/compose` map into a custom type that would use some of `cli/compose` types and its own. Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
b4e50635a2
commit
0246bc1b3b
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue