Parcourir la source

add tests for docker stats versioning

testing for #17549

Signed-off-by: Donald Huang <don.hcd@gmail.com>
Donald Huang il y a 9 ans
Parent
commit
8ceded6d03
1 fichiers modifiés avec 86 ajouts et 0 suppressions
  1. 86 0
      integration-cli/docker_api_stats_test.go

+ 86 - 0
integration-cli/docker_api_stats_test.go

@@ -12,9 +12,12 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/pkg/integration/checker"
+	"github.com/docker/docker/pkg/version"
 	"github.com/go-check/check"
 )
 
+var expectedNetworkInterfaceStats = strings.Split("rx_bytes rx_dropped rx_errors rx_packets tx_bytes tx_dropped tx_errors tx_packets", " ")
+
 func (s *DockerSuite) TestApiStatsNoStreamGetCpu(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done")
@@ -122,6 +125,28 @@ func (s *DockerSuite) TestApiStatsNetworkStats(c *check.C) {
 		check.Commentf("Reported less Txbytes than expected. Expected >= %d. Found %d. %s", expRxPkts, postRxPackets, pingouts))
 }
 
+func (s *DockerSuite) TestApiStatsNetworkStatsVersioning(c *check.C) {
+	testRequires(c, SameHostDaemon)
+	testRequires(c, DaemonIsLinux)
+	// Run container for 30 secs
+	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
+	id := strings.TrimSpace(out)
+	c.Assert(waitRun(id), checker.IsNil)
+
+	for i := 17; i <= 21; i++ {
+		apiVersion := fmt.Sprintf("v1.%d", i)
+		for _, statsJSONBlob := range getVersionedStats(c, id, 3, apiVersion) {
+			if version.Version(apiVersion).LessThan("v1.21") {
+				c.Assert(jsonBlobHasLTv121NetworkStats(statsJSONBlob), checker.Equals, true,
+					check.Commentf("Stats JSON blob from API %s %#v does not look like a <v1.21 API stats structure", apiVersion, statsJSONBlob))
+			} else {
+				c.Assert(jsonBlobHasGTE121NetworkStats(statsJSONBlob), checker.Equals, true,
+					check.Commentf("Stats JSON blob from API %s %#v does not look like a >=v1.21 API stats structure", apiVersion, statsJSONBlob))
+			}
+		}
+	}
+}
+
 func getNetworkStats(c *check.C, id string) map[string]types.NetworkStats {
 	var st *types.StatsJSON
 
@@ -135,6 +160,67 @@ func getNetworkStats(c *check.C, id string) map[string]types.NetworkStats {
 	return st.Networks
 }
 
+// getVersionedNetworkStats returns a slice of numStats stats results for the
+// container with id id using an API call with version apiVersion. Since the
+// stats result type differs between API versions, we simply return
+// []map[string]interface{}.
+func getVersionedStats(c *check.C, id string, numStats int, apiVersion string) []map[string]interface{} {
+	stats := make([]map[string]interface{}, numStats)
+
+	requestPath := fmt.Sprintf("/%s/containers/%s/stats?stream=true", apiVersion, id)
+	_, body, err := sockRequestRaw("GET", requestPath, nil, "")
+	c.Assert(err, checker.IsNil)
+	defer body.Close()
+
+	statsDecoder := json.NewDecoder(body)
+	for i := range stats {
+		err = statsDecoder.Decode(&stats[i])
+		c.Assert(err, checker.IsNil, check.Commentf("failed to decode %dth stat: %s", i, err))
+	}
+
+	return stats
+}
+
+func jsonBlobHasLTv121NetworkStats(blob map[string]interface{}) bool {
+	networkStatsIntfc, ok := blob["network"]
+	if !ok {
+		return false
+	}
+	networkStats, ok := networkStatsIntfc.(map[string]interface{})
+	if !ok {
+		return false
+	}
+	for _, expectedKey := range expectedNetworkInterfaceStats {
+		if _, ok := networkStats[expectedKey]; !ok {
+			return false
+		}
+	}
+	return true
+}
+
+func jsonBlobHasGTE121NetworkStats(blob map[string]interface{}) bool {
+	networksStatsIntfc, ok := blob["networks"]
+	if !ok {
+		return false
+	}
+	networksStats, ok := networksStatsIntfc.(map[string]interface{})
+	if !ok {
+		return false
+	}
+	for _, networkInterfaceStatsIntfc := range networksStats {
+		networkInterfaceStats, ok := networkInterfaceStatsIntfc.(map[string]interface{})
+		if !ok {
+			return false
+		}
+		for _, expectedKey := range expectedNetworkInterfaceStats {
+			if _, ok := networkInterfaceStats[expectedKey]; !ok {
+				return false
+			}
+		}
+	}
+	return true
+}
+
 func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) {
 	testRequires(c, DaemonIsLinux)