github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadget-collection/gadgets/interface.go (about) 1 // Copyright 2019-2021 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 gadgets 16 17 import ( 18 "errors" 19 "fmt" 20 "sync" 21 22 "github.com/cilium/ebpf" 23 24 gadgetv1alpha1 "github.com/inspektor-gadget/inspektor-gadget/pkg/apis/gadget/v1alpha1" 25 containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection" 26 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets" 27 28 log "github.com/sirupsen/logrus" 29 apimachineryruntime "k8s.io/apimachinery/pkg/runtime" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 ) 32 33 type TraceFactory interface { 34 // Initialize gives the Helpers and the Client to the gadget. Gadgets 35 // don't need to implement this method if they use BaseFactory as an 36 // anonymous field. 37 Initialize(Helpers GadgetHelpers, Client client.Client) 38 39 // Delete request a gadget to release the information it has about a 40 // trace. BaseFactory implements this method, so gadgets who embed 41 // BaseFactory don't need to implement it. 42 Delete(name string) 43 44 // Operations gives the list of operations on a gadget that users can 45 // call via the gadget.kinvolk.io/operation annotation. 46 Operations() map[gadgetv1alpha1.Operation]TraceOperation 47 48 // OutputModesSupported returns the set of OutputMode supported by the 49 // gadget. 50 OutputModesSupported() map[gadgetv1alpha1.TraceOutputMode]struct{} 51 } 52 53 type TraceFactoryWithScheme interface { 54 TraceFactory 55 56 // AddToScheme let gadgets inform the Trace controller of any scheme 57 // they want to use 58 AddToScheme(*apimachineryruntime.Scheme) 59 } 60 61 type TraceFactoryWithDocumentation interface { 62 Description() string 63 } 64 65 // TraceOperation packages an operation on a gadget that users can call via the 66 // annotation gadget.kinvolk.io/operation. 67 type TraceOperation struct { 68 // Operation is the function called by the controller 69 Operation func(name string, trace *gadgetv1alpha1.Trace) 70 71 // Doc documents the operation. It is used to generate the 72 // documentation. 73 Doc string 74 75 // Order controls the ordering of the operation in the documentation. 76 // It's only needed when ordering alphabetically is not suitable. 77 Order int 78 } 79 80 // GadgetHelpers provides different functions that are used in the 81 // gadgets implementation. 82 type GadgetHelpers interface { 83 containercollection.ContainerResolver 84 gadgets.DataEnricherByMntNs 85 gadgets.DataEnricherByNetNs 86 gadgets.DataNodeEnricher 87 88 PublishEvent(tracerID string, line string) error 89 TracerMountNsMap(tracerID string) (*ebpf.Map, error) 90 ContainersMap() *ebpf.Map 91 } 92 93 type BaseFactory struct { 94 Helpers GadgetHelpers 95 Client client.Client 96 97 // DeleteTrace is optionally set by gadgets if they need to do 98 // specialised clean up. Example: 99 // 100 // func NewFactory() gadgets.TraceFactory { 101 // return &TraceFactory{ 102 // BaseFactory: gadgets.BaseFactory{DeleteTrace: deleteTrace}, 103 // } 104 // } 105 DeleteTrace func(name string, trace interface{}) 106 107 mu sync.Mutex 108 traces map[string]interface{} 109 } 110 111 func (f *BaseFactory) Initialize(r GadgetHelpers, c client.Client) { 112 f.Helpers = r 113 f.Client = c 114 } 115 116 func (f *BaseFactory) LookupOrCreate(name string, newTrace func() interface{}) interface{} { 117 f.mu.Lock() 118 defer f.mu.Unlock() 119 if f.traces == nil { 120 f.traces = make(map[string]interface{}) 121 } else { 122 trace, ok := f.traces[name] 123 if ok { 124 return trace 125 } 126 } 127 128 if newTrace == nil { 129 return nil 130 } 131 132 trace := newTrace() 133 f.traces[name] = trace 134 135 return trace 136 } 137 138 func (f *BaseFactory) Lookup(name string) (interface{}, error) { 139 f.mu.Lock() 140 defer f.mu.Unlock() 141 142 if f.traces == nil { 143 return nil, errors.New("traces map is nil") 144 } 145 146 trace, ok := f.traces[name] 147 if !ok { 148 return nil, fmt.Errorf("no trace for name %q", name) 149 } 150 151 return trace, nil 152 } 153 154 func (f *BaseFactory) Delete(name string) { 155 log.Infof("Deleting %s", name) 156 f.mu.Lock() 157 defer f.mu.Unlock() 158 trace, ok := f.traces[name] 159 if !ok { 160 log.Infof("Deleting %s: does not exist", name) 161 return 162 } 163 if f.DeleteTrace != nil { 164 f.DeleteTrace(name, trace) 165 } 166 delete(f.traces, name) 167 } 168 169 func (f *BaseFactory) Operations() map[gadgetv1alpha1.Operation]TraceOperation { 170 return map[gadgetv1alpha1.Operation]TraceOperation{} 171 } 172 173 func (f *BaseFactory) OutputModesSupported() map[gadgetv1alpha1.TraceOutputMode]struct{} { 174 return map[gadgetv1alpha1.TraceOutputMode]struct{}{} 175 }