/
applicationoffer.go
136 lines (112 loc) · 3.83 KB
/
applicationoffer.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 2019 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package description
import (
"github.com/juju/errors"
"github.com/juju/schema"
)
// ApplicationOffer represents an offer for a an application's endpoints.
type ApplicationOffer interface {
OfferName() string
Endpoints() []string
ACL() map[string]string
}
var _ ApplicationOffer = (*applicationOffer)(nil)
type applicationOffers struct {
Version int `yaml:"version"`
Offers []*applicationOffer `yaml:"offers,omitempty"`
}
type applicationOffer struct {
OfferName_ string `yaml:"offer-name"`
Endpoints_ []string `yaml:"endpoints,omitempty"`
ACL_ map[string]string `yaml:"acl,omitempty"`
}
// OfferName implements ApplicationOffer.
func (o *applicationOffer) OfferName() string {
return o.OfferName_
}
// Endpoints implements ApplicationOffer.
func (o *applicationOffer) Endpoints() []string {
return o.Endpoints_
}
// ACL implements ApplicationOffer. It returns a map were keys are users and
// values are access permissions.
func (o *applicationOffer) ACL() map[string]string {
return o.ACL_
}
// ApplicationOfferArgs is an argument struct used to instanciate a new
// applicationOffer instance that implements ApplicationOffer.
type ApplicationOfferArgs struct {
OfferName string
Endpoints []string
ACL map[string]string
}
func newApplicationOffer(args ApplicationOfferArgs) *applicationOffer {
return &applicationOffer{
OfferName_: args.OfferName,
Endpoints_: args.Endpoints,
ACL_: args.ACL,
}
}
func importApplicationOffers(source map[string]interface{}) ([]*applicationOffer, error) {
checker := versionedChecker("offers")
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, errors.Annotatef(err, "offers version schema check failed")
}
valid := coerced.(map[string]interface{})
version := int(valid["version"].(int64))
importFunc, ok := applicationOfferDeserializationFuncs[version]
if !ok {
return nil, errors.NotValidf("version %d", version)
}
sourceList := valid["offers"].([]interface{})
return importApplicationOfferList(sourceList, importFunc)
}
func importApplicationOfferList(sourceList []interface{}, importFunc applicationOfferDeserializationFunc) ([]*applicationOffer, error) {
result := make([]*applicationOffer, 0, len(sourceList))
for i, value := range sourceList {
source, ok := value.(map[string]interface{})
if !ok {
return nil, errors.Errorf("unexpected value for application offer %d, %T", i, value)
}
offer, err := importFunc(source)
if err != nil {
return nil, errors.Annotatef(err, "application offer %d", i)
}
result = append(result, offer)
}
return result, nil
}
type applicationOfferDeserializationFunc func(interface{}) (*applicationOffer, error)
var applicationOfferDeserializationFuncs = map[int]applicationOfferDeserializationFunc{
1: importApplicationOfferV1,
}
func importApplicationOfferV1(source interface{}) (*applicationOffer, error) {
fields := schema.Fields{
"offer-name": schema.String(),
"endpoints": schema.List(schema.String()),
"acl": schema.Map(schema.String(), schema.String()),
}
checker := schema.FieldMap(fields, nil)
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, errors.Annotatef(err, "application offer v1 schema check failed")
}
valid := coerced.(map[string]interface{})
validEndpoints := valid["endpoints"].([]interface{})
endpoints := make([]string, len(validEndpoints))
for i, ep := range validEndpoints {
endpoints[i] = ep.(string)
}
validACL := valid["acl"].(map[interface{}]interface{})
aclMap := make(map[string]string, len(validACL))
for user, access := range validACL {
aclMap[user.(string)] = access.(string)
}
return &applicationOffer{
OfferName_: valid["offer-name"].(string),
Endpoints_: endpoints,
ACL_: aclMap,
}, nil
}