Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
308
plugins/common/starlark/field_dict.go
Normal file
308
plugins/common/starlark/field_dict.go
Normal file
|
@ -0,0 +1,308 @@
|
|||
package starlark
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"go.starlark.net/starlark"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
// FieldDict is a starlark.Value for the metric fields. It is heavily based on the
|
||||
// starlark.Dict.
|
||||
type FieldDict struct {
|
||||
*Metric
|
||||
}
|
||||
|
||||
func (d FieldDict) String() string {
|
||||
buf := new(strings.Builder)
|
||||
buf.WriteString("{")
|
||||
sep := ""
|
||||
for _, item := range d.Items() {
|
||||
k, v := item[0], item[1]
|
||||
buf.WriteString(sep)
|
||||
buf.WriteString(k.String())
|
||||
buf.WriteString(": ")
|
||||
buf.WriteString(v.String())
|
||||
sep = ", "
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (FieldDict) Type() string {
|
||||
return "Fields"
|
||||
}
|
||||
|
||||
func (d FieldDict) Freeze() {
|
||||
// Disable linter check as the frozen variable is modified despite
|
||||
// passing a value instead of a pointer, because `FieldDict` holds
|
||||
// a pointer to the underlying metric containing the `frozen` field.
|
||||
//revive:disable:modifies-value-receiver
|
||||
d.frozen = true
|
||||
}
|
||||
|
||||
func (d FieldDict) Truth() starlark.Bool {
|
||||
return len(d.metric.FieldList()) != 0
|
||||
}
|
||||
|
||||
func (FieldDict) Hash() (uint32, error) {
|
||||
return 0, errors.New("not hashable")
|
||||
}
|
||||
|
||||
// AttrNames implements the starlark.HasAttrs interface.
|
||||
func (FieldDict) AttrNames() []string {
|
||||
return builtinAttrNames(FieldDictMethods)
|
||||
}
|
||||
|
||||
// Attr implements the starlark.HasAttrs interface.
|
||||
func (d FieldDict) Attr(name string) (starlark.Value, error) {
|
||||
return builtinAttr(d, name, FieldDictMethods)
|
||||
}
|
||||
|
||||
var FieldDictMethods = map[string]builtinMethod{
|
||||
"clear": dictClear,
|
||||
"get": dictGet,
|
||||
"items": dictItems,
|
||||
"keys": dictKeys,
|
||||
"pop": dictPop,
|
||||
"popitem": dictPopitem,
|
||||
"setdefault": dictSetdefault,
|
||||
"update": dictUpdate,
|
||||
"values": dictValues,
|
||||
}
|
||||
|
||||
// Get implements the starlark.Mapping interface.
|
||||
func (d FieldDict) Get(key starlark.Value) (v starlark.Value, found bool, err error) {
|
||||
if k, ok := key.(starlark.String); ok {
|
||||
gv, found := d.metric.GetField(k.GoString())
|
||||
if !found {
|
||||
return starlark.None, false, nil
|
||||
}
|
||||
|
||||
v, err := asStarlarkValue(gv)
|
||||
if err != nil {
|
||||
return starlark.None, false, err
|
||||
}
|
||||
return v, true, nil
|
||||
}
|
||||
|
||||
return starlark.None, false, errors.New("key must be of type 'str'")
|
||||
}
|
||||
|
||||
// SetKey implements the starlark.HasSetKey interface to support map update
|
||||
// using x[k]=v syntax, like a dictionary.
|
||||
func (d FieldDict) SetKey(k, v starlark.Value) error {
|
||||
if d.fieldIterCount > 0 {
|
||||
return errors.New("cannot insert during iteration")
|
||||
}
|
||||
|
||||
key, ok := k.(starlark.String)
|
||||
if !ok {
|
||||
return errors.New("field key must be of type 'str'")
|
||||
}
|
||||
|
||||
gv, err := asGoValue(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.metric.AddField(key.GoString(), gv)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Items implements the starlark.IterableMapping interface.
|
||||
func (d FieldDict) Items() []starlark.Tuple {
|
||||
items := make([]starlark.Tuple, 0, len(d.metric.FieldList()))
|
||||
for _, field := range d.metric.FieldList() {
|
||||
key := starlark.String(field.Key)
|
||||
sv, err := asStarlarkValue(field.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pair := starlark.Tuple{key, sv}
|
||||
items = append(items, pair)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func (d FieldDict) Clear() error {
|
||||
if d.fieldIterCount > 0 {
|
||||
return errors.New("cannot delete during iteration")
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(d.metric.FieldList()))
|
||||
for _, field := range d.metric.FieldList() {
|
||||
keys = append(keys, field.Key)
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
d.metric.RemoveField(key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d FieldDict) PopItem() (starlark.Value, error) {
|
||||
if d.fieldIterCount > 0 {
|
||||
return nil, errors.New("cannot delete during iteration")
|
||||
}
|
||||
|
||||
if len(d.metric.FieldList()) == 0 {
|
||||
return nil, errors.New("popitem(): field dictionary is empty")
|
||||
}
|
||||
|
||||
field := d.metric.FieldList()[0]
|
||||
k := field.Key
|
||||
v := field.Value
|
||||
|
||||
d.metric.RemoveField(k)
|
||||
|
||||
sk := starlark.String(k)
|
||||
sv, err := asStarlarkValue(v)
|
||||
if err != nil {
|
||||
return nil, errors.New("could not convert to starlark value")
|
||||
}
|
||||
|
||||
return starlark.Tuple{sk, sv}, nil
|
||||
}
|
||||
|
||||
func (d FieldDict) Delete(k starlark.Value) (v starlark.Value, found bool, err error) {
|
||||
if d.fieldIterCount > 0 {
|
||||
return nil, false, errors.New("cannot delete during iteration")
|
||||
}
|
||||
|
||||
if key, ok := k.(starlark.String); ok {
|
||||
value, ok := d.metric.GetField(key.GoString())
|
||||
if ok {
|
||||
d.metric.RemoveField(key.GoString())
|
||||
sv, err := asStarlarkValue(value)
|
||||
return sv, ok, err
|
||||
}
|
||||
return starlark.None, false, nil
|
||||
}
|
||||
|
||||
return starlark.None, false, errors.New("key must be of type 'str'")
|
||||
}
|
||||
|
||||
// Iterate implements the starlark.Iterator interface.
|
||||
func (d FieldDict) Iterate() starlark.Iterator {
|
||||
d.fieldIterCount++
|
||||
return &FieldIterator{Metric: d.Metric, fields: d.metric.FieldList()}
|
||||
}
|
||||
|
||||
type FieldIterator struct {
|
||||
*Metric
|
||||
fields []*telegraf.Field
|
||||
}
|
||||
|
||||
// Next implements the starlark.Iterator interface.
|
||||
func (i *FieldIterator) Next(p *starlark.Value) bool {
|
||||
if len(i.fields) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
field := i.fields[0]
|
||||
i.fields = i.fields[1:]
|
||||
*p = starlark.String(field.Key)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Done implements the starlark.Iterator interface.
|
||||
func (i *FieldIterator) Done() {
|
||||
i.fieldIterCount--
|
||||
}
|
||||
|
||||
// AsStarlarkValue converts a field value to a starlark.Value.
|
||||
func asStarlarkValue(value interface{}) (starlark.Value, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
length := v.Len()
|
||||
array := make([]starlark.Value, 0, length)
|
||||
for i := 0; i < length; i++ {
|
||||
sVal, err := asStarlarkValue(v.Index(i).Interface())
|
||||
if err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
array = append(array, sVal)
|
||||
}
|
||||
return starlark.NewList(array), nil
|
||||
case reflect.Map:
|
||||
dict := starlark.NewDict(v.Len())
|
||||
iter := v.MapRange()
|
||||
for iter.Next() {
|
||||
sKey, err := asStarlarkValue(iter.Key().Interface())
|
||||
if err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
sValue, err := asStarlarkValue(iter.Value().Interface())
|
||||
if err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
if err := dict.SetKey(sKey, sValue); err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
}
|
||||
return dict, nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return starlark.Float(v.Float()), nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return starlark.MakeInt64(v.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return starlark.MakeUint64(v.Uint()), nil
|
||||
case reflect.String:
|
||||
return starlark.String(v.String()), nil
|
||||
case reflect.Bool:
|
||||
return starlark.Bool(v.Bool()), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid type %T", value)
|
||||
}
|
||||
|
||||
// AsGoValue converts a starlark.Value to a field value.
|
||||
func asGoValue(value interface{}) (interface{}, error) {
|
||||
switch v := value.(type) {
|
||||
case starlark.Float:
|
||||
return float64(v), nil
|
||||
case starlark.Int:
|
||||
n, ok := v.Int64()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot represent integer %v as int64", v)
|
||||
}
|
||||
return n, nil
|
||||
case starlark.String:
|
||||
return string(v), nil
|
||||
case starlark.Bool:
|
||||
return bool(v), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid starlark type %T", value)
|
||||
}
|
||||
|
||||
// ToFields converts a starlark.Value to a map of values.
|
||||
func toFields(value starlark.Value) (map[string]interface{}, error) {
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
items, err := items(value, "The type %T is unsupported as type of collection of fields")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make(map[string]interface{}, len(items))
|
||||
for _, item := range items {
|
||||
key, err := toString(item[0], "The type %T is unsupported as type of key for fields")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := asGoValue(item[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[key] = value
|
||||
}
|
||||
return result, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue