github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 }