github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/payload.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 // Payload represents a charm payload for a unit. 12 type Payload interface { 13 Name() string 14 Type() string 15 RawID() string 16 State() string 17 Labels() []string 18 } 19 20 type payloads struct { 21 Version int `yaml:"version"` 22 Payloads_ []*payload `yaml:"payloads"` 23 } 24 25 type payload struct { 26 Name_ string `yaml:"name"` 27 Type_ string `yaml:"type"` 28 RawID_ string `yaml:"raw-id"` 29 State_ string `yaml:"state"` 30 Labels_ []string `yaml:"labels,omitempty"` 31 } 32 33 // Name implements Payload. 34 func (p *payload) Name() string { 35 return p.Name_ 36 } 37 38 // Type implements Payload. 39 func (p *payload) Type() string { 40 return p.Type_ 41 } 42 43 // RawID implements Payload. 44 func (p *payload) RawID() string { 45 return p.RawID_ 46 } 47 48 // State implements Payload. 49 func (p *payload) State() string { 50 return p.State_ 51 } 52 53 // Labels implements Payload. 54 func (p *payload) Labels() []string { 55 return p.Labels_ 56 } 57 58 // PayloadArgs is an argument struct used to create a 59 // new internal payload type that supports the Payload interface. 60 type PayloadArgs struct { 61 Name string 62 Type string 63 RawID string 64 State string 65 Labels []string 66 } 67 68 func newPayload(args PayloadArgs) *payload { 69 return &payload{ 70 Name_: args.Name, 71 Type_: args.Type, 72 RawID_: args.RawID, 73 State_: args.State, 74 Labels_: args.Labels, 75 } 76 } 77 78 func importPayloads(source map[string]interface{}) ([]*payload, error) { 79 checker := versionedChecker("payloads") 80 coerced, err := checker.Coerce(source, nil) 81 if err != nil { 82 return nil, errors.Annotatef(err, "payloads version schema check failed") 83 } 84 valid := coerced.(map[string]interface{}) 85 86 version := int(valid["version"].(int64)) 87 importFunc, ok := payloadDeserializationFuncs[version] 88 if !ok { 89 return nil, errors.NotValidf("version %d", version) 90 } 91 sourceList := valid["payloads"].([]interface{}) 92 return importPayloadList(sourceList, importFunc) 93 } 94 95 func importPayloadList(sourceList []interface{}, importFunc payloadDeserializationFunc) ([]*payload, error) { 96 result := make([]*payload, 0, len(sourceList)) 97 for i, value := range sourceList { 98 source, ok := value.(map[string]interface{}) 99 if !ok { 100 return nil, errors.Errorf("unexpected value for payload %d, %T", i, value) 101 } 102 payload, err := importFunc(source) 103 if err != nil { 104 return nil, errors.Annotatef(err, "payload %d", i) 105 } 106 result = append(result, payload) 107 } 108 return result, nil 109 } 110 111 type payloadDeserializationFunc func(map[string]interface{}) (*payload, error) 112 113 var payloadDeserializationFuncs = map[int]payloadDeserializationFunc{ 114 1: importPayloadV1, 115 } 116 117 func importPayloadV1(source map[string]interface{}) (*payload, error) { 118 fields := schema.Fields{ 119 "name": schema.String(), 120 "type": schema.String(), 121 "raw-id": schema.String(), 122 "state": schema.String(), 123 "labels": schema.List(schema.String()), 124 } 125 // Some values don't have to be there. 126 defaults := schema.Defaults{ 127 "labels": schema.Omit, 128 } 129 checker := schema.FieldMap(fields, defaults) 130 131 coerced, err := checker.Coerce(source, nil) 132 if err != nil { 133 return nil, errors.Annotatef(err, "payload v1 schema check failed") 134 } 135 valid := coerced.(map[string]interface{}) 136 137 return &payload{ 138 Name_: valid["name"].(string), 139 Type_: valid["type"].(string), 140 RawID_: valid["raw-id"].(string), 141 State_: valid["state"].(string), 142 Labels_: convertToStringSlice(valid["labels"]), 143 }, nil 144 }