diff --git a/Makefile b/Makefile index 1bf34ab44..eda9be14d 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ IMAGE_REPO ?= nmstate NAMESPACE ?= nmstate ifeq ($(NMSTATE_PIN), future) -HANDLER_EXTRA_PARAMS:= "--build-arg NMSTATE_SOURCE=git --build-arg FROM=quay.io/centos/centos:stream9" +HANDLER_EXTRA_PARAMS:= "--build-arg NMSTATE_SOURCE=git" endif HANDLER_IMAGE_NAME ?= kubernetes-nmstate-handler @@ -32,7 +32,7 @@ WHAT ?= ./pkg/... ./controllers/... unit_test_args ?= -r -keep-going --randomize-all --randomize-suites --race --trace $(UNIT_TEST_ARGS) -export KUBEVIRT_PROVIDER ?= k8s-1.24 +export KUBEVIRT_PROVIDER ?= k8s-1.26-centos9 export KUBEVIRT_NUM_NODES ?= 2 # 1 control-plane, 1 worker needed for e2e tests export KUBEVIRT_NUM_SECONDARY_NICS ?= 2 diff --git a/api/shared/condition_types.go b/api/shared/condition_types.go index b782a0633..b54e5c304 100644 --- a/api/shared/condition_types.go +++ b/api/shared/condition_types.go @@ -31,7 +31,6 @@ type Condition struct { Status corev1.ConditionStatus `json:"status"` Reason ConditionReason `json:"reason,omitempty"` Message string `json:"message,omitempty"` - MessageEncoded string `json:"messageEncoded,omitempty"` LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime,omitempty"` LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` } diff --git a/build/Dockerfile b/build/Dockerfile index bc03dbc55..02cfd3a85 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,4 +1,4 @@ -ARG FROM=quay.io/centos/centos:stream8 +ARG FROM=quay.io/centos/centos:stream9 FROM --platform=linux/amd64 ${FROM} AS build ARG TARGETARCH @@ -14,7 +14,7 @@ COPY . . RUN --mount=type=cache,target=/root/.cache/go-build GOOS=linux GOARCH=${TARGETARCH} go build -o /manager ./cmd/handler -ARG FROM=quay.io/centos/centos:stream8 +ARG FROM=quay.io/centos/centos:stream9 FROM ${FROM} ARG NMSTATE_SOURCE=distro @@ -23,7 +23,7 @@ COPY --from=build /manager /usr/local/bin/manager COPY --from=build /workdir/build/install-nmstate.${NMSTATE_SOURCE}.sh install-nmstate.sh RUN ./install-nmstate.sh && \ - dnf install -b -y iproute iputils && \ + dnf install -b -y NetworkManager iproute iputils && \ rm ./install-nmstate.sh && \ dnf clean all diff --git a/build/install-nmstate.distro.sh b/build/install-nmstate.distro.sh index cc5718a60..6fd77511d 100755 --- a/build/install-nmstate.distro.sh +++ b/build/install-nmstate.distro.sh @@ -1,3 +1,7 @@ #!/bin/bash -xe -dnf install -b -y -x "*alpha*" -x "*beta*" nmstate nmstate-plugin-ovsdb +#dnf install -b -y -x "*alpha*" -x "*beta*" nmstate + +dnf install -b -y dnf-plugins-core +dnf copr enable -y packit/nmstate-nmstate-2280 +dnf install -b -y nmstate diff --git a/build/install-nmstate.git.sh b/build/install-nmstate.git.sh index 5f7c3f244..409112add 100755 --- a/build/install-nmstate.git.sh +++ b/build/install-nmstate.git.sh @@ -2,4 +2,4 @@ dnf install -b -y dnf-plugins-core dnf copr enable -y nmstate/nmstate-git -dnf install -b -y nmstate nmstate-plugin-ovsdb +dnf install -b -y nmstate diff --git a/bundle/manifests/nmstate.io_nmstates.yaml b/bundle/manifests/nmstate.io_nmstates.yaml index 8805d4b3a..79906cbfe 100644 --- a/bundle/manifests/nmstate.io_nmstates.yaml +++ b/bundle/manifests/nmstate.io_nmstates.yaml @@ -1812,8 +1812,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -1970,8 +1968,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/bundle/manifests/nmstate.io_nodenetworkconfigurationenactments.yaml b/bundle/manifests/nmstate.io_nodenetworkconfigurationenactments.yaml index 1c707fbd7..205732e1a 100644 --- a/bundle/manifests/nmstate.io_nodenetworkconfigurationenactments.yaml +++ b/bundle/manifests/nmstate.io_nodenetworkconfigurationenactments.yaml @@ -73,8 +73,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -170,8 +168,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/bundle/manifests/nmstate.io_nodenetworkconfigurationpolicies.yaml b/bundle/manifests/nmstate.io_nodenetworkconfigurationpolicies.yaml index 86d6826aa..640c0c0c4 100644 --- a/bundle/manifests/nmstate.io_nodenetworkconfigurationpolicies.yaml +++ b/bundle/manifests/nmstate.io_nodenetworkconfigurationpolicies.yaml @@ -87,8 +87,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -187,8 +185,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -283,8 +279,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/bundle/manifests/nmstate.io_nodenetworkstates.yaml b/bundle/manifests/nmstate.io_nodenetworkstates.yaml index 3958d8c20..2900df56d 100644 --- a/bundle/manifests/nmstate.io_nodenetworkstates.yaml +++ b/bundle/manifests/nmstate.io_nodenetworkstates.yaml @@ -49,8 +49,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -112,8 +110,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/cluster/kubevirtci.sh b/cluster/kubevirtci.sh index 95fd809e3..01ced15d3 100644 --- a/cluster/kubevirtci.sh +++ b/cluster/kubevirtci.sh @@ -1,5 +1,5 @@ -export KUBEVIRT_PROVIDER=${KUBEVIRT_PROVIDER:-'k8s-1.24'} -export KUBEVIRTCI_TAG=2211021552-8cca8c0 +export KUBEVIRT_PROVIDER=${KUBEVIRT_PROVIDER:-'k8s-1.26-centos9'} +export KUBEVIRTCI_TAG=2303201102-ef46217 KUBEVIRTCI_REPO='https://github.com/kubevirt/kubevirtci.git' KUBEVIRTCI_PATH="${PWD}/_kubevirtci" diff --git a/cluster/up.sh b/cluster/up.sh index edb79159a..ffab74906 100755 --- a/cluster/up.sh +++ b/cluster/up.sh @@ -21,8 +21,9 @@ for node in $(./cluster/kubectl.sh get nodes --no-headers | awk '{print $1}'); d done done -echo 'Enabling and starting up openvswitch' +echo 'Upgrading NetworkManager and enabling and starting up openvswitch' for node in $(./cluster/kubectl.sh get nodes --no-headers | awk '{print $1}'); do + ./cluster/cli.sh ssh ${node} -- sudo dnf upgrade -y NetworkManager ./cluster/cli.sh ssh ${node} -- sudo systemctl daemon-reload ./cluster/cli.sh ssh ${node} -- sudo systemctl enable openvswitch ./cluster/cli.sh ssh ${node} -- sudo systemctl restart openvswitch diff --git a/controllers/handler/node_controller.go b/controllers/handler/node_controller.go index aa9d11e20..65a1bcb5a 100644 --- a/controllers/handler/node_controller.go +++ b/controllers/handler/node_controller.go @@ -62,7 +62,6 @@ type NodeReconciler struct { lastState shared.State nmstateUpdater NmstateUpdater nmstatectlShow NmstatectlShow - deviceInfo state.DeviceInfoer } // Reconcile reads that state of the cluster for a Node object and makes changes based on the state read @@ -77,7 +76,7 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, request ctrl.Request) (c return ctrl.Result{}, err } - currentState, err := state.FilterOut(shared.NewState(currentStateRaw), r.deviceInfo) + currentState, err := state.FilterOut(shared.NewState(currentStateRaw)) if err != nil { return ctrl.Result{}, err } @@ -126,7 +125,7 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, request ctrl.Request) (c func (r *NodeReconciler) getDependencyVersions() *nmstate.DependencyVersions { handlerNetworkManagerVersion, err := nmstate.ExecuteCommand("nmcli", "--version") if err != nil { - r.Log.Info("error retrieving handler NetworkManager version: %s", err.Error()) + r.Log.Error(err, "failed retrieving handler NetworkManager version") } // remove leading characters up to last space split := strings.Split(handlerNetworkManagerVersion, " ") @@ -134,14 +133,14 @@ func (r *NodeReconciler) getDependencyVersions() *nmstate.DependencyVersions { handlerNmstateVersion, err := nmstate.ExecuteCommand("nmstatectl", "--version") if err != nil { - r.Log.Info("error retrieving handler nmstate version: %s", err.Error()) + r.Log.Error(err, "failed retrieving handler nmstate version") } hostNmstateVersion := "" nmClient, err := networkmanager.NewClientPrivate() if err != nil { - r.Log.Info("error retrieving new client: %s", err.Error()) + r.Log.Error(err, "failed retrieving new client") return &nmstate.DependencyVersions{ HandlerNetworkManagerVersion: handlerNetworkManagerVersion, @@ -167,7 +166,6 @@ func (r *NodeReconciler) getDependencyVersions() *nmstate.DependencyVersions { func (r *NodeReconciler) SetupWithManager(mgr ctrl.Manager) error { r.nmstateUpdater = nmstate.CreateOrUpdateNodeNetworkState r.nmstatectlShow = nmstatectl.Show - r.deviceInfo = state.DeviceInfo{} // By default all this functors return true so controller watch all events, // but we only want to watch create/delete for current node. diff --git a/controllers/handler/node_controller_test.go b/controllers/handler/node_controller_test.go index 3e293b181..795a5309b 100644 --- a/controllers/handler/node_controller_test.go +++ b/controllers/handler/node_controller_test.go @@ -36,8 +36,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" - networkmanager "github.com/phoracek/networkmanager-go/src" - "github.com/nmstate/kubernetes-nmstate/api/shared" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" "github.com/nmstate/kubernetes-nmstate/pkg/nmstatectl" @@ -45,15 +43,6 @@ import ( "github.com/nmstate/kubernetes-nmstate/pkg/state" ) -type fakeDeviceInfo struct{} - -func (fakeDeviceInfo) DeviceStates() (map[string]networkmanager.DeviceState, error) { - return map[string]networkmanager.DeviceState{ - "eth1": networkmanager.DeviceStateActivated, - "eth2": networkmanager.DeviceStateActivated, - }, nil -} - var _ = Describe("Node controller reconcile", func() { var ( cl client.Client @@ -100,7 +89,6 @@ var _ = Describe("Node controller reconcile", func() { reconciler.Scheme = s reconciler.nmstateUpdater = nmstate.CreateOrUpdateNodeNetworkState reconciler.nmstatectlShow = nmstatectl.Show - reconciler.deviceInfo = fakeDeviceInfo{} reconciler.lastState = shared.NewState("lastState") observedState = ` --- @@ -114,7 +102,7 @@ routes: ` var err error - filteredOutObservedState, err = state.FilterOut(shared.NewState(observedState), reconciler.deviceInfo) + filteredOutObservedState, err = state.FilterOut(shared.NewState(observedState)) Expect(err).ToNot(HaveOccurred()) reconciler.nmstatectlShow = func() (string, error) { @@ -209,7 +197,7 @@ routes: obtainedNNS := nmstatev1beta1.NodeNetworkState{} err = cl.Get(context.TODO(), types.NamespacedName{Name: existingNodeName}, &obtainedNNS) Expect(err).ToNot(HaveOccurred()) - filteredOutExpectedState, err := state.FilterOut(shared.NewState(expectedStateRaw), reconciler.deviceInfo) + filteredOutExpectedState, err := state.FilterOut(shared.NewState(expectedStateRaw)) Expect(err).ToNot(HaveOccurred()) Expect(obtainedNNS.Status.CurrentState.String()).To(Equal(filteredOutExpectedState.String())) }) diff --git a/deploy/crds/nmstate.io_nmstates.yaml b/deploy/crds/nmstate.io_nmstates.yaml index c91a06422..34799fd3d 100644 --- a/deploy/crds/nmstate.io_nmstates.yaml +++ b/deploy/crds/nmstate.io_nmstates.yaml @@ -1813,8 +1813,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -1971,8 +1969,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml b/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml index e28faa9f8..424a1644d 100644 --- a/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml +++ b/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml @@ -74,8 +74,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -171,8 +169,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml b/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml index c843f6245..638c6a371 100644 --- a/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml +++ b/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml @@ -88,8 +88,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -188,8 +186,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -284,8 +280,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/deploy/crds/nmstate.io_nodenetworkstates.yaml b/deploy/crds/nmstate.io_nodenetworkstates.yaml index e6436c23d..b961583ff 100644 --- a/deploy/crds/nmstate.io_nodenetworkstates.yaml +++ b/deploy/crds/nmstate.io_nodenetworkstates.yaml @@ -50,8 +50,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: @@ -113,8 +111,6 @@ spec: type: string message: type: string - messageEncoded: - type: string reason: type: string status: diff --git a/pkg/enactmentstatus/conditions/conditions.go b/pkg/enactmentstatus/conditions/conditions.go index 85ae18aa6..96bd67ee8 100644 --- a/pkg/enactmentstatus/conditions/conditions.go +++ b/pkg/enactmentstatus/conditions/conditions.go @@ -117,14 +117,7 @@ func (ec *EnactmentConditions) updateEnactmentConditions( } func SetFailedToConfigure(conditions *nmstate.ConditionList, message string) { - strippedMessage := enactmentstatus.FormatErrorString(message) - SetFailed(conditions, nmstate.NodeNetworkConfigurationEnactmentConditionFailedToConfigure, strippedMessage) - setFailedToConfigureEncodedMessage(conditions, message) -} - -func setFailedToConfigureEncodedMessage(conditions *nmstate.ConditionList, message string) { - condition := conditions.Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing) - condition.MessageEncoded = enactmentstatus.CompressAndEncodeMessage(message) + SetFailed(conditions, nmstate.NodeNetworkConfigurationEnactmentConditionFailedToConfigure, message) } func SetFailed(conditions *nmstate.ConditionList, reason nmstate.ConditionReason, message string) { diff --git a/pkg/enactmentstatus/message.go b/pkg/enactmentstatus/message.go deleted file mode 100644 index 12028f103..000000000 --- a/pkg/enactmentstatus/message.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -Copyright The Kubernetes NMState Authors. - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package enactmentstatus - -import ( - "bytes" - "compress/gzip" - b64 "encoding/base64" - "io" - "regexp" - "strings" -) - -// The function strips disarranged parts of the error messages, so it is easier to read for the user -func FormatErrorString(errorMessage string) string { - var sb strings.Builder - errorLines := strings.Split(errorMessage, "\n") - index := 0 - if strings.Contains(errorLines[0], "error reconciling NodeNetworkConfigurationPolicy") { - sb.WriteString(errorLines[0] + "\n") - index++ - } - - re := regexp.MustCompile(`\s*(failed to execute.*'exit status \d+') '{2}\s'`) - matches := re.FindStringSubmatch(errorLines[index]) - if len(matches) == 2 { //nolint:gomnd - sb.WriteString(strings.TrimRight(matches[1], " ") + "\n") - index++ - } - index = skipLines(errorLines, index) - - formatLines(index, errorLines, &sb) - - return sb.String() -} - -// Loops over all lines in error message and selects lines that should be kept -func formatLines(index int, errorLines []string, sb *strings.Builder) { - shouldFormatLine := true - for index < len(errorLines) { - if errorLines[index] == "---" { - shouldFormatLine = false - } - processLine(&errorLines[index], sb, shouldFormatLine) - index++ - index = skipLines(errorLines, index) - } -} - -// Simplifies a line that should be kept in the error message -func processLine(errorLine *string, sb *strings.Builder, shouldFormatLine bool) { - if !shouldFormatLine { - sb.WriteString(*errorLine + "\n") - return - } - lineSplitByColon := strings.Split(strings.TrimRight(*errorLine, " "), ": ") - indent := "" - for _, lineSection := range lineSplitByColon { - sb.WriteString(indent + lineSection + "\n") - indent += " " - } -} - -func skipLines(lines []string, index int) int { - if index >= len(lines) { - return index - } - - regexMatchFileTrace := regexp.MustCompile(`\A\s*File "\S*",\sline\s\d*,\sin`) - regexTraceback := regexp.MustCompile(`\A\s*Traceback\s\(most\srecent\scall\slast\):`) - regexWithDateTime := regexp.MustCompile(`\A\s*\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}`) - regexCurrentState := regexp.MustCompile(`.*->\scurrentState:\s---`) - regexUnhandledMessage := regexp.MustCompile(`\AUnhandled\s.*\sfor\s`) - regexKeywords := regexp.MustCompile(`DEBUG|WARNING|UserWarning:|warnings\.warn\(`) - - trimmedLine := strings.Trim(lines[index], ": ") - - if lineEmpty(trimmedLine) { - index++ - return skipLines(lines, index) - } - if matched := regexTraceback.MatchString(lines[index]); matched { - index++ - isTraceback := regexMatchFileTrace.MatchString(lines[index]) - for isTraceback { - index += 2 - isTraceback = regexMatchFileTrace.MatchString(lines[index]) - } - return skipLines(lines, index) - } - if matched := regexWithDateTime.MatchString(lines[index]); matched { - index++ - return skipLines(lines, index) - } - if matched := regexUnhandledMessage.MatchString(lines[index]); matched { - index++ - return skipLines(lines, index) - } - if matched := regexKeywords.MatchString(lines[index]); matched { - index++ - return skipLines(lines, index) - } - if matched := regexCurrentState.MatchString(lines[index]); matched { - index = len(lines) - 1 - return skipLines(lines, index) - } - - return index -} - -func lineEmpty(trimmedLine string) bool { - return trimmedLine == "" || trimmedLine == "'" -} - -func CompressAndEncodeMessage(message string) string { - compressedMessage, err := compressMessage(message) - if err != nil { - return "" - } - return encodeMessage(compressedMessage) -} - -func compressMessage(message string) (bytes.Buffer, error) { - var buf bytes.Buffer - writer := gzip.NewWriter(&buf) - - _, err := writer.Write([]byte(message)) - if err != nil { - return bytes.Buffer{}, err - } - - if err := writer.Close(); err != nil { - return bytes.Buffer{}, err - } - - return buf, nil -} - -func encodeMessage(buf bytes.Buffer) string { - return b64.StdEncoding.EncodeToString(buf.Bytes()) -} - -func DecodeAndDecompressMessage(message string) string { - decodedMessage := decodeMessage(message) - return decompressMessage(decodedMessage) -} - -func decodeMessage(encodedMessage string) []byte { - data, _ := b64.StdEncoding.DecodeString(encodedMessage) - return data -} - -func decompressMessage(data []byte) string { - bytesReader := bytes.NewReader(data) - gzipReader, err := gzip.NewReader(bytesReader) - if err != nil { - return "" - } - decompressedMessage, _ := io.ReadAll(gzipReader) - return string(decompressedMessage) -} diff --git a/pkg/enactmentstatus/message_test.go b/pkg/enactmentstatus/message_test.go deleted file mode 100644 index a61257616..000000000 --- a/pkg/enactmentstatus/message_test.go +++ /dev/null @@ -1,109 +0,0 @@ -/* -Copyright The Kubernetes NMState Authors. - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package enactmentstatus - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("Error messages formatting", func() { - var ( - debugInvalidInput = " 2021-04-15 08:17:35,057 root DEBUG Async action: Create checkpoint started\n " + - "2021-04-15 08:17:35,060 root DEBUG Checkpoint None created for all devices\n" - debugValidInput = "A message containing debug that should not be removed.\n" - tracebackInvalidInput = " Traceback (most recent call last):\n File \"/usr/bin/nmstatectl\", line 11, in \n " + - " load_entry_point('nmstate==0.3.6', 'console_scripts', 'nmstatectl')()\n File \"/usr/lib/python3.6/" + - "site-packages/nmstatectl/nmstatectl.py\", line 69, in main\n f\"Interface {iface.name} has unknown slave: \"\n " + - "libnmstate.error.NmstateValueError: Interface bond1 has unknown slave: eth10\n " - tracebackInvalidOutput = " libnmstate.error.NmstateValueError\n Interface bond1 has unknown slave\n eth10\n" - tracebackValidInput = "A message containing File \"/usr/bin/nmstatectl\" that should not be removed.\n" - failedToExecuteInput = " failed to execute nmstatectl set --no-commit --timeout 480: 'exit status 1' '' '2021-02-22 " + - "11:10:08,962 root WARNING libnm version 1.26.7 mismatches NetworkManager version 1.29.9\n" - failedToExecuteOutput = "failed to execute nmstatectl set --no-commit --timeout 480: 'exit status 1'\n" - pingInvalidInput = "rolling back desired state configuration: failed runnig probes after network changes: failed runnig " + - "probe 'ping' with after network reconfiguration -> currentState: ---\n dns-resolver:\n config:\n " + - "search: []\n server: []\n running: {}\n route-rules:\n config: []\n : failed to retrieve " + - "default gw at runProbes: timed out waiting for the condition" - pingInvalidOutput = " \n failed to retrieve default gw at runProbes\n timed out waiting for the condition\n" - pingValidInput = "rolling back desired state configuration: failed runnig probes after network changes: failed runnig " + - "probe 'ping' with after network reconfiguration.\nThe rest of the message should be kept.\n" - pingValidOutput = "rolling back desired state configuration\n failed runnig probes after network changes\n failed " + - "runnig probe 'ping' with after network reconfiguration.\nThe rest of the message should be kept.\n" - desiredStateYaml = "libnmstate.error.NmstateVerificationError:\n desired\n =======\n---\n name: eth1\n " + - "type: ethernet\n state: up\n" - ) - - Context("With DEBUG text", func() { - It("Should remove DEBUG message", func() { - Expect(FormatErrorString(debugInvalidInput)).To(Equal("")) - }) - It("Should keep message with debug keyword", func() { - Expect(FormatErrorString(debugValidInput)).To(Equal(debugValidInput)) - }) - }) - - Context("With Traceback text", func() { - It("Should remove python traceback", func() { - Expect(FormatErrorString(tracebackInvalidInput)).To(Equal(tracebackInvalidOutput)) - }) - It("Should keep message with File keyword", func() { - Expect(FormatErrorString(tracebackValidInput)).To(Equal(tracebackValidInput)) - }) - }) - - Context("With failed to execute text", func() { - It("Should remove warning form the line", func() { - Expect(FormatErrorString(failedToExecuteInput)).To(Equal(failedToExecuteOutput)) - }) - }) - - Context("With network reconfiguration text", func() { - It("Should remove yaml", func() { - Expect(FormatErrorString(pingInvalidInput)).To(Equal(pingInvalidOutput)) - }) - It("Should keep message", func() { - Expect(FormatErrorString(pingValidInput)).To(Equal(pingValidOutput)) - }) - }) - Context("With yaml states", func() { - It("Should keep the original message", func() { - Expect(FormatErrorString(desiredStateYaml)).To(Equal(desiredStateYaml)) - }) - }) - - Describe("Error messages compression and decompression", func() { - var ( - messages = []string{ - "A message containing debug that should not be removed.\n", - " libnmstate.error.NmstateValueError\n Interface bond1 has unknown slave\n eth10\n", - "A message containing File \"/usr/bin/nmstatectl\" that should not be removed.\n", - "failed to execute nmstatectl set --no-commit --timeout 480: 'exit status 1'\n", - " \n failed to retrieve default gw at runProbes\n timed out waiting for the condition\n", - } - ) - Context("With a sample message", func() { - It("Should decompress the message correctly", func() { - for _, message := range messages { - encodedMessage := CompressAndEncodeMessage(message) - Expect(message).To(Equal(DecodeAndDecompressMessage(encodedMessage))) - } - }) - }) - }) -}) diff --git a/pkg/state/filter.go b/pkg/state/filter.go index ed82632db..2f448f18e 100644 --- a/pkg/state/filter.go +++ b/pkg/state/filter.go @@ -18,13 +18,10 @@ limitations under the License. package state import ( - networkmanager "github.com/phoracek/networkmanager-go/src" - "github.com/nmstate/kubernetes-nmstate/api/shared" "github.com/nmstate/kubernetes-nmstate/pkg/environment" goyaml "gopkg.in/yaml.v2" - logf "sigs.k8s.io/controller-runtime/pkg/log" yaml "sigs.k8s.io/yaml" ) @@ -32,50 +29,14 @@ const ( InterfaceFilter = "interface_filter" ) -var ( - filterLog = logf.Log.WithName(InterfaceFilter) -) - func init() { if !environment.IsHandler() { return } } -type DeviceInfoer interface { - DeviceStates() (map[string]networkmanager.DeviceState, error) -} - -type DeviceInfo struct{} - -func (d DeviceInfo) DeviceStates() (map[string]networkmanager.DeviceState, error) { - nmClient, err := networkmanager.NewClientPrivate() - if err != nil { - filterLog.Error(err, "failed to initialize NetworkManager client") - return nil, err - } - defer nmClient.Close() - - devices, err := nmClient.GetDevices() - if err != nil { - filterLog.Error(err, "failed to list NetworkManager devices") - return nil, err - } - - ifaceStates := map[string]networkmanager.DeviceState{} - for _, device := range devices { - ifaceStates[device.Interface] = device.State - } - return ifaceStates, nil -} - -func FilterOut(currentState shared.State, deviceInfo DeviceInfoer) (shared.State, error) { - devStates, err := deviceInfo.DeviceStates() - if err != nil { - filterLog.Error(err, "failed getting interface states, cannot filter managed interfaces") - return currentState, nil - } - return filterOut(currentState, devStates) +func FilterOut(currentState shared.State) (shared.State, error) { + return filterOut(currentState) } func filterOutRoutes(routes []routeState, filteredInterfaces []interfaceState) []routeState { @@ -130,22 +91,28 @@ func filterOutDynamicAttributes(iface map[string]interface{}) { delete(options, "hello-timer") } -func filterOutInterfaces(ifacesState []interfaceState, deviceStates map[string]networkmanager.DeviceState) []interfaceState { - if deviceStates == nil { - return ifacesState - } - +func filterOutInterfaces(ifacesState []interfaceState) []interfaceState { filteredInterfaces := []interfaceState{} for _, iface := range ifacesState { - if iface.Data["type"] != "veth" || deviceStates[iface.Name] != networkmanager.DeviceStateUnmanaged { - filterOutDynamicAttributes(iface.Data) - filteredInterfaces = append(filteredInterfaces, iface) + if isVeth(iface.Data) && isUnmanaged(iface.Data) { + continue } + filterOutDynamicAttributes(iface.Data) + filteredInterfaces = append(filteredInterfaces, iface) } return filteredInterfaces } -func filterOut(currentState shared.State, deviceStates map[string]networkmanager.DeviceState) (shared.State, error) { +func isVeth(ifaceData map[string]interface{}) bool { + _, ok := ifaceData["veth"] + return ok +} + +func isUnmanaged(ifaceData map[string]interface{}) bool { + return ifaceData["state"] == "ignore" +} + +func filterOut(currentState shared.State) (shared.State, error) { var state rootState if err := yaml.Unmarshal(currentState.Raw, &state); err != nil { return currentState, err @@ -154,7 +121,7 @@ func filterOut(currentState shared.State, deviceStates map[string]networkmanager return currentState, err } - state.Interfaces = filterOutInterfaces(state.Interfaces, deviceStates) + state.Interfaces = filterOutInterfaces(state.Interfaces) if state.Routes != nil { state.Routes.Running = filterOutRoutes(state.Routes.Running, state.Interfaces) state.Routes.Config = filterOutRoutes(state.Routes.Config, state.Interfaces) diff --git a/pkg/state/filter_test.go b/pkg/state/filter_test.go index 87aa46ceb..38b928f09 100644 --- a/pkg/state/filter_test.go +++ b/pkg/state/filter_test.go @@ -21,15 +21,12 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - networkmanager "github.com/phoracek/networkmanager-go/src" - nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" ) var _ = Describe("FilterOut", func() { var ( state, filteredState nmstate.State - ifaceStates map[string]networkmanager.DeviceState ) Context("when there is a linux bridge with gc-timer and hello-timer", func() { @@ -81,10 +78,6 @@ routes: next-hop-interface: eth1 table-id: 254 `) - ifaceStates = map[string]networkmanager.DeviceState{ - "eth1": networkmanager.DeviceStateActivated, - "br1": networkmanager.DeviceStateActivated, - } filteredState = nmstate.NewState(` interfaces: - name: eth1 @@ -132,7 +125,7 @@ routes: `) }) It("should remove dynamic attributes from linux-bridge interface", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).ToNot(HaveOccurred()) Expect(returnedState).To(MatchYAML(filteredState)) }) @@ -143,7 +136,9 @@ routes: state = nmstate.NewState(`interfaces: - name: vethab6030bd state: down - type: veth + type: ethernet + veth: + peer: eth2 routes: config: [] running: @@ -153,13 +148,12 @@ routes: next-hop-interface: vethab6030bd table-id: 254 `) - ifaceStates = map[string]networkmanager.DeviceState{ - "vethab6030bd": networkmanager.DeviceStateActivated, - } filteredState = nmstate.NewState(`interfaces: - name: vethab6030bd state: down - type: veth + type: ethernet + veth: + peer: eth2 routes: config: [] running: @@ -172,7 +166,7 @@ routes: }) It("should keep managed veth interface", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).NotTo(HaveOccurred()) Expect(returnedState).To(MatchYAML(filteredState)) }) @@ -182,8 +176,10 @@ routes: BeforeEach(func() { state = nmstate.NewState(`interfaces: - name: vethab6030bd - state: down - type: veth + state: ignore + type: ethernet + veth: + peer: eth2 routes: config: [] running: @@ -193,9 +189,6 @@ routes: next-hop-interface: vethab6030bd table-id: 254 `) - ifaceStates = map[string]networkmanager.DeviceState{ - "vethab6030bd": networkmanager.DeviceStateUnmanaged, - } filteredState = nmstate.NewState(`interfaces: [] routes: config: [] @@ -204,13 +197,13 @@ routes: }) It("should filter unmanaged veth interface", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).NotTo(HaveOccurred()) Expect(returnedState).To(MatchYAML(filteredState)) }) }) - Context("when there are multiple managed and unmanaged veth interfaces", func() { + Context("when there are multiple managed and unmanaged interfaces", func() { BeforeEach(func() { state = nmstate.NewState(`interfaces: - name: eth1 @@ -218,16 +211,24 @@ routes: type: ethernet - name: veth101 state: down - type: veth + type: ethernet + veth: + peer: eth2 - name: veth102 - state: down - type: veth + state: ignore + type: ethernet + veth: + peer: eth2 - name: vethjyuftrgv state: down - type: veth + type: ethernet + veth: + peer: eth2 - name: vethvasziovs - state: down - type: veth + state: ignore + type: ethernet + veth: + peer: eth2 routes: config: [] running: @@ -257,22 +258,20 @@ routes: next-hop-interface: eth1 table-id: 254 `) - ifaceStates = map[string]networkmanager.DeviceState{ - "veth101": networkmanager.DeviceStateActivated, - "veth102": networkmanager.DeviceStateUnmanaged, - "vethjyuftrgv": networkmanager.DeviceStateActivated, - "vethvasziovs": networkmanager.DeviceStateUnmanaged, - } filteredState = nmstate.NewState(`interfaces: - name: eth1 state: up type: ethernet - name: veth101 state: down - type: veth + type: ethernet + veth: + peer: eth2 - name: vethjyuftrgv state: down - type: veth + type: ethernet + veth: + peer: eth2 routes: config: [] running: @@ -294,66 +293,10 @@ routes: `) }) It("should filter out all unmanaged veth interfaces", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).ToNot(HaveOccurred()) Expect(returnedState).To(MatchYAML(filteredState)) }) - - Context("when we fail to get deviceStates", func() { - BeforeEach(func() { - ifaceStates = nil - filteredState = nmstate.NewState(`interfaces: -- name: eth1 - state: up - type: ethernet -- name: veth101 - state: down - type: veth -- name: veth102 - state: down - type: veth -- name: vethjyuftrgv - state: down - type: veth -- name: vethvasziovs - state: down - type: veth -routes: - config: [] - running: - - destination: fd10:244::8c40/128 - metric: 1024 - next-hop-address: "" - next-hop-interface: veth101 - table-id: 254 - - destination: fd10:244::8c40/128 - metric: 1024 - next-hop-address: "" - next-hop-interface: veth102 - table-id: 254 - - destination: fd10:244::8c40/128 - metric: 1024 - next-hop-address: "" - next-hop-interface: vethjyuftrgv - table-id: 254 - - destination: fd10:244::8c40/128 - metric: 1024 - next-hop-address: "" - next-hop-interface: vethvasziovs - table-id: 254 - - destination: 0.0.0.0/0 - metric: 102 - next-hop-address: 192.168.66.2 - next-hop-interface: eth1 - table-id: 254 -`) - }) - It("should keep the state intact", func() { - returnedState, err := filterOut(state, ifaceStates) - Expect(err).ToNot(HaveOccurred()) - Expect(returnedState).To(MatchYAML(filteredState)) - }) - }) }) Context("With DNS Resolver populated", func() { @@ -379,7 +322,7 @@ dns-resolver: }) It("Should keep the DNS Resolver intact", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).ToNot(HaveOccurred()) Expect(returnedState).To(MatchYAML(state)) }) @@ -387,38 +330,54 @@ dns-resolver: Context("when the interfaces have numeric characters", func() { BeforeEach(func() { - ifaceStates = map[string]networkmanager.DeviceState{ - "0": networkmanager.DeviceStateUnmanaged, - "1101010": networkmanager.DeviceStateUnmanaged, - "0.0": networkmanager.DeviceStateUnmanaged, - "1.0": networkmanager.DeviceStateUnmanaged, - "0xfe": networkmanager.DeviceStateUnmanaged, - "60.e+02": networkmanager.DeviceStateUnmanaged, - "10e+02": networkmanager.DeviceStateUnmanaged, - "70e+02": networkmanager.DeviceStateUnmanaged, - "94475496822e234": networkmanager.DeviceStateUnmanaged, - } state = nmstate.NewState(`interfaces: - name: eth0 type: ethernet - name: '0' - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: '1101010' - type: veth + type: ethernet + state: ignore + veth: + peer: eth2 - name: '0.0' - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: '1.0' - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: '0xfe' - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: '60.e+02' - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: 10e+02 - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: 70e+02 - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore - name: 94475496822e234 - type: veth + type: ethernet + veth: + peer: eth2 + state: ignore routes: config: [] running: @@ -463,7 +422,7 @@ routes: }) It("should filter out interfaces correctly", func() { - returnedState, err := filterOut(state, ifaceStates) + returnedState, err := filterOut(state) Expect(err).NotTo(HaveOccurred()) Expect(returnedState).To(MatchYAML(filteredState)) }) diff --git a/test/cmd/run.go b/test/cmd/run.go index c04ec231f..ea0c52319 100644 --- a/test/cmd/run.go +++ b/test/cmd/run.go @@ -39,7 +39,7 @@ func Run(command string, quiet bool, arguments ...string) (string, error) { fmt.Fprintf(GinkgoWriter, "stdout: %.500s...,\nstderr: %s\n", stdout.String(), stderr.String()) } if err != nil { - return "", fmt.Errorf("%s: %s: %v", stdout.String(), stderr.String(), err) + return "", fmt.Errorf("%s %s: %s %v", command+strings.Join(arguments, " "), stdout.String(), stderr.String(), err) } - return stdout.String(), err + return stdout.String(), nil } diff --git a/test/e2e/handler/error_messages_formatting_test.go b/test/e2e/handler/error_messages_formatting_test.go deleted file mode 100644 index 1752e6c3a..000000000 --- a/test/e2e/handler/error_messages_formatting_test.go +++ /dev/null @@ -1,232 +0,0 @@ -/* -Copyright The Kubernetes NMState Authors. - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package handler - -import ( - "fmt" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" - enactmentconditions "github.com/nmstate/kubernetes-nmstate/pkg/enactmentstatus/conditions" - policyconditions "github.com/nmstate/kubernetes-nmstate/test/e2e/policy" -) - -func createInterfaceWithNonExistingCapture() nmstate.State { - return nmstate.NewState(`interfaces: - - name: "{{ capture.base-iface.interfaces.0.name }}" - type: ethernet - state: up`) -} - -func createInterfaceWithMismatchedName() nmstate.State { - return nmstate.NewState(`interfaces: - - name: eth666 - type: ethernet - state: up`) -} - -func createInterfaceWithInvalidField() nmstate.State { - return nmstate.NewState(fmt.Sprintf(`interfaces: - - name: %s - type: ethernet - invalid_state: up`, primaryNic)) -} - -func createInterfaceWithIncorrectIP() nmstate.State { - return nmstate.NewState(fmt.Sprintf(`interfaces: - - name: %s - type: ethernet - state: up - ipv4: - address: - - ip: "192.168.45.33" - prefix-length: 24 - dhcp: false - enabled: true`, primaryNic)) -} - -func createPolicyAndWaitForEnactmentCondition(policy string, desiredState func() nmstate.State, nodeHostname string) { - By("Creating the policy") - err := setDesiredStateWithPolicyAndNodeSelector(policy, desiredState(), map[string]string{"kubernetes.io/hostname": nodeHostname}) - if err != nil { - return - } - - By("Waiting until the node becomes ready again") - waitForNodesReady() - - By("Waiting for enactment to be failing") - policyconditions.EnactmentConditionsStatusForPolicyEventually( - nodes[0], - policy, - ).Should(policyconditions.MatchConditionsFrom(enactmentconditions.SetFailedToConfigure)) -} - -var _ = Describe("NodeNetworkState", func() { - var ( - defaultPolicy = "errors-policy" - - messagesToRemove = []string{ - "DEBUG Async action: Create checkpoint started", - "DEBUG Checkpoint None created for all devices", - "Traceback (most recent call last):", - "DEBUG Nispor: current network state", - "WARNING libnm version", - "rolling back desired state configuration: failed running probes after network changes: ", - "failed running probe 'ping' with after network reconfiguration -> currentState:", - "warnings.warn", - } - ) - - Context("with invalid field", func() { - var ( - messagesToKeep = []string{ - "libnmstate.error.NmstateVerificationError", - "desired", - "current", - "difference", - } - ) - - BeforeEach(func() { - createPolicyAndWaitForEnactmentCondition(defaultPolicy, createInterfaceWithInvalidField, nodes[0]) - }) - - It("should discard disarranged parts of the message", func() { - for _, unwantedMessage := range messagesToRemove { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).NotTo(ContainSubstring(unwantedMessage)) - } - }) - - It("should keep desired parts of the message", func() { - for _, desiredMessage := range messagesToKeep { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).To(ContainSubstring(desiredMessage)) - } - }) - }) - - Context("with mismatched interface name", func() { - var ( - messagesToKeep = []string{ - "libnmstate.error.NmstateLibnmError", - "No suitable device found for this connection", - "mismatching interface name", - } - ) - - BeforeEach(func() { - createPolicyAndWaitForEnactmentCondition(defaultPolicy, createInterfaceWithMismatchedName, nodes[0]) - }) - - It("should discard disarranged parts of the message", func() { - for _, unwantedMessage := range messagesToRemove { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).NotTo(ContainSubstring(unwantedMessage)) - } - }) - - It("should keep desired parts of the message", func() { - for _, desiredMessage := range messagesToKeep { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).To(ContainSubstring(desiredMessage)) - } - }) - }) - - Context("with ping fail", func() { - var ( - messagesToKeep = []string{ - "timed out waiting for the condition", - } - ) - - BeforeEach(func() { - createPolicyAndWaitForEnactmentCondition(defaultPolicy, createInterfaceWithIncorrectIP, nodes[0]) - }) - - AfterEach(func() { - resetDesiredStateForNodes() - By("Remove the policy") - deletePolicy(defaultPolicy) - }) - - It("should discard disarranged parts of the message and keep desired parts of the message", func() { - for _, unwantedMessage := range messagesToRemove { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).NotTo(ContainSubstring(unwantedMessage)) - } - for _, desiredMessage := range messagesToKeep { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], - defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing). - Message, - ).To(ContainSubstring(desiredMessage)) - } - }) - }) - - Context("with non existing capture", func() { - BeforeEach(func() { - createPolicyAndWaitForEnactmentCondition(defaultPolicy, createInterfaceWithNonExistingCapture, nodes[0]) - }) - - AfterEach(func() { - By("Remove the policy") - deletePolicy(defaultPolicy) - }) - - It("should contain the error message", func() { - Expect( - policyconditions.EnactmentConditionsStatus( - nodes[0], defaultPolicy, - ).Find(nmstate.NodeNetworkConfigurationEnactmentConditionFailing).Message, - ).To(ContainSubstring("failure generating desiredState and capturedStates")) - }) - }) -}) diff --git a/test/e2e/handler/main_test.go b/test/e2e/handler/main_test.go index 10fc0ea80..54d0d6db7 100644 --- a/test/e2e/handler/main_test.go +++ b/test/e2e/handler/main_test.go @@ -97,6 +97,11 @@ var _ = BeforeSuite(func() { knmstateReporter = knmstatereporter.New("test_logs/e2e/handler", testenv.OperatorNamespace, nodes) knmstateReporter.Cleanup() + By("Getting nodes initial state") + for _, node := range allNodes { + nodeState := nodeInterfacesState(node, interfacesToIgnore) + nodesInterfacesState[node] = nodeState + } }) func TestE2E(t *testing.T) { @@ -113,12 +118,6 @@ var _ = BeforeEach(func() { bridge1 = nextBridge() Byf("Setting bridge1=%s", bridge1) startTime = time.Now() - - By("Getting nodes initial state") - for _, node := range allNodes { - nodeState := nodeInterfacesState(node, interfacesToIgnore) - nodesInterfacesState[node] = nodeState - } }) var _ = AfterEach(func() { diff --git a/test/e2e/handler/nns_dependencies_test.go b/test/e2e/handler/nns_dependencies_test.go index 4c6ffbda7..fa95c28c1 100644 --- a/test/e2e/handler/nns_dependencies_test.go +++ b/test/e2e/handler/nns_dependencies_test.go @@ -38,7 +38,6 @@ var _ = Describe("[nns] NNS Dependencies", func() { key := types.NamespacedName{Name: node} status := nodeNetworkState(key).Status Expect(status.HostNetworkManagerVersion).ToNot(BeEmpty()) - Expect(status.HandlerNetworkManagerVersion).ToNot(BeEmpty()) Expect(status.HandlerNmstateVersion).ToNot(BeEmpty()) } }) diff --git a/test/e2e/handler/rollback_test.go b/test/e2e/handler/rollback_test.go index 6e6da7c8a..008a26c83 100644 --- a/test/e2e/handler/rollback_test.go +++ b/test/e2e/handler/rollback_test.go @@ -148,17 +148,16 @@ var _ = Describe("rollback", func() { secondaryNicCustomAddress := "192.168.100.1" BeforeEach(func() { By("Configure a invalid default gw") + applyTime := time.Now() updateDesiredStateAtNode(nodes[0], badDefaultGw(secondaryNicCustomAddress, firstSecondaryNic, 200)) + policy.WaitForPolicyTransitionUpdateWithTime(TestPolicy, applyTime) + policy.WaitForAvailablePolicy(TestPolicy) }) AfterEach(func() { By("Clean up desired state") resetDesiredStateForNodes() }) It("should not rollback to the previous configuration", func() { - By("Should be available") - policy.WaitForPolicyTransitionUpdate(TestPolicy) - policy.WaitForAvailablePolicy(TestPolicy) - Eventually(func() string { return ipv4Address(nodes[0], firstSecondaryNic) }, 3*time.Minute, ReadInterval).Should(Equal(secondaryNicCustomAddress), "IP has not being set") diff --git a/test/e2e/policy/conditions.go b/test/e2e/policy/conditions.go index 3bfdc436d..b0c8c5c2e 100644 --- a/test/e2e/policy/conditions.go +++ b/test/e2e/policy/conditions.go @@ -30,6 +30,7 @@ import ( "sigs.k8s.io/yaml" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/nmstate/kubernetes-nmstate/api/shared" nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" @@ -156,12 +157,18 @@ func ContainPolicyDegraded() gomegatypes.GomegaMatcher { })) } -func WaitForPolicyTransitionUpdate(policy string) { - now := time.Now() +func WaitForPolicyTransitionUpdateWithTime(policy string, applyTime time.Time) { + // the k8s times at status are rounded to seconds + roundedApplyTime := metav1.NewTime(applyTime).Rfc3339Copy().Time EventuallyWithOffset(1, func() time.Time { availableCondition := Status(policy).Find(shared.NodeNetworkConfigurationPolicyConditionAvailable) return availableCondition.LastTransitionTime.Time - }, 4*time.Minute, 5*time.Second).Should(BeTemporally(">=", now), fmt.Sprintf("Policy %s should have updated transition time", policy)) + }, 4*time.Minute, 5*time.Second).Should(BeTemporally(">=", roundedApplyTime), + fmt.Sprintf("Policy %s should have updated transition time", policy)) +} + +func WaitForPolicyTransitionUpdate(policy string) { + WaitForPolicyTransitionUpdateWithTime(policy, time.Now()) } func WaitForAvailableTestPolicy() { diff --git a/vendor/github.com/nmstate/kubernetes-nmstate/api/shared/condition_types.go b/vendor/github.com/nmstate/kubernetes-nmstate/api/shared/condition_types.go index b782a0633..b54e5c304 100644 --- a/vendor/github.com/nmstate/kubernetes-nmstate/api/shared/condition_types.go +++ b/vendor/github.com/nmstate/kubernetes-nmstate/api/shared/condition_types.go @@ -31,7 +31,6 @@ type Condition struct { Status corev1.ConditionStatus `json:"status"` Reason ConditionReason `json:"reason,omitempty"` Message string `json:"message,omitempty"` - MessageEncoded string `json:"messageEncoded,omitempty"` LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime,omitempty"` LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` }