You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2022/08/17 09:55:32 UTC

[apisix-ingress-controller] branch v1.5.0 updated: fix: nodes convert failed (#1222) (#1250)

This is an automated email from the ASF dual-hosted git repository.

zhangjintao pushed a commit to branch v1.5.0
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/v1.5.0 by this push:
     new ca063cdf fix: nodes convert failed (#1222) (#1250)
ca063cdf is described below

commit ca063cdfd400f6bd54421dd3168ebb4d42266fd8
Author: Jintao Zhang <zh...@gmail.com>
AuthorDate: Wed Aug 17 17:55:27 2022 +0800

    fix: nodes convert failed (#1222) (#1250)
    
    Co-authored-by: Xin Rong <ro...@api7.ai>
---
 pkg/apisix/resource_test.go  | 45 ++++++++++++++++++++++++++++++++++++++++++++
 pkg/types/apisix/v1/types.go | 43 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/pkg/apisix/resource_test.go b/pkg/apisix/resource_test.go
index 2c969960..528f801d 100644
--- a/pkg/apisix/resource_test.go
+++ b/pkg/apisix/resource_test.go
@@ -78,6 +78,51 @@ func TestItemConvertRoute(t *testing.T) {
 	assert.Equal(t, r.Name, "unknown")
 }
 
+func TestItemConvertUpstream(t *testing.T) {
+	ite := &item{
+		Key:   "/apisix/upstreams/419655639963271872",
+		Value: json.RawMessage(`{ "nodes":{"httpbin.org:80":1, "foo.com:8080": 2}}`),
+	}
+	ups, err := ite.upstream()
+	assert.Nil(t, err)
+	assert.Len(t, ups.Nodes, 2)
+	assert.Equal(t, ups.Nodes[0], v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1})
+	assert.Equal(t, ups.Nodes[1], v1.UpstreamNode{Host: "foo.com", Port: 8080, Weight: 2})
+
+	ite = &item{
+		Key: "/apisix/upstreams/419655639963271872",
+		Value: json.RawMessage(`
+{
+	"id": "419655639963271872",
+	"nodes": [
+		{
+			"host": "httpbin.org",
+			"port": 80,
+			  "weight": 1
+		},
+		{
+			"host": "httpbin.com",
+			"port": 8080,
+			"weight": 1
+		}
+	]
+}`),
+	}
+	ups, err = ite.upstream()
+	assert.Nil(t, err)
+	assert.Len(t, ups.Nodes, 2)
+	assert.Equal(t, ups.Nodes[0], v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1})
+	assert.Equal(t, ups.Nodes[1], v1.UpstreamNode{Host: "httpbin.com", Port: 8080, Weight: 1})
+
+	ite = &item{
+		Key:   "/apisix/upstreams/419655639963271872",
+		Value: json.RawMessage(`{ "id":"419655639963271872" }`),
+	}
+	ups, err = ite.upstream()
+	assert.Nil(t, err)
+	assert.Len(t, ups.Nodes, 0)
+}
+
 func TestRouteVarsUnmarshalJSONCompatibility(t *testing.T) {
 	var route v1.Route
 	data := `{"vars":{}}`
diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go
index 3da9d462..8ffcd0d3 100644
--- a/pkg/types/apisix/v1/types.go
+++ b/pkg/types/apisix/v1/types.go
@@ -18,6 +18,7 @@ import (
 	"bytes"
 	"encoding/json"
 	"errors"
+	"fmt"
 	"strconv"
 	"strings"
 	"time"
@@ -216,14 +217,22 @@ type UpstreamNodes []UpstreamNode
 // and by default empty array will be encoded as '{}'.
 // We have to maintain the compatibility.
 func (n *UpstreamNodes) UnmarshalJSON(p []byte) error {
+	var data []UpstreamNode
 	if p[0] == '{' {
-		if len(p) != 2 {
-			return errors.New("unexpected non-empty object")
+		value := map[string]float64{}
+		if err := json.Unmarshal(p, &value); err != nil {
+			return err
+		}
+		for k, v := range value {
+			node, err := mapKV2Node(k, v)
+			if err != nil {
+				return err
+			}
+			data = append(data, *node)
 		}
-		*n = UpstreamNodes{}
+		*n = data
 		return nil
 	}
-	var data []UpstreamNode
 	if err := json.Unmarshal(p, &data); err != nil {
 		return err
 	}
@@ -231,6 +240,32 @@ func (n *UpstreamNodes) UnmarshalJSON(p []byte) error {
 	return nil
 }
 
+func mapKV2Node(key string, val float64) (*UpstreamNode, error) {
+	hp := strings.Split(key, ":")
+	host := hp[0]
+	//  according to APISIX upstream nodes policy, port is required
+	port := "80"
+
+	if len(hp) > 2 {
+		return nil, errors.New("invalid upstream node")
+	} else if len(hp) == 2 {
+		port = hp[1]
+	}
+
+	portInt, err := strconv.Atoi(port)
+	if err != nil {
+		return nil, fmt.Errorf("parse port to int fail: %s", err.Error())
+	}
+
+	node := &UpstreamNode{
+		Host:   host,
+		Port:   portInt,
+		Weight: int(val),
+	}
+
+	return node, nil
+}
+
 // UpstreamNode is the node in upstream
 // +k8s:deepcopy-gen=true
 type UpstreamNode struct {