github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/address.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package description
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/schema"
     9  )
    10  
    11  // AddressArgs is an argument struct used to create a new internal address
    12  // type that supports the Address interface.
    13  type AddressArgs struct {
    14  	Value  string
    15  	Type   string
    16  	Scope  string
    17  	Origin string
    18  }
    19  
    20  func newAddress(args AddressArgs) *address {
    21  	return &address{
    22  		Version: 1,
    23  		Value_:  args.Value,
    24  		Type_:   args.Type,
    25  		Scope_:  args.Scope,
    26  		Origin_: args.Origin,
    27  	}
    28  }
    29  
    30  // address represents an IP Address of some form.
    31  type address struct {
    32  	Version int `yaml:"version"`
    33  
    34  	Value_  string `yaml:"value"`
    35  	Type_   string `yaml:"type"`
    36  	Scope_  string `yaml:"scope,omitempty"`
    37  	Origin_ string `yaml:"origin,omitempty"`
    38  }
    39  
    40  // Value implements Address.
    41  func (a *address) Value() string {
    42  	return a.Value_
    43  }
    44  
    45  // Type implements Address.
    46  func (a *address) Type() string {
    47  	return a.Type_
    48  }
    49  
    50  // Scope implements Address.
    51  func (a *address) Scope() string {
    52  	return a.Scope_
    53  }
    54  
    55  // Origin implements Address.
    56  func (a *address) Origin() string {
    57  	return a.Origin_
    58  }
    59  
    60  func importAddresses(sourceList []interface{}) ([]*address, error) {
    61  	var result []*address
    62  	for i, value := range sourceList {
    63  		source, ok := value.(map[string]interface{})
    64  		if !ok {
    65  			return nil, errors.Errorf("unexpected value for address %d, %T", i, value)
    66  		}
    67  		addr, err := importAddress(source)
    68  		if err != nil {
    69  			return nil, errors.Trace(err)
    70  		}
    71  		result = append(result, addr)
    72  	}
    73  	return result, nil
    74  }
    75  
    76  // importAddress constructs a new Address from a map representing a serialised
    77  // Address instance.
    78  func importAddress(source map[string]interface{}) (*address, error) {
    79  	version, err := getVersion(source)
    80  	if err != nil {
    81  		return nil, errors.Annotate(err, "address version schema check failed")
    82  	}
    83  
    84  	importFunc, ok := addressDeserializationFuncs[version]
    85  	if !ok {
    86  		return nil, errors.NotValidf("version %d", version)
    87  	}
    88  
    89  	return importFunc(source)
    90  }
    91  
    92  type addressDeserializationFunc func(map[string]interface{}) (*address, error)
    93  
    94  var addressDeserializationFuncs = map[int]addressDeserializationFunc{
    95  	1: importAddressV1,
    96  }
    97  
    98  func importAddressV1(source map[string]interface{}) (*address, error) {
    99  	fields := schema.Fields{
   100  		"value":  schema.String(),
   101  		"type":   schema.String(),
   102  		"scope":  schema.String(),
   103  		"origin": schema.String(),
   104  	}
   105  	// Some values don't have to be there.
   106  	defaults := schema.Defaults{
   107  		"scope":  "",
   108  		"origin": "",
   109  	}
   110  	checker := schema.FieldMap(fields, defaults)
   111  
   112  	coerced, err := checker.Coerce(source, nil)
   113  	if err != nil {
   114  		return nil, errors.Annotatef(err, "address v1 schema check failed")
   115  	}
   116  	valid := coerced.(map[string]interface{})
   117  	// From here we know that the map returned from the schema coercion
   118  	// contains fields of the right type.
   119  
   120  	return &address{
   121  		Version: 1,
   122  		Value_:  valid["value"].(string),
   123  		Type_:   valid["type"].(string),
   124  		Scope_:  valid["scope"].(string),
   125  		Origin_: valid["origin"].(string),
   126  	}, nil
   127  }