github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/container-collection/networktracer/connect.go (about) 1 // Copyright 2022 The Inspektor Gadget authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package networktracer 16 17 import ( 18 "fmt" 19 20 "github.com/google/uuid" 21 22 containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" 23 eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" 24 ) 25 26 type Tracer interface { 27 Attach(pid uint32) error 28 Detach(pid uint32) error 29 EventCallback(event any) 30 } 31 32 type ConnectionToContainerCollection struct { 33 subKey string 34 resolver containercollection.ContainerResolver 35 } 36 37 func (c *ConnectionToContainerCollection) Close() { 38 c.resolver.Unsubscribe(c.subKey) 39 } 40 41 type ConnectToContainerCollectionConfig[Event any] struct { 42 Tracer Tracer 43 Resolver containercollection.ContainerResolver 44 Selector containercollection.ContainerSelector 45 Base func(eventtypes.Event) *Event 46 } 47 48 // ConnectToContainerCollection connects a networking tracer to the 49 // container collection package. It creates the needed logic to call the 50 // Attach() function on the tracer each time a container is created and 51 // to call Detach() each time the container is removed. Callers must 52 // call Close() on the returned ConnectionToContainerCollection object. 53 func ConnectToContainerCollection[Event any]( 54 config *ConnectToContainerCollectionConfig[Event], 55 ) (*ConnectionToContainerCollection, error) { 56 // Variables to avoid using c. in all the places below 57 id := uuid.New() 58 subscribeKey := id.String() 59 tracer := config.Tracer 60 resolver := config.Resolver 61 selector := config.Selector 62 base := config.Base 63 64 attachContainerFunc := func(container *containercollection.Container) { 65 err := tracer.Attach(container.Pid) 66 if err != nil { 67 msg := fmt.Sprintf("start tracing container %q: %s", container.K8s.ContainerName, err) 68 tracer.EventCallback(base(eventtypes.Err(msg))) 69 return 70 } 71 tracer.EventCallback(base(eventtypes.Debug("tracer attached"))) 72 } 73 74 detachContainerFunc := func(container *containercollection.Container) { 75 err := tracer.Detach(container.Pid) 76 if err != nil { 77 msg := fmt.Sprintf("stop tracing container %q: %s", container.K8s.ContainerName, err) 78 tracer.EventCallback(base(eventtypes.Err(msg))) 79 return 80 } 81 tracer.EventCallback(base(eventtypes.Debug("tracer detached"))) 82 } 83 84 containers := resolver.Subscribe( 85 subscribeKey, 86 selector, 87 func(event containercollection.PubSubEvent) { 88 switch event.Type { 89 case containercollection.EventTypeAddContainer: 90 attachContainerFunc(event.Container) 91 case containercollection.EventTypeRemoveContainer: 92 detachContainerFunc(event.Container) 93 } 94 }, 95 ) 96 97 for _, container := range containers { 98 attachContainerFunc(container) 99 } 100 return &ConnectionToContainerCollection{ 101 subKey: subscribeKey, 102 resolver: resolver, 103 }, nil 104 }