Remove compose types.Dict alias

It is just an alias type and make the code a little bit more complex
and hard to use from outside `compose` package.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2017-03-22 15:42:03 +01:00
parent d8406fd7a0
commit d3dc27d145
No known key found for this signature in database
GPG key ID: 083CC6FD6EB699A3
5 changed files with 57 additions and 74 deletions

View file

@ -4,19 +4,18 @@ import (
"fmt"
"github.com/docker/docker/cli/compose/template"
"github.com/docker/docker/cli/compose/types"
)
// Interpolate replaces variables in a string with the values from a mapping
func Interpolate(config types.Dict, section string, mapping template.Mapping) (types.Dict, error) {
out := types.Dict{}
func Interpolate(config map[string]interface{}, section string, mapping template.Mapping) (map[string]interface{}, error) {
out := map[string]interface{}{}
for name, item := range config {
if item == nil {
out[name] = nil
continue
}
interpolatedItem, err := interpolateSectionItem(name, item.(types.Dict), section, mapping)
interpolatedItem, err := interpolateSectionItem(name, item.(map[string]interface{}), section, mapping)
if err != nil {
return nil, err
}
@ -28,12 +27,12 @@ func Interpolate(config types.Dict, section string, mapping template.Mapping) (t
func interpolateSectionItem(
name string,
item types.Dict,
item map[string]interface{},
section string,
mapping template.Mapping,
) (types.Dict, error) {
) (map[string]interface{}, error) {
out := types.Dict{}
out := map[string]interface{}{}
for key, value := range item {
interpolatedValue, err := recursiveInterpolate(value, mapping)
@ -60,8 +59,8 @@ func recursiveInterpolate(
case string:
return template.Substitute(value, mapping)
case types.Dict:
out := types.Dict{}
case map[string]interface{}:
out := map[string]interface{}{}
for key, elem := range value {
interpolatedElem, err := recursiveInterpolate(elem, mapping)
if err != nil {

View file

@ -4,8 +4,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/docker/docker/cli/compose/types"
)
var defaults = map[string]string{
@ -19,25 +17,25 @@ func defaultMapping(name string) (string, bool) {
}
func TestInterpolate(t *testing.T) {
services := types.Dict{
"servicea": types.Dict{
services := map[string]interface{}{
"servicea": map[string]interface{}{
"image": "example:${USER}",
"volumes": []interface{}{"$FOO:/target"},
"logging": types.Dict{
"logging": map[string]interface{}{
"driver": "${FOO}",
"options": types.Dict{
"options": map[string]interface{}{
"user": "$USER",
},
},
},
}
expected := types.Dict{
"servicea": types.Dict{
expected := map[string]interface{}{
"servicea": map[string]interface{}{
"image": "example:jenny",
"volumes": []interface{}{"bar:/target"},
"logging": types.Dict{
"logging": map[string]interface{}{
"driver": "bar",
"options": types.Dict{
"options": map[string]interface{}{
"user": "jenny",
},
},
@ -49,8 +47,8 @@ func TestInterpolate(t *testing.T) {
}
func TestInvalidInterpolation(t *testing.T) {
services := types.Dict{
"servicea": types.Dict{
services := map[string]interface{}{
"servicea": map[string]interface{}{
"image": "${",
},
}

View file

@ -28,7 +28,7 @@ var (
// ParseYAML reads the bytes from a file, parses the bytes into a mapping
// structure, and returns it.
func ParseYAML(source []byte) (types.Dict, error) {
func ParseYAML(source []byte) (map[string]interface{}, error) {
var cfg interface{}
if err := yaml.Unmarshal(source, &cfg); err != nil {
return nil, err
@ -41,7 +41,7 @@ func ParseYAML(source []byte) (types.Dict, error) {
if err != nil {
return nil, err
}
return converted.(types.Dict), nil
return converted.(map[string]interface{}), nil
}
// Load reads a ConfigDetails and returns a fully loaded configuration
@ -56,7 +56,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
configDict := getConfigDict(configDetails)
if services, ok := configDict["services"]; ok {
if servicesDict, ok := services.(types.Dict); ok {
if servicesDict, ok := services.(map[string]interface{}); ok {
forbidden := getProperties(servicesDict, types.ForbiddenProperties)
if len(forbidden) > 0 {
@ -75,7 +75,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
return v, ok
}
if services, ok := configDict["services"]; ok {
servicesConfig, err := interpolation.Interpolate(services.(types.Dict), "service", lookupEnv)
servicesConfig, err := interpolation.Interpolate(services.(map[string]interface{}), "service", lookupEnv)
if err != nil {
return nil, err
}
@ -89,7 +89,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
}
if networks, ok := configDict["networks"]; ok {
networksConfig, err := interpolation.Interpolate(networks.(types.Dict), "network", lookupEnv)
networksConfig, err := interpolation.Interpolate(networks.(map[string]interface{}), "network", lookupEnv)
if err != nil {
return nil, err
}
@ -103,7 +103,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
}
if volumes, ok := configDict["volumes"]; ok {
volumesConfig, err := interpolation.Interpolate(volumes.(types.Dict), "volume", lookupEnv)
volumesConfig, err := interpolation.Interpolate(volumes.(map[string]interface{}), "volume", lookupEnv)
if err != nil {
return nil, err
}
@ -117,7 +117,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
}
if secrets, ok := configDict["secrets"]; ok {
secretsConfig, err := interpolation.Interpolate(secrets.(types.Dict), "secret", lookupEnv)
secretsConfig, err := interpolation.Interpolate(secrets.(map[string]interface{}), "secret", lookupEnv)
if err != nil {
return nil, err
}
@ -139,7 +139,7 @@ func GetUnsupportedProperties(configDetails types.ConfigDetails) []string {
unsupported := map[string]bool{}
for _, service := range getServices(getConfigDict(configDetails)) {
serviceDict := service.(types.Dict)
serviceDict := service.(map[string]interface{})
for _, property := range types.UnsupportedProperties {
if _, isSet := serviceDict[property]; isSet {
unsupported[property] = true
@ -165,11 +165,11 @@ func GetDeprecatedProperties(configDetails types.ConfigDetails) map[string]strin
return getProperties(getServices(getConfigDict(configDetails)), types.DeprecatedProperties)
}
func getProperties(services types.Dict, propertyMap map[string]string) map[string]string {
func getProperties(services map[string]interface{}, propertyMap map[string]string) map[string]string {
output := map[string]string{}
for _, service := range services {
if serviceDict, ok := service.(types.Dict); ok {
if serviceDict, ok := service.(map[string]interface{}); ok {
for property, description := range propertyMap {
if _, isSet := serviceDict[property]; isSet {
output[property] = description
@ -192,18 +192,18 @@ func (e *ForbiddenPropertiesError) Error() string {
}
// TODO: resolve multiple files into a single config
func getConfigDict(configDetails types.ConfigDetails) types.Dict {
func getConfigDict(configDetails types.ConfigDetails) map[string]interface{} {
return configDetails.ConfigFiles[0].Config
}
func getServices(configDict types.Dict) types.Dict {
func getServices(configDict map[string]interface{}) map[string]interface{} {
if services, ok := configDict["services"]; ok {
if servicesDict, ok := services.(types.Dict); ok {
if servicesDict, ok := services.(map[string]interface{}); ok {
return servicesDict
}
}
return types.Dict{}
return map[string]interface{}{}
}
func transform(source map[string]interface{}, target interface{}) error {
@ -265,10 +265,9 @@ func transformHook(
}
// keys needs to be converted to strings for jsonschema
// TODO: don't use types.Dict
func convertToStringKeysRecursive(value interface{}, keyPrefix string) (interface{}, error) {
if mapping, ok := value.(map[interface{}]interface{}); ok {
dict := make(types.Dict)
dict := make(map[string]interface{})
for key, entry := range mapping {
str, ok := key.(string)
if !ok {
@ -315,11 +314,11 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error {
// LoadServices produces a ServiceConfig map from a compose file Dict
// the servicesDict is not validated if directly used. Use Load() to enable validation
func LoadServices(servicesDict types.Dict, workingDir string, lookupEnv template.Mapping) ([]types.ServiceConfig, error) {
func LoadServices(servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping) ([]types.ServiceConfig, error) {
var services []types.ServiceConfig
for name, serviceDef := range servicesDict {
serviceConfig, err := LoadService(name, serviceDef.(types.Dict), workingDir, lookupEnv)
serviceConfig, err := LoadService(name, serviceDef.(map[string]interface{}), workingDir, lookupEnv)
if err != nil {
return nil, err
}
@ -331,7 +330,7 @@ func LoadServices(servicesDict types.Dict, workingDir string, lookupEnv template
// LoadService produces a single ServiceConfig from a compose file Dict
// the serviceDict is not validated if directly used. Use Load() to enable validation
func LoadService(name string, serviceDict types.Dict, 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{}
if err := transform(serviceDict, serviceConfig); err != nil {
return nil, err
@ -409,7 +408,7 @@ func transformUlimits(data interface{}) (interface{}, error) {
switch value := data.(type) {
case int:
return types.UlimitsConfig{Single: value}, nil
case types.Dict:
case map[string]interface{}:
ulimit := types.UlimitsConfig{}
ulimit.Soft = value["soft"].(int)
ulimit.Hard = value["hard"].(int)
@ -421,7 +420,7 @@ func transformUlimits(data interface{}) (interface{}, error) {
// LoadNetworks produces a NetworkConfig map from a compose file Dict
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadNetworks(source types.Dict) (map[string]types.NetworkConfig, error) {
func LoadNetworks(source map[string]interface{}) (map[string]types.NetworkConfig, error) {
networks := make(map[string]types.NetworkConfig)
err := transform(source, &networks)
if err != nil {
@ -438,7 +437,7 @@ func LoadNetworks(source types.Dict) (map[string]types.NetworkConfig, error) {
// LoadVolumes produces a VolumeConfig map from a compose file Dict
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadVolumes(source types.Dict) (map[string]types.VolumeConfig, error) {
func LoadVolumes(source map[string]interface{}) (map[string]types.VolumeConfig, error) {
volumes := make(map[string]types.VolumeConfig)
err := transform(source, &volumes)
if err != nil {
@ -467,7 +466,7 @@ func LoadVolumes(source types.Dict) (map[string]types.VolumeConfig, error) {
// LoadSecrets produces a SecretConfig map from a compose file Dict
// the source Dict is not validated if directly used. Use Load() to enable validation
func LoadSecrets(source types.Dict, workingDir string) (map[string]types.SecretConfig, error) {
func LoadSecrets(source map[string]interface{}, workingDir string) (map[string]types.SecretConfig, error) {
secrets := make(map[string]types.SecretConfig)
if err := transform(source, &secrets); err != nil {
return secrets, err
@ -495,8 +494,6 @@ func transformMapStringString(data interface{}) (interface{}, error) {
switch value := data.(type) {
case map[string]interface{}:
return toMapStringString(value, false), nil
case types.Dict:
return toMapStringString(value, false), nil
case map[string]string:
return value, nil
default:
@ -508,8 +505,6 @@ func transformExternal(data interface{}) (interface{}, error) {
switch value := data.(type) {
case bool:
return map[string]interface{}{"external": value}, nil
case types.Dict:
return map[string]interface{}{"external": true, "name": value["name"]}, nil
case map[string]interface{}:
return map[string]interface{}{"external": true, "name": value["name"]}, nil
default:
@ -538,8 +533,6 @@ func transformServicePort(data interface{}) (interface{}, error) {
return data, err
}
ports = append(ports, v...)
case types.Dict:
ports = append(ports, value)
case map[string]interface{}:
ports = append(ports, value)
default:
@ -556,8 +549,6 @@ func transformServiceSecret(data interface{}) (interface{}, error) {
switch value := data.(type) {
case string:
return map[string]interface{}{"source": value}, nil
case types.Dict:
return data, nil
case map[string]interface{}:
return data, nil
default:
@ -569,8 +560,6 @@ func transformServiceVolumeConfig(data interface{}) (interface{}, error) {
switch value := data.(type) {
case string:
return parseVolume(value)
case types.Dict:
return data, nil
case map[string]interface{}:
return data, nil
default:
@ -612,7 +601,7 @@ func transformStringList(data interface{}) (interface{}, error) {
func transformMappingOrList(mappingOrList interface{}, sep string, allowNil bool) interface{} {
switch value := mappingOrList.(type) {
case types.Dict:
case map[string]interface{}:
return toMapStringString(value, allowNil)
case ([]interface{}):
result := make(map[string]interface{})

View file

@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
)
func buildConfigDetails(source types.Dict, env map[string]string) types.ConfigDetails {
func buildConfigDetails(source map[string]interface{}, env map[string]string) types.ConfigDetails {
workingDir, err := os.Getwd()
if err != nil {
panic(err)
@ -70,39 +70,39 @@ networks:
- subnet: 172.28.0.0/16
`
var sampleDict = types.Dict{
var sampleDict = map[string]interface{}{
"version": "3",
"services": types.Dict{
"foo": types.Dict{
"services": map[string]interface{}{
"foo": map[string]interface{}{
"image": "busybox",
"networks": types.Dict{"with_me": nil},
"networks": map[string]interface{}{"with_me": nil},
},
"bar": types.Dict{
"bar": map[string]interface{}{
"image": "busybox",
"environment": []interface{}{"FOO=1"},
"networks": []interface{}{"with_ipam"},
},
},
"volumes": types.Dict{
"hello": types.Dict{
"volumes": map[string]interface{}{
"hello": map[string]interface{}{
"driver": "default",
"driver_opts": types.Dict{
"driver_opts": map[string]interface{}{
"beep": "boop",
},
},
},
"networks": types.Dict{
"default": types.Dict{
"networks": map[string]interface{}{
"default": map[string]interface{}{
"driver": "bridge",
"driver_opts": types.Dict{
"driver_opts": map[string]interface{}{
"beep": "boop",
},
},
"with_ipam": types.Dict{
"ipam": types.Dict{
"with_ipam": map[string]interface{}{
"ipam": map[string]interface{}{
"driver": "default",
"config": []interface{}{
types.Dict{
map[string]interface{}{
"subnet": "172.28.0.0/16",
},
},

View file

@ -50,13 +50,10 @@ var ForbiddenProperties = map[string]string{
"memswap_limit": "Set resource limits using deploy.resources",
}
// Dict is a mapping of strings to interface{}
type Dict map[string]interface{}
// ConfigFile is a filename and the contents of the file as a Dict
type ConfigFile struct {
Filename string
Config Dict
Config map[string]interface{}
}
// ConfigDetails are the details about a group of ConfigFiles