github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/docker/debugger/transform.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 debugger 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/docker/docker/api/types/container" 24 "github.com/docker/docker/api/types/volume" 25 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/debug/types" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 31 ) 32 33 var ( 34 SupportVolumeMount = volume.VolumeCreateBody{Name: debug.DebuggingSupportFilesVolume} 35 TransformImage = transformImage // For testing 36 ) 37 38 type Transform func(string) string 39 40 func transformImage(ctx context.Context, artifact graph.Artifact, cfg *container.Config, insecureRegistries map[string]bool, debugHelpersRegistry string) (map[string]types.ContainerDebugConfiguration, []*container.Config, error) { 41 portAvailable := func(port int32) bool { 42 return isPortAvailable(cfg, port) 43 } 44 portAlloc := func(desiredPort int32) int32 { 45 return util.AllocatePort(portAvailable, desiredPort) 46 } 47 48 adapter := NewAdapter(cfg) 49 imageConfig, err := debug.RetrieveImageConfiguration(ctx, &artifact, insecureRegistries) 50 if err != nil { 51 return nil, nil, err 52 } 53 54 configurations := make(map[string]types.ContainerDebugConfiguration) 55 var initContainers []*container.Config 56 // the container images that require debugging support files 57 var containersRequiringSupport []*container.Config 58 // the set of image IDs required to provide debugging support files 59 requiredSupportImages := make(map[string]bool) 60 61 if configuration, requiredImage, err := debug.TransformContainer(adapter, imageConfig, portAlloc); err == nil { 62 configurations[adapter.GetContainer().Name] = configuration 63 if len(requiredImage) > 0 { 64 log.Entry(ctx).Infof("%q requires debugging support image %q", cfg.Image, requiredImage) 65 containersRequiringSupport = append(containersRequiringSupport, cfg) 66 requiredSupportImages[requiredImage] = true 67 } 68 } else { 69 log.Entry(ctx).Warnf("Image %q not configured for debugging: %v", cfg.Image, err) 70 } 71 72 // check if we have any images requiring additional debugging support files 73 if len(containersRequiringSupport) > 0 { 74 log.Entry(ctx).Infof("Configuring installation of debugging support files") 75 // the initContainers are responsible for populating the contents of `/dbg` 76 for imageID := range requiredSupportImages { 77 supportFilesInitContainer := &container.Config{ 78 Image: fmt.Sprintf("%s/%s", debugHelpersRegistry, imageID), 79 Volumes: map[string]struct{}{"/dbg": {}}, 80 } 81 initContainers = append(initContainers, supportFilesInitContainer) 82 } 83 // the populated volume is then mounted in the containers at `/dbg` too 84 for _, container := range containersRequiringSupport { 85 if container.Volumes == nil { 86 container.Volumes = make(map[string]struct{}) 87 } 88 container.Volumes["/dbg"] = struct{}{} 89 } 90 } 91 92 return configurations, initContainers, nil 93 } 94 95 // isPortAvailable returns true if none of the pod's containers specify the given port. 96 func isPortAvailable(cfg *container.Config, port int32) bool { 97 for exposedPort := range cfg.ExposedPorts { 98 if int32(exposedPort.Int()) == port { 99 return false 100 } 101 } 102 return true 103 }