func ToActioner(in interface{}) (Action, error) {
	min, ok := in.(map[string]interface{})
	if !ok {
		return Action{}, errors.New("action definition is not an object")
	}
	var a Actioner
	typ, _ := min["type"].(string)
	typ = strings.ToLower(typ)
	switch typ {
	case "log":
		a = &Log{}
	case "http":
		a = &HTTP{}
	case "slack":
		a = &Slack{}
	default:
		return Action{}, fmt.Errorf("unknown action type: %q", typ)
	}
	if err := mapstructure.Decode(min, a); err != nil {
		return Action{}, err
	}
	return Action{Type: typ, Actioner: a}, nil
}
ToActioner takes in some arbitrary data (hopefully a map[string]interface{},
looks at its "type" key, and any other fields necessary based on that type,
and returns an Actioner (or an error)
package action
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
	"github.com/Akagi201/esalert/config"
	"github.com/Akagi201/esalert/context"
	"github.com/mitchellh/mapstructure"
	log "github.com/sirupsen/logrus"
)
type Actioner interface {
	Do(context.Context) error
}
type Action struct {
	Type string
	Actioner
}