This repository has been archived by the owner on Nov 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathresource.go
174 lines (156 loc) · 4.13 KB
/
resource.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package resource
import (
"strings"
yaml "gopkg.in/yaml.v2"
"github.com/weaveworks/flux"
fluxerr "github.com/weaveworks/flux/errors"
"github.com/weaveworks/flux/policy"
"github.com/weaveworks/flux/resource"
)
const (
PolicyPrefix = "flux.weave.works/"
)
// -- unmarshaling code for specific object and field types
// struct to embed in objects, to provide default implementation
type baseObject struct {
source string
bytes []byte
Kind string `yaml:"kind"`
Meta struct {
Namespace string `yaml:"namespace"`
Name string `yaml:"name"`
Annotations map[string]string `yaml:"annotations,omitempty"`
} `yaml:"metadata"`
}
func (o baseObject) ResourceID() flux.ResourceID {
ns := o.Meta.Namespace
if ns == "" {
ns = "default"
}
return flux.MakeResourceID(ns, o.Kind, o.Meta.Name)
}
// It's useful for comparisons in tests to be able to remove the
// record of bytes
func (o *baseObject) debyte() {
o.bytes = nil
}
func (o baseObject) Policy() policy.Set {
set := policy.Set{}
for k, v := range o.Meta.Annotations {
if strings.HasPrefix(k, PolicyPrefix) {
p := strings.TrimPrefix(k, PolicyPrefix)
if v == "true" {
set = set.Add(policy.Policy(p))
} else {
set = set.Set(policy.Policy(p), v)
}
}
}
return set
}
func (o baseObject) Source() string {
return o.source
}
func (o baseObject) Bytes() []byte {
return o.bytes
}
func unmarshalObject(source string, bytes []byte) (resource.Resource, error) {
var base = baseObject{source: source, bytes: bytes}
if err := yaml.Unmarshal(bytes, &base); err != nil {
return nil, err
}
r, err := unmarshalKind(base, bytes)
if err != nil {
return nil, makeUnmarshalObjectErr(source, err)
}
return r, nil
}
func unmarshalKind(base baseObject, bytes []byte) (resource.Resource, error) {
switch base.Kind {
case "CronJob":
var cj = CronJob{baseObject: base}
if err := yaml.Unmarshal(bytes, &cj); err != nil {
return nil, err
}
return &cj, nil
case "DaemonSet":
var ds = DaemonSet{baseObject: base}
if err := yaml.Unmarshal(bytes, &ds); err != nil {
return nil, err
}
return &ds, nil
case "Deployment":
var dep = Deployment{baseObject: base}
if err := yaml.Unmarshal(bytes, &dep); err != nil {
return nil, err
}
return &dep, nil
case "Namespace":
var ns = Namespace{baseObject: base}
if err := yaml.Unmarshal(bytes, &ns); err != nil {
return nil, err
}
return &ns, nil
case "StatefulSet":
var ss = StatefulSet{baseObject: base}
if err := yaml.Unmarshal(bytes, &ss); err != nil {
return nil, err
}
return &ss, nil
case "List":
var raw rawList
if err := yaml.Unmarshal(bytes, &raw); err != nil {
return nil, err
}
var list List
unmarshalList(base, &raw, &list)
return &list, nil
case "FluxHelmRelease", "HelmRelease":
var fhr = FluxHelmRelease{baseObject: base}
if err := yaml.Unmarshal(bytes, &fhr); err != nil {
return nil, err
}
return &fhr, nil
case "":
// If there is an empty resource (due to eg an introduced comment),
// we are returning nil for the resource and nil for an error
// (as not really an error). We are not, at least at the moment,
// reporting an error for invalid non-resource yamls on the
// assumption it is unlikely to happen.
return nil, nil
// The remainder are things we have to care about, but not
// treat specially
default:
return &base, nil
}
}
type rawList struct {
Items []map[string]interface{}
}
func unmarshalList(base baseObject, raw *rawList, list *List) error {
list.baseObject = base
list.Items = make([]resource.Resource, len(raw.Items), len(raw.Items))
for i, item := range raw.Items {
bytes, err := yaml.Marshal(item)
if err != nil {
return err
}
res, err := unmarshalObject(base.source, bytes)
if err != nil {
return err
}
list.Items[i] = res
}
return nil
}
func makeUnmarshalObjectErr(source string, err error) *fluxerr.Error {
return &fluxerr.Error{
Type: fluxerr.User,
Err: err,
Help: `Could not parse "` + source + `".
This likely means it is malformed YAML.
`,
}
}
// For reference, the Kubernetes v1 types are in:
// https://github.com/kubernetes/client-go/blob/master/pkg/api/v1/types.go