lang: interfaces, funcs: Implement fmt.Stringer for functions

This adds the requirement that all function implementations provider a
String() string method so that these can be used as vertices in the
pgraph library. If we eventually move to generics for the pgraph DAG,
then this might not matter, but it's not bad that these have names
either.
This commit is contained in:
James Shubin
2023-03-03 14:12:09 -05:00
parent 8366cf0873
commit 5d664855de
35 changed files with 365 additions and 39 deletions

View File

@@ -48,6 +48,12 @@ type ContainsPolyFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ContainsPolyFunc) String() string {
return ContainsFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *ContainsPolyFunc) ArgGen(index int) (string, error) { func (obj *ContainsPolyFunc) ArgGen(index int) (string, error) {
seq := []string{"needle", "haystack"} seq := []string{"needle", "haystack"}

View File

@@ -24,8 +24,14 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// NowFuncName is the name this fact is registered as. It's still a Func
// Name because this is the name space the fact is actually using.
NowFuncName = "now"
)
func init() { func init() {
facts.ModuleRegister(ModuleName, "now", func() facts.Fact { return &DateTimeFact{} }) // must register the fact and name facts.ModuleRegister(ModuleName, NowFuncName, func() facts.Fact { return &DateTimeFact{} }) // must register the fact and name
} }
// DateTimeFact is a fact which returns the current date and time. // DateTimeFact is a fact which returns the current date and time.
@@ -34,6 +40,12 @@ type DateTimeFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *DateTimeFact) String() string {
return NowFuncName
}
// Validate makes sure we've built our struct properly. It is usually unused for // Validate makes sure we've built our struct properly. It is usually unused for
// normal facts that users can use directly. // normal facts that users can use directly.
//func (obj *DateTimeFact) Validate() error { //func (obj *DateTimeFact) Validate() error {

View File

@@ -26,14 +26,17 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// AbsPathFuncName is the name this function is registered as.
AbsPathFuncName = "abspath"
pathArg = "path"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "abspath", func() interfaces.Func { return &AbsPathFunc{} }) // must register the func and name funcs.ModuleRegister(ModuleName, "abspath", func() interfaces.Func { return &AbsPathFunc{} }) // must register the func and name
} }
const (
pathArg = "path"
)
// AbsPathFunc is a function that returns the absolute, full path in the deploy // AbsPathFunc is a function that returns the absolute, full path in the deploy
// from an input path that is relative to the calling file. If you pass it an // from an input path that is relative to the calling file. If you pass it an
// empty string, you'll just get the absolute deploy directory path that you're // empty string, you'll just get the absolute deploy directory path that you're
@@ -49,6 +52,12 @@ type AbsPathFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *AbsPathFunc) String() string {
return AbsPathFuncName
}
// SetData is used by the language to pass our function some code-level context. // SetData is used by the language to pass our function some code-level context.
func (obj *AbsPathFunc) SetData(data *interfaces.FuncData) { func (obj *AbsPathFunc) SetData(data *interfaces.FuncData) {
obj.data = data obj.data = data

View File

@@ -27,8 +27,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// ReadFileFuncName is the name this function is registered as.
ReadFileFuncName = "readfile"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "readfile", func() interfaces.Func { return &ReadFileFunc{} }) // must register the func and name funcs.ModuleRegister(ModuleName, ReadFileFuncName, func() interfaces.Func { return &ReadFileFunc{} }) // must register the func and name
} }
// ReadFileFunc is a function that reads the full contents from a file in our // ReadFileFunc is a function that reads the full contents from a file in our
@@ -46,6 +51,12 @@ type ReadFileFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ReadFileFunc) String() string {
return ReadFileFuncName
}
// SetData is used by the language to pass our function some code-level context. // SetData is used by the language to pass our function some code-level context.
func (obj *ReadFileFunc) SetData(data *interfaces.FuncData) { func (obj *ReadFileFunc) SetData(data *interfaces.FuncData) {
obj.data = data obj.data = data

View File

@@ -26,8 +26,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// ReadFileAbsFuncName is the name this function is registered as.
ReadFileAbsFuncName = "readfileabs"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "readfileabs", func() interfaces.Func { return &ReadFileAbsFunc{} }) // must register the func and name funcs.ModuleRegister(ModuleName, ReadFileAbsFuncName, func() interfaces.Func { return &ReadFileAbsFunc{} }) // must register the func and name
} }
// ReadFileAbsFunc is a function that reads the full contents from a file in our // ReadFileAbsFunc is a function that reads the full contents from a file in our
@@ -46,6 +51,12 @@ type ReadFileAbsFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ReadFileAbsFunc) String() string {
return ReadFileAbsFuncName
}
// SetData is used by the language to pass our function some code-level context. // SetData is used by the language to pass our function some code-level context.
func (obj *ReadFileAbsFunc) SetData(data *interfaces.FuncData) { func (obj *ReadFileAbsFunc) SetData(data *interfaces.FuncData) {
obj.data = data obj.data = data

View File

@@ -24,8 +24,14 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// FlipFlopFuncName is the name this fact is registered as. It's still a
// Func Name because this is the name space the fact is actually using.
FlipFlopFuncName = "flipflop"
)
func init() { func init() {
facts.ModuleRegister(ModuleName, "flipflop", func() facts.Fact { return &FlipFlopFact{} }) // must register the fact and name facts.ModuleRegister(ModuleName, FlipFlopFuncName, func() facts.Fact { return &FlipFlopFact{} }) // must register the fact and name
} }
// FlipFlopFact is a fact which flips a bool repeatedly. This is an example fact // FlipFlopFact is a fact which flips a bool repeatedly. This is an example fact
@@ -37,6 +43,12 @@ type FlipFlopFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *FlipFlopFact) String() string {
return FlipFlopFuncName
}
// Validate makes sure we've built our struct properly. It is usually unused for // Validate makes sure we've built our struct properly. It is usually unused for
// normal facts that users can use directly. // normal facts that users can use directly.
//func (obj *FlipFlopFact) Validate() error { //func (obj *FlipFlopFact) Validate() error {

View File

@@ -35,8 +35,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// VUMeterFuncName is the name this function is registered as.
VUMeterFuncName = "vumeter"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "vumeter", func() interfaces.Func { return &VUMeterFunc{} }) // must register the func and name funcs.ModuleRegister(ModuleName, VUMeterFuncName, func() interfaces.Func { return &VUMeterFunc{} }) // must register the func and name
} }
// VUMeterFunc is a gimmic function to display a vu meter from the microphone. // VUMeterFunc is a gimmic function to display a vu meter from the microphone.
@@ -53,6 +58,12 @@ type VUMeterFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *VUMeterFunc) String() string {
return VUMeterFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *VUMeterFunc) ArgGen(index int) (string, error) { func (obj *VUMeterFunc) ArgGen(index int) (string, error) {
seq := []string{"symbol", "multiplier", "peak"} seq := []string{"symbol", "multiplier", "peak"}

View File

@@ -27,15 +27,18 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
func init() {
// FIXME: should this be named sprintf instead?
funcs.ModuleRegister(ModuleName, "printf", func() interfaces.Func { return &PrintfFunc{} })
}
const ( const (
// PrintfFuncName is the name this function is registered as.
// FIXME: should this be named sprintf instead?
PrintfFuncName = "printf"
formatArgName = "format" // name of the first arg formatArgName = "format" // name of the first arg
) )
func init() {
funcs.ModuleRegister(ModuleName, PrintfFuncName, func() interfaces.Func { return &PrintfFunc{} })
}
// PrintfFunc is a static polymorphic function that compiles a format string and // PrintfFunc is a static polymorphic function that compiles a format string and
// returns the output as a string. It bases its output on the values passed in // returns the output as a string. It bases its output on the values passed in
// to it. It examines the type of the arguments at compile time and then // to it. It examines the type of the arguments at compile time and then
@@ -56,6 +59,12 @@ type PrintfFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *PrintfFunc) String() string {
return PrintfFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *PrintfFunc) ArgGen(index int) (string, error) { func (obj *PrintfFunc) ArgGen(index int) (string, error) {
if index == 0 { if index == 0 {

View File

@@ -27,9 +27,14 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
func init() { const (
// MapFuncName is the name this function is registered as.
// XXX: rename to map once our parser sees a function name and not a type // XXX: rename to map once our parser sees a function name and not a type
funcs.ModuleRegister(ModuleName, "xmap", func() interfaces.Func { return &MapFunc{} }) // must register the func and name MapFuncName = "xmap"
)
func init() {
funcs.ModuleRegister(ModuleName, MapFuncName, func() interfaces.Func { return &MapFunc{} }) // must register the func and name
} }
const ( const (
@@ -62,6 +67,12 @@ type MapFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *MapFunc) String() string {
return MapFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *MapFunc) ArgGen(index int) (string, error) { func (obj *MapFunc) ArgGen(index int) (string, error) {
seq := []string{argNameInputs, argNameFunction} // inverted for pretty! seq := []string{argNameInputs, argNameFunction} // inverted for pretty!

View File

@@ -29,8 +29,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// ReadFileFuncName is the name this function is registered as.
ReadFileFuncName = "readfile"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "readfile", func() interfaces.Func { return &ReadFileFunc{} }) // must register the func and name funcs.ModuleRegister(ModuleName, ReadFileFuncName, func() interfaces.Func { return &ReadFileFunc{} }) // must register the func and name
} }
// ReadFileFunc is a function that reads the full contents from a local file. If // ReadFileFunc is a function that reads the full contents from a local file. If
@@ -51,6 +56,12 @@ type ReadFileFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ReadFileFunc) String() string {
return ReadFileFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *ReadFileFunc) ArgGen(index int) (string, error) { func (obj *ReadFileFunc) ArgGen(index int) (string, error) {
seq := []string{"filename"} seq := []string{"filename"}

View File

@@ -29,8 +29,13 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// SystemFuncName is the name this function is registered as.
SystemFuncName = "system"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "system", func() interfaces.Func { return &SystemFunc{} }) funcs.ModuleRegister(ModuleName, SystemFuncName, func() interfaces.Func { return &SystemFunc{} })
} }
// SystemFunc runs a string as a shell command, then produces each line from // SystemFunc runs a string as a shell command, then produces each line from
@@ -47,6 +52,12 @@ type SystemFunc struct {
cancel context.CancelFunc cancel context.CancelFunc
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *SystemFunc) String() string {
return SystemFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *SystemFunc) ArgGen(index int) (string, error) { func (obj *SystemFunc) ArgGen(index int) (string, error) {
seq := []string{"shell_command"} seq := []string{"shell_command"}

View File

@@ -28,10 +28,15 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" const (
// Random1FuncName is the name this function is registered as.
Random1FuncName = "random1"
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
)
func init() { func init() {
funcs.Register("random1", func() interfaces.Func { return &Random1Func{} }) funcs.Register(Random1FuncName, func() interfaces.Func { return &Random1Func{} })
} }
// Random1Func returns one random string of a certain length. // Random1Func returns one random string of a certain length.
@@ -52,6 +57,12 @@ type Random1Func struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *Random1Func) String() string {
return Random1FuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *Random1Func) ArgGen(index int) (string, error) { func (obj *Random1Func) ArgGen(index int) (string, error) {
seq := []string{"length"} seq := []string{"length"}

View File

@@ -35,13 +35,17 @@ import (
) )
const ( const (
// CPUCountFuncName is the name this fact is registered as. It's still a
// Func Name because this is the name space the fact is actually using.
CPUCountFuncName = "cpu_count"
rtmGrps = 0x1 // make me a multicast receiver rtmGrps = 0x1 // make me a multicast receiver
socketFile = "pipe.sock" socketFile = "pipe.sock"
cpuDevpathRegex = "/devices/system/cpu/cpu[0-9]" cpuDevpathRegex = "/devices/system/cpu/cpu[0-9]"
) )
func init() { func init() {
facts.ModuleRegister(ModuleName, "cpu_count", func() facts.Fact { return &CPUCountFact{} }) // must register the fact and name facts.ModuleRegister(ModuleName, CPUCountFuncName, func() facts.Fact { return &CPUCountFact{} }) // must register the fact and name
} }
// CPUCountFact is a fact that returns the current CPU count. // CPUCountFact is a fact that returns the current CPU count.
@@ -50,6 +54,12 @@ type CPUCountFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *CPUCountFact) String() string {
return CPUCountFuncName
}
// Info returns static typing info about what the fact returns. // Info returns static typing info about what the fact returns.
func (obj *CPUCountFact) Info() *facts.Info { func (obj *CPUCountFact) Info() *facts.Info {
return &facts.Info{ return &facts.Info{

View File

@@ -22,8 +22,14 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// HostnameFuncName is the name this fact is registered as. It's still a
// Func Name because this is the name space the fact is actually using.
HostnameFuncName = "hostname"
)
func init() { func init() {
facts.ModuleRegister(ModuleName, "hostname", func() facts.Fact { return &HostnameFact{} }) // must register the fact and name facts.ModuleRegister(ModuleName, HostnameFuncName, func() facts.Fact { return &HostnameFact{} }) // must register the fact and name
} }
// HostnameFact is a function that returns the hostname. // HostnameFact is a function that returns the hostname.
@@ -33,6 +39,12 @@ type HostnameFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *HostnameFact) String() string {
return HostnameFuncName
}
// Validate makes sure we've built our struct properly. It is usually unused for // Validate makes sure we've built our struct properly. It is usually unused for
// normal facts that users can use directly. // normal facts that users can use directly.
//func (obj *HostnameFact) Validate() error { //func (obj *HostnameFact) Validate() error {

View File

@@ -26,11 +26,15 @@ import (
) )
const ( const (
// LoadFuncName is the name this fact is registered as. It's still a
// Func Name because this is the name space the fact is actually using.
LoadFuncName = "load"
loadSignature = "struct{x1 float; x5 float; x15 float}" loadSignature = "struct{x1 float; x5 float; x15 float}"
) )
func init() { func init() {
facts.ModuleRegister(ModuleName, "load", func() facts.Fact { return &LoadFact{} }) // must register the fact and name facts.ModuleRegister(ModuleName, LoadFuncName, func() facts.Fact { return &LoadFact{} }) // must register the fact and name
} }
// LoadFact is a fact which returns the current system load. // LoadFact is a fact which returns the current system load.
@@ -39,6 +43,12 @@ type LoadFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *LoadFact) String() string {
return LoadFuncName
}
// Validate makes sure we've built our struct properly. It is usually unused for // Validate makes sure we've built our struct properly. It is usually unused for
// normal facts that users can use directly. // normal facts that users can use directly.
//func (obj *LoadFact) Validate() error { //func (obj *LoadFact) Validate() error {

View File

@@ -25,8 +25,14 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// UptimeFuncName is the name this fact is registered as. It's still a
// Func Name because this is the name space the fact is actually using.
UptimeFuncName = "uptime"
)
func init() { func init() {
facts.ModuleRegister(ModuleName, "uptime", func() facts.Fact { return &UptimeFact{} }) facts.ModuleRegister(ModuleName, UptimeFuncName, func() facts.Fact { return &UptimeFact{} })
} }
// UptimeFact is a fact which returns the current uptime of your system. // UptimeFact is a fact which returns the current uptime of your system.
@@ -35,6 +41,12 @@ type UptimeFact struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this fact. This is needed so this struct can
// satisfy the pgraph.Vertex interface.
func (obj *UptimeFact) String() string {
return UptimeFuncName
}
// Info returns some static info about itself. // Info returns some static info about itself.
func (obj *UptimeFact) Info() *facts.Info { func (obj *UptimeFact) Info() *facts.Info {
return &facts.Info{ return &facts.Info{

View File

@@ -31,17 +31,10 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
var (
// errorType represents a reflection type of error as seen in:
// https://github.com/golang/go/blob/ec62ee7f6d3839fe69aeae538dadc1c9dc3bf020/src/text/template/exec.go#L612
errorType = reflect.TypeOf((*error)(nil)).Elem()
)
func init() {
funcs.Register("template", func() interfaces.Func { return &TemplateFunc{} })
}
const ( const (
// TemplateFuncName is the name this function is registered as.
TemplateFuncName = "template"
// TemplateName is the name of our template as required by the template // TemplateName is the name of our template as required by the template
// library. // library.
TemplateName = "template" TemplateName = "template"
@@ -50,6 +43,16 @@ const (
argNameVars = "vars" argNameVars = "vars"
) )
var (
// errorType represents a reflection type of error as seen in:
// https://github.com/golang/go/blob/ec62ee7f6d3839fe69aeae538dadc1c9dc3bf020/src/text/template/exec.go#L612
errorType = reflect.TypeOf((*error)(nil)).Elem()
)
func init() {
funcs.Register(TemplateFuncName, func() interfaces.Func { return &TemplateFunc{} })
}
// TemplateFunc is a static polymorphic function that compiles a template and // TemplateFunc is a static polymorphic function that compiles a template and
// returns the output as a string. It bases its output on the values passed in // returns the output as a string. It bases its output on the values passed in
// to it. It examines the type of the second argument (the input data vars) at // to it. It examines the type of the second argument (the input data vars) at
@@ -73,6 +76,12 @@ type TemplateFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *TemplateFunc) String() string {
return TemplateFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *TemplateFunc) ArgGen(index int) (string, error) { func (obj *TemplateFunc) ArgGen(index int) (string, error) {
seq := []string{argNameTemplate, argNameVars} seq := []string{argNameTemplate, argNameVars}

View File

@@ -27,8 +27,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// ExchangeFuncName is the name this function is registered as.
ExchangeFuncName = "exchange"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "exchange", func() interfaces.Func { return &ExchangeFunc{} }) funcs.ModuleRegister(ModuleName, ExchangeFuncName, func() interfaces.Func { return &ExchangeFunc{} })
} }
// ExchangeFunc is special function which returns all the values of a given key // ExchangeFunc is special function which returns all the values of a given key
@@ -46,6 +51,12 @@ type ExchangeFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ExchangeFunc) String() string {
return ExchangeFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *ExchangeFunc) ArgGen(index int) (string, error) { func (obj *ExchangeFunc) ArgGen(index int) (string, error) {
seq := []string{"namespace", "value"} seq := []string{"namespace", "value"}

View File

@@ -27,8 +27,13 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// KVLookupFuncName is the name this function is registered as.
KVLookupFuncName = "kvlookup"
)
func init() { func init() {
funcs.ModuleRegister(ModuleName, "kvlookup", func() interfaces.Func { return &KVLookupFunc{} }) funcs.ModuleRegister(ModuleName, KVLookupFuncName, func() interfaces.Func { return &KVLookupFunc{} })
} }
// KVLookupFunc is special function which returns all the values of a given key // KVLookupFunc is special function which returns all the values of a given key
@@ -46,6 +51,12 @@ type KVLookupFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *KVLookupFunc) String() string {
return KVLookupFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *KVLookupFunc) ArgGen(index int) (string, error) { func (obj *KVLookupFunc) ArgGen(index int) (string, error) {
seq := []string{"namespace"} seq := []string{"namespace"}

View File

@@ -42,6 +42,9 @@ import (
) )
const ( const (
// ScheduleFuncName is the name this function is registered as.
ScheduleFuncName = "schedule"
// DefaultStrategy is the strategy to use if none has been specified. // DefaultStrategy is the strategy to use if none has been specified.
DefaultStrategy = "rr" DefaultStrategy = "rr"
@@ -58,7 +61,7 @@ const (
) )
func init() { func init() {
funcs.ModuleRegister(ModuleName, "schedule", func() interfaces.Func { return &SchedulePolyFunc{} }) funcs.ModuleRegister(ModuleName, ScheduleFuncName, func() interfaces.Func { return &SchedulePolyFunc{} })
} }
// SchedulePolyFunc is special function which determines where code should run // SchedulePolyFunc is special function which determines where code should run
@@ -80,6 +83,12 @@ type SchedulePolyFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *SchedulePolyFunc) String() string {
return ScheduleFuncName
}
// validOpts returns the available mapping of valid opts fields to types. // validOpts returns the available mapping of valid opts fields to types.
func (obj *SchedulePolyFunc) validOpts() map[string]*types.Type { func (obj *SchedulePolyFunc) validOpts() map[string]*types.Type {
return map[string]*types.Type{ return map[string]*types.Type{

View File

@@ -79,6 +79,7 @@ type Init struct {
// never change to avoid the overhead of the goroutine and channel listener? // never change to avoid the overhead of the goroutine and channel listener?
// TODO: should we move this to the interface package? // TODO: should we move this to the interface package?
type Fact interface { type Fact interface {
String() string
//Validate() error // currently not needed since no facts are internal //Validate() error // currently not needed since no facts are internal
Info() *Info Info() *Info
Init(*Init) error Init(*Init) error

View File

@@ -30,6 +30,12 @@ type FactFunc struct { // implements `interfaces.Func`
Fact Fact Fact Fact
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *FactFunc) String() string {
return obj.Fact.String()
}
// Validate makes sure we've built our struct properly. // Validate makes sure we've built our struct properly.
func (obj *FactFunc) Validate() error { func (obj *FactFunc) Validate() error {
if obj.Fact == nil { if obj.Fact == nil {

View File

@@ -58,6 +58,12 @@ type HistoryFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *HistoryFunc) String() string {
return HistoryFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *HistoryFunc) ArgGen(index int) (string, error) { func (obj *HistoryFunc) ArgGen(index int) (string, error) {
seq := []string{"value", "index"} seq := []string{"value", "index"}

View File

@@ -52,6 +52,12 @@ type MapLookupPolyFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *MapLookupPolyFunc) String() string {
return MapLookupFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *MapLookupPolyFunc) ArgGen(index int) (string, error) { func (obj *MapLookupPolyFunc) ArgGen(index int) (string, error) {
seq := []string{argNameMap, argNameKey, argNameDef} seq := []string{argNameMap, argNameKey, argNameDef}

View File

@@ -435,6 +435,13 @@ type OperatorPolyFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *OperatorPolyFunc) String() string {
// TODO: return the exact operator if we can guarantee it doesn't change
return OperatorFuncName
}
// argNames returns the maximum list of possible argNames. This can be truncated // argNames returns the maximum list of possible argNames. This can be truncated
// if needed. The first arg name is the operator. // if needed. The first arg name is the operator.
func (obj *OperatorPolyFunc) argNames() ([]string, error) { func (obj *OperatorPolyFunc) argNames() ([]string, error) {

View File

@@ -58,7 +58,7 @@ func Register(name string, fn *types.FuncValue) {
RegisteredFuncs[name] = fn // store a copy for ourselves RegisteredFuncs[name] = fn // store a copy for ourselves
// register a copy in the main function database // register a copy in the main function database
funcs.Register(name, func() interfaces.Func { return &WrappedFunc{Fn: fn} }) funcs.Register(name, func() interfaces.Func { return &WrappedFunc{Name: name, Fn: fn} })
} }
// ModuleRegister is exactly like Register, except that it registers within a // ModuleRegister is exactly like Register, except that it registers within a
@@ -70,6 +70,8 @@ func ModuleRegister(module, name string, fn *types.FuncValue) {
// WrappedFunc is a scaffolding function struct which fulfills the boiler-plate // WrappedFunc is a scaffolding function struct which fulfills the boiler-plate
// for the function API, but that can run a very simple, static, pure function. // for the function API, but that can run a very simple, static, pure function.
type WrappedFunc struct { type WrappedFunc struct {
Name string
Fn *types.FuncValue Fn *types.FuncValue
init *interfaces.Init init *interfaces.Init
@@ -80,6 +82,12 @@ type WrappedFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *WrappedFunc) String() string {
return obj.Name
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *WrappedFunc) ArgGen(index int) (string, error) { func (obj *WrappedFunc) ArgGen(index int) (string, error) {
typ := obj.Fn.Type() typ := obj.Fn.Type()

View File

@@ -90,7 +90,7 @@ func Register(name string, fns []*types.FuncValue) {
RegisteredFuncs[name] = fns // store a copy for ourselves RegisteredFuncs[name] = fns // store a copy for ourselves
// register a copy in the main function database // register a copy in the main function database
funcs.Register(name, func() interfaces.Func { return &WrappedFunc{Fns: fns} }) funcs.Register(name, func() interfaces.Func { return &WrappedFunc{Name: name, Fns: fns} })
} }
// ModuleRegister is exactly like Register, except that it registers within a // ModuleRegister is exactly like Register, except that it registers within a
@@ -131,6 +131,8 @@ func consistentArgs(fns []*types.FuncValue) ([]string, error) {
// for the function API, but that can run a very simple, static, pure, // for the function API, but that can run a very simple, static, pure,
// polymorphic function. // polymorphic function.
type WrappedFunc struct { type WrappedFunc struct {
Name string
Fns []*types.FuncValue // list of possible functions Fns []*types.FuncValue // list of possible functions
fn *types.FuncValue // the concrete version of our chosen function fn *types.FuncValue // the concrete version of our chosen function
@@ -143,6 +145,12 @@ type WrappedFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *WrappedFunc) String() string {
return obj.Name
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *WrappedFunc) ArgGen(index int) (string, error) { func (obj *WrappedFunc) ArgGen(index int) (string, error) {
seq, err := consistentArgs(obj.Fns) seq, err := consistentArgs(obj.Fns)

View File

@@ -50,6 +50,12 @@ type StructLookupPolyFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *StructLookupPolyFunc) String() string {
return StructLookupFuncName
}
// ArgGen returns the Nth arg name for this function. // ArgGen returns the Nth arg name for this function.
func (obj *StructLookupPolyFunc) ArgGen(index int) (string, error) { func (obj *StructLookupPolyFunc) ArgGen(index int) (string, error) {
seq := []string{"struct", "field"} seq := []string{"struct", "field"}

View File

@@ -25,6 +25,11 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// CallFuncName is the unique name identifier for this function.
CallFuncName = "call"
)
// CallFunc is a function that takes in a function and all the args, and passes // CallFunc is a function that takes in a function and all the args, and passes
// through the results of running the function call. // through the results of running the function call.
type CallFunc struct { type CallFunc struct {
@@ -45,6 +50,12 @@ type CallFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *CallFunc) String() string {
return CallFuncName
}
// Validate makes sure we've built our struct properly. // Validate makes sure we've built our struct properly.
func (obj *CallFunc) Validate() error { func (obj *CallFunc) Validate() error {
if obj.Type == nil { if obj.Type == nil {

View File

@@ -25,6 +25,11 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// CompositeFuncName is the unique name identifier for this function.
CompositeFuncName = "composite"
)
// CompositeFunc is a function that passes through the value it receives. It is // CompositeFunc is a function that passes through the value it receives. It is
// used to take a series of inputs to a list, map or struct, and return that // used to take a series of inputs to a list, map or struct, and return that
// value as a stream that depends on those inputs. It helps the list, map, and // value as a stream that depends on those inputs. It helps the list, map, and
@@ -40,6 +45,12 @@ type CompositeFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *CompositeFunc) String() string {
return CompositeFuncName
}
// Validate makes sure we've built our struct properly. // Validate makes sure we've built our struct properly.
func (obj *CompositeFunc) Validate() error { func (obj *CompositeFunc) Validate() error {
if obj.Type == nil { if obj.Type == nil {

View File

@@ -24,6 +24,11 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// ConstFuncName is the unique name identifier for this function.
ConstFuncName = "const"
)
// ConstFunc is a function that returns the constant value passed to Value. // ConstFunc is a function that returns the constant value passed to Value.
type ConstFunc struct { type ConstFunc struct {
Value types.Value Value types.Value
@@ -32,6 +37,12 @@ type ConstFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *ConstFunc) String() string {
return ConstFuncName
}
// Validate makes sure we've built our struct properly. // Validate makes sure we've built our struct properly.
func (obj *ConstFunc) Validate() error { func (obj *ConstFunc) Validate() error {
if obj.Value == nil { if obj.Value == nil {

View File

@@ -26,6 +26,11 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// FunctionFuncName is the unique name identifier for this function.
FunctionFuncName = "function"
)
// FunctionFunc is a function that passes through the function body it receives. // FunctionFunc is a function that passes through the function body it receives.
type FunctionFunc struct { type FunctionFunc struct {
Type *types.Type // this is the type of the function that we hold Type *types.Type // this is the type of the function that we hold
@@ -40,6 +45,12 @@ type FunctionFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *FunctionFunc) String() string {
return FunctionFuncName
}
// fn returns the function that wraps the Func interface if that API is used. // fn returns the function that wraps the Func interface if that API is used.
func (obj *FunctionFunc) fn() (*types.FuncValue, error) { func (obj *FunctionFunc) fn() (*types.FuncValue, error) {
fn := func(args []types.Value) (types.Value, error) { fn := func(args []types.Value) (types.Value, error) {

View File

@@ -24,6 +24,11 @@ import (
"github.com/purpleidea/mgmt/lang/types" "github.com/purpleidea/mgmt/lang/types"
) )
const (
// IfFuncName is the unique name identifier for this function.
IfFuncName = "if"
)
// IfFunc is a function that passes through the value of the correct branch // IfFunc is a function that passes through the value of the correct branch
// based on the conditional value it gets. // based on the conditional value it gets.
type IfFunc struct { type IfFunc struct {
@@ -36,6 +41,12 @@ type IfFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *IfFunc) String() string {
return IfFuncName
}
// Validate tells us if the input struct takes a valid form. // Validate tells us if the input struct takes a valid form.
func (obj *IfFunc) Validate() error { func (obj *IfFunc) Validate() error {
if obj.Type == nil { if obj.Type == nil {

View File

@@ -25,6 +25,11 @@ import (
//"github.com/purpleidea/mgmt/util/errwrap" //"github.com/purpleidea/mgmt/util/errwrap"
) )
const (
// VarFuncName is the unique name identifier for this function.
VarFuncName = "var"
)
// VarFunc is a function that passes through a function that came from a bind // VarFunc is a function that passes through a function that came from a bind
// lookup. It exists so that the reactive function engine type checks correctly. // lookup. It exists so that the reactive function engine type checks correctly.
type VarFunc struct { type VarFunc struct {
@@ -39,6 +44,12 @@ type VarFunc struct {
closeChan chan struct{} closeChan chan struct{}
} }
// String returns a simple name for this function. This is needed so this struct
// can satisfy the pgraph.Vertex interface.
func (obj *VarFunc) String() string {
return VarFuncName
}
// Validate makes sure we've built our struct properly. // Validate makes sure we've built our struct properly.
func (obj *VarFunc) Validate() error { func (obj *VarFunc) Validate() error {
if obj.Type == nil { if obj.Type == nil {

View File

@@ -18,6 +18,7 @@
package interfaces package interfaces
import ( import (
"fmt"
"strings" "strings"
"github.com/purpleidea/mgmt/engine" "github.com/purpleidea/mgmt/engine"
@@ -57,6 +58,8 @@ type Init struct {
// TODO: should we support a static version of this interface for funcs that // TODO: should we support a static version of this interface for funcs that
// never change to avoid the overhead of the goroutine and channel listener? // never change to avoid the overhead of the goroutine and channel listener?
type Func interface { type Func interface {
fmt.Stringer // so that this can be stored as a Vertex
Validate() error // FIXME: this is only needed for PolyFunc. Get it moved and used! Validate() error // FIXME: this is only needed for PolyFunc. Get it moved and used!
// Info returns some information about the function in question, which // Info returns some information about the function in question, which