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  }