github.com/nmstate/kubernetes-nmstate@v0.82.0/test/e2e/upgrade/upgrade_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 upgrade 19 20 import ( 21 "context" 22 "fmt" 23 "os" 24 "path" 25 "time" 26 27 . "github.com/onsi/ginkgo/v2" 28 . "github.com/onsi/gomega" 29 30 corev1 "k8s.io/api/core/v1" 31 32 nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" 33 nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" 34 "github.com/nmstate/kubernetes-nmstate/test/cmd" 35 "github.com/nmstate/kubernetes-nmstate/test/doc" 36 "github.com/nmstate/kubernetes-nmstate/test/e2e/operator" 37 testenv "github.com/nmstate/kubernetes-nmstate/test/env" 38 ) 39 40 var _ = Describe("Upgrade", func() { 41 interfaceAbsent := func(iface string) nmstate.State { 42 return nmstate.NewState(fmt.Sprintf(`interfaces: 43 - name: %s 44 state: absent 45 `, iface)) 46 } 47 48 previousTagExamplesPath := "test/e2e/upgrade/examples" 49 currentExamplesPath := "docs/examples" 50 51 fileExists := func(path string) (bool, error) { 52 _, err := os.Stat(path) 53 exists := false 54 55 if err == nil { 56 exists = true 57 } else if os.IsNotExist(err) { 58 err = nil 59 } 60 return exists, err 61 } 62 63 kubectlAndCheck := func(command ...string) { 64 out, err := cmd.Kubectl(command...) 65 Expect(err).ShouldNot(HaveOccurred(), out) 66 } 67 68 createUpgradeCasePolicy := func(example doc.ExampleSpec) { 69 examplePath := path.Join(previousTagExamplesPath, example.FileName) 70 exists, err := fileExists(examplePath) 71 Expect(err).NotTo(HaveOccurred()) 72 if !exists { 73 examplePath = path.Join(currentExamplesPath, example.FileName) 74 } 75 76 By(fmt.Sprintf("Creating policy %s", example.PolicyName)) 77 kubectlAndCheck("apply", "-f", examplePath) 78 By("Waiting for policy to be available") 79 kubectlAndCheck("wait", "nncp", example.PolicyName, "--for", "condition=Available", "--timeout", "3m") 80 } 81 82 createUpgradeCaseCleanupPolicy := func(example doc.ExampleSpec) { 83 if example.CleanupState != nil { 84 setDesiredStateWithPolicyEventually(example.PolicyName, *example.CleanupState) 85 } 86 if len(example.IfaceNames) > 0 { 87 for _, ifaceName := range example.IfaceNames { 88 setDesiredStateWithPolicyEventually( 89 example.PolicyName, 90 interfaceAbsent(ifaceName), 91 ) 92 } 93 } 94 95 kubectlAndCheck("wait", "nncp", example.PolicyName, "--for", "condition=Available", "--timeout", "3m") 96 } 97 98 BeforeEach(func() { 99 operator.UninstallOperator(latestOperator) 100 operator.InstallOperator(previousReleaseOperator) 101 operator.EventuallyOperandIsReady(previousReleaseOperator) 102 }) 103 104 Context("With examples", func() { 105 for _, e := range doc.ExampleSpecs() { 106 example := e 107 108 Context(example.Name, func() { 109 It("should succeed applying the policy", func() { 110 //TODO: remove when no longer required 111 for _, policyToSkip := range []string{"vlan", "linux-bridge-vlan", "dns", "enable-lldp-ethernets-up"} { 112 if policyToSkip == example.PolicyName { 113 Skip("Skipping due to malformed example manifest") 114 } 115 } 116 createUpgradeCasePolicy(example) 117 }) 118 AfterEach(func() { 119 policiesLastHeartbeatTimestamps := map[string]time.Time{} 120 121 nncps := nmstatev1.NodeNetworkConfigurationPolicyList{} 122 err := testenv.Client.List(context.TODO(), &nncps) 123 Expect(err).ToNot(HaveOccurred()) 124 125 By("Collecting LastHeartbeatTime timestamps of present policies") 126 for _, nncp := range nncps.Items { 127 availableCondition := nncp.Status.Conditions.Find(nmstate.NodeNetworkConfigurationPolicyConditionAvailable) 128 Expect(availableCondition).ToNot(BeNil()) 129 policiesLastHeartbeatTimestamps[nncp.Name] = availableCondition.LastHeartbeatTime.Time 130 } 131 132 By("Applying new nmstate operator") 133 operator.UninstallOperator(previousReleaseOperator) 134 operator.InstallOperator(latestOperator) 135 operator.EventuallyOperandIsReady(latestOperator) 136 137 By("Waiting for all policies to be re-reconciled") 138 allPoliciesReReconciled := func() error { 139 nncps = nmstatev1.NodeNetworkConfigurationPolicyList{} 140 err = testenv.Client.List(context.TODO(), &nncps) 141 if err != nil { 142 return err 143 } 144 for _, nncp := range nncps.Items { 145 availableCondition := nncp.Status.Conditions.Find(nmstate.NodeNetworkConfigurationPolicyConditionAvailable) 146 if availableCondition.Status != corev1.ConditionTrue { 147 return fmt.Errorf("policy %s is not Available", nncp.Name) 148 } 149 if !availableCondition.LastHeartbeatTime.Time.After(policiesLastHeartbeatTimestamps[nncp.Name]) { 150 return fmt.Errorf("policy %s hasn't re-reconciled yet", nncp.Name) 151 } 152 } 153 return nil 154 } 155 Eventually(func() error { 156 return allPoliciesReReconciled() 157 }, ReadTimeout, ReadInterval).Should(Succeed()) 158 159 By("Wait for policy to be Available again") 160 kubectlAndCheck("wait", "nncp", example.PolicyName, "--for", "condition=Available", "--timeout", "3m") 161 162 By("Apply cleanup policy configuration") 163 createUpgradeCaseCleanupPolicy(example) 164 165 By("Delete policy") 166 deletePolicy(example.PolicyName) 167 }) 168 }) 169 } 170 }) 171 })