You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2020/11/23 07:00:17 UTC

[GitHub] [apisix-dashboard] tokers commented on a change in pull request #847: fix: nodes format not works

tokers commented on a change in pull request #847:
URL: https://github.com/apache/apisix-dashboard/pull/847#discussion_r528495218



##########
File path: api/internal/core/entity/format.go
##########
@@ -17,26 +17,30 @@
 package entity
 
 import (
-	"log"
 	"strconv"
 	"strings"
+
+	"github.com/apisix/manager-api/log"
 )
 
 func NodesFormat(obj interface{}) interface{} {
 	var nodes []*Node
-	if value, ok := obj.(map[string]float64); ok {
+	switch objType := obj.(type) {
+	case map[string]float64:
+		log.Infof("nodes type: %v", objType)
 		var strArr []string
+		value := obj.(map[string]float64)
 		for key, val := range value {
 			node := &Node{}
 			strArr = strings.Split(key, ":")
 			if len(strArr) != 2 {
-				log.Println("length of string array is not 2")
+				log.Warn("length of string array is not 2")
 				return obj
 			}
 
 			port, err := strconv.Atoi(strArr[1])
 			if err != nil {
-				log.Println("parse int fail:", err)
+				log.Errorf("parse int fail:", err)

Review comment:
       Missing format prompt like `%v` or `%s`, the `%s` is preferred since we don't want to see the dynamic type of error, we only need the literal string. This lint error can be detected by golangci-lint.

##########
File path: api/internal/core/entity/format.go
##########
@@ -46,13 +50,35 @@ func NodesFormat(obj interface{}) interface{} {
 			nodes = append(nodes, node)

Review comment:
       What about using structure literal initialization:
   
   ```go
   node := &Node{
       Host: strArr[0].
       Port: port,
       Weight: int(val)
   }
   ```

##########
File path: api/internal/core/entity/format.go
##########
@@ -46,13 +50,35 @@ func NodesFormat(obj interface{}) interface{} {
 			nodes = append(nodes, node)
 		}
 		return nodes
-	}
+	case map[string]interface{}:
+		log.Infof("nodes type: %v", objType)
+		var strArr []string
+		value := obj.(map[string]interface{})
+		for key, val := range value {
+			node := &Node{}
+			strArr = strings.Split(key, ":")
+			if len(strArr) != 2 {
+				log.Warn("length of string array is not 2")
+				return obj
+			}
 
-	if nodes, ok := obj.([]*Node); ok {
-		return nodes
-	}
+			port, err := strconv.Atoi(strArr[1])
+			if err != nil {
+				log.Errorf("parse int fail:", err)
+				return obj
+			}
 
-	if list, ok := obj.([]interface{}); ok {
+			node.Host = strArr[0]
+			node.Port = port
+			node.Weight = int(val.(float64))

Review comment:
       Ditto (literal structure initialization)

##########
File path: api/internal/core/entity/format_test.go
##########
@@ -23,19 +23,62 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestConsumer(t *testing.T) {
-	nodesStr := `{
-    "127.0.0.1:8080": 1
-  }`
-	nodesMap := map[string]float64{}
-	err := json.Unmarshal([]byte(nodesStr), &nodesMap)
+func TestNodesFormat(t *testing.T){
+	// route data saved in ETCD
+	routeStr := `{
+        "uris": ["/*"],
+        "upstream": {
+            "type": "roundrobin",
+            "nodes": [{
+                "host": "127.0.0.1",
+                "port": 80,
+                "weight": 0
+            }]
+        }
+    }`
+
+	// bind struct
+	var  route Route
+	err := json.Unmarshal([]byte(routeStr), &route)
 	assert.Nil(t, err)
 
-	res := NodesFormat(nodesMap)
-	nodes := res.([]*Node)
+	// nodes format
+	nodes := NodesFormat(route.Upstream.Nodes)
 
-	assert.Equal(t, 1, len(nodes))
-	assert.Equal(t, "127.0.0.1", nodes[0].Host)
-	assert.Equal(t, 8080, nodes[0].Port)
-	assert.Equal(t, 1, nodes[0].Weight)
+	// json encode for client
+	res, err := json.Marshal(nodes)
+	assert.Nil(t,err)

Review comment:
       Style: need a space after `,`.

##########
File path: api/internal/core/entity/format.go
##########
@@ -17,26 +17,30 @@
 package entity
 
 import (
-	"log"
 	"strconv"
 	"strings"
+
+	"github.com/apisix/manager-api/log"
 )
 
 func NodesFormat(obj interface{}) interface{} {
 	var nodes []*Node
-	if value, ok := obj.(map[string]float64); ok {
+	switch objType := obj.(type) {
+	case map[string]float64:
+		log.Infof("nodes type: %v", objType)
 		var strArr []string
+		value := obj.(map[string]float64)
 		for key, val := range value {
 			node := &Node{}
 			strArr = strings.Split(key, ":")

Review comment:
       The key splitting logic can be replaced by using `net.SplitHostPort`, we may encapsulate it with port validation and IP/domain check.

##########
File path: api/internal/core/entity/format_test.go
##########
@@ -23,19 +23,62 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestConsumer(t *testing.T) {
-	nodesStr := `{
-    "127.0.0.1:8080": 1
-  }`
-	nodesMap := map[string]float64{}
-	err := json.Unmarshal([]byte(nodesStr), &nodesMap)
+func TestNodesFormat(t *testing.T){
+	// route data saved in ETCD
+	routeStr := `{
+        "uris": ["/*"],
+        "upstream": {
+            "type": "roundrobin",
+            "nodes": [{
+                "host": "127.0.0.1",
+                "port": 80,
+                "weight": 0
+            }]
+        }
+    }`
+
+	// bind struct
+	var  route Route
+	err := json.Unmarshal([]byte(routeStr), &route)
 	assert.Nil(t, err)
 
-	res := NodesFormat(nodesMap)
-	nodes := res.([]*Node)
+	// nodes format
+	nodes := NodesFormat(route.Upstream.Nodes)
 
-	assert.Equal(t, 1, len(nodes))
-	assert.Equal(t, "127.0.0.1", nodes[0].Host)
-	assert.Equal(t, 8080, nodes[0].Port)
-	assert.Equal(t, 1, nodes[0].Weight)
+	// json encode for client
+	res, err := json.Marshal(nodes)
+	assert.Nil(t,err)
+	jsonStr := string(res)
+	assert.Contains(t, jsonStr, `"weight":0`)
+	assert.Contains(t, jsonStr, `"port":80`)
+	assert.Contains(t, jsonStr, `"host":"127.0.0.1"`)
 }
+
+func TestNodesFormat_Map(t *testing.T){
+	// route data saved in ETCD
+	routeStr := `{
+        "uris": ["/*"],
+        "upstream": {
+            "type": "roundrobin",
+            "nodes": {"127.0.0.1:8080": 0}
+        }
+    }`
+
+	// bind struct
+	var  route Route
+	err := json.Unmarshal([]byte(routeStr), &route)
+	assert.Nil(t, err)
+
+	// nodes format
+	nodes := NodesFormat(route.Upstream.Nodes)
+
+	// json encode for client
+	res, err := json.Marshal(nodes)
+	assert.Nil(t,err)
+	jsonStr := string(res)
+	assert.Contains(t, jsonStr, `"weight":0`)
+	assert.Contains(t, jsonStr, `"port":8080`)
+	assert.Contains(t, jsonStr, `"host":"127.0.0.1"`)
+

Review comment:
       Redundant empty line.

##########
File path: api/internal/core/entity/format.go
##########
@@ -46,13 +50,35 @@ func NodesFormat(obj interface{}) interface{} {
 			nodes = append(nodes, node)
 		}
 		return nodes
-	}
+	case map[string]interface{}:
+		log.Infof("nodes type: %v", objType)
+		var strArr []string
+		value := obj.(map[string]interface{})
+		for key, val := range value {
+			node := &Node{}
+			strArr = strings.Split(key, ":")

Review comment:
       Key splitting can be extracted as a function, it's used multiple times.

##########
File path: api/internal/core/entity/format_test.go
##########
@@ -23,19 +23,62 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestConsumer(t *testing.T) {
-	nodesStr := `{
-    "127.0.0.1:8080": 1
-  }`
-	nodesMap := map[string]float64{}
-	err := json.Unmarshal([]byte(nodesStr), &nodesMap)
+func TestNodesFormat(t *testing.T){
+	// route data saved in ETCD
+	routeStr := `{
+        "uris": ["/*"],
+        "upstream": {
+            "type": "roundrobin",
+            "nodes": [{
+                "host": "127.0.0.1",
+                "port": 80,
+                "weight": 0
+            }]
+        }
+    }`
+
+	// bind struct
+	var  route Route
+	err := json.Unmarshal([]byte(routeStr), &route)
 	assert.Nil(t, err)
 
-	res := NodesFormat(nodesMap)
-	nodes := res.([]*Node)
+	// nodes format
+	nodes := NodesFormat(route.Upstream.Nodes)
 
-	assert.Equal(t, 1, len(nodes))
-	assert.Equal(t, "127.0.0.1", nodes[0].Host)
-	assert.Equal(t, 8080, nodes[0].Port)
-	assert.Equal(t, 1, nodes[0].Weight)
+	// json encode for client
+	res, err := json.Marshal(nodes)
+	assert.Nil(t,err)
+	jsonStr := string(res)
+	assert.Contains(t, jsonStr, `"weight":0`)
+	assert.Contains(t, jsonStr, `"port":80`)
+	assert.Contains(t, jsonStr, `"host":"127.0.0.1"`)
 }
+
+func TestNodesFormat_Map(t *testing.T){
+	// route data saved in ETCD
+	routeStr := `{
+        "uris": ["/*"],
+        "upstream": {
+            "type": "roundrobin",
+            "nodes": {"127.0.0.1:8080": 0}
+        }
+    }`
+
+	// bind struct
+	var  route Route

Review comment:
       Redundant spaces after `var`.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org