-
Notifications
You must be signed in to change notification settings - Fork 23
/
secretremoteconsumers.go
138 lines (119 loc) · 3.99 KB
/
secretremoteconsumers.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
// Copyright 2023 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package description
import (
"github.com/juju/errors"
"github.com/juju/names/v5"
"github.com/juju/schema"
)
// SecretRemoteConsumer represents consumer info for a secret remote consumer.
type SecretRemoteConsumer interface {
ID() string
Consumer() (names.Tag, error)
CurrentRevision() int
LatestRevision() int
}
type secretRemoteConsumer struct {
ID_ string `yaml:"id"`
Consumer_ string `yaml:"consumer"`
CurrentRevision_ int `yaml:"current-revision"`
// Updated when added to a secret
// but not exported.
LatestRevision_ int `yaml:"-"`
}
// SecretRemoteConsumerArgs is an argument struct used to create a
// new internal remote secret type that supports the secret remote
// consumer interface.
type SecretRemoteConsumerArgs struct {
ID string
Consumer names.Tag
CurrentRevision int
}
func newSecretRemoteConsumer(args SecretRemoteConsumerArgs) *secretRemoteConsumer {
s := &secretRemoteConsumer{
ID_: args.ID,
CurrentRevision_: args.CurrentRevision,
}
if args.Consumer != nil {
s.Consumer_ = args.Consumer.String()
}
return s
}
// ID implements SecretRemoteConsumer.
func (i *secretRemoteConsumer) ID() string {
return i.ID_
}
// Consumer implements SecretRemoteConsumer.
func (i *secretRemoteConsumer) Consumer() (names.Tag, error) {
if i.Consumer_ == "" {
return nil, nil
}
tag, err := names.ParseTag(i.Consumer_)
if err != nil {
return nil, errors.Trace(err)
}
return tag, nil
}
// CurrentRevision implements SecretRemoteConsumer.
func (i *secretRemoteConsumer) CurrentRevision() int {
return i.CurrentRevision_
}
// LatestRevision implements SecretRemoteConsumer.
func (i *secretRemoteConsumer) LatestRevision() int {
return i.LatestRevision_
}
func importSecretRemoteConsumers(source map[string]interface{}, version int) ([]*secretRemoteConsumer, error) {
importFunc, ok := secretRemoteConsumerDeserializationFuncs[version]
if !ok {
return nil, errors.NotValidf("version %d", version)
}
sourceList, ok := source["remote-consumers"].([]interface{})
if !ok {
return nil, nil
}
return importSecretRemoteConsumersList(sourceList, importFunc)
}
func importSecretRemoteConsumersList(sourceList []interface{}, importFunc secretRemoteConsumerDeserializationFunc) ([]*secretRemoteConsumer, error) {
result := make([]*secretRemoteConsumer, 0, len(sourceList))
for i, consumer := range sourceList {
source, ok := consumer.(map[interface{}]interface{})
if !ok {
return nil, errors.Errorf("unexpected value for consumer %d, %T", i, consumer)
}
consumer, err := importFunc(source)
if err != nil {
return nil, errors.Annotatef(err, "consumer %v", i)
}
result = append(result, consumer)
}
return result, nil
}
type secretRemoteConsumerDeserializationFunc func(map[interface{}]interface{}) (*secretRemoteConsumer, error)
var secretRemoteConsumerDeserializationFuncs = map[int]secretRemoteConsumerDeserializationFunc{
1: importSecretRemoteConsumerV1,
2: importSecretRemoteConsumerV2,
}
func importSecretRemoteConsumerV2(source map[interface{}]interface{}) (*secretRemoteConsumer, error) {
return importSecretRemoteConsumerV1(source)
}
func importSecretRemoteConsumerV1(source map[interface{}]interface{}) (*secretRemoteConsumer, error) {
fields := schema.Fields{
"id": schema.String(),
"consumer": schema.String(),
"current-revision": schema.Int(),
}
checker := schema.FieldMap(fields, schema.Defaults{})
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, errors.Annotatef(err, "secret remote consumers v1 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.
consumer := &secretRemoteConsumer{
ID_: valid["id"].(string),
Consumer_: valid["consumer"].(string),
CurrentRevision_: int(valid["current-revision"].(int64)),
}
return consumer, nil
}