~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/core/description/ports.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 versionedOpenedPorts struct {
 
12
        Version      int            `yaml:"version"`
 
13
        OpenedPorts_ []*openedPorts `yaml:"opened-ports"`
 
14
}
 
15
 
 
16
type openedPorts struct {
 
17
        SubnetID_    string      `yaml:"subnet-id"`
 
18
        OpenedPorts_ *portRanges `yaml:"opened-ports"`
 
19
}
 
20
 
 
21
// OpenedPortsArgs is an argument struct used to add a set of opened port ranges
 
22
// to a machine.
 
23
type OpenedPortsArgs struct {
 
24
        SubnetID    string
 
25
        OpenedPorts []PortRangeArgs
 
26
}
 
27
 
 
28
func newOpenedPorts(args OpenedPortsArgs) *openedPorts {
 
29
        result := &openedPorts{SubnetID_: args.SubnetID}
 
30
        result.setOpenedPorts(nil)
 
31
        for _, pargs := range args.OpenedPorts {
 
32
                result.OpenedPorts_.add(pargs)
 
33
        }
 
34
        return result
 
35
}
 
36
 
 
37
// SubnetID implements OpenedPorts.
 
38
func (p *openedPorts) SubnetID() string {
 
39
        return p.SubnetID_
 
40
}
 
41
 
 
42
// OpenPorts implements OpenedPorts.
 
43
func (p *openedPorts) OpenPorts() []PortRange {
 
44
        var result []PortRange
 
45
        for _, pr := range p.OpenedPorts_.OpenedPorts_ {
 
46
                result = append(result, pr)
 
47
        }
 
48
        return result
 
49
}
 
50
 
 
51
func (p *openedPorts) setOpenedPorts(ports []*portRange) {
 
52
        p.OpenedPorts_ = &portRanges{
 
53
                Version:      1,
 
54
                OpenedPorts_: ports,
 
55
        }
 
56
}
 
57
 
 
58
func importOpenedPorts(source map[string]interface{}) ([]*openedPorts, error) {
 
59
        checker := versionedChecker("opened-ports")
 
60
        coerced, err := checker.Coerce(source, nil)
 
61
        if err != nil {
 
62
                return nil, errors.Annotatef(err, "opened-ports version schema check failed")
 
63
        }
 
64
        valid := coerced.(map[string]interface{})
 
65
 
 
66
        version := int(valid["version"].(int64))
 
67
        importFunc, ok := openedPortsDeserializationFuncs[version]
 
68
        if !ok {
 
69
                return nil, errors.NotValidf("version %d", version)
 
70
        }
 
71
        sourceList := valid["opened-ports"].([]interface{})
 
72
        return importOpenedPortsList(sourceList, importFunc)
 
73
}
 
74
 
 
75
func importOpenedPortsList(sourceList []interface{}, importFunc openedPortsDeserializationFunc) ([]*openedPorts, error) {
 
76
        result := make([]*openedPorts, 0, len(sourceList))
 
77
        for i, value := range sourceList {
 
78
                source, ok := value.(map[string]interface{})
 
79
                if !ok {
 
80
                        return nil, errors.Errorf("unexpected value for opened-ports %d, %T", i, value)
 
81
                }
 
82
                ports, err := importFunc(source)
 
83
                if err != nil {
 
84
                        return nil, errors.Annotatef(err, "opened-ports %d", i)
 
85
                }
 
86
                result = append(result, ports)
 
87
        }
 
88
        return result, nil
 
89
}
 
90
 
 
91
type openedPortsDeserializationFunc func(map[string]interface{}) (*openedPorts, error)
 
92
 
 
93
var openedPortsDeserializationFuncs = map[int]openedPortsDeserializationFunc{
 
94
        1: importOpenedPortsV1,
 
95
}
 
96
 
 
97
func importOpenedPortsV1(source map[string]interface{}) (*openedPorts, error) {
 
98
        fields := schema.Fields{
 
99
                "subnet-id":    schema.String(),
 
100
                "opened-ports": schema.StringMap(schema.Any()),
 
101
        }
 
102
 
 
103
        checker := schema.FieldMap(fields, nil) // no defaults
 
104
 
 
105
        coerced, err := checker.Coerce(source, nil)
 
106
        if err != nil {
 
107
                return nil, errors.Annotatef(err, "opened-ports v1 schema check failed")
 
108
        }
 
109
        valid := coerced.(map[string]interface{})
 
110
        // From here we know that the map returned from the schema coercion
 
111
        // contains fields of the right type.
 
112
 
 
113
        ports, err := importPortRanges(valid["opened-ports"].(map[string]interface{}))
 
114
        if err != nil {
 
115
                return nil, errors.Trace(err)
 
116
        }
 
117
        result := &openedPorts{
 
118
                SubnetID_: valid["subnet-id"].(string),
 
119
        }
 
120
        result.setOpenedPorts(ports)
 
121
        return result, nil
 
122
}
 
123
 
 
124
type portRanges struct {
 
125
        Version      int          `yaml:"version"`
 
126
        OpenedPorts_ []*portRange `yaml:"opened-ports"`
 
127
}
 
128
 
 
129
type portRange struct {
 
130
        UnitName_ string `yaml:"unit-name"`
 
131
        FromPort_ int    `yaml:"from-port"`
 
132
        ToPort_   int    `yaml:"to-port"`
 
133
        Protocol_ string `yaml:"protocol"`
 
134
}
 
135
 
 
136
// PortRangeArgs is an argument struct used to create a PortRange. This is only
 
137
// done as part of creating OpenedPorts for a Machine.
 
138
type PortRangeArgs struct {
 
139
        UnitName string
 
140
        FromPort int
 
141
        ToPort   int
 
142
        Protocol string
 
143
}
 
144
 
 
145
func newPortRange(args PortRangeArgs) *portRange {
 
146
        return &portRange{
 
147
                UnitName_: args.UnitName,
 
148
                FromPort_: args.FromPort,
 
149
                ToPort_:   args.ToPort,
 
150
                Protocol_: args.Protocol,
 
151
        }
 
152
}
 
153
 
 
154
func (p *portRanges) add(args PortRangeArgs) {
 
155
        p.OpenedPorts_ = append(p.OpenedPorts_, newPortRange(args))
 
156
}
 
157
 
 
158
// UnitName implements PortRange.
 
159
func (p *portRange) UnitName() string {
 
160
        return p.UnitName_
 
161
}
 
162
 
 
163
// FromPort implements PortRange.
 
164
func (p *portRange) FromPort() int {
 
165
        return p.FromPort_
 
166
}
 
167
 
 
168
// ToPort implements PortRange.
 
169
func (p *portRange) ToPort() int {
 
170
        return p.ToPort_
 
171
}
 
172
 
 
173
// Protocol implements PortRange.
 
174
func (p *portRange) Protocol() string {
 
175
        return p.Protocol_
 
176
}
 
177
 
 
178
func importPortRanges(source map[string]interface{}) ([]*portRange, error) {
 
179
        checker := versionedChecker("opened-ports")
 
180
        coerced, err := checker.Coerce(source, nil)
 
181
        if err != nil {
 
182
                return nil, errors.Annotatef(err, "port-range version schema check failed")
 
183
        }
 
184
        valid := coerced.(map[string]interface{})
 
185
 
 
186
        version := int(valid["version"].(int64))
 
187
        importFunc, ok := portRangeDeserializationFuncs[version]
 
188
        if !ok {
 
189
                return nil, errors.NotValidf("version %d", version)
 
190
        }
 
191
        sourceList := valid["opened-ports"].([]interface{})
 
192
        return importPortRangeList(sourceList, importFunc)
 
193
}
 
194
 
 
195
func importPortRangeList(sourceList []interface{}, importFunc portRangeDeserializationFunc) ([]*portRange, error) {
 
196
        result := make([]*portRange, 0, len(sourceList))
 
197
        for i, value := range sourceList {
 
198
                source, ok := value.(map[string]interface{})
 
199
                if !ok {
 
200
                        return nil, errors.Errorf("unexpected value for port-range %d, %T", i, value)
 
201
                }
 
202
                ports, err := importFunc(source)
 
203
                if err != nil {
 
204
                        return nil, errors.Annotatef(err, "port-range %d", i)
 
205
                }
 
206
                result = append(result, ports)
 
207
        }
 
208
        return result, nil
 
209
}
 
210
 
 
211
type portRangeDeserializationFunc func(map[string]interface{}) (*portRange, error)
 
212
 
 
213
var portRangeDeserializationFuncs = map[int]portRangeDeserializationFunc{
 
214
        1: importPortRangeV1,
 
215
}
 
216
 
 
217
func importPortRangeV1(source map[string]interface{}) (*portRange, error) {
 
218
        fields := schema.Fields{
 
219
                "unit-name": schema.String(),
 
220
                "from-port": schema.Int(),
 
221
                "to-port":   schema.Int(),
 
222
                "protocol":  schema.String(),
 
223
        }
 
224
 
 
225
        checker := schema.FieldMap(fields, nil) // no defaults
 
226
 
 
227
        coerced, err := checker.Coerce(source, nil)
 
228
        if err != nil {
 
229
                return nil, errors.Annotatef(err, "port-range v1 schema check failed")
 
230
        }
 
231
        valid := coerced.(map[string]interface{})
 
232
        // From here we know that the map returned from the schema coercion
 
233
        // contains fields of the right type.
 
234
 
 
235
        return &portRange{
 
236
                UnitName_: valid["unit-name"].(string),
 
237
                FromPort_: int(valid["from-port"].(int64)),
 
238
                ToPort_:   int(valid["to-port"].(int64)),
 
239
                Protocol_: valid["protocol"].(string),
 
240
        }, nil
 
241
}