346 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2017 The Kubernetes 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 integration
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
	runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
 | 
						|
)
 | 
						|
 | 
						|
// Test to verify for a container ID
 | 
						|
func TestContainerStats(t *testing.T) {
 | 
						|
	t.Logf("Create a pod config and run sandbox container")
 | 
						|
	sbConfig := PodSandboxConfig("sandbox1", "stats")
 | 
						|
	sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopPodSandbox(sb))
 | 
						|
		assert.NoError(t, runtimeService.RemovePodSandbox(sb))
 | 
						|
	}()
 | 
						|
	t.Logf("Create a container config and run container in a pod")
 | 
						|
	containerConfig := ContainerConfig(
 | 
						|
		"container1",
 | 
						|
		pauseImage,
 | 
						|
		WithTestLabels(),
 | 
						|
		WithTestAnnotations(),
 | 
						|
	)
 | 
						|
	cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.RemoveContainer(cn))
 | 
						|
	}()
 | 
						|
	require.NoError(t, runtimeService.StartContainer(cn))
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopContainer(cn, 10))
 | 
						|
	}()
 | 
						|
 | 
						|
	t.Logf("Fetch stats for container")
 | 
						|
	var s *runtime.ContainerStats
 | 
						|
	require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
		s, err = runtimeService.ContainerStats(cn)
 | 
						|
		if err != nil {
 | 
						|
			return false, err
 | 
						|
		}
 | 
						|
		if s.GetWritableLayer().GetUsedBytes().GetValue() != 0 &&
 | 
						|
			s.GetWritableLayer().GetInodesUsed().GetValue() != 0 {
 | 
						|
			return true, nil
 | 
						|
		}
 | 
						|
		return false, nil
 | 
						|
	}, time.Second, 30*time.Second))
 | 
						|
 | 
						|
	t.Logf("Verify stats received for container %q", cn)
 | 
						|
	testStats(t, s, containerConfig)
 | 
						|
}
 | 
						|
 | 
						|
// Test to verify filtering without any filter
 | 
						|
func TestContainerListStats(t *testing.T) {
 | 
						|
	t.Logf("Create a pod config and run sandbox container")
 | 
						|
	sbConfig := PodSandboxConfig("running-pod", "statsls")
 | 
						|
	sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopPodSandbox(sb))
 | 
						|
		assert.NoError(t, runtimeService.RemovePodSandbox(sb))
 | 
						|
	}()
 | 
						|
	t.Logf("Create a container config and run containers in a pod")
 | 
						|
	containerConfigMap := make(map[string]*runtime.ContainerConfig)
 | 
						|
	for i := 0; i < 3; i++ {
 | 
						|
		cName := fmt.Sprintf("container%d", i)
 | 
						|
		containerConfig := ContainerConfig(
 | 
						|
			cName,
 | 
						|
			pauseImage,
 | 
						|
			WithTestLabels(),
 | 
						|
			WithTestAnnotations(),
 | 
						|
		)
 | 
						|
		cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig)
 | 
						|
		require.NoError(t, err)
 | 
						|
		containerConfigMap[cn] = containerConfig
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.RemoveContainer(cn))
 | 
						|
		}()
 | 
						|
		require.NoError(t, runtimeService.StartContainer(cn))
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.StopContainer(cn, 10))
 | 
						|
		}()
 | 
						|
	}
 | 
						|
 | 
						|
	t.Logf("Fetch all container stats")
 | 
						|
	var stats []*runtime.ContainerStats
 | 
						|
	require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
		stats, err = runtimeService.ListContainerStats(&runtime.ContainerStatsFilter{})
 | 
						|
		if err != nil {
 | 
						|
			return false, err
 | 
						|
		}
 | 
						|
		for _, s := range stats {
 | 
						|
			if s.GetWritableLayer().GetUsedBytes().GetValue() == 0 &&
 | 
						|
				s.GetWritableLayer().GetInodesUsed().GetValue() == 0 {
 | 
						|
				return false, nil
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return true, nil
 | 
						|
	}, time.Second, 30*time.Second))
 | 
						|
 | 
						|
	t.Logf("Verify all container stats")
 | 
						|
	for _, s := range stats {
 | 
						|
		testStats(t, s, containerConfigMap[s.GetAttributes().GetId()])
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Test to verify filtering given a specific container ID
 | 
						|
// TODO Convert the filter tests into table driven tests and unit tests
 | 
						|
func TestContainerListStatsWithIdFilter(t *testing.T) {
 | 
						|
	t.Logf("Create a pod config and run sandbox container")
 | 
						|
	sbConfig := PodSandboxConfig("running-pod", "statsls")
 | 
						|
	sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopPodSandbox(sb))
 | 
						|
		assert.NoError(t, runtimeService.RemovePodSandbox(sb))
 | 
						|
	}()
 | 
						|
	t.Logf("Create a container config and run containers in a pod")
 | 
						|
	containerConfigMap := make(map[string]*runtime.ContainerConfig)
 | 
						|
	for i := 0; i < 3; i++ {
 | 
						|
		cName := fmt.Sprintf("container%d", i)
 | 
						|
		containerConfig := ContainerConfig(
 | 
						|
			cName,
 | 
						|
			pauseImage,
 | 
						|
			WithTestLabels(),
 | 
						|
			WithTestAnnotations(),
 | 
						|
		)
 | 
						|
		cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig)
 | 
						|
		containerConfigMap[cn] = containerConfig
 | 
						|
		require.NoError(t, err)
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.RemoveContainer(cn))
 | 
						|
		}()
 | 
						|
		require.NoError(t, runtimeService.StartContainer(cn))
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.StopContainer(cn, 10))
 | 
						|
		}()
 | 
						|
	}
 | 
						|
 | 
						|
	t.Logf("Fetch container stats for each container with Filter")
 | 
						|
	var stats []*runtime.ContainerStats
 | 
						|
	for id := range containerConfigMap {
 | 
						|
		require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
			stats, err = runtimeService.ListContainerStats(
 | 
						|
				&runtime.ContainerStatsFilter{Id: id})
 | 
						|
			if err != nil {
 | 
						|
				return false, err
 | 
						|
			}
 | 
						|
			if len(stats) != 1 {
 | 
						|
				return false, errors.New("unexpected stats length")
 | 
						|
			}
 | 
						|
			if stats[0].GetWritableLayer().GetUsedBytes().GetValue() != 0 &&
 | 
						|
				stats[0].GetWritableLayer().GetInodesUsed().GetValue() != 0 {
 | 
						|
				return true, nil
 | 
						|
			}
 | 
						|
			return false, nil
 | 
						|
		}, time.Second, 30*time.Second))
 | 
						|
 | 
						|
		t.Logf("Verify container stats for %s", id)
 | 
						|
		for _, s := range stats {
 | 
						|
			require.Equal(t, s.GetAttributes().GetId(), id)
 | 
						|
			testStats(t, s, containerConfigMap[id])
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Test to verify filtering given a specific Sandbox ID. Stats for
 | 
						|
// all the containers in a pod should be returned
 | 
						|
func TestContainerListStatsWithSandboxIdFilter(t *testing.T) {
 | 
						|
	t.Logf("Create a pod config and run sandbox container")
 | 
						|
	sbConfig := PodSandboxConfig("running-pod", "statsls")
 | 
						|
	sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopPodSandbox(sb))
 | 
						|
		assert.NoError(t, runtimeService.RemovePodSandbox(sb))
 | 
						|
	}()
 | 
						|
	t.Logf("Create a container config and run containers in a pod")
 | 
						|
	containerConfigMap := make(map[string]*runtime.ContainerConfig)
 | 
						|
	for i := 0; i < 3; i++ {
 | 
						|
		cName := fmt.Sprintf("container%d", i)
 | 
						|
		containerConfig := ContainerConfig(
 | 
						|
			cName,
 | 
						|
			pauseImage,
 | 
						|
			WithTestLabels(),
 | 
						|
			WithTestAnnotations(),
 | 
						|
		)
 | 
						|
		cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig)
 | 
						|
		containerConfigMap[cn] = containerConfig
 | 
						|
		require.NoError(t, err)
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.RemoveContainer(cn))
 | 
						|
		}()
 | 
						|
		require.NoError(t, runtimeService.StartContainer(cn))
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.StopContainer(cn, 10))
 | 
						|
		}()
 | 
						|
	}
 | 
						|
 | 
						|
	t.Logf("Fetch container stats for each container with Filter")
 | 
						|
	var stats []*runtime.ContainerStats
 | 
						|
	require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
		stats, err = runtimeService.ListContainerStats(
 | 
						|
			&runtime.ContainerStatsFilter{PodSandboxId: sb})
 | 
						|
		if err != nil {
 | 
						|
			return false, err
 | 
						|
		}
 | 
						|
		if len(stats) != 3 {
 | 
						|
			return false, errors.New("unexpected stats length")
 | 
						|
		}
 | 
						|
		if stats[0].GetWritableLayer().GetUsedBytes().GetValue() != 0 &&
 | 
						|
			stats[0].GetWritableLayer().GetInodesUsed().GetValue() != 0 {
 | 
						|
			return true, nil
 | 
						|
		}
 | 
						|
		return false, nil
 | 
						|
	}, time.Second, 30*time.Second))
 | 
						|
	t.Logf("Verify container stats for sandbox %q", sb)
 | 
						|
	for _, s := range stats {
 | 
						|
		testStats(t, s, containerConfigMap[s.GetAttributes().GetId()])
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Test to verify filtering given a specific container ID and
 | 
						|
// sandbox ID
 | 
						|
func TestContainerListStatsWithIdSandboxIdFilter(t *testing.T) {
 | 
						|
	t.Logf("Create a pod config and run sandbox container")
 | 
						|
	sbConfig := PodSandboxConfig("running-pod", "statsls")
 | 
						|
	sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
 | 
						|
	require.NoError(t, err)
 | 
						|
	defer func() {
 | 
						|
		assert.NoError(t, runtimeService.StopPodSandbox(sb))
 | 
						|
		assert.NoError(t, runtimeService.RemovePodSandbox(sb))
 | 
						|
	}()
 | 
						|
	t.Logf("Create container config and run containers in a pod")
 | 
						|
	containerConfigMap := make(map[string]*runtime.ContainerConfig)
 | 
						|
	for i := 0; i < 3; i++ {
 | 
						|
		cName := fmt.Sprintf("container%d", i)
 | 
						|
		containerConfig := ContainerConfig(
 | 
						|
			cName,
 | 
						|
			pauseImage,
 | 
						|
			WithTestLabels(),
 | 
						|
			WithTestAnnotations(),
 | 
						|
		)
 | 
						|
		cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig)
 | 
						|
		containerConfigMap[cn] = containerConfig
 | 
						|
		require.NoError(t, err)
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.RemoveContainer(cn))
 | 
						|
		}()
 | 
						|
		require.NoError(t, runtimeService.StartContainer(cn))
 | 
						|
		defer func() {
 | 
						|
			assert.NoError(t, runtimeService.StopContainer(cn, 10))
 | 
						|
		}()
 | 
						|
	}
 | 
						|
	t.Logf("Fetch container stats for sandbox ID and container ID filter")
 | 
						|
	var stats []*runtime.ContainerStats
 | 
						|
	for id, config := range containerConfigMap {
 | 
						|
		require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
			stats, err = runtimeService.ListContainerStats(
 | 
						|
				&runtime.ContainerStatsFilter{Id: id, PodSandboxId: sb})
 | 
						|
			if err != nil {
 | 
						|
				return false, err
 | 
						|
			}
 | 
						|
			if len(stats) != 1 {
 | 
						|
				return false, errors.New("unexpected stats length")
 | 
						|
			}
 | 
						|
			if stats[0].GetWritableLayer().GetUsedBytes().GetValue() != 0 &&
 | 
						|
				stats[0].GetWritableLayer().GetInodesUsed().GetValue() != 0 {
 | 
						|
				return true, nil
 | 
						|
			}
 | 
						|
			return false, nil
 | 
						|
		}, time.Second, 30*time.Second))
 | 
						|
		t.Logf("Verify container stats for sandbox %q and container %q filter", sb, id)
 | 
						|
		for _, s := range stats {
 | 
						|
			testStats(t, s, config)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	t.Logf("Fetch container stats for sandbox truncID and container truncID filter ")
 | 
						|
	for id, config := range containerConfigMap {
 | 
						|
		require.NoError(t, Eventually(func() (bool, error) {
 | 
						|
			stats, err = runtimeService.ListContainerStats(
 | 
						|
				&runtime.ContainerStatsFilter{Id: id[:3], PodSandboxId: sb[:3]})
 | 
						|
			if err != nil {
 | 
						|
				return false, err
 | 
						|
			}
 | 
						|
			if len(stats) != 1 {
 | 
						|
				return false, errors.New("unexpected stats length")
 | 
						|
			}
 | 
						|
			if stats[0].GetWritableLayer().GetUsedBytes().GetValue() != 0 &&
 | 
						|
				stats[0].GetWritableLayer().GetInodesUsed().GetValue() != 0 {
 | 
						|
				return true, nil
 | 
						|
			}
 | 
						|
			return false, nil
 | 
						|
		}, time.Second, 30*time.Second))
 | 
						|
		t.Logf("Verify container stats for sandbox %q and container %q filter", sb, id)
 | 
						|
		for _, s := range stats {
 | 
						|
			testStats(t, s, config)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// TODO make this as options to use for dead container tests
 | 
						|
func testStats(t *testing.T,
 | 
						|
	s *runtime.ContainerStats,
 | 
						|
	config *runtime.ContainerConfig,
 | 
						|
) {
 | 
						|
	require.NotEmpty(t, s.GetAttributes().GetId())
 | 
						|
	require.NotEmpty(t, s.GetAttributes().GetMetadata())
 | 
						|
	require.NotEmpty(t, s.GetAttributes().GetAnnotations())
 | 
						|
	require.Equal(t, s.GetAttributes().GetLabels(), config.Labels)
 | 
						|
	require.Equal(t, s.GetAttributes().GetAnnotations(), config.Annotations)
 | 
						|
	require.Equal(t, s.GetAttributes().GetMetadata().Name, config.Metadata.Name)
 | 
						|
	require.NotEmpty(t, s.GetAttributes().GetLabels())
 | 
						|
	require.NotEmpty(t, s.GetCpu().GetTimestamp())
 | 
						|
	require.NotEmpty(t, s.GetCpu().GetUsageCoreNanoSeconds().GetValue())
 | 
						|
	require.NotEmpty(t, s.GetMemory().GetTimestamp())
 | 
						|
	require.NotEmpty(t, s.GetMemory().GetWorkingSetBytes().GetValue())
 | 
						|
	require.NotEmpty(t, s.GetWritableLayer().GetTimestamp())
 | 
						|
	require.NotEmpty(t, s.GetWritableLayer().GetFsId().GetMountpoint())
 | 
						|
	require.NotEmpty(t, s.GetWritableLayer().GetUsedBytes().GetValue())
 | 
						|
	require.NotEmpty(t, s.GetWritableLayer().GetInodesUsed().GetValue())
 | 
						|
}
 |