-
Notifications
You must be signed in to change notification settings - Fork 36
/
bootresource.go
136 lines (117 loc) · 3.89 KB
/
bootresource.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2016 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package gomaasapi
import (
"strings"
"github.com/juju/collections/set"
"github.com/juju/errors"
"github.com/juju/schema"
"github.com/juju/version"
)
type bootResource struct {
// Add the controller in when we need to do things with the bootResource.
// controller Controller
resourceURI string
id int
name string
type_ string
architecture string
subArches string
kernelFlavor string
}
// ID implements BootResource.
func (b *bootResource) ID() int {
return b.id
}
// Name implements BootResource.
func (b *bootResource) Name() string {
return b.name
}
// Name implements BootResource.
func (b *bootResource) Type() string {
return b.type_
}
// Name implements BootResource.
func (b *bootResource) Architecture() string {
return b.architecture
}
// SubArchitectures implements BootResource.
func (b *bootResource) SubArchitectures() set.Strings {
return set.NewStrings(strings.Split(b.subArches, ",")...)
}
// KernelFlavor implements BootResource.
func (b *bootResource) KernelFlavor() string {
return b.kernelFlavor
}
func readBootResources(controllerVersion version.Number, source interface{}) ([]*bootResource, error) {
checker := schema.List(schema.StringMap(schema.Any()))
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, WrapWithDeserializationError(err, "boot resource base schema check failed")
}
valid := coerced.([]interface{})
var deserialisationVersion version.Number
for v := range bootResourceDeserializationFuncs {
if v.Compare(deserialisationVersion) > 0 && v.Compare(controllerVersion) <= 0 {
deserialisationVersion = v
}
}
if deserialisationVersion == version.Zero {
return nil, NewUnsupportedVersionError("no boot resource read func for version %s", controllerVersion)
}
readFunc := bootResourceDeserializationFuncs[deserialisationVersion]
return readBootResourceList(valid, readFunc)
}
// readBootResourceList expects the values of the sourceList to be string maps.
func readBootResourceList(sourceList []interface{}, readFunc bootResourceDeserializationFunc) ([]*bootResource, error) {
result := make([]*bootResource, 0, len(sourceList))
for i, value := range sourceList {
source, ok := value.(map[string]interface{})
if !ok {
return nil, NewDeserializationError("unexpected value for boot resource %d, %T", i, value)
}
bootResource, err := readFunc(source)
if err != nil {
return nil, errors.Annotatef(err, "boot resource %d", i)
}
result = append(result, bootResource)
}
return result, nil
}
type bootResourceDeserializationFunc func(map[string]interface{}) (*bootResource, error)
var bootResourceDeserializationFuncs = map[version.Number]bootResourceDeserializationFunc{
twoDotOh: bootResource_2_0,
}
func bootResource_2_0(source map[string]interface{}) (*bootResource, error) {
fields := schema.Fields{
"resource_uri": schema.String(),
"id": schema.ForceInt(),
"name": schema.String(),
"type": schema.String(),
"architecture": schema.String(),
"subarches": schema.String(),
"kflavor": schema.String(),
}
defaults := schema.Defaults{
"subarches": "",
"kflavor": "",
}
checker := schema.FieldMap(fields, defaults)
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, WrapWithDeserializationError(err, "boot resource 2.0 schema check failed")
}
valid := coerced.(map[string]interface{})
// From here we know that the map returned from the schema coercion
// contains fields of the right type.
result := &bootResource{
resourceURI: valid["resource_uri"].(string),
id: valid["id"].(int),
name: valid["name"].(string),
type_: valid["type"].(string),
architecture: valid["architecture"].(string),
subArches: valid["subarches"].(string),
kernelFlavor: valid["kflavor"].(string),
}
return result, nil
}