Skip to content

Commit

Permalink
Add breaking labeling to release drafter configuration (#188)
Browse files Browse the repository at this point in the history
* Add `breaking` labeling to release drafter configuration

* Add golangci-lint configuration

* Fix linting issues

* Fix linting issues
  • Loading branch information
afritzler committed Sep 25, 2024
1 parent a07c2c0 commit e8ccf83
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 138 deletions.
6 changes: 6 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
categories:
- title: '⚠️ Breaking'
labels:
- 'breaking'
- title: '🚀 Features'
labels:
- 'feature'
Expand Down Expand Up @@ -51,6 +54,9 @@ autolabeler:
- label: 'enhancement'
branch:
- '/enh\/.+/'
- label: 'chore'
branch:
- '/chore\/.+/'
template: |
## Changes
$CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Lint Golang Codebase
name: Lint

on:
pull_request:
Expand All @@ -14,6 +14,7 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- uses: golangci/golangci-lint-action@v6
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.61
42 changes: 42 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
run:
timeout: 10m
allow-parallel-runners: true

issues:
# don't skip warning about doc comments
# don't exclude the default set of lint
exclude-use-default: false
# restore some of the defaults
# (fill in the rest as needed)
exclude-rules:
- path: "plugins/*"
linters:
- dupl
- lll
- path: "internal/*"
linters:
- dupl
- lll
linters:
disable-all: true
enable:
- copyloopvar
- dupl
- errcheck
- goconst
- gocyclo
- gofmt
- goimports
- gosimple
- govet
- ineffassign
- ginkgolinter
- lll
- misspell
- nakedret
- prealloc
- staticcheck
- typecheck
- unconvert
- unparam
- unused
2 changes: 1 addition & 1 deletion .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Source: https://github.com/ironcore-dev/FeDHCP
Files:
.github/*
.gitignore
.golangci.yaml
.golangci.yml
Dockerfile
Makefile
config/*
Expand Down
2 changes: 1 addition & 1 deletion internal/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ package kubernetes

import (
"fmt"
"k8s.io/client-go/rest"

ipamv1alpha1 "github.com/ironcore-dev/ipam/api/ipam/v1alpha1"
metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package main
import (
"flag"
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
"os"

"github.com/coredhcp/coredhcp/config"
Expand Down Expand Up @@ -35,6 +34,7 @@ import (
"github.com/ironcore-dev/fedhcp/plugins/onmetal"
"github.com/ironcore-dev/fedhcp/plugins/oob"
"github.com/ironcore-dev/fedhcp/plugins/pxeboot"
"k8s.io/apimachinery/pkg/util/sets"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)
Expand Down
4 changes: 3 additions & 1 deletion plugins/httpboot/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ func fetchUKIURL(url string, clientIPs []string) (string, error) {
log.Errorf("HTTP request failed: %v", err)
return "", err
}
defer resp.Body.Close()
defer func() {
_ = resp.Body.Close()
}()

body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down
117 changes: 44 additions & 73 deletions plugins/httpboot/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ import (
"testing"
"time"

"github.com/insomniacslk/dhcp/iana"

"github.com/insomniacslk/dhcp/dhcpv4"

"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/insomniacslk/dhcp/iana"
)

const (
Expand Down Expand Up @@ -221,13 +219,19 @@ func TestHTTPBootNotRequested6(t *testing.T) {
req.MessageType = dhcpv6.MessageTypeRequest
req.AddOption(dhcpv6.OptRequestedOption(dhcpv6.OptionBootfileURL))

// known LinkAddr
relayedRequest, err := dhcpv6.EncapsulateRelay(req, dhcpv6.MessageTypeRelayForward, net.IPv6loopback, net.IPv6loopback)
if err != nil {
t.Fatal(err)
}

stub, err := dhcpv6.NewMessage()
if err != nil {
t.Fatal(err)
}
stub.MessageType = dhcpv6.MessageTypeReply

resp, stop := handler6(req, stub)
resp, stop := handler6(relayedRequest, stub)
if resp == nil {
t.Fatal("plugin did not return a message")
}
Expand Down Expand Up @@ -285,7 +289,10 @@ func TestHTTPBootNotRelayedMsg6(t *testing.T) {
func TestGenericHTTPBootRequested4(t *testing.T) {
Init4(expectedGenericBootURL)

req, err := dhcpv4.NewDiscovery(net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier))
req, err := dhcpv4.NewDiscovery(net.HardwareAddr{
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier),
)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -320,7 +327,10 @@ func TestGenericHTTPBootRequested4(t *testing.T) {
func TestMalformedHTTPBootRequested4(t *testing.T) {
Init4(expectedGenericBootURL)

req, err := dhcpv4.NewDiscovery(net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier))
req, err := dhcpv4.NewDiscovery(net.HardwareAddr{
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier),
)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -385,7 +395,10 @@ func TestMalformedHTTPBootRequested4(t *testing.T) {
func TestHTTPBootNotRequested4(t *testing.T) {
Init4(expectedGenericBootURL)

req, err := dhcpv4.NewDiscovery(net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier))
req, err := dhcpv4.NewDiscovery(net.HardwareAddr{
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
dhcpv4.WithRequestedOptions(dhcpv4.OptionClassIdentifier),
)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -489,30 +502,18 @@ func TestCustomHTTPBootRequestedKnownIP(t *testing.T) {
}

func TestCustomHTTPBootRequestedKnownMAC(t *testing.T) {
Init6(fmt.Sprintf(bootServiceEndpoint, bootServicePort))
req, err := dhcpv6.NewMessage()
if err != nil {
t.Fatal(err)
}
req.MessageType = dhcpv6.MessageTypeRequest
req.AddOption(dhcpv6.OptRequestedOption(dhcpv6.OptionBootfileURL))
optVendorClass := dhcpv6.OptVendorClass{}
buf := []byte{
0, 0, 5, 57, // nice "random" enterprise number, can be ignored
0, 10, // length ot vendor class
'H', 'T', 'T', 'P', 'C', 'l', 'i', 'e', 'n', 't', // vendor class
}
_ = optVendorClass.FromBytes(buf)
req.UpdateOption(&optVendorClass)
// known LinkLayerAddress
macAddress, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff")

// not known LinkAddr
relayedRequest, err := dhcpv6.EncapsulateRelay(req, dhcpv6.MessageTypeRelayForward, net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, net.IPv6loopback)
err, relayedRequest := createHTTPBootRequest(t)
if err != nil {
t.Fatal(err)
}

// known LinkLayerAddress
macAddress, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff")
ensureBootURL(t, macAddress, relayedRequest, expectedCustomBootURL)
}

func ensureBootURL(t *testing.T, macAddress net.HardwareAddr, relayedRequest *dhcpv6.RelayMessage, expectedBootURL string) {
opt := dhcpv6.OptClientLinkLayerAddress(iana.HWTypeEthernet, macAddress)
relayedRequest.AddOption(opt)

Expand All @@ -536,8 +537,8 @@ func TestCustomHTTPBootRequestedKnownMAC(t *testing.T) {
}

bootFileURL := resp.(*dhcpv6.Message).Options.BootFileURL()
if bootFileURL != expectedCustomBootURL {
t.Errorf("Found BootFileURL %s, expected %s", bootFileURL, expectedCustomBootURL)
if bootFileURL != expectedBootURL {
t.Errorf("Found BootFileURL %s, expected %s", bootFileURL, expectedBootURL)
}

opts = resp.GetOption(dhcpv6.OptionVendorClass)
Expand All @@ -557,6 +558,18 @@ func TestCustomHTTPBootRequestedKnownMAC(t *testing.T) {
}

func TestCustomHTTPBootRequestedUnknownClient(t *testing.T) {
// not known LinkLayerAddress
macAddress, _ := net.ParseMAC("11:22:33:44:55:66")

err, relayedRequest := createHTTPBootRequest(t)
if err != nil {
t.Fatal(err)
}

ensureBootURL(t, macAddress, relayedRequest, expectedDefaultCustomBootURL)
}

func createHTTPBootRequest(t *testing.T) (error, *dhcpv6.RelayMessage) {
Init6(fmt.Sprintf(bootServiceEndpoint, bootServicePort))
req, err := dhcpv6.NewMessage()
if err != nil {
Expand All @@ -574,54 +587,12 @@ func TestCustomHTTPBootRequestedUnknownClient(t *testing.T) {
req.UpdateOption(&optVendorClass)

// not known LinkAddr
relayedRequest, err := dhcpv6.EncapsulateRelay(req, dhcpv6.MessageTypeRelayForward, net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, net.IPv6loopback)
if err != nil {
t.Fatal(err)
}

// not known LinkLayerAddress
macAddress, _ := net.ParseMAC("11:22:33:44:55:66")
opt := dhcpv6.OptClientLinkLayerAddress(iana.HWTypeEthernet, macAddress)
relayedRequest.AddOption(opt)

stub, err := dhcpv6.NewMessage()
relayedRequest, err := dhcpv6.EncapsulateRelay(req, dhcpv6.MessageTypeRelayForward,
net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, net.IPv6loopback)
if err != nil {
t.Fatal(err)
}
stub.MessageType = dhcpv6.MessageTypeReply

resp, stop := handler6(relayedRequest, stub)
if resp == nil {
t.Fatal("plugin did not return a message")
}
if stop {
t.Error("plugin interrupted processing, but it shouldn't have")
}

opts := resp.GetOption(dhcpv6.OptionBootfileURL)
if len(opts) != optionEnabled {
t.Fatalf("Expected %d BootFileUrl option, got %d: %v", optionEnabled, len(opts), opts)
}

bootFileURL := resp.(*dhcpv6.Message).Options.BootFileURL()
if bootFileURL != expectedDefaultCustomBootURL {
t.Errorf("Found BootFileURL %s, expected %s", bootFileURL, expectedDefaultCustomBootURL)
}

opts = resp.GetOption(dhcpv6.OptionVendorClass)
if len(opts) != optionEnabled {
t.Fatalf("Expected %d VendorClass option, got %d: %v", optionEnabled, len(opts), opts)
}

vc := resp.(*dhcpv6.Message).Options.VendorClasses()[0]
if vc.EnterpriseNumber != expectedEnterpriseNumber {
t.Errorf("Found EnterpriseNumber %d, expected %d", vc.EnterpriseNumber, expectedEnterpriseNumber)
}

vcData := resp.(*dhcpv6.Message).Options.VendorClass(vc.EnterpriseNumber)
if !bytes.Equal(vcData[0], expectedHTTPClient) {
t.Errorf("Found VendorClass %x, expected %x", vcData[0], expectedHTTPClient)
}
return err, relayedRequest
}

func TestNoRelayCustomHTTPBootRequested(t *testing.T) {
Expand Down
22 changes: 15 additions & 7 deletions plugins/ipam/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/ironcore-dev/fedhcp/internal/kubernetes"
"net"
"os"
"reflect"
"strings"

"github.com/ironcore-dev/fedhcp/internal/kubernetes"
ipamv1alpha1 "github.com/ironcore-dev/ipam/api/ipam/v1alpha1"
ipam "github.com/ironcore-dev/ipam/clientgo/ipam"
"github.com/pkg/errors"
Expand Down Expand Up @@ -135,7 +135,10 @@ func (k K8sClient) getMatchingSubnet(subnetName string, ipaddr net.IP) (*ipamv1a
return subnet, nil
}

func (k K8sClient) prepareCreateIpamIP(subnetName string, ipaddr net.IP, mac net.HardwareAddr) (*ipamv1alpha1.IP, error) {
func (k K8sClient) prepareCreateIpamIP(
subnetName string,
ipaddr net.IP,
mac net.HardwareAddr) (*ipamv1alpha1.IP, error) {
ip, err := ipamv1alpha1.IPAddrFromString(ipaddr.String())
if err != nil {
return nil, fmt.Errorf("failed to parse IP %s: %w", ipaddr, err)
Expand Down Expand Up @@ -176,23 +179,28 @@ func (k K8sClient) prepareCreateIpamIP(subnetName string, ipaddr net.IP, mac net
noop()
} else {
if !reflect.DeepEqual(ipamIP.Spec, existingIpamIP.Spec) {
log.Debugf("IP mismatch:\nold IP: %v,\nnew IP: %v", prettyFormat(existingIpamIP.Spec), prettyFormat(ipamIP.Spec))
log.Debugf("IP mismatch:\nold IP: %v,\nnew IP: %v", prettyFormat(existingIpamIP.Spec),
prettyFormat(ipamIP.Spec))
log.Infof("Deleting old IP %s/%s", existingIpamIP.Namespace, existingIpamIP.Name)
// delete old IP object
err = k.Client.Delete(k.Ctx, existingIpamIP)
if err != nil {
return nil, fmt.Errorf("failed to delete IP %s/%s: %w", existingIpamIP.Namespace, existingIpamIP.Name, err)
return nil, fmt.Errorf("failed to delete IP %s/%s: %w", existingIpamIP.Namespace,
existingIpamIP.Name, err)
}

err = k.waitForDeletion(existingIpamIP)
if err != nil {
return nil, fmt.Errorf("failed to delete IP %s/%s: %w", existingIpamIP.Namespace, existingIpamIP.Name, err)
return nil, fmt.Errorf("failed to delete IP %s/%s: %w", existingIpamIP.Namespace,
existingIpamIP.Name, err)
}

k.EventRecorder.Eventf(existingIpamIP, corev1.EventTypeNormal, "Deleted", "Deleted old IPAM IP")
log.Infof("Old IP %s/%s deleted from subnet %s", existingIpamIP.Namespace, existingIpamIP.Name, existingIpamIP.Spec.Subnet.Name)
log.Infof("Old IP %s/%s deleted from subnet %s", existingIpamIP.Namespace, existingIpamIP.Name,
existingIpamIP.Spec.Subnet.Name)
} else {
log.Infof("IP %s/%s already exists in subnet %s, nothing to do", existingIpamIP.Namespace, existingIpamIP.Name, existingIpamIP.Spec.Subnet.Name)
log.Infof("IP %s/%s already exists in subnet %s, nothing to do", existingIpamIP.Namespace,
existingIpamIP.Name, existingIpamIP.Spec.Subnet.Name)
return nil, nil
}
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/ipam/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ var (

func parseArgs(args ...string) (string, []string, error) {
if len(args) < 2 {
return "", []string{""}, fmt.Errorf("at least two arguments must be passed to ipam plugin, a namespace and a comma-separated subnet names list, got %d", len(args))
return "", []string{""}, fmt.Errorf("at least two arguments must be passed to ipam plugin, a namespace "+
"and a comma-separated subnet names list, got %d", len(args))
}

namespace := args[0]
Expand Down
Loading

0 comments on commit e8ccf83

Please sign in to comment.