func TestStatsEngineTerminalTask(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() resolver := mock_resolver.NewMockContainerMetadataResolver(mockCtrl) resolver.EXPECT().ResolveTask("c1").Return(&api.Task{Arn: "t1", KnownStatus: api.TaskStopped}, nil) engine := NewDockerStatsEngine(&cfg) engine.resolver = resolver engine.addContainer("c1") err := validateIdleContainerMetrics(engine) if err != nil { t.Fatal("Error validating metadata: ", err) } }
func TestStatsEngineMetadataInStatsSets(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() resolver := mock_resolver.NewMockContainerMetadataResolver(mockCtrl) t1 := &api.Task{Arn: "t1", Family: "f1"} resolver.EXPECT().ResolveTask("c1").AnyTimes().Return(t1, nil) resolver.EXPECT().ResolveContainer(gomock.Any()).AnyTimes().Return(&api.DockerContainer{ Container: &api.Container{}, }, nil) engine := NewDockerStatsEngine(&cfg, nil, eventStream("TestStatsEngineMetadataInStatsSets")) engine.resolver = resolver engine.cluster = defaultCluster engine.containerInstanceArn = defaultContainerInstance engine.addContainer("c1") containerStats := []*ContainerStats{ &ContainerStats{22400432, 1839104, parseNanoTime("2015-02-12T21:22:05.131117533Z")}, &ContainerStats{116499979, 3649536, parseNanoTime("2015-02-12T21:22:05.232291187Z")}, } containers, _ := engine.tasksToContainers["t1"] for _, statsContainer := range containers { for i := 0; i < 2; i++ { statsContainer.statsQueue.Add(containerStats[i]) } } metadata, taskMetrics, err := engine.GetInstanceMetrics() if err != nil { t.Errorf("Error gettting instance metrics: %v", err) } if len(taskMetrics) != 1 { t.Fatalf("Incorrect number of tasks. Expected: 1, got: %d", len(taskMetrics)) } err = validateContainerMetrics(taskMetrics[0].ContainerMetrics, 1) if err != nil { t.Errorf("Error validating container metrics: %v", err) } if *taskMetrics[0].TaskArn != "t1" { t.Errorf("Incorrect task arn. Expected: t1, got: %s", *taskMetrics[0].TaskArn) } err = validateMetricsMetadata(metadata) if err != nil { t.Errorf("Error validating metadata: %v", err) } engine.removeContainer("c1") err = validateIdleContainerMetrics(engine) if err != nil { t.Fatalf("Error validating metadata: %v", err) } }
func TestStatsEngineMetadataInStatsSets(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() resolver := mock_resolver.NewMockContainerMetadataResolver(mockCtrl) t1 := &api.Task{Arn: "t1", Family: "f1"} resolver.EXPECT().ResolveTask("c1").AnyTimes().Return(t1, nil) engine := NewDockerStatsEngine(&cfg) engine.resolver = resolver engine.metricsMetadata = newMetricsMetadata(&defaultCluster, &defaultContainerInstance) engine.addContainer("c1") containerStats := []*ContainerStats{ createContainerStats(22400432, 1839104, parseNanoTime("2015-02-12T21:22:05.131117533Z")), createContainerStats(116499979, 3649536, parseNanoTime("2015-02-12T21:22:05.232291187Z")), } containers, _ := engine.tasksToContainers["t1"] for _, cronContainer := range containers { for i := 0; i < 2; i++ { cronContainer.statsQueue.Add(containerStats[i]) } } metadata, taskMetrics, err := engine.GetInstanceMetrics() if err != nil { t.Error("Error gettting instance metrics: ", err) } if len(taskMetrics) != 1 { t.Fatal("Incorrect number of tasks. Expected: 1, got: ", len(taskMetrics)) } err = validateContainerMetrics(taskMetrics[0].ContainerMetrics, 1) if err != nil { t.Error("Error validating container metrics: ", err) } if *taskMetrics[0].TaskArn != "t1" { t.Error("Incorrect task arn. Expected: t1, got: ", *taskMetrics[0].TaskArn) } if *metadata.Cluster != defaultCluster { t.Errorf("Cluster Arn not set in metadata. Expected: %s, got: %s", defaultCluster, *metadata.Cluster) } if *metadata.ContainerInstance != defaultContainerInstance { t.Errorf("Container Instance Arn not set in metadata. Expected: %s, got: %s", defaultContainerInstance, *metadata.ContainerInstance) } engine.removeContainer("c1") err = validateIdleContainerMetrics(engine) if err != nil { t.Fatal("Error validating metadata: ", err) } }
func TestContainerStatsCollectionReconnection(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDockerClient := ecsengine.NewMockDockerClient(ctrl) resolver := mock_resolver.NewMockContainerMetadataResolver(ctrl) dockerID := "container1" ctx, cancel := context.WithCancel(context.TODO()) statChan := make(chan *docker.Stats) statErr := fmt.Errorf("test error") closedChan := make(chan *docker.Stats) close(closedChan) mockContainer := &api.DockerContainer{ DockerId: dockerID, Container: &api.Container{ KnownStatus: api.ContainerRunning, }, } gomock.InOrder( mockDockerClient.EXPECT().Stats(dockerID, ctx).Return(nil, statErr), resolver.EXPECT().ResolveContainer(dockerID).Return(mockContainer, nil), mockDockerClient.EXPECT().Stats(dockerID, ctx).Return(closedChan, nil), resolver.EXPECT().ResolveContainer(dockerID).Return(mockContainer, nil), mockDockerClient.EXPECT().Stats(dockerID, ctx).Return(statChan, nil), ) container := &StatsContainer{ containerMetadata: &ContainerMetadata{ DockerID: dockerID, }, ctx: ctx, cancel: cancel, client: mockDockerClient, resolver: resolver, } container.StartStatsCollection() time.Sleep(checkPointSleep) container.StopStatsCollection() }
func TestContainerStatsCollectionStopsIfContainerIsTerminal(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDockerClient := ecsengine.NewMockDockerClient(ctrl) resolver := mock_resolver.NewMockContainerMetadataResolver(ctrl) dockerID := "container1" ctx, cancel := context.WithCancel(context.TODO()) closedChan := make(chan *docker.Stats) close(closedChan) statsErr := fmt.Errorf("test error") mockContainer := &api.DockerContainer{ DockerId: dockerID, Container: &api.Container{ KnownStatus: api.ContainerStopped, }, } gomock.InOrder( mockDockerClient.EXPECT().Stats(dockerID, ctx).Return(closedChan, nil), resolver.EXPECT().ResolveContainer(dockerID).Return(mockContainer, statsErr), ) container := &StatsContainer{ containerMetadata: &ContainerMetadata{ DockerID: dockerID, }, ctx: ctx, cancel: cancel, client: mockDockerClient, resolver: resolver, } container.StartStatsCollection() select { case <-ctx.Done(): } }
func TestStatsEngineAddRemoveContainers(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() resolver := mock_resolver.NewMockContainerMetadataResolver(mockCtrl) t1 := &api.Task{Arn: "t1", Family: "f1"} t2 := &api.Task{Arn: "t2", Family: "f2"} t3 := &api.Task{Arn: "t3"} resolver.EXPECT().ResolveTask("c1").AnyTimes().Return(t1, nil) resolver.EXPECT().ResolveTask("c2").AnyTimes().Return(t1, nil) resolver.EXPECT().ResolveTask("c3").AnyTimes().Return(t2, nil) resolver.EXPECT().ResolveTask("c4").AnyTimes().Return(nil, fmt.Errorf("unmapped container")) resolver.EXPECT().ResolveTask("c5").AnyTimes().Return(t2, nil) resolver.EXPECT().ResolveTask("c6").AnyTimes().Return(t3, nil) engine := NewDockerStatsEngine(&cfg) engine.resolver = resolver engine.cluster = defaultCluster engine.containerInstanceArn = defaultContainerInstance engine.addContainer("c1") engine.addContainer("c1") if len(engine.tasksToContainers) != 1 { t.Error("Adding containers failed. Expected num tasks = 1, got: ", len(engine.tasksToContainers)) } containers, _ := engine.tasksToContainers["t1"] if len(containers) != 1 { t.Error("Adding duplicate containers failed.") } _, exists := containers["c1"] if !exists { t.Error("Container c1 not found in engine") } engine.addContainer("c2") containers, _ = engine.tasksToContainers["t1"] _, exists = containers["c2"] if !exists { t.Error("Container c2 not found in engine") } for _, cronContainer := range containers { for _, fakeContainerStats := range createFakeContainerStats() { cronContainer.statsQueue.Add(fakeContainerStats) } } // Ensure task shows up in metrics. containerMetrics, err := engine.getContainerMetricsForTask("t1") if err != nil { t.Error("Error getting container metrics: ", err) } err = validateContainerMetrics(containerMetrics, 2) if err != nil { t.Error("Error validating container metrics: ", err) } metadata, taskMetrics, err := engine.GetInstanceMetrics() if err != nil { t.Error("Error gettting instance metrics: ", err) } err = validateMetricsMetadata(metadata) if err != nil { t.Error("Error validating metadata: ", err) } if len(taskMetrics) != 1 { t.Error("Incorrect number of tasks. Expected: 1, got: ", len(taskMetrics)) } err = validateContainerMetrics(taskMetrics[0].ContainerMetrics, 2) if err != nil { t.Error("Error validating container metrics: ", err) } if *taskMetrics[0].TaskArn != "t1" { t.Error("Incorrect task arn. Expected: t1, got: ", *taskMetrics[0].TaskArn) } // Ensure that only valid task shows up in metrics. _, err = engine.getContainerMetricsForTask("t2") if err == nil { t.Error("Expected non-empty error for non existent task") } engine.removeContainer("c1") containers, _ = engine.tasksToContainers["t1"] _, exists = containers["c1"] if exists { t.Error("Container c1 not removed from engine") } engine.removeContainer("c2") containers, _ = engine.tasksToContainers["t1"] _, exists = containers["c2"] if exists { t.Error("Container c2 not removed from engine") } engine.addContainer("c3") containers, _ = engine.tasksToContainers["t2"] _, exists = containers["c3"] if !exists { t.Error("Container c3 not found in engine") } _, _, err = engine.GetInstanceMetrics() if err == nil { t.Error("Expected non-empty error for empty stats.") } engine.removeContainer("c3") // Should get an error while adding this container due to unmapped // container to task. engine.addContainer("c4") err = validateIdleContainerMetrics(engine) if err != nil { t.Fatal("Error validating metadata: ", err) } // Should get an error while adding this container due to unmapped // task arn to task definition family. engine.addContainer("c6") err = validateIdleContainerMetrics(engine) if err != nil { t.Fatal("Error validating metadata: ", err) } }