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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ on:
jobs:

build:
runs-on: "windows-2022"
runs-on: "windows-2025"
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.25'

- name: Verify Dependencies
run: go mod verify
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ on:

jobs:
integration:
runs-on: windows-2022
runs-on: windows-2025
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22'
go-version: '1.25'

- name: Run integration tests
run: |
Expand Down
29 changes: 27 additions & 2 deletions hcn/hcnerrors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func checkForErrors(methodName string, hr error, resultBuffer *uint16) error {
}

if errorFound {
returnError := new(hr, methodName, result)
returnError := newHcnError(hr, methodName, result)
logrus.Debugf(returnError.Error()) // HCN errors logged for debugging.
Comment thread
princepereira marked this conversation as resolved.
return returnError
}
Expand All @@ -52,6 +52,11 @@ const (
ERROR_NOT_FOUND = ErrorCode(windows.ERROR_NOT_FOUND)
HCN_E_PORT_ALREADY_EXISTS ErrorCode = ErrorCode(windows.HCN_E_PORT_ALREADY_EXISTS)
HCN_E_NOTIMPL ErrorCode = ErrorCode(windows.E_NOTIMPL)
HCN_E_NETWORK_NOT_FOUND ErrorCode = ErrorCode(windows.HCN_E_NETWORK_NOT_FOUND)
HCN_E_ENDPOINT_NOT_FOUND ErrorCode = ErrorCode(windows.HCN_E_ENDPOINT_NOT_FOUND)
HCN_E_PORT_NOT_FOUND ErrorCode = ErrorCode(windows.HCN_E_PORT_NOT_FOUND)
HCN_E_INVALID_IP ErrorCode = ErrorCode(windows.HCN_E_INVALID_IP)
HCN_E_ADAPTER_NOT_FOUND ErrorCode = ErrorCode(windows.HCN_E_ADAPTER_NOT_FOUND)
)

type HcnError struct {
Expand Down Expand Up @@ -83,7 +88,27 @@ func IsNotImplemented(err error) bool {
return CheckErrorWithCode(err, HCN_E_NOTIMPL)
}

func new(hr error, title string, rest string) error {
func IsNetworkNotFoundError(err error) bool {
return CheckErrorWithCode(err, HCN_E_NETWORK_NOT_FOUND)
}

func IsEndpointNotFoundError(err error) bool {
return CheckErrorWithCode(err, HCN_E_ENDPOINT_NOT_FOUND)
}

func IsPortNotFoundError(err error) bool {
return CheckErrorWithCode(err, HCN_E_PORT_NOT_FOUND)
}

func IsInvalidIPError(err error) bool {
return CheckErrorWithCode(err, HCN_E_INVALID_IP)
}

func IsAdapterNotFoundError(err error) bool {
return CheckErrorWithCode(err, HCN_E_ADAPTER_NOT_FOUND)
}

func newHcnError(hr error, title string, rest string) error {
err := &HcnError{}
hnsError := hns.NewHnsError(hr, title, rest)
err.HnsError = hnsError.(*hns.HnsError) //nolint:errorlint
Expand Down
151 changes: 151 additions & 0 deletions hcn/hcnerrors_unit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//go:build windows
Comment thread
princepereira marked this conversation as resolved.
// +build windows

package hcn

import (
"fmt"
"testing"

"golang.org/x/sys/windows"
)

func TestHCNErrorHelpers(t *testing.T) {
for _, tc := range []struct {
name string
err error
checkFn func(error) bool
expected bool
}{
// IsElementNotFoundError
{
name: "IsElementNotFoundError with matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsElementNotFoundError,
Comment thread
princepereira marked this conversation as resolved.
expected: true,
},
{
name: "IsElementNotFoundError with non-matching error",
err: newHcnError(windows.Errno(windows.E_NOTIMPL), "test", ""),
checkFn: IsElementNotFoundError,
expected: false,
},

// IsPortAlreadyExistsError
{
name: "IsPortAlreadyExistsError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_PORT_ALREADY_EXISTS), "test", ""),
checkFn: IsPortAlreadyExistsError,
expected: true,
},
{
name: "IsPortAlreadyExistsError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsPortAlreadyExistsError,
expected: false,
},

// IsNotImplemented
{
name: "IsNotImplemented with matching error",
err: newHcnError(windows.Errno(windows.E_NOTIMPL), "test", ""),
checkFn: IsNotImplemented,
expected: true,
},
{
name: "IsNotImplemented with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsNotImplemented,
expected: false,
},

// IsNetworkNotFound
{
name: "IsNetworkNotFoundError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_NETWORK_NOT_FOUND), "test", ""),
checkFn: IsNetworkNotFoundError,
expected: true,
},
{
name: "IsNetworkNotFoundError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsNetworkNotFoundError,
expected: false,
},

// IsEndpointNotFoundError
{
name: "IsEndpointNotFoundError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_ENDPOINT_NOT_FOUND), "test", ""),
checkFn: IsEndpointNotFoundError,
expected: true,
},
{
name: "IsEndpointNotFoundError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsEndpointNotFoundError,
expected: false,
},

// IsPortNotFoundError
{
name: "IsPortNotFoundError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_PORT_NOT_FOUND), "test", ""),
checkFn: IsPortNotFoundError,
expected: true,
},
{
name: "IsPortNotFoundError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsPortNotFoundError,
expected: false,
},

// IsInvalidIPError
{
name: "IsInvalidIPError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_INVALID_IP), "test", ""),
checkFn: IsInvalidIPError,
expected: true,
},
{
name: "IsInvalidIPError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsInvalidIPError,
expected: false,
},

// IsAdapterNotFoundError
{
name: "IsAdapterNotFoundError with matching error",
err: newHcnError(windows.Errno(windows.HCN_E_ADAPTER_NOT_FOUND), "test", ""),
checkFn: IsAdapterNotFoundError,
expected: true,
},
{
name: "IsAdapterNotFoundError with non-matching error",
err: newHcnError(windows.Errno(windows.ERROR_NOT_FOUND), "test", ""),
checkFn: IsAdapterNotFoundError,
expected: false,
},

// Non-HcnError
{
name: "non-HcnError returns false",
err: fmt.Errorf("random error"),
checkFn: IsPortAlreadyExistsError,
expected: false,
},
} {
t.Run(tc.name, func(t *testing.T) {
if got := tc.checkFn(tc.err); got != tc.expected {
t.Errorf("expected %t, got %t for error: %v", tc.expected, got, tc.err)
}
// Also test wrapped error
wrapped := fmt.Errorf("wrapped: %w", tc.err)
if got := tc.checkFn(wrapped); got != tc.expected {
t.Errorf("expected %t for wrapped error, got %t for error: %v", tc.expected, got, wrapped)
}
})
}
}
20 changes: 13 additions & 7 deletions hcn/hcnloadbalancer_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//go:build windows && integration_loadbalancer
// +build windows,integration_loadbalancer

// TODO: https://github.com/microsoft/hnslib/issues/19
//go:build windows && integration
// +build windows,integration

package hcn

Expand Down Expand Up @@ -72,7 +70,12 @@ func TestCreateUpdateDeleteLoadBalancer(t *testing.T) {

loadBalancer, err = loadBalancer.Update(loadBalancer.Id)
if err != nil {
t.Fatal(err)
if IsNotImplemented(err) {
t.Logf("LoadBalancer Update is not implemented on this version of Windows")
return
} else {
t.Fatal(err)
}
}

if len(loadBalancer.HostComputeEndpoints) != 2 {
Expand All @@ -83,7 +86,11 @@ func TestCreateUpdateDeleteLoadBalancer(t *testing.T) {

loadBalancer, err = loadBalancer.Update(loadBalancer.Id)
if err != nil {
t.Fatal(err)
if IsNotImplemented(err) {
t.Logf("LoadBalancer Update is not implemented on this version of Windows")
} else {
t.Fatal(err)
}
}

if len(loadBalancer.HostComputeEndpoints) != 1 {
Expand Down Expand Up @@ -210,7 +217,6 @@ func TestAddLoadBalancer(t *testing.T) {
if err != nil {
t.Fatal(err)
}

loadBalancer, err := AddLoadBalancer([]HostComputeEndpoint{*endpoint}, LoadBalancerFlagsNone, LoadBalancerPortMappingFlagsNone, "10.0.0.1", []string{"1.1.1.2", "1.1.1.3"}, 6, 8080, 80)
if err != nil {
t.Fatal(err)
Expand Down
11 changes: 11 additions & 0 deletions hcn/hcntestconsts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build windows
// +build windows

package hcn

const (
NatTestNetworkName string = "GoTestNat"
NatTestEndpointName string = "GoTestNatEndpoint"
OverlayTestNetworkName string = "GoTestOverlay"
BridgeTestNetworkName string = "GoTestL2Bridge"
)
6 changes: 4 additions & 2 deletions hcn/hcnutils_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//go:build windows && integration
// +build windows,integration
//go:build windows
// +build windows

package hcn

import (
"encoding/json"
"time"
)

func CreateSubnet(AddressPrefix string, NextHop string, DestPrefix string) *Subnet {
Expand Down Expand Up @@ -35,6 +36,7 @@ func cleanup(networkName string) {
return
}
}
time.Sleep(2 * time.Second)
}

func HcnGenerateNATNetwork(subnet *Subnet) *HostComputeNetwork {
Expand Down
7 changes: 0 additions & 7 deletions hcn/hnsv1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ import (
"github.com/Microsoft/hnslib"
)

const (
NatTestNetworkName string = "GoTestNat"
NatTestEndpointName string = "GoTestNatEndpoint"
OverlayTestNetworkName string = "GoTestOverlay"
BridgeTestNetworkName string = "GoTestL2Bridge"
)

func TestMain(m *testing.M) {
os.Exit(m.Run())
}
Expand Down
Loading