github.com/nmstate/kubernetes-nmstate@v0.82.0/test/e2e/handler/rollback_test.go (about) 1 /* 2 Copyright The Kubernetes NMState Authors. 3 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 */ 17 18 package handler 19 20 import ( 21 "fmt" 22 "time" 23 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 27 nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" 28 "github.com/nmstate/kubernetes-nmstate/test/e2e/policy" 29 ) 30 31 // We cannot change routes at nmstate if the interface is with dhcp true 32 // that's why we need to set it static with the same ip it has previously. 33 func badDefaultGw(address, nic string, routingTable int) nmstate.State { 34 return nmstate.NewState(fmt.Sprintf(`interfaces: 35 - name: %s 36 type: ethernet 37 state: up 38 ipv4: 39 dhcp: false 40 enabled: true 41 address: 42 - ip: %s 43 prefix-length: 24 44 routes: 45 config: 46 - destination: 0.0.0.0/0 47 metric: 150 48 next-hop-address: 192.0.2.1 49 next-hop-interface: %s 50 table-id: %d 51 `, nic, address, nic, routingTable)) 52 } 53 54 func removeNameServers(nic string) nmstate.State { 55 return nmstate.NewState(fmt.Sprintf(`dns-resolver: 56 config: 57 search: [] 58 server: [] 59 interfaces: 60 - name: %s 61 type: ethernet 62 state: up 63 ipv4: 64 auto-dns: false 65 dhcp: true 66 enabled: true 67 ipv6: 68 auto-dns: false 69 dhcp: true 70 autoconf: true 71 enabled: true 72 `, nic)) 73 } 74 75 func setBadNameServers(nic string) nmstate.State { 76 return nmstate.NewState(fmt.Sprintf(`dns-resolver: 77 config: 78 search: [] 79 server: 80 - "fe80::deef:1%%%[1]s" 81 - "fe80::deef:2%%%[1]s" 82 interfaces: 83 - name: %[1]s 84 type: ethernet 85 state: up 86 ipv4: 87 auto-dns: false 88 dhcp: true 89 enabled: true 90 ipv6: 91 auto-dns: false 92 dhcp: true 93 autoconf: true 94 enabled: true 95 `, nic)) 96 } 97 98 func discoverNameServers(nic string) nmstate.State { 99 return nmstate.NewState(fmt.Sprintf(` 100 dns-resolver: 101 config: 102 search: [] 103 server: [] 104 interfaces: 105 - name: %s 106 type: ethernet 107 state: up 108 ipv4: 109 auto-dns: true 110 dhcp: true 111 enabled: true 112 ipv6: 113 auto-dns: true 114 dhcp: true 115 autoconf: true 116 enabled: true 117 `, nic)) 118 } 119 120 var _ = Describe("rollback", func() { 121 // This spec is done only at first node since policy has to be different 122 // per node (ip addresses has to be different at cluster). 123 Context("when connectivity to default gw is lost after state configuration", func() { 124 BeforeEach(func() { 125 By("Configure a invalid default gw") 126 var address string 127 Eventually(func() string { 128 address = ipv4Address(nodes[0], primaryNic) 129 return address 130 }, ReadTimeout, ReadInterval).ShouldNot(BeEmpty()) 131 updateDesiredStateAtNode(nodes[0], badDefaultGw(address, primaryNic, 254)) 132 }) 133 AfterEach(func() { 134 By("Clean up desired state") 135 resetDesiredStateForNodes() 136 }) 137 It("should rollback to a good gw configuration", func() { 138 By("Should not be available") // Fail fast 139 policy.StatusConsistently().ShouldNot(policy.ContainPolicyAvailable()) 140 141 By("Wait for reconcile to fail") 142 policy.WaitForDegradedTestPolicy() 143 Byf("Check that %s is rolled back", primaryNic) 144 Eventually(func() bool { 145 return dhcpFlag(nodes[0], primaryNic) 146 }, 480*time.Second, ReadInterval).Should(BeTrue(), "DHCP flag hasn't rollback to true") 147 148 Byf("Check that %s continue with rolled back state", primaryNic) 149 Consistently(func() bool { 150 return dhcpFlag(nodes[0], primaryNic) 151 }, 5*time.Second, 1*time.Second).Should(BeTrue(), "DHCP flag has change to false") 152 }) 153 }) 154 155 Context("when changing the default gw to a routing table different from main", func() { 156 secondaryNicCustomAddress := "192.168.100.1" 157 BeforeEach(func() { 158 By("Configure a invalid default gw") 159 applyTime := time.Now() 160 updateDesiredStateAtNode(nodes[0], badDefaultGw(secondaryNicCustomAddress, firstSecondaryNic, 200)) 161 policy.WaitForPolicyTransitionUpdateWithTime(TestPolicy, applyTime) 162 policy.WaitForAvailablePolicy(TestPolicy) 163 }) 164 AfterEach(func() { 165 By("Clean up desired state") 166 resetDesiredStateForNodes() 167 }) 168 It("should not rollback to the previous configuration", func() { 169 Eventually(func() string { 170 return ipv4Address(nodes[0], firstSecondaryNic) 171 }, 3*time.Minute, ReadInterval).Should(Equal(secondaryNicCustomAddress), "IP has not being set") 172 173 Byf("Check that %s is not rolled back", firstSecondaryNic) 174 Consistently(func() string { 175 return ipv4Address(nodes[0], firstSecondaryNic) 176 }, 20*time.Second, ReadInterval).Should(Equal(secondaryNicCustomAddress), "IP has rolled back to empty") 177 }) 178 }) 179 180 Context("when name servers are lost after state configuration", func() { 181 BeforeEach(func() { 182 updateDesiredStateAtNode(nodes[0], removeNameServers(primaryNic)) 183 }) 184 AfterEach(func() { 185 updateDesiredStateAtNode(nodes[0], discoverNameServers(primaryNic)) 186 By("Clean up desired state") 187 resetDesiredStateForNodes() 188 }) 189 It("should rollback to previous name servers", func() { 190 By("Should not be available") // Fail fast 191 policy.StatusConsistently().ShouldNot(policy.ContainPolicyAvailable()) 192 193 By("Wait for reconcile to fail") 194 policy.WaitForDegradedTestPolicy() 195 Byf("Check that %s is rolled back", primaryNic) 196 Eventually(func() bool { 197 return autoDNS(nodes[0], primaryNic) 198 }, 480*time.Second, ReadInterval).Should(BeTrue(), "should eventually have auto-dns=true") 199 200 Byf("Check that %s continue with rolled back state", primaryNic) 201 Consistently(func() bool { 202 return autoDNS(nodes[0], primaryNic) 203 }, 5*time.Second, 1*time.Second).Should(BeTrue(), "should consistently have auto-dns=true") 204 205 }) 206 }) 207 208 Context("when name servers are wrong after state configuration", func() { 209 BeforeEach(func() { 210 updateDesiredStateAtNode(nodes[0], setBadNameServers(primaryNic)) 211 }) 212 AfterEach(func() { 213 updateDesiredStateAtNode(nodes[0], discoverNameServers(primaryNic)) 214 By("Clean up desired state") 215 resetDesiredStateForNodes() 216 }) 217 It("should rollback to previous name servers", func() { 218 By("Should not be available") // Fail fast 219 policy.StatusConsistently().ShouldNot(policy.ContainPolicyAvailable()) 220 221 By("Wait for reconcile to fail") 222 policy.WaitForDegradedTestPolicy() 223 Byf("Check that %s is rolled back", primaryNic) 224 Eventually(func() bool { 225 return autoDNS(nodes[0], primaryNic) 226 }, 480*time.Second, ReadInterval).Should(BeTrue(), "should eventually have auto-dns=true") 227 228 Byf("Check that %s continue with rolled back state", primaryNic) 229 Consistently(func() bool { 230 return autoDNS(nodes[0], primaryNic) 231 }, 5*time.Second, 1*time.Second).Should(BeTrue(), "should consistently have auto-dns=true") 232 233 }) 234 }) 235 })