Skip to content
Draft
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
19 changes: 14 additions & 5 deletions cns/restserver/persistent_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ var (
errSnapshotProvider = errors.New("provider failure")
)

const (
persistentStateTestNetwork = "network"
persistentStateTestNestedKey = "nested"
)

func TestPersistentStateHandlerConstructors(t *testing.T) {
statusHandler, err := NewPersistentStateStatusHandler(nil)
require.Error(t, err)
Expand Down Expand Up @@ -109,7 +114,7 @@ func TestPersistentStateHandlersProviderErrors(t *testing.T) {
status int
body string
}{
{name: "canceled", err: context.Canceled, status: http.StatusRequestTimeout, body: "request canceled\n"},
{name: delTestCanceled, err: context.Canceled, status: http.StatusRequestTimeout, body: "request canceled\n"},
{name: "deadline", err: context.DeadlineExceeded, status: http.StatusRequestTimeout, body: "request canceled\n"},
{name: "provider", err: errPersistentStateProvider, status: http.StatusServiceUnavailable, body: "persistent state unavailable\n"},
}
Expand Down Expand Up @@ -192,8 +197,8 @@ func TestPersistentStateSnapshotHandlerErrors(t *testing.T) {

t.Run("encoding", func(t *testing.T) {
snapshot := state.NewSnapshot()
snapshot.Networks["network"] = state.NetworkRecord{
NetworkName: "network",
snapshot.Networks[persistentStateTestNetwork] = state.NetworkRecord{
NetworkName: persistentStateTestNetwork,
Options: map[string]any{"unsupported": make(chan struct{})},
}
handler, err := NewPersistentStateSnapshotHandler(func(context.Context) (state.Snapshot, error) {
Expand All @@ -210,13 +215,17 @@ func TestPersistentStateSnapshotHandlerErrors(t *testing.T) {
t.Run("recursive sanitizer", func(t *testing.T) {
document := map[string]any{
"AuthorizationToken": "secret",
"nested": []any{
persistentStateTestNestedKey: []any{
map[string]any{"authorizationtoken": "another"},
},
}
removeAuthorizationTokens(document)
assert.NotContains(t, document, "AuthorizationToken")
assert.NotContains(t, document["nested"].([]any)[0].(map[string]any), "authorizationtoken")
assert.NotContains(
t,
document[persistentStateTestNestedKey].([]any)[0].(map[string]any),
"authorizationtoken",
)
})
}

Expand Down
6 changes: 6 additions & 0 deletions cns/state/cni_import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"encoding/json"
"errors"
"math"
"net"
"sort"
"sync"
Expand All @@ -22,6 +23,11 @@ var errInjectedCNIImport = errors.New("injected commit failure")

const cniImportTestSecondaryInterface = "net1"

func TestCNIImportCountsRejectOverflow(t *testing.T) {
_, err := cniImportCounts(NewSnapshot(), math.MaxInt)
require.ErrorIs(t, err, ErrInvalidInput)
}

func TestCNIEndpointImportPreflightAndAtomicImport(t *testing.T) {
db, _ := openTestDB(t)
seedCNIImportInventory(t, db)
Expand Down
38 changes: 29 additions & 9 deletions cns/state/coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,31 @@ const (
hardeningContainerID2 = "container-2"
hardeningMultipleValues = "multiple values"
hardeningUnsupportedOption = "unsupported"
coverageEmptyPodName = "empty pod name"
coverageEmptyPodNamespace = "empty pod namespace"
hardeningLocation = "eastus"
hardeningStateNamespace = "state-machine"
hardeningNet1 = "net1"
)

func TestBoundedInvariantClassification(t *testing.T) {
tests := []struct {
name string
err error
want InvariantName
}{
{name: "schema", err: ErrSchemaMismatch, want: InvariantSchema},
{name: "corrupt", err: ErrCorrupt, want: InvariantStructural},
{name: "inconsistent", err: ErrInconsistentState, want: InvariantStructural},
{name: "unclassified error", err: errAbort, want: InvariantStructural},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, boundedInvariant(tt.err))
})
}
}

func TestOwnershipNormalizationRejectsMalformedRecords(t *testing.T) {
validPod := PodIdentity{
PodKey: hardeningContainerID,
Expand All @@ -48,8 +68,8 @@ func TestOwnershipNormalizationRejectsMalformedRecords(t *testing.T) {
{name: "empty infra container", mutate: func(pod *PodIdentity) { pod.InfraContainerID = "" }},
{name: "pod key differs without interface", mutate: func(pod *PodIdentity) { pod.PodKey = testMismatchValue }},
{name: "interface differs from pod key", mutate: func(pod *PodIdentity) { pod.InterfaceID = testMismatchValue }},
{name: "empty pod name", mutate: func(pod *PodIdentity) { pod.PodName = "" }},
{name: "empty pod namespace", mutate: func(pod *PodIdentity) { pod.PodNamespace = "" }},
{name: coverageEmptyPodName, mutate: func(pod *PodIdentity) { pod.PodName = "" }},
{name: coverageEmptyPodNamespace, mutate: func(pod *PodIdentity) { pod.PodNamespace = "" }},
}
for _, tt := range podTests {
t.Run("pod/"+tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -102,15 +122,15 @@ func TestOwnershipNormalizationRejectsMalformedRecords(t *testing.T) {
}{
{name: "empty container", record: validEndpoint},
{
name: "empty pod name",
name: coverageEmptyPodName,
containerID: hardeningContainerID,
record: EndpointRecord{
PodNamespace: hardeningNamespace,
IfnameToIPMap: validEndpoint.IfnameToIPMap,
},
},
{
name: "empty pod namespace",
name: coverageEmptyPodNamespace,
containerID: hardeningContainerID,
record: EndpointRecord{
PodName: importOrchestratorContextKey,
Expand Down Expand Up @@ -570,7 +590,7 @@ func TestReleaseIdentityRejectsConflictingOwnership(t *testing.T) {
name: "retained endpoint pod mismatch",
pod: PodIdentity{
PodKey: testIfacePrimary,
InfraContainerID: "container-1",
InfraContainerID: exportContainerID,
InterfaceID: testIfacePrimary,
PodName: testMismatchValue,
PodNamespace: exportPodNamespace,
Expand All @@ -582,23 +602,23 @@ func TestReleaseIdentityRejectsConflictingOwnership(t *testing.T) {
PodKey: testIfacePrimary,
InfraContainerID: hardeningOtherContainerID,
InterfaceID: testIfacePrimary,
PodName: "pod-1",
PodName: exportPodName,
PodNamespace: exportPodNamespace,
},
},
{
name: "container assignment pod mismatch",
mutate: func(value *Snapshot) {
delete(value.Endpoints, "container-1")
delete(value.Endpoints, exportContainerID)
record := value.Assignments[testIfacePrimary]
record.Pod.PodName = testMismatchValue
value.Assignments[testIfacePrimary] = record
},
pod: PodIdentity{
PodKey: "unknown-interface",
InfraContainerID: "container-1",
InfraContainerID: exportContainerID,
InterfaceID: "unknown-interface",
PodName: "pod-1",
PodName: exportPodName,
PodNamespace: exportPodNamespace,
},
},
Expand Down
15 changes: 10 additions & 5 deletions cns/state/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const (
exportPodName = "pod-1"
exportPodNamespace = "ns-1"
exportNetworkType = "azure"
testEndpointsKey = "Endpoints"
)

type rollbackFailureStage string
Expand Down Expand Up @@ -115,7 +116,7 @@ func TestExportLegacySuccess(t *testing.T) {
assert.Contains(t, string(cnsData), `"`+key+`"`)
}
for _, key := range []string{
"Endpoints",
testEndpointsKey,
"DeleteIntents",
"PodName",
"IfnameToIPMap",
Expand Down Expand Up @@ -168,10 +169,14 @@ func TestExportLegacySuccess(t *testing.T) {
var endpointEnvelope map[string]json.RawMessage
require.NoError(t, json.Unmarshal(endpointData, &endpointEnvelope))
var endpoints map[string]*rollbackEndpointInfo
require.NoError(t, json.Unmarshal(endpointEnvelope["Endpoints"], &endpoints))
require.NoError(t, json.Unmarshal(endpointEnvelope[testEndpointsKey], &endpoints))
assert.Equal(t, exportPodName, endpoints[exportContainerID].PodName)
assert.Equal(t, exportPodNamespace, endpoints[exportContainerID].PodNamespace)
assert.ElementsMatch(t, []string{exportIfnameEth0, "net1"}, sortedKeys(endpoints[exportContainerID].IfnameToIPMap))
assert.ElementsMatch(
t,
[]string{exportIfnameEth0, cniImportTestSecondaryInterface},
sortedKeys(endpoints[exportContainerID].IfnameToIPMap),
)
info := endpoints[exportContainerID].IfnameToIPMap[exportIfnameEth0]
require.Len(t, info.IPv4, 1)
assert.Equal(t, net.ParseIP(exportIPv4Address), info.IPv4[0].IP)
Expand All @@ -183,7 +188,7 @@ func TestExportLegacySuccess(t *testing.T) {
assert.Equal(t, "00:11:22:33:44:55", info.MacAddress)
assert.Equal(t, exportNC1, info.NetworkContainerID)
assert.Equal(t, cns.InfraNIC, info.NICType)
delegated := endpoints[exportContainerID].IfnameToIPMap["net1"]
delegated := endpoints[exportContainerID].IfnameToIPMap[cniImportTestSecondaryInterface]
require.Len(t, delegated.IPv4, 1)
assert.Equal(t, net.ParseIP("10.1.0.4"), delegated.IPv4[0].IP)
assert.Equal(t, exportNC2, delegated.NetworkContainerID)
Expand Down Expand Up @@ -684,7 +689,7 @@ func openPopulatedExportDB(t *testing.T) (db *DB, path string) {

endpoint := completeEndpointRecord()
endpoint.IfnameToIPMap[exportIfnameEth0].NetworkContainerID = exportNC1
endpoint.IfnameToIPMap["net1"].NetworkContainerID = exportNC2
endpoint.IfnameToIPMap[cniImportTestSecondaryInterface].NetworkContainerID = exportNC2
changed, err = db.AssignEndpoint(
context.Background(),
AssignmentRecord{
Expand Down
2 changes: 1 addition & 1 deletion cns/state/import_legacy_keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func TestImportLegacyCapitalizedRestserverKeys(t *testing.T) {
require.NoError(t, err)

endpointData, err := json.Marshal(map[string]any{
"Endpoints": map[string]*capitalizedEndpointFixture{
testEndpointsKey: map[string]*capitalizedEndpointFixture{
"capitalized-container": {
PodName: "pod-capitalized",
PodNamespace: "ns-capitalized",
Expand Down
4 changes: 2 additions & 2 deletions cns/state/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ func completeLegacyImportData(t testing.TB) (cnsData, endpointData []byte) {
NetworkContainerID: importNC1,
NICType: cns.InfraNIC,
},
"net1": {
cniImportTestSecondaryInterface: {
IPv4: []net.IPNet{mustIPNet(t, importNet1Address+"/24")},
HNSEndpointID: "hns-endpoint-2",
HNSNetworkID: "hns-network-2",
Expand All @@ -714,7 +714,7 @@ func completeLegacyImportData(t testing.TB) (cnsData, endpointData []byte) {
},
}
endpointData, err = json.Marshal(map[string]any{
"Endpoints": map[string]*EndpointRecord{importContainerID: &endpoint},
testEndpointsKey: map[string]*EndpointRecord{importContainerID: &endpoint},
"DeleteIntents": map[string]DeleteIntent{
"deleted-container": {CreatedAt: testNow.Add(-time.Minute)},
},
Expand Down
7 changes: 7 additions & 0 deletions cns/state/observability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const (
metricTestDeleteIntent = "delete intent"
)

func TestNilMetricsClock(t *testing.T) {
started := time.Now()
duration := metricDuration(nil, started)
assert.GreaterOrEqual(t, duration, time.Duration(0))
assert.Less(t, duration, time.Second)
}

func TestNewMetricsRegistration(t *testing.T) {
t.Run("descriptors", func(t *testing.T) {
registry := prometheus.NewRegistry()
Expand Down
2 changes: 1 addition & 1 deletion cns/state/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func completeEndpointRecord() EndpointRecord {
NetworkContainerID: testNCID,
NICType: cns.InfraNIC,
},
"net1": {
cniImportTestSecondaryInterface: {
IPv4: []net.IPNet{{
IP: net.ParseIP("10.1.0.4"),
Mask: net.CIDRMask(24, 32),
Expand Down
Loading