Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move BlockNetwork() to e2enetwork #89411

Merged
merged 1 commit into from Mar 24, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions test/e2e/apps/network_partition.go
Expand Up @@ -211,7 +211,7 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() {
defer func() {
ginkgo.By(fmt.Sprintf("Unblock traffic from node %s to the master", node.Name))
for _, masterAddress := range masterAddresses {
framework.UnblockNetwork(host, masterAddress)
e2enetwork.UnblockNetwork(host, masterAddress)
}

if ginkgo.CurrentGinkgoTestDescription().Failed {
Expand All @@ -226,7 +226,7 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() {
}()

for _, masterAddress := range masterAddresses {
framework.BlockNetwork(host, masterAddress)
e2enetwork.BlockNetwork(host, masterAddress)
}

ginkgo.By("Expect to observe node and pod status change from Ready to NotReady after network partition")
Expand Down Expand Up @@ -599,7 +599,7 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() {
defer func() {
ginkgo.By(fmt.Sprintf("Unblock traffic from node %s to the master", node.Name))
for _, masterAddress := range masterAddresses {
framework.UnblockNetwork(host, masterAddress)
e2enetwork.UnblockNetwork(host, masterAddress)
}

if ginkgo.CurrentGinkgoTestDescription().Failed {
Expand All @@ -611,7 +611,7 @@ var _ = SIGDescribe("Network Partition [Disruptive] [Slow]", func() {
}()

for _, masterAddress := range masterAddresses {
framework.BlockNetwork(host, masterAddress)
e2enetwork.BlockNetwork(host, masterAddress)
}

ginkgo.By("Expect to observe node and pod status change from Ready to NotReady after network partition")
Expand Down
1 change: 1 addition & 0 deletions test/e2e/framework/network/BUILD
Expand Up @@ -20,6 +20,7 @@ go_library(
"//test/e2e/framework/node:go_default_library",
"//test/e2e/framework/pod:go_default_library",
"//test/e2e/framework/skipper:go_default_library",
"//test/e2e/framework/ssh:go_default_library",
"//test/utils/image:go_default_library",
"//vendor/github.com/onsi/ginkgo:go_default_library",
],
Expand Down
61 changes: 59 additions & 2 deletions test/e2e/framework/network/utils.go
Expand Up @@ -42,6 +42,7 @@ import (
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
imageutils "k8s.io/kubernetes/test/utils/image"
)

Expand Down Expand Up @@ -872,7 +873,7 @@ func TestUnderTemporaryNetworkFailure(c clientset.Interface, ns string, node *v1
// separately, but I prefer to stay on the safe side).
ginkgo.By(fmt.Sprintf("Unblock network traffic from node %s to the master", node.Name))
for _, masterAddress := range masterAddresses {
framework.UnblockNetwork(host, masterAddress)
UnblockNetwork(host, masterAddress)
}
}()

Expand All @@ -881,7 +882,7 @@ func TestUnderTemporaryNetworkFailure(c clientset.Interface, ns string, node *v1
framework.Failf("Node %s did not become ready within %v", node.Name, resizeNodeReadyTimeout)
}
for _, masterAddress := range masterAddresses {
framework.BlockNetwork(host, masterAddress)
BlockNetwork(host, masterAddress)
}

framework.Logf("Waiting %v for node %s to be not ready after simulated network failure", resizeNodeNotReadyTimeout, node.Name)
Expand All @@ -892,3 +893,59 @@ func TestUnderTemporaryNetworkFailure(c clientset.Interface, ns string, node *v1
testFunc()
// network traffic is unblocked in a deferred function
}

// BlockNetwork blocks network between the given from value and the given to value.
// The following helper functions can block/unblock network from source
// host to destination host by manipulating iptable rules.
// This function assumes it can ssh to the source host.
//
// Caution:
// Recommend to input IP instead of hostnames. Using hostnames will cause iptables to
// do a DNS lookup to resolve the name to an IP address, which will
// slow down the test and cause it to fail if DNS is absent or broken.
//
// Suggested usage pattern:
// func foo() {
// ...
// defer UnblockNetwork(from, to)
// BlockNetwork(from, to)
// ...
// }
//
func BlockNetwork(from string, to string) {
framework.Logf("block network traffic from %s to %s", from, to)
iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
dropCmd := fmt.Sprintf("sudo iptables --insert %s", iptablesRule)
if result, err := e2essh.SSH(dropCmd, from, framework.TestContext.Provider); result.Code != 0 || err != nil {
e2essh.LogResult(result)
framework.Failf("Unexpected error: %v", err)
}
}

// UnblockNetwork unblocks network between the given from value and the given to value.
func UnblockNetwork(from string, to string) {
framework.Logf("Unblock network traffic from %s to %s", from, to)
iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
undropCmd := fmt.Sprintf("sudo iptables --delete %s", iptablesRule)
// Undrop command may fail if the rule has never been created.
// In such case we just lose 30 seconds, but the cluster is healthy.
// But if the rule had been created and removing it failed, the node is broken and
// not coming back. Subsequent tests will run or fewer nodes (some of the tests
// may fail). Manual intervention is required in such case (recreating the
// cluster solves the problem too).
err := wait.Poll(time.Millisecond*100, time.Second*30, func() (bool, error) {
result, err := e2essh.SSH(undropCmd, from, framework.TestContext.Provider)
if result.Code == 0 && err == nil {
return true, nil
}
e2essh.LogResult(result)
if err != nil {
framework.Logf("Unexpected error: %v", err)
}
return false, nil
})
if err != nil {
framework.Failf("Failed to remove the iptable REJECT rule. Manual intervention is "+
"required on host %s: remove rule %s, if exists", from, iptablesRule)
}
}
56 changes: 0 additions & 56 deletions test/e2e/framework/util.go
Expand Up @@ -1406,62 +1406,6 @@ func EnsureLoadBalancerResourcesDeleted(ip, portRange string) error {
return TestContext.CloudConfig.Provider.EnsureLoadBalancerResourcesDeleted(ip, portRange)
}

// BlockNetwork blocks network between the given from value and the given to value.
// The following helper functions can block/unblock network from source
// host to destination host by manipulating iptable rules.
// This function assumes it can ssh to the source host.
//
// Caution:
// Recommend to input IP instead of hostnames. Using hostnames will cause iptables to
// do a DNS lookup to resolve the name to an IP address, which will
// slow down the test and cause it to fail if DNS is absent or broken.
//
// Suggested usage pattern:
// func foo() {
// ...
// defer UnblockNetwork(from, to)
// BlockNetwork(from, to)
// ...
// }
//
func BlockNetwork(from string, to string) {
Logf("block network traffic from %s to %s", from, to)
iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
dropCmd := fmt.Sprintf("sudo iptables --insert %s", iptablesRule)
if result, err := e2essh.SSH(dropCmd, from, TestContext.Provider); result.Code != 0 || err != nil {
e2essh.LogResult(result)
Failf("Unexpected error: %v", err)
}
}

// UnblockNetwork unblocks network between the given from value and the given to value.
func UnblockNetwork(from string, to string) {
Logf("Unblock network traffic from %s to %s", from, to)
iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to)
undropCmd := fmt.Sprintf("sudo iptables --delete %s", iptablesRule)
// Undrop command may fail if the rule has never been created.
// In such case we just lose 30 seconds, but the cluster is healthy.
// But if the rule had been created and removing it failed, the node is broken and
// not coming back. Subsequent tests will run or fewer nodes (some of the tests
// may fail). Manual intervention is required in such case (recreating the
// cluster solves the problem too).
err := wait.Poll(time.Millisecond*100, time.Second*30, func() (bool, error) {
result, err := e2essh.SSH(undropCmd, from, TestContext.Provider)
if result.Code == 0 && err == nil {
return true, nil
}
e2essh.LogResult(result)
if err != nil {
Logf("Unexpected error: %v", err)
}
return false, nil
})
if err != nil {
Failf("Failed to remove the iptable REJECT rule. Manual intervention is "+
"required on host %s: remove rule %s, if exists", from, iptablesRule)
}
}

// CoreDump SSHs to the master and all nodes and dumps their logs into dir.
// It shells out to cluster/log-dump/log-dump.sh to accomplish this.
func CoreDump(dir string) {
Expand Down