-
Notifications
You must be signed in to change notification settings - Fork 1
/
definition_calls.go
143 lines (124 loc) · 5.08 KB
/
definition_calls.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
137
138
139
140
141
142
143
package lib
import (
"encoding/json"
"fmt"
"regexp"
"sort"
"github.com/BytemarkHosting/bytemark-client/lib/brain"
)
// Definitions represent all the possible things that can be returned as part of BigV's /definitions endpoint.
type Definitions struct {
Distributions []string
StorageGrades []string
ZoneNames []string
DistributionDescriptions map[string]string
StorageGradeDescriptions map[string]string
HardwareProfiles []string
Keymaps []string
Sendkeys []string
}
// DistributionDefinitions processes DistributionDescriptions into a slice of DistributionDefinitions
func (d Definitions) DistributionDefinitions() (dists brain.DistributionDefinitions) {
// TODO: mix in data from the imager.
dists = make([]brain.DistributionDefinition, 0, len(d.DistributionDescriptions))
for name, desc := range d.DistributionDescriptions {
dists = append(dists, brain.DistributionDefinition{Name: name, Description: desc})
}
return
}
// HardwareProfileDefinitions processes HardwareProfiles into a slice of HardwareProfileDefinitions and mixes in some static data since the API doesn't return any more useful information yet.
func (d Definitions) HardwareProfileDefinitions() (profs brain.HardwareProfileDefinitions) {
profs = make([]brain.HardwareProfileDefinition, 0, len(d.HardwareProfiles))
descriptions := map[string]string{
"^virtio": "Default, high-performance hardware profile",
"^compat": "More-compatible, but slower, hardware profile. May be useful for getting niche operating systems or older kernels to boot",
}
for _, name := range d.HardwareProfiles {
desc := ""
for regex, newDesc := range descriptions {
if match, _ := regexp.MatchString(regex, name); match {
desc = newDesc
}
}
profs = append(profs, brain.HardwareProfileDefinition{Name: name, Description: desc})
}
return
}
// StorageGradeDefinitions processes StorageGradeDescriptions into a slice of StorageGradeDefinitions
func (d Definitions) StorageGradeDefinitions() (grades brain.StorageGradeDefinitions) {
grades = make([]brain.StorageGradeDefinition, 0, len(d.StorageGradeDescriptions))
for name, desc := range d.StorageGradeDescriptions {
grades = append(grades, brain.StorageGradeDefinition{Name: name, Description: desc})
}
return
}
// ZoneDefinitions processes ZoneNames into a slice of ZoneDefinitions, adding some static data of our own since there's nothing coming from the API about that right now
func (d Definitions) ZoneDefinitions() (zones brain.ZoneDefinitions) {
zones = make([]brain.ZoneDefinition, 0, len(d.ZoneNames))
zoneDescriptionsMap := map[string]string{
"york": "Cloud Servers in York",
"manchester": "Cloud Servers in Manchester",
}
for _, name := range d.ZoneNames {
zones = append(zones, brain.ZoneDefinition{Name: name, Description: zoneDescriptionsMap[name]})
}
return
}
// JSONDefinition is an intermediate type used for converting BigV's JSON output for /definitions into the beautiful Definitions struct above. It should not be exported.
type JSONDefinition struct {
ID string `json:"id"`
Data json.RawMessage `json:"data"`
}
// JSONDefinitions should not be exported.
type JSONDefinitions []*JSONDefinition
// Process unmarshals the data from this JSONDefinition into the right field of the Definitions object.
func (d *JSONDefinition) Process(into *Definitions) error {
switch d.ID {
case "distributions":
return json.Unmarshal(d.Data, &into.Distributions)
case "storage_grades":
return json.Unmarshal(d.Data, &into.StorageGrades)
case "zone_names":
return json.Unmarshal(d.Data, &into.ZoneNames)
case "hardware_profiles":
return json.Unmarshal(d.Data, &into.HardwareProfiles)
case "keymaps":
return json.Unmarshal(d.Data, &into.Keymaps)
case "sendkeys":
return json.Unmarshal(d.Data, &into.Sendkeys)
case "distribution_descriptions":
return json.Unmarshal(d.Data, &into.DistributionDescriptions)
case "storage_grade_descriptions":
return json.Unmarshal(d.Data, &into.StorageGradeDescriptions)
}
// Shouldn't be a fatal error. into may still be useful
// return fmt.Errorf("Unknown definition returned: %v", d.ID)
// Don't return an error here, as older version of bytemark-client
// may simply be unaware of newly added definitions. It's not
// strictly an error, just not handled by the current version.
return nil
}
// Process processes our intermediate JSONDefinitions into a Definitions object.
func (defs JSONDefinitions) Process() (out Definitions) {
for _, def := range defs {
if err := def.Process(&out); err != nil {
fmt.Printf("WARN: %v\n", err)
}
}
sort.StringSlice(out.Distributions).Sort()
sort.StringSlice(out.StorageGrades).Sort()
sort.StringSlice(out.ZoneNames).Sort()
sort.StringSlice(out.HardwareProfiles).Sort()
return
}
// ReadDefinitions queries the brain for its definitions
func (c *bytemarkClient) ReadDefinitions() (definitions Definitions, err error) {
var defs JSONDefinitions
r, err := c.BuildRequestNoAuth("GET", BrainEndpoint, "/definitions")
if err != nil {
return
}
_, _, err = r.Run(nil, &defs)
definitions = defs.Process()
return
}