github.com/Jeffail/benthos/v3@v3.65.0/internal/bundle/inputs.go (about)

     1  package bundle
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/Jeffail/benthos/v3/internal/docs"
     8  	"github.com/Jeffail/benthos/v3/lib/input"
     9  	"github.com/Jeffail/benthos/v3/lib/types"
    10  )
    11  
    12  // AllInputs is a set containing every single input that has been imported.
    13  var AllInputs = &InputSet{
    14  	specs: map[string]inputSpec{},
    15  }
    16  
    17  //------------------------------------------------------------------------------
    18  
    19  // InputAdd adds a new input to this environment by providing a constructor and
    20  // documentation.
    21  func (e *Environment) InputAdd(constructor InputConstructor, spec docs.ComponentSpec) error {
    22  	return e.inputs.Add(constructor, spec)
    23  }
    24  
    25  // InputInit attempts to initialise an input from a config.
    26  func (e *Environment) InputInit(
    27  	hasBatchProc bool,
    28  	conf input.Config,
    29  	mgr NewManagement,
    30  	pipelines ...types.PipelineConstructorFunc,
    31  ) (types.Input, error) {
    32  	return e.inputs.Init(hasBatchProc, conf, mgr, pipelines...)
    33  }
    34  
    35  // InputDocs returns a slice of input specs, which document each method.
    36  func (e *Environment) InputDocs() []docs.ComponentSpec {
    37  	return e.inputs.Docs()
    38  }
    39  
    40  //------------------------------------------------------------------------------
    41  
    42  // InputConstructorFromSimple provides a way to define an input constructor
    43  // without manually initializing processors of the config.
    44  func InputConstructorFromSimple(fn func(input.Config, NewManagement) (input.Type, error)) InputConstructor {
    45  	return func(b bool, c input.Config, nm NewManagement, pcf ...types.PipelineConstructorFunc) (input.Type, error) {
    46  		i, err := fn(c, nm)
    47  		if err != nil {
    48  			return nil, fmt.Errorf("failed to create input '%v': %w", c.Type, err)
    49  		}
    50  		pcf = input.AppendProcessorsFromConfig(c, nm, nm.Logger(), nm.Metrics(), pcf...)
    51  		return input.WrapWithPipelines(i, pcf...)
    52  	}
    53  }
    54  
    55  //------------------------------------------------------------------------------
    56  
    57  // InputConstructor constructs an input component.
    58  type InputConstructor func(bool, input.Config, NewManagement, ...types.PipelineConstructorFunc) (input.Type, error)
    59  
    60  type inputSpec struct {
    61  	constructor InputConstructor
    62  	spec        docs.ComponentSpec
    63  }
    64  
    65  // InputSet contains an explicit set of inputs available to a Benthos service.
    66  type InputSet struct {
    67  	specs map[string]inputSpec
    68  }
    69  
    70  // Add a new input to this set by providing a constructor and documentation.
    71  func (s *InputSet) Add(constructor InputConstructor, spec docs.ComponentSpec) error {
    72  	if s.specs == nil {
    73  		s.specs = map[string]inputSpec{}
    74  	}
    75  	s.specs[spec.Name] = inputSpec{
    76  		constructor: constructor,
    77  		spec:        spec,
    78  	}
    79  	docs.RegisterDocs(spec)
    80  	return nil
    81  }
    82  
    83  // Init attempts to initialise an input from a config.
    84  func (s *InputSet) Init(
    85  	hasBatchProc bool,
    86  	conf input.Config,
    87  	mgr NewManagement,
    88  	pipelines ...types.PipelineConstructorFunc,
    89  ) (types.Input, error) {
    90  	spec, exists := s.specs[conf.Type]
    91  	if !exists {
    92  		// TODO: V4 Remove this
    93  		if ctor, exists := input.GetDeprecatedPlugin(conf.Type); exists {
    94  			return ctor(hasBatchProc, conf, mgr, mgr.Logger(), mgr.Metrics(), pipelines...)
    95  		}
    96  		return nil, types.ErrInvalidInputType
    97  	}
    98  	return spec.constructor(hasBatchProc, conf, mgr, pipelines...)
    99  }
   100  
   101  // Docs returns a slice of input specs, which document each method.
   102  func (s *InputSet) Docs() []docs.ComponentSpec {
   103  	var docs []docs.ComponentSpec
   104  	for _, v := range s.specs {
   105  		docs = append(docs, v.spec)
   106  	}
   107  	sort.Slice(docs, func(i, j int) bool {
   108  		return docs[i].Name < docs[j].Name
   109  	})
   110  	return docs
   111  }
   112  
   113  // DocsFor returns the documentation for a given component name, returns a
   114  // boolean indicating whether the component name exists.
   115  func (s *InputSet) DocsFor(name string) (docs.ComponentSpec, bool) {
   116  	c, ok := s.specs[name]
   117  	if !ok {
   118  		return docs.ComponentSpec{}, false
   119  	}
   120  	return c.spec, true
   121  }