Skip to content

Commit

Permalink
Report last seed updated controllerstatus (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 authored Oct 24, 2023
1 parent ac26b7f commit e91b5cc
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ clean:
rm -f bin/*

# Run tests
test:
test: generate manifests
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out

# Build manager binary
Expand Down
8 changes: 6 additions & 2 deletions api/v2/types_firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ const (
FirewallCreated ConditionType = "Created"
// FirewallReady indicates that the firewall is running and and according to the metal-api in a healthy, working state
FirewallReady ConditionType = "Ready"
// FirewallControllerConnected indicates that the firewall-controller running on the firewall is reconciling the firewall resource
// FirewallControllerConnected indicates that the firewall-controller running on the firewall is reconciling the shoot
FirewallControllerConnected ConditionType = "Connected"
// FirewallControllerSeedConnected indicates that the firewall-controller running on the firewall is reconciling the firewall resource
FirewallControllerSeedConnected ConditionType = "SeedConnected"
// FirewallMonitorDeployed indicates that the firewall monitor is deployed into the shoot cluster
FirewallMonitorDeployed ConditionType = "MonitorDeployed"
// FirewallDistanceConfigured indicates that the firewall-controller has configured the given firewall distance.
Expand Down Expand Up @@ -226,8 +228,10 @@ type MachineLastEvent struct {
type ControllerConnection struct {
// ActualVersion is the actual version running at the firewall-controller.
ActualVersion string `json:"actualVersion,omitempty"`
// Updated is a timestamp when the controller has last reconciled the firewall resource.
// Updated is a timestamp when the controller has last reconciled the shoot cluster.
Updated metav1.Time `json:"lastRun,omitempty"`
// SeedUpdated is a timestamp when the controller has last reconciled the firewall resource.
SeedUpdated metav1.Time `json:"lastRunAgainstSeed,omitempty"`
// ActualDistance is the actual distance as reflected by the firewall-controller.
ActualDistance FirewallDistance `json:"actualDistance,omitempty"`
}
Expand Down
1 change: 1 addition & 0 deletions api/v2/types_firewallmonitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type ControllerStatus struct {
ControllerVersion string `json:"controllerVersion,omitempty"`
NftablesExporterVersion string `json:"nftablesExporterVersion,omitempty"`
Updated metav1.Time `json:"lastRun,omitempty"`
SeedUpdated metav1.Time `json:"lastRunAgainstSeed,omitempty"`
Distance FirewallDistance `json:"distance,omitempty"`
DistanceSupported bool `json:"distanceSupported,omitempty"`
}
Expand Down
2 changes: 2 additions & 0 deletions api/v2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions config/crds/firewall.metal-stack.io_firewallmonitors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ spec:
lastRun:
format: date-time
type: string
lastRunAgainstSeed:
format: date-time
type: string
message:
type: string
nftablesExporterVersion:
Expand Down
7 changes: 6 additions & 1 deletion config/crds/firewall.metal-stack.io_firewalls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,12 @@ spec:
type: string
lastRun:
description: Updated is a timestamp when the controller has last
reconciled the firewall resource.
reconciled the shoot cluster.
format: date-time
type: string
lastRunAgainstSeed:
description: SeedUpdated is a timestamp when the controller has
last reconciled the firewall resource.
format: date-time
type: string
type: object
Expand Down
24 changes: 21 additions & 3 deletions controllers/firewall/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ func SetFirewallStatusFromMonitor(fw *v2.Firewall, mon *v2.FirewallMonitor) {
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionTrue, "NotChecking", "Not checking controller connection due to firewall annotation.")
fw.Status.Conditions.Set(cond)

cond = v2.NewCondition(v2.FirewallControllerSeedConnected, v2.ConditionTrue, "NotChecking", "Not checking controller seed connection due to firewall annotation.")
fw.Status.Conditions.Set(cond)

cond = v2.NewCondition(v2.FirewallDistanceConfigured, v2.ConditionTrue, "NotChecking", "Not checking distance due to firewall annotation.")
fw.Status.Conditions.Set(cond)

Expand All @@ -144,22 +147,37 @@ func SetFirewallStatusFromMonitor(fw *v2.Firewall, mon *v2.FirewallMonitor) {
connection := &v2.ControllerConnection{
ActualVersion: mon.ControllerStatus.ControllerVersion,
Updated: mon.ControllerStatus.Updated,
SeedUpdated: mon.ControllerStatus.SeedUpdated,
ActualDistance: mon.ControllerStatus.Distance,
}

fw.Status.ControllerStatus = connection

// Check if the firewall-controller has reconciled the shoot
if connection.Updated.Time.IsZero() {
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionFalse, "NotConnected", "Controller has not yet connected.")
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionFalse, "NotConnected", "Controller has not yet connected to shoot.")
fw.Status.Conditions.Set(cond)
} else if time.Since(connection.Updated.Time) > 5*time.Minute {
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionFalse, "StoppedReconciling", fmt.Sprintf("Controller has stopped reconciling since %s.", connection.Updated.Time.String()))
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionFalse, "StoppedReconciling", fmt.Sprintf("Controller has stopped reconciling since %s to shoot.", connection.Updated.Time.String()))
fw.Status.Conditions.Set(cond)
} else {
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionTrue, "Connected", fmt.Sprintf("Controller reconciled shoot at %s.", connection.Updated.Time.String()))
fw.Status.Conditions.Set(cond)
}

// Check if the firewall-controller has reconciled the firewall
if connection.SeedUpdated.Time.IsZero() {
cond := v2.NewCondition(v2.FirewallControllerSeedConnected, v2.ConditionFalse, "NotConnected", "Controller has not yet connected to seed.")
fw.Status.Conditions.Set(cond)
} else if time.Since(connection.SeedUpdated.Time) > 5*time.Minute {
cond := v2.NewCondition(v2.FirewallControllerSeedConnected, v2.ConditionFalse, "StoppedReconciling", fmt.Sprintf("Controller has stopped reconciling since %s to seed.", connection.SeedUpdated.Time.String()))
fw.Status.Conditions.Set(cond)
} else {
cond := v2.NewCondition(v2.FirewallControllerConnected, v2.ConditionTrue, "Connected", fmt.Sprintf("Controller reconciled firewall at %s.", connection.Updated.Time.String()))
cond := v2.NewCondition(v2.FirewallControllerSeedConnected, v2.ConditionTrue, "Connected", fmt.Sprintf("Controller reconciled firewall at %s.", connection.SeedUpdated.Time.String()))
fw.Status.Conditions.Set(cond)
}

// Check if the firewall-controller has reconciled the distance
if !mon.ControllerStatus.DistanceSupported {
cond := v2.NewCondition(v2.FirewallDistanceConfigured, v2.ConditionTrue, "NotChecking", "Controller does not support distance reconciliation.")
fw.Status.Conditions.Set(cond)
Expand Down
11 changes: 6 additions & 5 deletions controllers/set/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ func (c *controller) setStatus(r *controllers.Ctx[*v2.FirewallSet], ownedFirewal
var (
fw = fw

created = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallCreated)).Status == v2.ConditionTrue
ready = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallReady)).Status == v2.ConditionTrue
connected = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallControllerConnected)).Status == v2.ConditionTrue
distance = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallDistanceConfigured)).Status == v2.ConditionTrue
created = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallCreated)).Status == v2.ConditionTrue
ready = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallReady)).Status == v2.ConditionTrue
connected = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallControllerConnected)).Status == v2.ConditionTrue
seedConnected = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallControllerSeedConnected)).Status == v2.ConditionTrue
distance = pointer.SafeDeref(fw.Status.Conditions.Get(v2.FirewallDistanceConfigured)).Status == v2.ConditionTrue
)

if created && ready && connected && distance {
if created && ready && connected && seedConnected && distance {
r.Target.Status.ReadyReplicas++
continue
}
Expand Down
41 changes: 37 additions & 4 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ var _ = Context("integration test", Ordered, func() {
Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mon), mon)).To(Succeed()) // refetch
mon.ControllerStatus = &v2.ControllerStatus{
Updated: metav1.NewTime(time.Now()),
SeedUpdated: metav1.NewTime(time.Now()),
Distance: v2.FirewallShortestDistance,
DistanceSupported: true,
}
Expand Down Expand Up @@ -307,9 +308,18 @@ var _ = Context("integration test", Ordered, func() {
Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", mon.ControllerStatus.Updated.Time.String())))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled shoot at %s.", mon.ControllerStatus.Updated.Time.String())))
})
It("should have the firewall-controller connected to seed condition true", func() {
cond := testcommon.WaitForCondition(k8sClient, ctx, fw.DeepCopy(), func(fd *v2.Firewall) v2.Conditions {
return fd.Status.Conditions
}, v2.FirewallControllerSeedConnected, v2.ConditionTrue, 15*time.Second)

Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", mon.ControllerStatus.SeedUpdated.Time.String())))
})
It("should have configured the distance", func() {
cond := testcommon.WaitForCondition(k8sClient, ctx, fw.DeepCopy(), func(fd *v2.Firewall) v2.Conditions {
return fd.Status.Conditions
Expand Down Expand Up @@ -735,6 +745,7 @@ var _ = Context("integration test", Ordered, func() {
// simulating a firewall-controller updating the resource
mon.ControllerStatus = &v2.ControllerStatus{
Updated: metav1.NewTime(time.Now()),
SeedUpdated: metav1.NewTime(time.Now()),
Distance: v2.FirewallRollingUpdateSetDistance,
DistanceSupported: true,
}
Expand Down Expand Up @@ -779,7 +790,7 @@ var _ = Context("integration test", Ordered, func() {
Expect(set.Status.ObservedRevision).To(Equal(1))
})

Context("the update is finalizes", func() {
Context("the update is finalized", func() {
It("should populate the controller status field in the firewall resource", func() {
var fw = fw.DeepCopy()
Eventually(func() *v2.ControllerConnection {
Expand Down Expand Up @@ -909,6 +920,7 @@ var _ = Context("integration test", Ordered, func() {
Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mon), mon)).To(Succeed()) // refetch
mon.ControllerStatus = &v2.ControllerStatus{
Updated: metav1.NewTime(time.Now()),
SeedUpdated: metav1.NewTime(time.Now()),
Distance: v2.FirewallShortestDistance,
DistanceSupported: true,
}
Expand Down Expand Up @@ -992,9 +1004,18 @@ var _ = Context("integration test", Ordered, func() {
Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", mon.ControllerStatus.Updated.Time.String())))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled shoot at %s.", mon.ControllerStatus.Updated.Time.String())))
})
It("should have the firewall-controller connected to seed condition true", func() {
cond := testcommon.WaitForCondition(k8sClient, ctx, fw.DeepCopy(), func(fd *v2.Firewall) v2.Conditions {
return fd.Status.Conditions
}, v2.FirewallControllerSeedConnected, v2.ConditionTrue, 15*time.Second)

Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", mon.ControllerStatus.SeedUpdated.Time.String())))
})
It("should have configured the distance", func() {
cond := testcommon.WaitForCondition(k8sClient, ctx, fw.DeepCopy(), func(fd *v2.Firewall) v2.Conditions {
return fd.Status.Conditions
Expand Down Expand Up @@ -1257,6 +1278,7 @@ var _ = Context("integration test", Ordered, func() {
// simulating a firewall-controller updating the resource
newMon.ControllerStatus = &v2.ControllerStatus{
Updated: metav1.NewTime(time.Now()),
SeedUpdated: metav1.NewTime(time.Now()),
Distance: v2.FirewallShortestDistance,
DistanceSupported: true,
}
Expand Down Expand Up @@ -1341,7 +1363,18 @@ var _ = Context("integration test", Ordered, func() {
Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", newMon.ControllerStatus.Updated.Time.String())))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled shoot at %s.", newMon.ControllerStatus.Updated.Time.String())))
})

It("should have the firewall-controller connected to seed condition true", func() {
cond := testcommon.WaitForCondition(k8sClient, ctx, newFw.DeepCopy(), func(fd *v2.Firewall) v2.Conditions {
return fd.Status.Conditions
}, v2.FirewallControllerSeedConnected, v2.ConditionTrue, 15*time.Second)

Expect(cond.LastTransitionTime).NotTo(BeZero())
Expect(cond.LastUpdateTime).NotTo(BeZero())
Expect(cond.Reason).To(Equal("Connected"))
Expect(cond.Message).To(Equal(fmt.Sprintf("Controller reconciled firewall at %s.", newMon.ControllerStatus.SeedUpdated.Time.String())))
})

It("should have firewall networks populated", func() {
Expand Down

0 comments on commit e91b5cc

Please sign in to comment.