104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
|
package yaml
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
// Networks represents a list of service networks in compose file.
|
||
|
// It has several representation, hence this specific struct.
|
||
|
type Networks struct {
|
||
|
Networks []*Network
|
||
|
}
|
||
|
|
||
|
// Network represents a service network in compose file.
|
||
|
type Network struct {
|
||
|
Name string `yaml:"-"`
|
||
|
RealName string `yaml:"-"`
|
||
|
Aliases []string `yaml:"aliases,omitempty"`
|
||
|
IPv4Address string `yaml:"ipv4_address,omitempty"`
|
||
|
IPv6Address string `yaml:"ipv6_address,omitempty"`
|
||
|
}
|
||
|
|
||
|
// MarshalYAML implements the Marshaller interface.
|
||
|
func (n Networks) MarshalYAML() (tag string, value interface{}, err error) {
|
||
|
m := map[string]*Network{}
|
||
|
for _, network := range n.Networks {
|
||
|
m[network.Name] = network
|
||
|
}
|
||
|
return "", m, nil
|
||
|
}
|
||
|
|
||
|
// UnmarshalYAML implements the Unmarshaller interface.
|
||
|
func (n *Networks) UnmarshalYAML(tag string, value interface{}) error {
|
||
|
switch v := value.(type) {
|
||
|
case []interface{}:
|
||
|
n.Networks = []*Network{}
|
||
|
for _, network := range v {
|
||
|
name, ok := network.(string)
|
||
|
if !ok {
|
||
|
return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name)
|
||
|
}
|
||
|
n.Networks = append(n.Networks, &Network{
|
||
|
Name: name,
|
||
|
})
|
||
|
}
|
||
|
case map[interface{}]interface{}:
|
||
|
n.Networks = []*Network{}
|
||
|
for mapKey, mapValue := range v {
|
||
|
name, ok := mapKey.(string)
|
||
|
if !ok {
|
||
|
return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name)
|
||
|
}
|
||
|
network, err := handleNetwork(name, mapValue)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
n.Networks = append(n.Networks, network)
|
||
|
}
|
||
|
default:
|
||
|
return fmt.Errorf("Failed to unmarshal Networks: %#v", value)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func handleNetwork(name string, value interface{}) (*Network, error) {
|
||
|
if value == nil {
|
||
|
return &Network{
|
||
|
Name: name,
|
||
|
}, nil
|
||
|
}
|
||
|
switch v := value.(type) {
|
||
|
case map[interface{}]interface{}:
|
||
|
network := &Network{
|
||
|
Name: name,
|
||
|
}
|
||
|
for mapKey, mapValue := range v {
|
||
|
name, ok := mapKey.(string)
|
||
|
if !ok {
|
||
|
return &Network{}, fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name)
|
||
|
}
|
||
|
switch name {
|
||
|
case "aliases":
|
||
|
aliases, ok := mapValue.([]interface{})
|
||
|
if !ok {
|
||
|
return &Network{}, fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", aliases, aliases)
|
||
|
}
|
||
|
network.Aliases = []string{}
|
||
|
for _, alias := range aliases {
|
||
|
network.Aliases = append(network.Aliases, alias.(string))
|
||
|
}
|
||
|
case "ipv4_address":
|
||
|
network.IPv4Address = mapValue.(string)
|
||
|
case "ipv6_address":
|
||
|
network.IPv6Address = mapValue.(string)
|
||
|
default:
|
||
|
// Ignorer unknown keys ?
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
return network, nil
|
||
|
default:
|
||
|
return &Network{}, fmt.Errorf("Failed to unmarshal Network: %#v", value)
|
||
|
}
|
||
|
}
|