forked from crossplane-contrib/function-auto-ready
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfn.go
97 lines (78 loc) · 3.18 KB
/
fn.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
package main
import (
"context"
corev1 "k8s.io/api/core/v1"
"github.com/crossplane/function-sdk-go/errors"
"github.com/crossplane/function-sdk-go/logging"
fnv1 "github.com/crossplane/function-sdk-go/proto/v1"
"github.com/crossplane/function-sdk-go/request"
"github.com/crossplane/function-sdk-go/resource"
"github.com/crossplane/function-sdk-go/response"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
)
// Function returns whatever response you ask it to.
type Function struct {
fnv1.UnimplementedFunctionRunnerServiceServer
log logging.Logger
}
// RunFunction runs the Function.
func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
f.log.Info("Running Function", "tag", req.GetMeta().GetTag())
rsp := response.To(req, response.DefaultTTL)
oxr, err := request.GetObservedCompositeResource(req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get observed composite resource from %T", req))
return rsp, nil
}
log := f.log.WithValues(
"xr-apiversion", oxr.Resource.GetAPIVersion(),
"xr-kind", oxr.Resource.GetKind(),
"xr-name", oxr.Resource.GetName(),
)
observed, err := request.GetObservedComposedResources(req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get observed composed resources from %T", req))
return rsp, nil
}
desired, err := request.GetDesiredComposedResources(req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get desired composed resources from %T", req))
return rsp, nil
}
f.log.Debug("Found desired resources", "count", len(desired))
// Our goal here is to automatically determine (from the Ready status
// condition) whether existing composed resources are ready.
for name, dr := range desired {
log := log.WithValues("composed-resource-name", name)
// If this desired resource doesn't exist in the observed resources, it
// can't be ready because it doesn't yet exist.
or, ok := observed[name]
if !ok {
log.Debug("Ignoring desired resource that does not appear in observed resources")
continue
}
// A previous Function in the pipeline either said this resource was
// explicitly ready, or explicitly not ready. We only want to
// automatically determine readiness for desired resources where no
// other Function has an opinion about their readiness.
if dr.Ready != resource.ReadyUnspecified {
log.Debug("Ignoring desired resource that already has explicit readiness", "ready", dr.Ready)
continue
}
// Now we know this resource exists, and no Function that ran before us
// has an opinion about whether it's ready.
log.Debug("Found desired resource with unknown readiness")
// If this observed resource has a status condition with type: Ready,
// status: True, we set its readiness to true.
c := or.Resource.GetCondition(xpv1.TypeReady)
if c.Status == corev1.ConditionTrue {
log.Info("Automatically determined that composed resource is ready")
dr.Ready = resource.ReadyTrue
}
}
if err := response.SetDesiredComposedResources(rsp, desired); err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot set desired composed resources from %T", req))
return rsp, nil
}
return rsp, nil
}