Documentation

Overview

Package bloblang provides high level APIs for registering custom Bloblang plugins, as well as for parsing and executing Bloblang mappings.

Plugins can either be registered globally, and will be accessible to any component parsing Bloblang expressions in the executable, or they can be registered as part of an isolated environment.

Example (BloblangPlugins)

ExampleBloblangPlugins demonstrates how to create Bloblang methods and functions and execute them with a Bloblang mapping.

package main

import (
	"encoding/json"
	"fmt"
	"math/rand"

	"github.com/Jeffail/benthos/v3/public/bloblang"
)

func main() {
	if err := bloblang.RegisterMethod("cuddle", func(args ...interface{}) (bloblang.Method, error) {
		var prefix string
		var suffix string

		if err := bloblang.NewArgSpec().
			StringVar(&prefix).
			StringVar(&suffix).
			Extract(args); err != nil {
			return nil, err
		}

		return bloblang.StringMethod(func(s string) (interface{}, error) {
			return prefix + s + suffix, nil
		}), nil
	}); err != nil {
		panic(err)
	}

	if err := bloblang.RegisterMethod("shuffle", func(_ ...interface{}) (bloblang.Method, error) {
		rand := rand.New(rand.NewSource(0))
		return bloblang.ArrayMethod(func(in []interface{}) (interface{}, error) {
			out := make([]interface{}, len(in))
			copy(out, in)
			rand.Shuffle(len(out), func(i, j int) {
				out[i], out[j] = out[j], out[i]
			})
			return out, nil
		}), nil
	}); err != nil {
		panic(err)
	}

	if err := bloblang.RegisterFunction("add_but_always_slightly_wrong", func(args ...interface{}) (bloblang.Function, error) {
		var left, right float64

		if err := bloblang.NewArgSpec().
			Float64Var(&left).
			Float64Var(&right).
			Extract(args); err != nil {
			return nil, err
		}

		return func() (interface{}, error) {
			return left + right + 0.02, nil
		}, nil
	}); err != nil {
		panic(err)
	}

	mapping := `
root.new_summary = this.summary.cuddle("meow", "woof")
root.shuffled = this.names.shuffle()
root.num = add_but_always_slightly_wrong(1.2, 2.6)
`

	exe, err := bloblang.Parse(mapping)
	if err != nil {
		panic(err)
	}

	res, err := exe.Query(map[string]interface{}{
		"summary": "quack",
		"names":   []interface{}{"denny", "pixie", "olaf", "jen", "spuz"},
	})
	if err != nil {
		panic(err)
	}

	jsonBytes, err := json.Marshal(res)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(jsonBytes))
}
Output:

{"new_summary":"meowquackwoof","num":3.82,"shuffled":["olaf","jen","pixie","denny","spuz"]}
Example (BloblangRestrictedEnvironment)

ExampleBloblangRestrictedEnvironment demonstrates how to create and use an isolated Bloblang environment with some standard functions removed.

package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/Jeffail/benthos/v3/public/bloblang"
)

func main() {
	env := bloblang.NewEnvironment().WithoutFunctions("env", "file")

	if err := env.RegisterMethod("custom_thing", func(args ...interface{}) (bloblang.Method, error) {
		return bloblang.StringMethod(func(s string) (interface{}, error) {
			return strings.ToUpper(s), nil
		}), nil
	}); err != nil {
		panic(err)
	}

	mapping := `
root.foo = this.foo.string()
root.bar = this.bar + this.baz
root.buz = this.buz.content.custom_thing()
`

	exe, err := env.Parse(mapping)
	if err != nil {
		panic(err)
	}

	res, err := exe.Query(map[string]interface{}{
		"foo": 50.0,
		"bar": "first bit ",
		"baz": "second bit",
		"buz": map[string]interface{}{
			"id":      "XXXX",
			"content": "some nested content",
		},
	})
	if err != nil {
		panic(err)
	}

	jsonBytes, err := json.Marshal(res)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(jsonBytes))
}
Output:

{"bar":"first bit second bit","buz":"SOME NESTED CONTENT","foo":"50"}

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrRootDeleted = errors.New("root was deleted")

ErrRootDeleted is returned by a Bloblang query when the mapping results in the root being deleted. It might be considered correct to do this in situations where filtering is allowed or expected.

Functions

func RegisterFunction

func RegisterFunction(name string, ctor FunctionConstructor) error

RegisterFunction adds a new Bloblang function to the global enviromment. All function names must match the regular expression /^[a-z0-9]+(_[a-z0-9]+)*$/ (snake case).

func RegisterMethod

func RegisterMethod(name string, ctor MethodConstructor) error

RegisterMethod adds a new Bloblang method to the global enviromment. All method names must match the regular expression /^[a-z0-9]+(_[a-z0-9]+)*$/ (snake case).

Types

type ArgSpec

type ArgSpec struct {
	// contains filtered or unexported fields
}

ArgSpec provides an API for validating and extracting function or method arguments by registering them with pointer receivers.

func NewArgSpec

func NewArgSpec() *ArgSpec

NewArgSpec creates an argument parser/validator.

func (*ArgSpec) AnyVar

func (a *ArgSpec) AnyVar(i *interface{}) *ArgSpec

AnyVar creates an argument to follow the previously created argument that can have any value.

func (*ArgSpec) BoolVar

func (a *ArgSpec) BoolVar(b *bool) *ArgSpec

BoolVar creates a boolean argument to follow the previously created argument.

func (*ArgSpec) Extract

func (a *ArgSpec) Extract(args []interface{}) error

Extract the specified typed arguments from a slice of generic arguments. Returns an error if the type of an argument is mismatched, or if the number of arguments is mismatched.

func (*ArgSpec) Float64Var

func (a *ArgSpec) Float64Var(f *float64) *ArgSpec

Float64Var creates a Float64 argument to follow the previously created argument.

func (*ArgSpec) Int64Var

func (a *ArgSpec) Int64Var(i *int64) *ArgSpec

Int64Var creates an int64 argument to follow the previously created argument.

func (*ArgSpec) IntVar

func (a *ArgSpec) IntVar(i *int) *ArgSpec

IntVar creates an int argument to follow the previously created argument.

func (*ArgSpec) StringVar

func (a *ArgSpec) StringVar(s *string) *ArgSpec

StringVar creates a string argument to follow the previously created argument.

type Environment

type Environment struct {
	// contains filtered or unexported fields
}

Environment provides an isolated Bloblang environment where the available features, functions and methods can be modified.

func NewEnvironment

func NewEnvironment() *Environment

NewEnvironment creates a fresh Bloblang environment, starting with the full range of globally defined features (functions and methods), and provides APIs for expanding or contracting the features available to this environment.

It's worth using an environment when you need to restrict the access or capabilities that certain bloblang mappings have versus others.

For example, an environment could be created that removes any functions for accessing environment variables or reading data from the host disk, which could be used in certain situations without removing those functions globally for all mappings.

func (*Environment) Parse

func (e *Environment) Parse(blobl string) (*Executor, error)

Parse a Bloblang mapping using the Environment to determine the features (functions and methods) available to the mapping.

func (*Environment) RegisterFunction

func (e *Environment) RegisterFunction(name string, ctor FunctionConstructor) error

RegisterFunction adds a new Bloblang function to the environment. All function names must match the regular expression /^[a-z0-9]+(_[a-z0-9]+)*$/ (snake case).

func (*Environment) RegisterMethod

func (e *Environment) RegisterMethod(name string, ctor MethodConstructor) error

RegisterMethod adds a new Bloblang method to the environment. All method names must match the regular expression /^[a-z0-9]+(_[a-z0-9]+)*$/ (snake case).

func (*Environment) WithoutFunctions

func (e *Environment) WithoutFunctions(names ...string) *Environment

WithoutFunctions returns a copy of the environment but with a variadic list of function names removed. Instantiation of these removed functions within a mapping will cause errors at parse time.

func (*Environment) WithoutMethods

func (e *Environment) WithoutMethods(names ...string) *Environment

WithoutMethods returns a copy of the environment but with a variadic list of method names removed. Instantiation of these removed methods within a mapping will cause errors at parse time.

type Executor

type Executor struct {
	// contains filtered or unexported fields
}

Executor stores a parsed Bloblang mapping and provides APIs for executing it.

func Parse

func Parse(blobl string) (*Executor, error)

Parse a Bloblang mapping allowing the use of the globally accessible range of features (functions and methods).

func (*Executor) Overlay

func (e *Executor) Overlay(value interface{}, onto *interface{}) error

Overlay executes a Bloblang mapping against a value, where assignments are overlayed onto an existing structure.

func (*Executor) Query

func (e *Executor) Query(value interface{}) (interface{}, error)

Query executes a Bloblang mapping against a value and returns the result. The argument and return values can be structured using the same map[string]interface{} and []interface{} types as would be returned by the Go standard json package unmarshaler.

If the mapping results in the root of the new document being deleted then ErrRootDeleted is returned, which can be used as a signal to filter rather than fail the mapping.

type Function

type Function func() (interface{}, error)

Function defines a Bloblang function, arguments are provided to the constructor, allowing the implementation of this function to resolve them statically when possible.

type FunctionConstructor

type FunctionConstructor func(args ...interface{}) (Function, error)

FunctionConstructor defines a constructor for a Bloblang function, where a variadic list of arguments are provided.

When a function is parsed from a mapping with static arguments the constructor will be called only once at parse time. When a function is parsed with dynamic arguments, such as a value derived from the mapping input, the constructor will be called on each invocation of the mapping with the derived arguments.

For a convenient way to perform type checking and coercion on the arguments use an ArgSpec.

type Method

type Method func(v interface{}) (interface{}, error)

Method defines a Bloblang function that executes on a value. Arguments are provided to the constructor, allowing the implementation of this method to resolve them statically when possible.

In order to avoid type checking the value use one of the typed variants such as StringMethod.

func ArrayMethod

func ArrayMethod(methodFn func([]interface{}) (interface{}, error)) Method

ArrayMethod creates a general method signature from an array method by performing type checking on the method target.

func BoolMethod

func BoolMethod(methodFn func(bool) (interface{}, error)) Method

BoolMethod creates a general method signature from a bool method by performing type checking on the method target.

func BytesMethod

func BytesMethod(methodFn func([]byte) (interface{}, error)) Method

BytesMethod creates a general method signature from a byte slice method by performing type checking on the method target.

func Float64Method

func Float64Method(methodFn func(float64) (interface{}, error)) Method

Float64Method creates a general method signature from a float method by performing type checking on the method target.

func Int64Method

func Int64Method(methodFn func(int64) (interface{}, error)) Method

Int64Method creates a general method signature from an int method by performing type checking on the method target.

func ObjectMethod

func ObjectMethod(methodFn func(obj map[string]interface{}) (interface{}, error)) Method

ObjectMethod creates a general method signature from an object method by performing type checking on the method target.

func StringMethod

func StringMethod(methodFn func(string) (interface{}, error)) Method

StringMethod creates a general method signature from a string method by performing type checking on the method target.

func TimestampMethod

func TimestampMethod(methodFn func(time.Time) (interface{}, error)) Method

TimestampMethod creates a general method signature from a timestamp method by performing type checking on the method target.

type MethodConstructor

type MethodConstructor func(args ...interface{}) (Method, error)

MethodConstructor defines a constructor for a Bloblang method, where a variadic list of arguments are provided.

When a method is parsed from a mapping with static arguments the constructor will be called only once at parse time. When a method is parsed with dynamic arguments, such as a value derived from the mapping input, the constructor will be called on each invocation of the mapping with the derived arguments.

For a convenient way to perform type checking and coercion on the arguments use an ArgSpec.