Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Go 1.24
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
go-version-file: 'go.mod'
cache: false

- name: Lint
uses: golangci/golangci-lint-action@v7
uses: golangci/golangci-lint-action@v9
with:
args: --build-tags integration --timeout=10m

Expand All @@ -65,12 +65,13 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Go 1.24
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
go-version-file: 'go.mod'
cache: false

- name: Test
run: |
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the firewall-controller-manager binary
FROM golang:1.24 AS builder
FROM golang:1.26 AS builder

WORKDIR /work
COPY . .
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.21
FROM alpine:3.23
COPY bin/firewall-controller-manager /firewall-controller-manager
USER 65534
ENTRYPOINT ["/firewall-controller-manager"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ GITVERSION := $(shell git describe --long --all)
BUILDDATE := $(shell date -Iseconds)
VERSION := $(or ${VERSION},$(shell git describe --tags --exact-match 2> /dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD))

CONTROLLER_TOOLS_VERSION ?= v0.14.0
CONTROLLER_TOOLS_VERSION ?= v0.20.0
LOCALBIN ?= $(shell pwd)/bin
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ kubectl annotate fwmon <firewall-name> firewall.metal-stack.io/roll-set=true

## Development

Most of the functionality is developed with the help of the [intgration](integration) test suite.
Most of the functionality is developed with the help of the [integration](integration) test suite.

To play with the FCM, you can also run this controller inside the [mini-lab](https://github.com/metal-stack/mini-lab) and without a running Gardener installation:

Expand Down
32 changes: 8 additions & 24 deletions api/v2/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/metal-stack/firewall-controller-manager/api/v2/helper"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
Expand All @@ -26,21 +25,21 @@ type (
}
firewallSetDefaulter struct {
c *config.ControllerConfig
fd *firewallDefaulter
fd admission.Defaulter[*v2.Firewall]
log logr.Logger
}
firewallDeploymentDefaulter struct {
c *config.ControllerConfig
fd *firewallDefaulter
fd admission.Defaulter[*v2.Firewall]
log logr.Logger
}
)

func NewFirewallDefaulter(log logr.Logger, c *config.ControllerConfig) (*firewallDefaulter, error) {
func NewFirewallDefaulter(log logr.Logger, c *config.ControllerConfig) (admission.Defaulter[*v2.Firewall], error) {
return &firewallDefaulter{log: log, c: c}, nil
}

func NewFirewallSetDefaulter(log logr.Logger, c *config.ControllerConfig) (admission.CustomDefaulter, error) {
func NewFirewallSetDefaulter(log logr.Logger, c *config.ControllerConfig) (admission.Defaulter[*v2.FirewallSet], error) {
fd, err := NewFirewallDefaulter(log, c)
if err != nil {
return nil, err
Expand All @@ -49,7 +48,7 @@ func NewFirewallSetDefaulter(log logr.Logger, c *config.ControllerConfig) (admis
return &firewallSetDefaulter{log: log, c: c, fd: fd}, nil
}

func NewFirewallDeploymentDefaulter(log logr.Logger, c *config.ControllerConfig) (admission.CustomDefaulter, error) {
func NewFirewallDeploymentDefaulter(log logr.Logger, c *config.ControllerConfig) (admission.Defaulter[*v2.FirewallDeployment], error) {
fd, err := NewFirewallDefaulter(log, c)
if err != nil {
return nil, err
Expand All @@ -58,25 +57,15 @@ func NewFirewallDeploymentDefaulter(log logr.Logger, c *config.ControllerConfig)
return &firewallDeploymentDefaulter{log: log, c: c, fd: fd}, nil
}

func (r *firewallDefaulter) Default(ctx context.Context, obj runtime.Object) error {
f, ok := obj.(*v2.Firewall)
if !ok {
return fmt.Errorf("mutator received unexpected type: %T", obj)
}

func (r *firewallDefaulter) Default(ctx context.Context, f *v2.Firewall) error {
r.log.Info("defaulting firewall resource", "name", f.GetName(), "namespace", f.GetNamespace())

defaultFirewallSpec(&f.Spec)

return nil
}

func (r *firewallSetDefaulter) Default(ctx context.Context, obj runtime.Object) error {
f, ok := obj.(*v2.FirewallSet)
if !ok {
return fmt.Errorf("mutator received unexpected type: %T", obj)
}

func (r *firewallSetDefaulter) Default(ctx context.Context, f *v2.FirewallSet) error {
r.log.Info("defaulting firewallset resource", "name", f.GetName(), "namespace", f.GetNamespace())

if f.Spec.Selector == nil {
Expand All @@ -88,12 +77,7 @@ func (r *firewallSetDefaulter) Default(ctx context.Context, obj runtime.Object)
return nil
}

func (r *firewallDeploymentDefaulter) Default(ctx context.Context, obj runtime.Object) error {
f, ok := obj.(*v2.FirewallDeployment)
if !ok {
return fmt.Errorf("mutator received unexpected type: %T", obj)
}

func (r *firewallDeploymentDefaulter) Default(ctx context.Context, f *v2.FirewallDeployment) error {
r.log.Info("defaulting firewalldeployment resource", "name", f.GetName(), "namespace", f.GetNamespace())

if f.Spec.Strategy == "" {
Expand Down
1 change: 0 additions & 1 deletion api/v2/defaults/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ package defaults
// },
// }
// for _, tt := range tests {
// tt := tt
// t.Run(tt.name, func(t *testing.T) {
// r, err := NewFirewallDeploymentDefaulter(&DefaulterConfig{
// Log: testr.New(t),
Expand Down
5 changes: 2 additions & 3 deletions api/v2/defaults/userdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"

"github.com/flatcar/container-linux-config-transpiler/config/types"
"github.com/metal-stack/metal-lib/pkg/pointer"
)

const (
Expand All @@ -24,12 +23,12 @@ func renderUserdata(kubeconfig, seedKubeconfig []byte) (string, error) {
{
Name: fmt.Sprintf("%s.service", FirewallControllerName),
Enable: true,
Enabled: pointer.Pointer(true),
Enabled: new(true),
},
{
Name: fmt.Sprintf("%s.service", DroptailerClientName),
Enable: true,
Enabled: pointer.Pointer(true),
Enabled: new(true),
},
},
},
Expand Down
4 changes: 1 addition & 3 deletions api/v2/helper/shoot_access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ users:
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
h := NewShootAccessHelper(tt.seed, tt.access)
got, err := h.RESTConfig(context.Background())
Expand Down Expand Up @@ -90,14 +89,13 @@ contexts:
name: shoot-name
current-context: shoot-name
kind: Config
preferences: {}
users:
- name: shoot-name
user:
token: /var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/token
`))
require.NoError(t, err)
assert.True(t, equal)
assert.True(t, equal, string(gotRaw))
})
}
}
10 changes: 0 additions & 10 deletions api/v2/types_annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,6 @@ func TestAddAnnotation(t *testing.T) {
value: "true",
wantErr: nil,
want: &Firewall{
TypeMeta: v1.TypeMeta{
Kind: "Firewall",
APIVersion: "firewall.metal-stack.io/v2",
},
ObjectMeta: v1.ObjectMeta{
Name: "test",
ResourceVersion: "1",
Expand Down Expand Up @@ -279,10 +275,6 @@ func TestRemoveAnnotation(t *testing.T) {
key: "test",
wantErr: nil,
want: &Firewall{
TypeMeta: v1.TypeMeta{
Kind: "Firewall",
APIVersion: "firewall.metal-stack.io/v2",
},
ObjectMeta: v1.ObjectMeta{
Name: "test",
ResourceVersion: "1",
Expand Down Expand Up @@ -348,7 +340,6 @@ func Test_annotationWasRemoved(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if got := annotationWasRemoved(event.UpdateEvent{
ObjectOld: &Firewall{
Expand Down Expand Up @@ -406,7 +397,6 @@ func Test_annotationWasAdded(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if got := annotationWasAdded(event.UpdateEvent{
ObjectOld: &Firewall{
Expand Down
1 change: 0 additions & 1 deletion api/v2/types_firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ func Test_SortFirewallsByImportance(t *testing.T) {
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
SortFirewallsByImportance(tt.fws)

Expand Down
101 changes: 0 additions & 101 deletions api/v2/validation/common.go
Original file line number Diff line number Diff line change
@@ -1,110 +1,11 @@
package validation

import (
"context"
"fmt"
"reflect"

"github.com/go-logr/logr"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
apivalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

type genericValidation[O client.Object] interface {
ValidateCreate(log logr.Logger, obj O) field.ErrorList
ValidateUpdate(log logr.Logger, old, new O) field.ErrorList
}

type genericValidator[O client.Object, V genericValidation[O]] struct {
log logr.Logger
}

func (g *genericValidator[O, V]) Instance() V {
var v V
return v
}

func (g *genericValidator[O, V]) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
var (
v = g.Instance()
o, ok = obj.(O)
allErrs field.ErrorList
)

if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("validator received unexpected type: %T", obj))
}

accessor, err := meta.Accessor(obj)
if err != nil {
return nil, apierrors.NewBadRequest(fmt.Sprintf("failed to get accessor for object: %s", err))
}

g.log.Info("validating resource creation", "name", accessor.GetName(), "namespace", accessor.GetNamespace())

allErrs = append(allErrs, apivalidation.ValidateObjectMetaAccessor(accessor, true, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))...)
allErrs = append(allErrs, v.ValidateCreate(g.log, o)...)

if len(allErrs) == 0 {
return nil, nil
}

return nil, apierrors.NewInvalid(
obj.GetObjectKind().GroupVersionKind().GroupKind(),
accessor.GetName(),
allErrs,
)
}

func (g *genericValidator[O, V]) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
var (
v = g.Instance()
oldO, oldOk = oldObj.(O)
newO, newOk = newObj.(O)
allErrs field.ErrorList
)

if !oldOk {
return nil, apierrors.NewBadRequest(fmt.Sprintf("validator received unexpected type: %T", oldO))
}
if !newOk {
return nil, apierrors.NewBadRequest(fmt.Sprintf("validator received unexpected type: %T", newO))
}

oldAccessor, err := meta.Accessor(oldO)
if err != nil {
return nil, apierrors.NewBadRequest(fmt.Sprintf("failed to get accessor for object: %s", err))
}
newAccessor, err := meta.Accessor(newO)
if err != nil {
return nil, apierrors.NewBadRequest(fmt.Sprintf("failed to get accessor for object: %s", err))
}

g.log.Info("validating resource update", "name", newAccessor.GetName(), "namespace", newAccessor.GetNamespace())

allErrs = append(allErrs, apivalidation.ValidateObjectMetaAccessorUpdate(newAccessor, oldAccessor, field.NewPath("metadata"))...)
allErrs = append(allErrs, v.ValidateUpdate(g.log, oldO, newO)...)

if len(allErrs) == 0 {
return nil, nil
}

return nil, apierrors.NewInvalid(
newO.GetObjectKind().GroupVersionKind().GroupKind(),
newAccessor.GetName(),
allErrs,
)
}

func (_ *genericValidator[O, V]) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
return nil, nil
}

type (
requiredFields []*requiredField
requiredField struct {
Expand All @@ -117,8 +18,6 @@ func (rs requiredFields) check() field.ErrorList {
var allErrs field.ErrorList

for _, r := range rs {
r := r

if reflect.ValueOf(r.value).IsZero() {
allErrs = append(allErrs, field.Required(r.path, "field is required"))
}
Expand Down
Loading