-
Notifications
You must be signed in to change notification settings - Fork 26
/
connection.go
80 lines (69 loc) · 3 KB
/
connection.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
package main
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/json"
"github.com/crossplane/crossplane-runtime/pkg/errors"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane-contrib/function-patch-and-transform/input/v1beta1"
)
// ConnectionDetailsExtractor extracts the connection details of a resource.
type ConnectionDetailsExtractor interface {
// ExtractConnection of the supplied resource.
ExtractConnection(cd resource.Composed, conn managed.ConnectionDetails, cfg ...v1beta1.ConnectionDetail) (managed.ConnectionDetails, error)
}
// A ConnectionDetailsExtractorFn is a function that satisfies
// ConnectionDetailsExtractor.
type ConnectionDetailsExtractorFn func(cd resource.Composed, conn managed.ConnectionDetails, cfg ...v1beta1.ConnectionDetail) (managed.ConnectionDetails, error)
// ExtractConnection of the supplied resource.
func (fn ConnectionDetailsExtractorFn) ExtractConnection(cd resource.Composed, conn managed.ConnectionDetails, cfg ...v1beta1.ConnectionDetail) (managed.ConnectionDetails, error) {
return fn(cd, conn, cfg...)
}
// ExtractConnectionDetails extracts XR connection details from the supplied
// composed resource. If no ExtractConfigs are supplied no connection details
// will be returned.
func ExtractConnectionDetails(cd resource.Composed, data managed.ConnectionDetails, cfgs ...v1beta1.ConnectionDetail) (managed.ConnectionDetails, error) {
out := map[string][]byte{}
for _, cfg := range cfgs {
if err := ValidateConnectionDetail(cfg); err != nil {
return nil, errors.Wrap(err, "invalid")
}
switch cfg.Type {
case v1beta1.ConnectionDetailTypeFromValue:
out[cfg.Name] = []byte(*cfg.Value)
case v1beta1.ConnectionDetailTypeFromConnectionSecretKey:
if data[*cfg.FromConnectionSecretKey] == nil {
// We don't consider this an error because it's possible the
// key will still be written at some point in the future.
continue
}
out[cfg.Name] = data[*cfg.FromConnectionSecretKey]
case v1beta1.ConnectionDetailTypeFromFieldPath:
// Note we're checking that the error _is_ nil. If we hit an error
// we silently avoid including this connection secret. It's possible
// the path will start existing with a valid value in future.
if b, err := fromFieldPath(cd, *cfg.FromFieldPath); err == nil {
out[cfg.Name] = b
}
}
}
return out, nil
}
// fromFieldPath tries to read the value from the supplied field path first as a
// plain string. If this fails, it falls back to reading it as JSON.
func fromFieldPath(from runtime.Object, path string) ([]byte, error) {
fromMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(from)
if err != nil {
return nil, err
}
str, err := fieldpath.Pave(fromMap).GetString(path)
if err == nil {
return []byte(str), nil
}
in, err := fieldpath.Pave(fromMap).GetValue(path)
if err != nil {
return nil, err
}
return json.Marshal(in)
}