github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/space.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  type spaces struct {
    12  	Version int      `yaml:"version"`
    13  	Spaces_ []*space `yaml:"spaces"`
    14  }
    15  
    16  type space struct {
    17  	Name_       string `yaml:"name"`
    18  	Public_     bool   `yaml:"public"`
    19  	ProviderID_ string `yaml:"provider-id,omitempty"`
    20  }
    21  
    22  // SpaceArgs is an argument struct used to create a new internal space
    23  // type that supports the Space interface.
    24  type SpaceArgs struct {
    25  	Name       string
    26  	Public     bool
    27  	ProviderID string
    28  }
    29  
    30  func newSpace(args SpaceArgs) *space {
    31  	return &space{
    32  		Name_:       args.Name,
    33  		Public_:     args.Public,
    34  		ProviderID_: args.ProviderID,
    35  	}
    36  }
    37  
    38  // Name implements Space.
    39  func (s *space) Name() string {
    40  	return s.Name_
    41  }
    42  
    43  // Public implements Space.
    44  func (s *space) Public() bool {
    45  	return s.Public_
    46  }
    47  
    48  // ProviderID implements Space.
    49  func (s *space) ProviderID() string {
    50  	return s.ProviderID_
    51  }
    52  
    53  func importSpaces(source map[string]interface{}) ([]*space, error) {
    54  	checker := versionedChecker("spaces")
    55  	coerced, err := checker.Coerce(source, nil)
    56  	if err != nil {
    57  		return nil, errors.Annotatef(err, "spaces version schema check failed")
    58  	}
    59  	valid := coerced.(map[string]interface{})
    60  
    61  	version := int(valid["version"].(int64))
    62  	importFunc, ok := spaceDeserializationFuncs[version]
    63  	if !ok {
    64  		return nil, errors.NotValidf("version %d", version)
    65  	}
    66  	sourceList := valid["spaces"].([]interface{})
    67  	return importSpaceList(sourceList, importFunc)
    68  }
    69  
    70  func importSpaceList(sourceList []interface{}, importFunc spaceDeserializationFunc) ([]*space, error) {
    71  	result := make([]*space, 0, len(sourceList))
    72  	for i, value := range sourceList {
    73  		source, ok := value.(map[string]interface{})
    74  		if !ok {
    75  			return nil, errors.Errorf("unexpected value for space %d, %T", i, value)
    76  		}
    77  		space, err := importFunc(source)
    78  		if err != nil {
    79  			return nil, errors.Annotatef(err, "space %d", i)
    80  		}
    81  		result = append(result, space)
    82  	}
    83  	return result, nil
    84  }
    85  
    86  type spaceDeserializationFunc func(map[string]interface{}) (*space, error)
    87  
    88  var spaceDeserializationFuncs = map[int]spaceDeserializationFunc{
    89  	1: importSpaceV1,
    90  }
    91  
    92  func importSpaceV1(source map[string]interface{}) (*space, error) {
    93  	fields := schema.Fields{
    94  		"name":        schema.String(),
    95  		"public":      schema.Bool(),
    96  		"provider-id": schema.String(),
    97  	}
    98  	// Some values don't have to be there.
    99  	defaults := schema.Defaults{
   100  		"provider-id": "",
   101  	}
   102  	checker := schema.FieldMap(fields, defaults)
   103  
   104  	coerced, err := checker.Coerce(source, nil)
   105  	if err != nil {
   106  		return nil, errors.Annotatef(err, "space v1 schema check failed")
   107  	}
   108  	valid := coerced.(map[string]interface{})
   109  	// From here we know that the map returned from the schema coercion
   110  	// contains fields of the right type.
   111  
   112  	return &space{
   113  		Name_:       valid["name"].(string),
   114  		Public_:     valid["public"].(bool),
   115  		ProviderID_: valid["provider-id"].(string),
   116  	}, nil
   117  }