~juju-qa/ubuntu/xenial/juju/2.0-rc2

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/constraints/validation.go

  • Committer: Nicholas Skaggs
  • Date: 2016-09-30 14:39:30 UTC
  • mfrom: (1.8.1)
  • Revision ID: nicholas.skaggs@canonical.com-20160930143930-vwwhrefh6ftckccy
import upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
import (
7
7
        "fmt"
8
 
        "math"
9
8
        "reflect"
10
9
 
11
10
        "github.com/juju/utils/set"
80
79
 
81
80
// RegisterVocabulary is defined on Validator.
82
81
func (v *validator) RegisterVocabulary(attributeName string, allowedValues interface{}) {
83
 
        v.vocab[attributeName] = convertToSlice(allowedValues)
 
82
        v.vocab[resolveAlias(attributeName)] = convertToSlice(allowedValues)
84
83
}
85
84
 
86
85
var checkIsCollection = func(coll interface{}) {
102
101
 
103
102
// UpdateVocabulary is defined on Validator.
104
103
func (v *validator) UpdateVocabulary(attributeName string, allowedValues interface{}) {
 
104
        attributeName = resolveAlias(attributeName)
105
105
        // If this attribute is not registered, delegate to RegisterVocabulary()
106
106
        currentValues, ok := v.vocab[attributeName]
107
107
        if !ok {
124
124
}
125
125
 
126
126
func (v *validator) updateVocabularyFromMap(attributeName string, valuesMap map[interface{}]bool) {
 
127
        attributeName = resolveAlias(attributeName)
127
128
        var merged []interface{}
128
129
        for one, _ := range valuesMap {
129
130
                // TODO (anastasiamac) Because it's coming from the map, the order maybe affected
186
187
// checkInVocab returns an error if the attribute value is not allowed by the
187
188
// vocab which may have been registered for it.
188
189
func (v *validator) checkInVocab(attributeName string, attributeValue interface{}) error {
189
 
        validValues, ok := v.vocab[attributeName]
 
190
        validValues, ok := v.vocab[resolveAlias(attributeName)]
190
191
        if !ok {
191
192
                return nil
192
193
        }
199
200
                "invalid constraint value: %v=%v\nvalid values are: %v", attributeName, attributeValue, validValues)
200
201
}
201
202
 
202
 
// coerce returns v in a format that allows constraint values to be easily compared.
203
 
// Its main purpose is to cast all numeric values to int64 or float64.
 
203
// coerce returns v in a format that allows constraint values to be easily
 
204
// compared. Its main purpose is to cast all numeric values to float64 (since
 
205
// the numbers we compare are generated from json serialization).
204
206
func coerce(v interface{}) interface{} {
205
 
        if v != nil {
206
 
                switch vv := reflect.TypeOf(v); vv.Kind() {
207
 
                case reflect.String:
208
 
                        return v
209
 
                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
210
 
                        return int64(reflect.ValueOf(v).Int())
211
 
                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
212
 
                        uval := reflect.ValueOf(v).Uint()
213
 
                        // Just double check the value is in range.
214
 
                        if uval > math.MaxInt64 {
215
 
                                panic(fmt.Errorf("constraint value %v is too large", uval))
216
 
                        }
217
 
                        return int64(uval)
218
 
                case reflect.Float32, reflect.Float64:
219
 
                        return float64(reflect.ValueOf(v).Float())
220
 
                }
 
207
        switch val := v.(type) {
 
208
        case string:
 
209
                return v
 
210
        // Yes, these are all the same, however we can't put them into a single
 
211
        // case, or the value becomes interface{}, which can't be converted to a
 
212
        // float64.
 
213
        case int:
 
214
                return float64(val)
 
215
        case int8:
 
216
                return float64(val)
 
217
        case int16:
 
218
                return float64(val)
 
219
        case int32:
 
220
                return float64(val)
 
221
        case int64:
 
222
                return float64(val)
 
223
        case uint:
 
224
                return float64(val)
 
225
        case uint8:
 
226
                return float64(val)
 
227
        case uint16:
 
228
                return float64(val)
 
229
        case uint32:
 
230
                return float64(val)
 
231
        case uint64:
 
232
                return float64(val)
 
233
        case float32:
 
234
                return float64(val)
 
235
        case float64:
 
236
                return val
221
237
        }
222
238
        return v
223
239
}
224
240
 
225
241
// withFallbacks returns a copy of v with nil values taken from vFallback.
226
242
func withFallbacks(v Value, vFallback Value) Value {
227
 
        result := vFallback
228
 
        for _, fieldName := range fieldNames {
229
 
                resultVal := reflect.ValueOf(&result).Elem().FieldByName(fieldName)
230
 
                val := reflect.ValueOf(&v).Elem().FieldByName(fieldName)
231
 
                if !val.IsNil() {
232
 
                        resultVal.Set(val)
 
243
        vAttr := v.attributesWithValues()
 
244
        fbAttr := vFallback.attributesWithValues()
 
245
        for k, v := range fbAttr {
 
246
                if _, ok := vAttr[k]; !ok {
 
247
                        vAttr[k] = v
233
248
                }
234
249
        }
235
 
        return result
 
250
        return fromAttributes(vAttr)
236
251
}
237
252
 
238
253
// Validate is defined on Validator.
266
281
        // Null out the conflicting consFallback attribute values because
267
282
        // cons takes priority. We can't error here because we
268
283
        // know that aConflicts contains valid attr names.
269
 
        consFallbackMinusConflicts, _ := consFallback.without(fallbackConflicts...)
 
284
        consFallbackMinusConflicts := consFallback.without(fallbackConflicts...)
270
285
        // The result is cons with fallbacks coming from any
271
286
        // non conflicting consFallback attributes.
272
287
        return withFallbacks(cons, consFallbackMinusConflicts), nil