-
Notifications
You must be signed in to change notification settings - Fork 11
/
firewall_state.go
102 lines (78 loc) · 2.72 KB
/
firewall_state.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
package worker
import (
"context"
"encoding/json"
"fmt"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
"github.com/go-logr/logr"
fcmv2 "github.com/metal-stack/firewall-controller-manager/api/v2"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
)
// InfrastructureState represents the last known State of an Infrastructure resource.
// It is saved after a reconciliation and used during restore operations.
// We use this for restoring firewalls, which are actually maintained by the worker controller
// because the worker controller does not allow adding our state to the worker resource as it
// is used by the MCM already.
type InfrastructureState struct {
// Firewalls contains the running firewalls.
Firewalls []string `json:"firewalls"`
}
func (a *actuator) updateState(ctx context.Context, log logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure) error {
patch := client.MergeFrom(infrastructure.DeepCopy())
var (
namespace = infrastructure.Namespace
infraState = &InfrastructureState{}
firewalls = &fcmv2.FirewallList{}
)
err := a.client.List(ctx, firewalls, client.InNamespace(namespace))
if err != nil {
return fmt.Errorf("unable to list firewalls: %w", err)
}
for _, fw := range firewalls.Items {
fw := fw
fw.ResourceVersion = ""
fw.OwnerReferences = nil
fw.Status = fcmv2.FirewallStatus{}
fw.ManagedFields = nil
raw, err := yaml.Marshal(fw)
if err != nil {
return err
}
infraState.Firewalls = append(infraState.Firewalls, string(raw))
}
infraStateBytes, err := json.Marshal(infraState)
if err != nil {
return err
}
infrastructure.Status.State = &runtime.RawExtension{Raw: infraStateBytes}
err = a.client.Status().Patch(ctx, infrastructure, patch)
if err != nil {
return err
}
log.Info("firewall state updated in infrastructure status", "firewalls", len(infraState.Firewalls))
return nil
}
func (a *actuator) restoreState(ctx context.Context, log logr.Logger, infrastructure *extensionsv1alpha1.Infrastructure) error {
infraState := &InfrastructureState{}
err := json.Unmarshal(infrastructure.Status.State.Raw, infraState)
if err != nil {
return fmt.Errorf("unable to decode infrastructure status: %w", err)
}
log.Info("restoring firewalls from infrastructure status", "firewalls", len(infraState.Firewalls))
for _, raw := range infraState.Firewalls {
raw := raw
fw := &fcmv2.Firewall{}
err := yaml.Unmarshal([]byte(raw), fw)
if err != nil {
return err
}
err = a.client.Create(ctx, fw)
if err != nil && !apierrors.IsAlreadyExists(err) {
return fmt.Errorf("unable restoring firewall resource: %w", err)
}
}
return nil
}