Skip to content

Commit

Permalink
Test nns update timestamp currentState dependecy (#711)
Browse files Browse the repository at this point in the history
The network configuration at nodes is chaning sometimes without human
intervention (at kubevirtci some ipv6 routes disappear sometimes or
appear sometimes). This change do a best effort and checks nns update
timestamp according to currentState changed or not.

Signed-off-by: Quique Llorente <[email protected]>
  • Loading branch information
qinqon authored Mar 10, 2021
1 parent e89b51b commit 125a7c5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 42 deletions.
56 changes: 37 additions & 19 deletions test/e2e/handler/nns_update_timestamp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@ import (

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"

"github.com/andreyvit/diff"

"k8s.io/apimachinery/pkg/types"

"github.com/nmstate/kubernetes-nmstate/api/shared"
nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1"
nmstatenode "github.com/nmstate/kubernetes-nmstate/pkg/node"
)
Expand All @@ -28,24 +24,46 @@ var _ = Describe("[nns] NNS LastSuccessfulUpdateTime", func() {
originalNNSs[node] = nodeNetworkState(key)
}
})
Context("when network configuration hasn't change", func() {
It("should not be updated", func() {
for node, originalNNS := range originalNNSs {
// Give enough time for the NNS to be updated (3 interval times)
timeout := 3 * nmstatenode.NetworkStateRefresh
key := types.NamespacedName{Name: node}
Context("when network configuration is not changed by a NNCP", func() {
It("nns should not be updated after reconcile", func() {
// Give enough time for the NNS to be reconcile(2 interval times)
interval := 2 * nmstatenode.NetworkStateRefresh
timeout := 4 * interval
Eventually(func() error {
for node, originalNNS := range originalNNSs {
key := types.NamespacedName{Name: node}
currentStatus := nodeNetworkState(key).Status
originalStatus := originalNNS.Status
if currentStatus.CurrentState.String() == originalStatus.CurrentState.String() {
By(fmt.Sprintf("Check LastSuccessfulUpdateTime changed at %s", node))
Expect(currentStatus.LastSuccessfulUpdateTime).To(Equal(originalStatus.LastSuccessfulUpdateTime))
} else {
return fmt.Errorf("Network configuration changed, sending and error to retry")
}
}
return nil
}, timeout, interval).Should(Succeed())
})
})
Context("when network configuration is changed externally", func() {
expectedDummyName := "dummy0"

Consistently(func() shared.NodeNetworkStateStatus {
return nodeNetworkState(key).Status
}, timeout, time.Second).Should(MatchAllFields(Fields{
"CurrentState": WithTransform(shared.State.String, Equal(originalNNS.Status.CurrentState.String())),
"LastSuccessfulUpdateTime": Equal(originalNNS.Status.LastSuccessfulUpdateTime),
"Conditions": Equal(originalNNS.Status.Conditions),
}), func() string {
return fmt.Sprintf("currentState diff: \n%s", diff.LineDiff(originalNNS.Status.CurrentState.String(), nodeNetworkState(key).Status.CurrentState.String()))
})
BeforeEach(func() {
createDummyConnectionAtAllNodes(expectedDummyName)
})
AfterEach(func() {
deleteConnectionAndWait(allNodes, expectedDummyName)
})
It("should update it with according to network state refresh duration", func() {
for node, originalNNS := range originalNNSs {
By(fmt.Sprintf("Checking timestamp against original one %s", originalNNS.Status.LastSuccessfulUpdateTime))
Eventually(func() time.Time {
currentNNS := nodeNetworkState(types.NamespacedName{Name: node})
return currentNNS.Status.LastSuccessfulUpdateTime.Time
}, 2*nmstatenode.NetworkStateRefresh, 10*time.Second).Should(BeTemporally(">", originalNNS.Status.LastSuccessfulUpdateTime.Time), "should update it at %s", node)
}
})

})
Context("when network configuration is changed by a NNCP", func() {
BeforeEach(func() {
Expand Down
19 changes: 5 additions & 14 deletions test/e2e/handler/nodes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,19 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:[email protected]][level:com
})
})
Context("and new interface is configured", func() {
var (
expectedDummyName = "dummy0"
)
expectedDummyName := "dummy0"

BeforeEach(func() {
createDummyAtNodes(expectedDummyName)
createDummyConnectionAtNodes(expectedDummyName)
})
AfterEach(func() {
deleteConnectionAtNodes(expectedDummyName)
By("Make sure the dummy interface gets deleted")
for _, node := range nodes {
for _, iface := range interfacesNameForNode(node) {
if iface == expectedDummyName {
deleteDeviceAtNode(node, expectedDummyName)
}
}
}
deleteConnectionAndWait(nodes, expectedDummyName)
})
It("[test_id:3794]should update node network state with it", func() {
for _, nodeName := range nodes {
Eventually(func() []string {
return interfacesNameForNode(nodeName)
}, node.NetworkStateRefresh, time.Second).Should(ContainElement(expectedDummyName))
}, 2*node.NetworkStateRefresh, time.Second).Should(ContainElement(expectedDummyName))
}
})
})
Expand Down
48 changes: 39 additions & 9 deletions test/e2e/handler/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

nmstate "github.com/nmstate/kubernetes-nmstate/api/shared"
nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1"
nmstatenode "github.com/nmstate/kubernetes-nmstate/pkg/node"
"github.com/nmstate/kubernetes-nmstate/test/cmd"
"github.com/nmstate/kubernetes-nmstate/test/e2e/handler/linuxbridge"
testenv "github.com/nmstate/kubernetes-nmstate/test/env"
Expand Down Expand Up @@ -221,24 +222,53 @@ func deleteBridgeAtNodes(bridgeName string, ports ...string) []error {
return errs
}

func createDummyAtNodes(dummyName string) []error {
func createDummyConnection(nodesToModify []string, dummyName string) []error {
By(fmt.Sprintf("Creating dummy %s", dummyName))
_, errs := runner.RunAtNodes(nodes, "sudo", "nmcli", "con", "add", "type", "dummy", "con-name", dummyName, "ifname", dummyName, "ip4", "192.169.1.50/24")
_, upErrs := runner.RunAtNodes(nodes, "sudo", "nmcli", "con", "up", dummyName)
_, errs := runner.RunAtNodes(nodesToModify, "sudo", "nmcli", "con", "add", "type", "dummy", "con-name", dummyName, "ifname", dummyName, "ip4", "192.169.1.50/24")
_, upErrs := runner.RunAtNodes(nodesToModify, "sudo", "nmcli", "con", "up", dummyName)
errs = append(errs, upErrs...)
return errs
}

func deleteConnectionAtNodes(name string) []error {
func createDummyConnectionAtNodes(dummyName string) []error {
return createDummyConnection(nodes, dummyName)
}

func createDummyConnectionAtAllNodes(dummyName string) []error {
return createDummyConnection(allNodes, dummyName)
}

func deleteConnection(nodesToModify []string, name string) []error {
By(fmt.Sprintf("Delete connection %s", name))
_, errs := runner.RunAtNodes(nodes, "sudo", "nmcli", "con", "delete", name)
_, errs := runner.RunAtNodes(nodesToModify, "sudo", "nmcli", "con", "delete", name)
return errs
}

func deleteDeviceAtNode(node string, name string) error {
By(fmt.Sprintf("Delete device %s at node %s", name, node))
_, err := runner.RunAtNode(node, "sudo", "nmcli", "device", "delete", name)
return err
func deleteConnectionAtNodes(name string) []error {
return deleteConnection(nodes, name)
}
func deleteConnectionAtAllNodes(name string) []error {
return deleteConnection(allNodes, name)
}

func deleteDevice(nodesToModify []string, name string) []error {
By(fmt.Sprintf("Delete device %s at nodes %v", name, nodesToModify))
_, errs := runner.RunAtNodes(nodesToModify, "sudo", "nmcli", "device", "delete", name)
return errs
}

func waitForInterfaceDeletion(nodesToCheck []string, interfaceName string) {
for _, nodeName := range nodesToCheck {
Eventually(func() []string {
return interfacesNameForNode(nodeName)
}, 2*nmstatenode.NetworkStateRefresh, time.Second).ShouldNot(ContainElement(interfaceName))
}
}

func deleteConnectionAndWait(nodesToModify []string, interfaceName string) {
deleteConnection(nodesToModify, interfaceName)
deleteDevice(nodesToModify, interfaceName)
waitForInterfaceDeletion(nodesToModify, interfaceName)
}

func interfaces(state nmstate.State) []interface{} {
Expand Down

0 comments on commit 125a7c5

Please sign in to comment.