github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/kubernetes/debugging/transform_go_test.go (about) 1 /* 2 Copyright 2021 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 "testing" 21 22 appsv1 "k8s.io/api/apps/v1" 23 batchv1 "k8s.io/api/batch/v1" 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime" 27 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug/types" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/debugging/adapter" 31 "github.com/GoogleContainerTools/skaffold/testutil" 32 ) 33 34 func TestDlvTransformerApply(t *testing.T) { 35 tests := []struct { 36 description string 37 containerSpec v1.Container 38 configuration debug.ImageConfiguration 39 shouldErr bool 40 result v1.Container 41 debugConfig types.ContainerDebugConfiguration 42 image string 43 }{ 44 { 45 description: "empty", 46 containerSpec: v1.Container{}, 47 configuration: debug.ImageConfiguration{}, 48 shouldErr: true, 49 }, 50 { 51 description: "basic", 52 containerSpec: v1.Container{}, 53 configuration: debug.ImageConfiguration{Entrypoint: []string{"app", "arg"}}, 54 result: v1.Container{ 55 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 56 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 57 }, 58 debugConfig: types.ContainerDebugConfiguration{Runtime: "go", Ports: map[string]uint32{"dlv": 56268}}, 59 image: "go", 60 }, 61 { 62 description: "existing port", 63 containerSpec: v1.Container{ 64 Ports: []v1.ContainerPort{{Name: "http-server", ContainerPort: 8080}}, 65 }, 66 configuration: debug.ImageConfiguration{Entrypoint: []string{"app", "arg"}}, 67 result: v1.Container{ 68 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 69 Ports: []v1.ContainerPort{{Name: "http-server", ContainerPort: 8080}, {Name: "dlv", ContainerPort: 56268}}, 70 }, 71 debugConfig: types.ContainerDebugConfiguration{Runtime: "go", Ports: map[string]uint32{"dlv": 56268}}, 72 image: "go", 73 }, 74 { 75 description: "existing dlv port", 76 containerSpec: v1.Container{ 77 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 7896}}, 78 }, 79 configuration: debug.ImageConfiguration{Entrypoint: []string{"app", "arg"}}, 80 result: v1.Container{ 81 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 82 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 83 }, 84 debugConfig: types.ContainerDebugConfiguration{Runtime: "go", Ports: map[string]uint32{"dlv": 56268}}, 85 image: "go", 86 }, 87 { 88 description: "command not entrypoint", 89 containerSpec: v1.Container{}, 90 configuration: debug.ImageConfiguration{Arguments: []string{"app", "arg"}}, 91 result: v1.Container{ 92 Args: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 93 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 94 }, 95 debugConfig: types.ContainerDebugConfiguration{Runtime: "go", Ports: map[string]uint32{"dlv": 56268}}, 96 image: "go", 97 }, 98 { 99 description: "entrypoint with args in container spec", 100 containerSpec: v1.Container{ 101 Args: []string{"arg1", "arg2"}, 102 }, 103 configuration: debug.ImageConfiguration{Entrypoint: []string{"app"}}, 104 result: v1.Container{ 105 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--"}, 106 Args: []string{"arg1", "arg2"}, 107 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 108 }, 109 debugConfig: types.ContainerDebugConfiguration{Runtime: "go", Ports: map[string]uint32{"dlv": 56268}}, 110 image: "go", 111 }, 112 } 113 var identity debug.PortAllocator = func(port int32) int32 { 114 return port 115 } 116 for _, test := range tests { 117 testutil.Run(t, test.description, func(t *testutil.T) { 118 adapter := adapter.NewAdapter(&test.containerSpec) 119 config, image, err := debug.NewDlvTransformer().Apply(adapter, test.configuration, identity, nil) 120 adapter.Apply() 121 122 t.CheckError(test.shouldErr, err) 123 t.CheckDeepEqual(test.result, test.containerSpec) 124 t.CheckDeepEqual(test.debugConfig, config) 125 t.CheckDeepEqual(test.image, image) 126 }) 127 } 128 } 129 130 func TestTransformManifestDelve(t *testing.T) { 131 int32p := func(x int32) *int32 { return &x } 132 tests := []struct { 133 description string 134 in runtime.Object 135 transformed bool 136 out runtime.Object 137 }{ 138 { 139 "Pod with no transformable container", 140 &v1.Pod{ 141 Spec: v1.PodSpec{Containers: []v1.Container{ 142 { 143 Name: "test", 144 Command: []string{"echo", "Hello World"}, 145 }, 146 }}}, 147 false, 148 &v1.Pod{ 149 Spec: v1.PodSpec{Containers: []v1.Container{ 150 { 151 Name: "test", 152 Command: []string{"echo", "Hello World"}, 153 }, 154 }}}, 155 }, 156 { 157 "Pod with Go container with GOMAXPROCS", 158 &v1.Pod{ 159 Spec: v1.PodSpec{ 160 Containers: []v1.Container{{ 161 Name: "test", 162 Command: []string{"app", "arg"}, 163 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 164 }}, 165 }}, 166 true, 167 &v1.Pod{ 168 ObjectMeta: metav1.ObjectMeta{ 169 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 170 }, 171 Spec: v1.PodSpec{ 172 Containers: []v1.Container{{ 173 Name: "test", 174 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 175 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 176 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 177 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 178 }}, 179 InitContainers: []v1.Container{{ 180 Name: "install-go-debug-support", 181 Image: "HELPERS/go", 182 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 183 }}, 184 Volumes: []v1.Volume{{ 185 Name: "debugging-support-files", 186 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 187 }}, 188 }}, 189 }, 190 { 191 "Deployment with Go container", 192 &appsv1.Deployment{ 193 Spec: appsv1.DeploymentSpec{ 194 Replicas: int32p(2), 195 Template: v1.PodTemplateSpec{ 196 Spec: v1.PodSpec{ 197 Containers: []v1.Container{{ 198 Name: "test", 199 Command: []string{"app", "arg"}, 200 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 201 }}, 202 }}}}, 203 true, 204 &appsv1.Deployment{ 205 // ObjectMeta: metav1.ObjectMeta{ 206 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 207 // }, 208 Spec: appsv1.DeploymentSpec{ 209 Replicas: int32p(1), 210 Template: v1.PodTemplateSpec{ 211 ObjectMeta: metav1.ObjectMeta{ 212 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 213 }, 214 Spec: v1.PodSpec{ 215 Containers: []v1.Container{{ 216 Name: "test", 217 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 218 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 219 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 220 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 221 }}, 222 InitContainers: []v1.Container{{ 223 Name: "install-go-debug-support", 224 Image: "HELPERS/go", 225 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 226 }}, 227 Volumes: []v1.Volume{{ 228 Name: "debugging-support-files", 229 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 230 }}, 231 }}}}, 232 }, 233 { 234 "ReplicaSet with Go container", 235 &appsv1.ReplicaSet{ 236 Spec: appsv1.ReplicaSetSpec{ 237 Replicas: int32p(2), 238 Template: v1.PodTemplateSpec{ 239 Spec: v1.PodSpec{ 240 Containers: []v1.Container{{ 241 Name: "test", 242 Command: []string{"app", "arg"}, 243 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 244 }}, 245 }}}}, 246 true, 247 &appsv1.ReplicaSet{ 248 // ObjectMeta: metav1.ObjectMeta{ 249 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 250 // }, 251 Spec: appsv1.ReplicaSetSpec{ 252 Replicas: int32p(1), 253 Template: v1.PodTemplateSpec{ 254 ObjectMeta: metav1.ObjectMeta{ 255 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 256 }, 257 Spec: v1.PodSpec{ 258 Containers: []v1.Container{{ 259 Name: "test", 260 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 261 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 262 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 263 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 264 }}, 265 InitContainers: []v1.Container{{ 266 Name: "install-go-debug-support", 267 Image: "HELPERS/go", 268 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 269 }}, 270 Volumes: []v1.Volume{{ 271 Name: "debugging-support-files", 272 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 273 }}, 274 }}}}, 275 }, 276 { 277 "StatefulSet with Go container", 278 &appsv1.StatefulSet{ 279 Spec: appsv1.StatefulSetSpec{ 280 Replicas: int32p(2), 281 Template: v1.PodTemplateSpec{ 282 Spec: v1.PodSpec{ 283 Containers: []v1.Container{{ 284 Name: "test", 285 Command: []string{"app", "arg"}, 286 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 287 }}, 288 }}}}, 289 true, 290 &appsv1.StatefulSet{ 291 // ObjectMeta: metav1.ObjectMeta{ 292 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 293 // }, 294 Spec: appsv1.StatefulSetSpec{ 295 Replicas: int32p(1), 296 Template: v1.PodTemplateSpec{ 297 ObjectMeta: metav1.ObjectMeta{ 298 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 299 }, 300 Spec: v1.PodSpec{ 301 Containers: []v1.Container{{ 302 Name: "test", 303 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 304 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 305 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 306 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 307 }}, 308 InitContainers: []v1.Container{{ 309 Name: "install-go-debug-support", 310 Image: "HELPERS/go", 311 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 312 }}, 313 Volumes: []v1.Volume{{ 314 Name: "debugging-support-files", 315 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 316 }}, 317 }}}}, 318 }, 319 { 320 "DaemonSet with Go container", 321 &appsv1.DaemonSet{ 322 Spec: appsv1.DaemonSetSpec{ 323 Template: v1.PodTemplateSpec{ 324 Spec: v1.PodSpec{ 325 Containers: []v1.Container{{ 326 Name: "test", 327 Command: []string{"app", "arg"}, 328 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 329 }}, 330 }}}}, 331 true, 332 &appsv1.DaemonSet{ 333 // ObjectMeta: metav1.ObjectMeta{ 334 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 335 // }, 336 Spec: appsv1.DaemonSetSpec{ 337 Template: v1.PodTemplateSpec{ 338 ObjectMeta: metav1.ObjectMeta{ 339 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 340 }, 341 Spec: v1.PodSpec{ 342 Containers: []v1.Container{{ 343 Name: "test", 344 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 345 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 346 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 347 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 348 }}, 349 InitContainers: []v1.Container{{ 350 Name: "install-go-debug-support", 351 Image: "HELPERS/go", 352 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 353 }}, 354 Volumes: []v1.Volume{{ 355 Name: "debugging-support-files", 356 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 357 }}, 358 }}}}, 359 }, 360 { 361 "Job with Go container", 362 &batchv1.Job{ 363 Spec: batchv1.JobSpec{ 364 Template: v1.PodTemplateSpec{ 365 Spec: v1.PodSpec{ 366 Containers: []v1.Container{{ 367 Name: "test", 368 Command: []string{"app", "arg"}, 369 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 370 }}, 371 }}}}, 372 true, 373 &batchv1.Job{ 374 // ObjectMeta: metav1.ObjectMeta{ 375 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 376 // }, 377 Spec: batchv1.JobSpec{ 378 Template: v1.PodTemplateSpec{ 379 ObjectMeta: metav1.ObjectMeta{ 380 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 381 }, 382 Spec: v1.PodSpec{ 383 Containers: []v1.Container{{ 384 Name: "test", 385 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 386 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 387 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 388 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 389 }}, 390 InitContainers: []v1.Container{{ 391 Name: "install-go-debug-support", 392 Image: "HELPERS/go", 393 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 394 }}, 395 Volumes: []v1.Volume{{ 396 Name: "debugging-support-files", 397 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 398 }}, 399 }}}}, 400 }, 401 { 402 "ReplicationController with Go container", 403 &v1.ReplicationController{ 404 Spec: v1.ReplicationControllerSpec{ 405 Replicas: int32p(2), 406 Template: &v1.PodTemplateSpec{ 407 Spec: v1.PodSpec{ 408 Containers: []v1.Container{{ 409 Name: "test", 410 Command: []string{"app", "arg"}, 411 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 412 }}, 413 }}}}, 414 true, 415 &v1.ReplicationController{ 416 // ObjectMeta: metav1.ObjectMeta{ 417 // Labels: map[string]string{"debug.cloud.google.com/enabled": `yes`}, 418 // }, 419 Spec: v1.ReplicationControllerSpec{ 420 Replicas: int32p(1), 421 Template: &v1.PodTemplateSpec{ 422 ObjectMeta: metav1.ObjectMeta{ 423 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 424 }, 425 Spec: v1.PodSpec{ 426 Containers: []v1.Container{{ 427 Name: "test", 428 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 429 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 430 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 431 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 432 }}, 433 InitContainers: []v1.Container{{ 434 Name: "install-go-debug-support", 435 Image: "HELPERS/go", 436 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 437 }}, 438 Volumes: []v1.Volume{{ 439 Name: "debugging-support-files", 440 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 441 }}, 442 }}}}, 443 }, 444 { 445 "PodList with Go and non-Go container", 446 &v1.PodList{ 447 Items: []v1.Pod{ 448 { 449 Spec: v1.PodSpec{ 450 Containers: []v1.Container{{ 451 Name: "echo", 452 Command: []string{"echo", "Hello World"}, 453 }}, 454 }}, 455 { 456 Spec: v1.PodSpec{ 457 Containers: []v1.Container{{ 458 Name: "test", 459 Command: []string{"app", "arg"}, 460 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 461 }}, 462 }}, 463 }}, 464 true, 465 &v1.PodList{ 466 Items: []v1.Pod{ 467 { 468 Spec: v1.PodSpec{ 469 Containers: []v1.Container{{ 470 Name: "echo", 471 Command: []string{"echo", "Hello World"}, 472 }}, 473 }}, 474 { 475 ObjectMeta: metav1.ObjectMeta{ 476 Annotations: map[string]string{"debug.cloud.google.com/config": `{"test":{"runtime":"go","ports":{"dlv":56268}}}`}, 477 }, 478 Spec: v1.PodSpec{ 479 Containers: []v1.Container{{ 480 Name: "test", 481 Command: []string{"/dbg/go/bin/dlv", "exec", "--headless", "--continue", "--accept-multiclient", "--listen=:56268", "--api-version=2", "app", "--", "arg"}, 482 Ports: []v1.ContainerPort{{Name: "dlv", ContainerPort: 56268}}, 483 Env: []v1.EnvVar{{Name: "GOMAXPROCS", Value: "1"}}, 484 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 485 }}, 486 InitContainers: []v1.Container{{ 487 Name: "install-go-debug-support", 488 Image: "HELPERS/go", 489 VolumeMounts: []v1.VolumeMount{{Name: "debugging-support-files", MountPath: "/dbg"}}, 490 }}, 491 Volumes: []v1.Volume{{ 492 Name: "debugging-support-files", 493 VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}}, 494 }}, 495 }}, 496 }}, 497 }, 498 } 499 for _, test := range tests { 500 testutil.Run(t, test.description, func(t *testutil.T) { 501 value := test.in.DeepCopyObject() 502 503 retriever := func(image string) (debug.ImageConfiguration, error) { 504 return debug.ImageConfiguration{}, nil 505 } 506 result := transformManifest(value, retriever, "HELPERS") 507 508 t.CheckDeepEqual(test.transformed, result) 509 t.CheckDeepEqual(test.out, value) 510 }) 511 } 512 }