/
cf_host.go
132 lines (116 loc) · 3.99 KB
/
cf_host.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
package cf
import (
ar "github.com/Apicurio/apicurio-registry-operator/api/v1"
"github.com/Apicurio/apicurio-registry-operator/controllers/loop"
"github.com/Apicurio/apicurio-registry-operator/controllers/loop/context"
"github.com/Apicurio/apicurio-registry-operator/controllers/loop/services"
"github.com/Apicurio/apicurio-registry-operator/controllers/svc/resources"
"github.com/Apicurio/apicurio-registry-operator/controllers/svc/status"
networking "k8s.io/api/networking/v1"
)
var _ loop.ControlFunction = &HostCF{}
type HostCF struct {
ctx context.LoopContext
svcResourceCache resources.ResourceCache
svcStatus *status.Status
ingressEntry resources.ResourceCacheEntry
ingressExists bool
serviceName string
existingHost string
targetHost string
}
// This CF makes sure number of host is aligned
// If there is some other way of determining the number of host needed outside of CR,
// modify the Sense stage so this CF knows about it
func NewHostCF(ctx context.LoopContext, services services.LoopServices) loop.ControlFunction {
return &HostCF{
ctx: ctx,
svcResourceCache: ctx.GetResourceCache(),
svcStatus: services.GetStatus(),
ingressEntry: nil,
ingressExists: false,
serviceName: resources.RC_NOT_CREATED_NAME_EMPTY,
existingHost: "",
targetHost: "",
}
}
func (this *HostCF) Describe() string {
return "HostCF"
}
func (this *HostCF) Sense() {
// Observation #1
// Get the cached Ingress (if it exists and/or the value)
ingressEntry, ingressExists := this.svcResourceCache.Get(resources.RC_KEY_INGRESS)
this.ingressEntry = ingressEntry
this.ingressExists = ingressExists
// Observation #2
// Is there a Service already? It must have been created (has a name)
serviceEntry, serviceExists := this.svcResourceCache.Get(resources.RC_KEY_SERVICE)
if serviceExists {
this.serviceName = serviceEntry.GetName().Str() // TODO this may still end up empty, refactor?
} else {
this.serviceName = resources.RC_NOT_CREATED_NAME_EMPTY
}
// Observation #3
// Get the existing host (if present)
this.existingHost = resources.RC_NOT_CREATED_NAME_EMPTY
if this.ingressExists && this.serviceName != resources.RC_NOT_CREATED_NAME_EMPTY {
this.existingHost = readHost(this.serviceName, this.ingressEntry.GetValue().(*networking.Ingress))
}
// Observation #4
// Get target host
if specEntry, exists := this.svcResourceCache.Get(resources.RC_KEY_SPEC); exists {
this.targetHost = specEntry.GetValue().(*ar.ApicurioRegistry).Spec.Deployment.Host
}
// Update state
this.svcStatus.SetConfig(status.CFG_STA_ROUTE, this.existingHost)
}
func (this *HostCF) Compare() bool {
// Condition #1
// Ingress exists
// Condition #2
// Service exists & is created
// Condition #3
// Existing host is not the same as the target host (assuming it is never empty)
// Condition #4
// Host must not be empty
return this.ingressEntry != nil &&
this.serviceName != resources.RC_NOT_CREATED_NAME_EMPTY &&
this.existingHost != this.targetHost &&
this.targetHost != ""
}
func (this *HostCF) Respond() {
// Response #1
// Patch the resource
this.ingressEntry.ApplyPatch(func(value interface{}) interface{} {
ingress := value.(*networking.Ingress).DeepCopy()
writeHost(this.serviceName, ingress, this.targetHost)
return ingress
})
}
func (this *HostCF) Cleanup() bool {
// No cleanup
return true
}
func readHost(serviceName string, ingress *networking.Ingress) string {
for _, rule := range ingress.Spec.Rules {
for _, path := range rule.HTTP.Paths {
if path.Backend.Service.Name == serviceName {
return rule.Host
}
}
}
return resources.RC_NOT_CREATED_NAME_EMPTY
}
func writeHost(serviceName string, ingress *networking.Ingress, host string) {
for i, rule := range ingress.Spec.Rules {
for _, path := range rule.HTTP.Paths {
if path.Backend.Service.Name == serviceName {
ingress.Spec.Rules[i] = networking.IngressRule{
Host: host,
IngressRuleValue: rule.IngressRuleValue,
}
}
}
}
}