github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/kubernetes/debugging/container_manager_test.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package debugging 18 19 import ( 20 "context" 21 "testing" 22 23 v1 "k8s.io/api/core/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/watch" 26 27 "github.com/GoogleContainerTools/skaffold/testutil" 28 ) 29 30 func TestContainerManager(t *testing.T) { 31 makePod := func(name string, state v1.ContainerState) v1.Pod { 32 return v1.Pod{ 33 ObjectMeta: metav1.ObjectMeta{ 34 Name: name, 35 Namespace: "ns", 36 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"jvm","debugPorts":{"jdwp":5005}}}`}, 37 }, 38 Spec: v1.PodSpec{Containers: []v1.Container{ 39 { 40 Name: "test", 41 Command: []string{"java", "-jar", "foo.jar"}, 42 Env: []v1.EnvVar{{Name: "JAVA_TOOL_OPTIONS", Value: "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n,quiet=y"}}, 43 Ports: []v1.ContainerPort{{Name: "jdwp", ContainerPort: 5005}}, 44 }}}, 45 Status: v1.PodStatus{ContainerStatuses: []v1.ContainerStatus{{Name: "test", State: state}}}, 46 } 47 } 48 49 type podEvent struct { 50 eventType watch.EventType 51 pod v1.Pod 52 53 wantActiveKeys []string 54 wantStartCount int 55 wantTerminatedCount int 56 } 57 tests := []struct { 58 description string 59 events []podEvent 60 }{ 61 { 62 description: "pod added, container started, and then terminates", 63 events: []podEvent{ 64 {eventType: watch.Added, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 65 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 66 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 1, wantActiveKeys: []string{"ns/pod/test"}}, 67 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 1, wantActiveKeys: []string{"ns/pod/test"}}, 68 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 1, wantTerminatedCount: 1}, 69 {eventType: watch.Deleted, pod: makePod("pod", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 1, wantTerminatedCount: 1}, 70 }, 71 }, 72 { 73 description: "pod added, container started, and then deleted before termination", 74 events: []podEvent{ 75 {eventType: watch.Added, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 76 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 77 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 1, wantActiveKeys: []string{"ns/pod/test"}}, 78 {eventType: watch.Deleted, pod: makePod("pod", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 1, wantTerminatedCount: 1}, 79 }, 80 }, 81 { 82 description: "pods added, container started, and terminated several times (like iterative debugging)", 83 events: []podEvent{ 84 {eventType: watch.Added, pod: makePod("pod1", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 85 {eventType: watch.Modified, pod: makePod("pod1", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 86 {eventType: watch.Modified, pod: makePod("pod1", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 1, wantActiveKeys: []string{"ns/pod1/test"}}, 87 {eventType: watch.Added, pod: makePod("pod2", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 1, wantActiveKeys: []string{"ns/pod1/test"}}, 88 {eventType: watch.Modified, pod: makePod("pod2", v1.ContainerState{Running: &v1.ContainerStateRunning{}}), wantStartCount: 2, wantActiveKeys: []string{"ns/pod1/test", "ns/pod2/test"}}, 89 {eventType: watch.Modified, pod: makePod("pod1", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 2, wantTerminatedCount: 1, wantActiveKeys: []string{"ns/pod2/test"}}, 90 {eventType: watch.Deleted, pod: makePod("pod1", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 2, wantTerminatedCount: 1, wantActiveKeys: []string{"ns/pod2/test"}}, 91 {eventType: watch.Deleted, pod: makePod("pod2", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 2, wantTerminatedCount: 2}, 92 }, 93 }, 94 { 95 description: "pod added, container never started, and then deleted", 96 events: []podEvent{ 97 {eventType: watch.Added, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 98 {eventType: watch.Modified, pod: makePod("pod", v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}}), wantStartCount: 0}, 99 {eventType: watch.Deleted, pod: makePod("pod", v1.ContainerState{Terminated: &v1.ContainerStateTerminated{}}), wantStartCount: 0, wantTerminatedCount: 0}, 100 }, 101 }, 102 } 103 104 for _, tc := range tests { 105 testutil.Run(t, tc.description, func(t *testutil.T) { 106 ev1StartCount, ev1TerminatedCount := 0, 0 107 ev2StartCount, ev2TerminatedCount := 0, 0 108 // Override event v1 funcs to do nothing to avoid additional overhead 109 t.Override(¬ifyDebuggingContainerStarted, func(podName string, containerName string, namespace string, artifactImage string, runtime string, workingDir string, debugPorts map[string]uint32) { 110 ev1StartCount++ 111 }) 112 t.Override(¬ifyDebuggingContainerTerminated, func(podName string, containerName string, namespace string, artifactImage string, runtime string, workingDir string, debugPorts map[string]uint32) { 113 ev1TerminatedCount++ 114 }) 115 t.Override(&debuggingContainerStartedV2, func(podName string, containerName string, namespace string, artifactImage string, runtime string, workingDir string, debugPorts map[string]uint32) { 116 ev2StartCount++ 117 }) 118 t.Override(&debuggingContainerTerminatedV2, func(podName string, containerName string, namespace string, artifactImage string, runtime string, workingDir string, debugPorts map[string]uint32) { 119 ev2TerminatedCount++ 120 }) 121 122 m := &ContainerManager{active: make(map[string]string)} 123 124 for i, event := range tc.events { 125 m.checkPod(event.eventType, &event.pod) 126 if len(event.wantActiveKeys) != len(m.active) { 127 t.Fatalf("step %d: active pod count: got=%d want=%d: active=%v", i, len(m.active), len(event.wantActiveKeys), m.active) 128 } 129 if event.wantStartCount != ev1StartCount { 130 t.Fatalf("step %d: v1 start count: got=%d want=%d", i, ev1StartCount, event.wantStartCount) 131 } 132 if event.wantTerminatedCount != ev1TerminatedCount { 133 t.Fatalf("step %d: v1 terminated count: got=%d want=%d", i, ev1TerminatedCount, event.wantTerminatedCount) 134 } 135 if event.wantStartCount != ev2StartCount { 136 t.Fatalf("step %d: v2 start count: got=%d want=%d", i, ev2StartCount, event.wantStartCount) 137 } 138 if event.wantTerminatedCount != ev2TerminatedCount { 139 t.Fatalf("step %d: v2 terminated count: got=%d want=%d", i, ev2TerminatedCount, event.wantTerminatedCount) 140 } 141 for _, key := range event.wantActiveKeys { 142 if _, found := m.active[key]; !found { 143 t.Fatalf("step %d: expected to find pod %q in active list: got=%v want=%v", i, key, m.active, event.wantActiveKeys) 144 } 145 } 146 } 147 }) 148 } 149 } 150 151 func TestContainerManagerZeroValue(t *testing.T) { 152 var m *ContainerManager 153 154 // Should not raise a nil dereference 155 m.Start(context.Background()) 156 m.Stop() 157 }