зеркало из https://github.com/microsoft/docker.git
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:
Родитель
d8406fd7a0
Коммит
d3dc27d145
|
@ -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 {
|
||||
|
|
|
@ -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": "${",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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{})
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче