зеркало из https://github.com/mozilla/mig.git
Merge pull request #64 from djmitche/module-init
Revamp module initialization
This commit is contained in:
Коммит
e836686e78
|
@ -30,20 +30,37 @@ Registration
|
|||
A module must import ``mig/modules``.
|
||||
|
||||
A module registers itself at runtime via its ``init()`` function which must
|
||||
call ``modules.Register`` with a module name and a "runner function" returning
|
||||
an anonymous object (``interface {}``) that must implement the
|
||||
call ``modules.Register`` with a module name and an instance implementing
|
||||
``modules.Moduler``:
|
||||
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Moduler interface {
|
||||
type Moduler interface {
|
||||
NewRun() Runner
|
||||
}
|
||||
|
||||
A module must have a unique name. A good practice is to use the same name for
|
||||
the module name as for the Go package name. However, it is possible for a
|
||||
single Go package to implement multiple modules, simply by registering
|
||||
different Modulers with different names.
|
||||
|
||||
The sole method of a Moduler creates a new instance to represent a "run" of the
|
||||
module, implementing the ``modules.Runner`` interface:
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Runner interface {
|
||||
Run(io.Reader) string
|
||||
ValidateParameters() error
|
||||
}
|
||||
|
||||
A module must have a unique name. A good practice is to use the same name for
|
||||
the module name as for the Go package name. The code sample below shows how the
|
||||
``example`` module uses package name ``example`` and registers with name ``example``.
|
||||
Any run-specific information should be associated with this instance and not with
|
||||
the Moduler or stored in a global variable. It should be possible for multiple
|
||||
runs of the module to execute simultaneously.
|
||||
|
||||
The code sample below shows how the ``example`` module uses package name
|
||||
``example`` and registers with name ``example``.
|
||||
|
||||
.. code:: go
|
||||
|
||||
|
@ -53,18 +70,27 @@ the module name as for the Go package name. The code sample below shows how the
|
|||
"mig/modules"
|
||||
)
|
||||
|
||||
type Runner struct {
|
||||
// ...
|
||||
// An instance of this type will represent this module; it's possible to add
|
||||
// additional data fields here, although that is rarely needed.
|
||||
type module struct {
|
||||
}
|
||||
|
||||
func (m *module) NewRun() interface{} {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
// init is called by the Go runtime at startup. We use this function to
|
||||
// register the module in a global array of available modules, so the
|
||||
// agent knows we exist
|
||||
func init() {
|
||||
modules.Register("example", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
||||
// init is called by the Go runtime at startup. We use this function to
|
||||
// register the module in a global array of available modules, so the
|
||||
// agent knows we exist
|
||||
func init() {
|
||||
modules.Register("example", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
}
|
||||
|
||||
``init()`` is a go builtin function that is executed automatically in all
|
||||
imported packages when a program starts. In the agents, modules are imported
|
||||
|
@ -93,23 +119,22 @@ Execution
|
|||
|
||||
When the agent receives a command to execute, it looks up modules in
|
||||
the global list ``modules.Available``, and if a module is registered to execute
|
||||
the command, calls its runner function to get a new object representing the run,
|
||||
and then calls that object's ``Run`` method.
|
||||
the command, calls its runner function to get a new instance representing the run,
|
||||
and then calls that instance's ``Run`` method.
|
||||
|
||||
Runner Structure
|
||||
Runner Interface
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
A mig module typically defines its own ``Runner`` struct implementing the
|
||||
``modules.Moduler`` interface and representing a single run of the module. The
|
||||
``Runner`` struct contains two fields: module parameters and module results.
|
||||
A mig module typically defines its own ``run`` struct implementing the
|
||||
``modules.Runner`` interface and representing a single run of the module. The
|
||||
``run`` struct typically contains two fields: module parameters and module results.
|
||||
The former is any format the module choses to use, while the latter generally
|
||||
implements the ``modules.Result`` struct (note that this is not required, but
|
||||
it is the easiest way to return a properly-formatted JSON result).
|
||||
|
||||
.. code:: go
|
||||
|
||||
// Runner gives access to the exported functions and structs of the module
|
||||
type Runner struct {
|
||||
type run struct {
|
||||
Parameters myModuleParams
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -139,7 +164,7 @@ formatting rules, performs work and returns results in a JSON string.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) Run(in io.Reader) string {
|
||||
func (r *run) Run(in io.Reader) string {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", e))
|
||||
|
@ -273,7 +298,7 @@ The function returns results into an array of strings.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
@ -323,7 +348,7 @@ A module implementation would have the function:
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
fmt.Println("initializing netstat parameters creation")
|
||||
var err error
|
||||
var p params
|
||||
|
@ -380,7 +405,7 @@ A typical implementation from the ``timedrift`` module looks as follows:
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
drift string
|
||||
|
@ -442,12 +467,11 @@ needed structs.
|
|||
// agent knows we exist
|
||||
func init() {
|
||||
modules.Register("example", func() interface{} {
|
||||
return new(Runner)
|
||||
return new(run)
|
||||
})
|
||||
}
|
||||
|
||||
// Runner gives access to the exported functions and structs of the module
|
||||
type Runner struct {
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -494,7 +518,7 @@ Next we'll implement a parameters validation function.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
fqdn := regexp.MustCompilePOSIX(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`)
|
||||
for _, host := range r.Parameters.LookupHost {
|
||||
if !fqdn.MatchString(host) {
|
||||
|
@ -522,7 +546,7 @@ valid parameters, it panics.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", e))
|
||||
|
@ -588,7 +612,7 @@ implement the rules defined earlier in this page.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) doModuleStuff(out *string, moduleDone *chan bool) error {
|
||||
func (r *run) doModuleStuff(out *string, moduleDone *chan bool) error {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
@ -637,7 +661,7 @@ implement the rules defined earlier in this page.
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r Runner) buildResults(el elements, stats statistics) string {
|
||||
func (r *run) buildResults(el elements, stats statistics) string {
|
||||
if len(r.Results.Errors) == 0 {
|
||||
r.Results.Success = true
|
||||
}
|
||||
|
@ -669,7 +693,7 @@ the ``prints`` array of strings.
|
|||
|
||||
.. code:: go
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
|
|
@ -527,4 +527,4 @@
|
|||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -163,8 +163,8 @@ func runModuleDirectly(mode string, args []byte, pretty bool) (out string) {
|
|||
return fmt.Sprintf(`{"errors": ["module '%s' is not available"]}`, mode)
|
||||
}
|
||||
// instanciate and call module
|
||||
modRunner := modules.Available[mode].Runner()
|
||||
out = modRunner.(modules.Moduler).Run(os.Stdin)
|
||||
run := modules.Available[mode].NewRun()
|
||||
out = run.Run(os.Stdin)
|
||||
if pretty {
|
||||
var modres modules.Result
|
||||
err := json.Unmarshal([]byte(out), &modres)
|
||||
|
@ -172,8 +172,8 @@ func runModuleDirectly(mode string, args []byte, pretty bool) (out string) {
|
|||
panic(err)
|
||||
}
|
||||
out = ""
|
||||
if _, ok := modRunner.(modules.HasResultsPrinter); ok {
|
||||
outRes, err := modRunner.(modules.HasResultsPrinter).PrintResults(modres, false)
|
||||
if _, ok := run.(modules.HasResultsPrinter); ok {
|
||||
outRes, err := run.(modules.HasResultsPrinter).PrintResults(modres, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -872,10 +872,10 @@ func PrintCommandResults(cmd mig.Command, onlyFound, showAgent bool) (err error)
|
|||
}
|
||||
continue
|
||||
}
|
||||
modRunner := modules.Available[moduleName].Runner()
|
||||
run := modules.Available[moduleName].NewRun()
|
||||
// look for a result printer in the module
|
||||
if _, ok := modRunner.(modules.HasResultsPrinter); ok {
|
||||
outRes, err := modRunner.(modules.HasResultsPrinter).PrintResults(result, onlyFound)
|
||||
if _, ok := run.(modules.HasResultsPrinter); ok {
|
||||
outRes, err := run.(modules.HasResultsPrinter).PrintResults(result, onlyFound)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ func main() {
|
|||
a mig.Action
|
||||
migrc, show, render, target, expiration, afile string
|
||||
modargs []string
|
||||
modRunner interface{}
|
||||
run interface{}
|
||||
)
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
|
@ -155,12 +155,12 @@ func main() {
|
|||
for _, arg := range fs.Args() {
|
||||
modargs = append(modargs, arg)
|
||||
}
|
||||
modRunner = modules.Available[op.Module].Runner()
|
||||
if _, ok := modRunner.(modules.HasParamsParser); !ok {
|
||||
run = modules.Available[op.Module].NewRun()
|
||||
if _, ok := run.(modules.HasParamsParser); !ok {
|
||||
fmt.Fprintf(os.Stderr, "[error] module '%s' does not support command line invocation\n", op.Module)
|
||||
os.Exit(2)
|
||||
}
|
||||
op.Parameters, err = modRunner.(modules.HasParamsParser).ParamsParser(modargs)
|
||||
op.Parameters, err = run.(modules.HasParamsParser).ParamsParser(modargs)
|
||||
if err != nil || op.Parameters == nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -83,13 +83,13 @@ func actionLauncher(tpl mig.Action, cli client.Client) (err error) {
|
|||
operation.Module = orders[1]
|
||||
if _, ok := modules.Available[operation.Module]; ok {
|
||||
// instanciate and call module parameters creation function
|
||||
modRunner := modules.Available[operation.Module].Runner()
|
||||
if _, ok := modRunner.(modules.HasParamsCreator); !ok {
|
||||
run := modules.Available[operation.Module].NewRun()
|
||||
if _, ok := run.(modules.HasParamsCreator); !ok {
|
||||
fmt.Println(operation.Module, "module does not provide a parameters creator.")
|
||||
fmt.Println("You can write your action by hand and import it using 'load <file>'")
|
||||
break
|
||||
}
|
||||
operation.Parameters, err = modRunner.(modules.HasParamsCreator).ParamsCreator()
|
||||
operation.Parameters, err = run.(modules.HasParamsCreator).ParamsCreator()
|
||||
if err != nil {
|
||||
fmt.Printf("Parameters creation failed with error: %v\n", err)
|
||||
break
|
||||
|
|
|
@ -20,13 +20,18 @@ import (
|
|||
"runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("agentdestroy", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("agentdestroy", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters Parameters
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -49,7 +54,7 @@ type results struct {
|
|||
Errors []string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
if r.Parameters.PID < 2 || r.Parameters.PID > 65535 {
|
||||
return fmt.Errorf("PID '%s' is not in the range [2:65535]", r.Parameters.PID)
|
||||
}
|
||||
|
@ -59,7 +64,7 @@ func (r Runner) ValidateParameters() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", e))
|
||||
|
@ -166,7 +171,7 @@ func getAgentVersion(binary string) (cversion string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) buildResults() (jsonResults string) {
|
||||
func (r *run) buildResults() (jsonResults string) {
|
||||
jsonOutput, err := json.Marshal(r.Results)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -36,17 +36,23 @@ import (
|
|||
"regexp"
|
||||
)
|
||||
|
||||
// An instance of this type will represent this module; it's possible to add
|
||||
// additional data fields here, although that is rarely needed.
|
||||
type module struct {
|
||||
}
|
||||
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
// init is called by the Go runtime at startup. We use this function to
|
||||
// register the module in a global array of available modules, so the
|
||||
// agent knows we exist
|
||||
func init() {
|
||||
modules.Register("example", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
modules.Register("example", new(module))
|
||||
}
|
||||
|
||||
// Runner gives access to the exported functions and structs of the module
|
||||
type Runner struct {
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -71,7 +77,7 @@ type statistics struct {
|
|||
// ValidateParameters *must* be implemented by a module. It provides a method
|
||||
// to verify that the parameters passed to the module conform the expected format.
|
||||
// It must return an error if the parameters do not validate.
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
fqdn := regexp.MustCompilePOSIX(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`)
|
||||
for _, host := range r.Parameters.LookupHost {
|
||||
if !fqdn.MatchString(host) {
|
||||
|
@ -84,7 +90,7 @@ func (r Runner) ValidateParameters() (err error) {
|
|||
// Run *must* be implemented by a module. Its the function that executes the module.
|
||||
// It must return a string of marshalled json that contains the results from the module.
|
||||
// The code below provides a base module skeleton that can be reused in all modules.
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
// a good way to handle execution failures is to catch panics and store
|
||||
// the panicked error into modules.Results.Errors, marshal that, and output
|
||||
// the JSON string back to the caller
|
||||
|
@ -127,7 +133,7 @@ func (r Runner) Run(in io.Reader) (out string) {
|
|||
// module. There is no implementation requirement. It's good practice to have it
|
||||
// return the JSON string Run() expects to return. We also make it return a boolean
|
||||
// in the `moduleDone` channel to do flow control in Run().
|
||||
func (r Runner) doModuleStuff(out *string, moduleDone *chan bool) error {
|
||||
func (r *run) doModuleStuff(out *string, moduleDone *chan bool) error {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
@ -182,7 +188,7 @@ func (r Runner) doModuleStuff(out *string, moduleDone *chan bool) error {
|
|||
// buildResults takes the results found by the module, as well as statistics,
|
||||
// and puts all that into a JSON string. It also takes care of setting the
|
||||
// success and foundanything flags.
|
||||
func (r Runner) buildResults(el elements, stats statistics) string {
|
||||
func (r *run) buildResults(el elements, stats statistics) string {
|
||||
if len(r.Results.Errors) == 0 {
|
||||
r.Results.Success = true
|
||||
}
|
||||
|
@ -201,7 +207,7 @@ func (r Runner) buildResults(el elements, stats statistics) string {
|
|||
// PrintResults() is an *optional* method that returns results in a human-readable format.
|
||||
// if matchOnly is set, only results that have at least one match are returned.
|
||||
// If matchOnly is not set, all results are returned, along with errors and statistics.
|
||||
func (r Runner) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
|
|
@ -35,13 +35,18 @@ import (
|
|||
|
||||
var debug bool = false
|
||||
|
||||
func init() {
|
||||
modules.Register("file", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("file", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters Parameters
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -373,7 +378,7 @@ func (c *check) storeMatch(file string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
var labels []string
|
||||
for label, s := range r.Parameters.Searches {
|
||||
labels = append(labels, label)
|
||||
|
@ -618,7 +623,7 @@ var stats statistics
|
|||
|
||||
var walkingErrors []string
|
||||
|
||||
func (r Runner) Run(in io.Reader) (resStr string) {
|
||||
func (r *run) Run(in io.Reader) (resStr string) {
|
||||
var (
|
||||
roots []string
|
||||
traversed []string
|
||||
|
@ -733,7 +738,7 @@ func (r Runner) Run(in io.Reader) (resStr string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) pathWalk(path string, roots []string) (traversed []string, err error) {
|
||||
func (r *run) pathWalk(path string, roots []string) (traversed []string, err error) {
|
||||
var (
|
||||
subdirs []string
|
||||
target *os.File
|
||||
|
@ -940,7 +945,7 @@ func followSymLink(link string) (mode os.FileMode, path string, err error) {
|
|||
}
|
||||
|
||||
// evaluateFile takes a single file and applies searches to it
|
||||
func (r Runner) evaluateFile(file string) (err error) {
|
||||
func (r *run) evaluateFile(file string) (err error) {
|
||||
var activeSearches []string
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
|
@ -1100,7 +1105,7 @@ func (s search) checkMtime(file string, fi os.FileInfo) (matchedall bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) checkContent(file string) {
|
||||
func (r *run) checkContent(file string) {
|
||||
var (
|
||||
err error
|
||||
fd *os.File
|
||||
|
@ -1191,7 +1196,7 @@ func (r Runner) checkContent(file string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) checkHash(file string, hashtype checkType) {
|
||||
func (r *run) checkHash(file string, hashtype checkType) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
@ -1315,7 +1320,7 @@ func newResults() *modules.Result {
|
|||
return &modules.Result{Elements: make(SearchResults), FoundAnything: false}
|
||||
}
|
||||
|
||||
func (r Runner) buildResults(t0 time.Time) (resStr string, err error) {
|
||||
func (r *run) buildResults(t0 time.Time) (resStr string, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("buildResults() -> %v", e)
|
||||
|
@ -1496,7 +1501,7 @@ func (r Runner) buildResults(t0 time.Time) (resStr string, err error) {
|
|||
// only results that have at least one match are returned.
|
||||
// If foundOnly is not set, all results are returned, along with errors and
|
||||
// statistics.
|
||||
func (r Runner) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el SearchResults
|
||||
stats statistics
|
||||
|
|
|
@ -81,7 +81,7 @@ detailled doc at http://mig.mozilla.org/doc/module_file.html
|
|||
// ParamsCreator implements an interactive parameters creation interface, which
|
||||
// receives user input, stores it into a Parameters structure, validates it,
|
||||
// and returns that structure as an interface. It is mainly used by the MIG Console
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
var err error
|
||||
p := newParameters()
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
@ -270,7 +270,7 @@ exit:
|
|||
// ParamsParser implements a command line parameters parser that takes a string
|
||||
// and returns a Parameters structure in an interface. It will display the module
|
||||
// help if the arguments string spell the work 'help'
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
paths, names, sizes, modes, mtimes, contents, md5s, sha1s, sha256s,
|
||||
|
|
|
@ -23,13 +23,18 @@ import (
|
|||
|
||||
var debug bool = false
|
||||
|
||||
func init() {
|
||||
modules.Register("memory", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("memory", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -208,7 +213,7 @@ func (c *check) storeMatch(proc process.Process) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
var labels []string
|
||||
for label, s := range r.Parameters.Searches {
|
||||
labels = append(labels, label)
|
||||
|
@ -293,7 +298,7 @@ func validateBytes(bytes string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
var ts statistics
|
||||
stats = ts
|
||||
// in debug mode, we just panic
|
||||
|
@ -388,7 +393,7 @@ func (r Runner) Run(in io.Reader) (out string) {
|
|||
// evaluateProcess takes a single process and applies searches to it. All searches are evaluated. The `name` and `library`
|
||||
// checks are run first, and if needed, the memory of the process is read to run the checks on `contents` and `bytes`.
|
||||
// The logic is optimized to only read the process memory once and apply all the checks to it.
|
||||
func (r Runner) evaluateProcess(proc process.Process) (err error) {
|
||||
func (r *run) evaluateProcess(proc process.Process) (err error) {
|
||||
if !debug {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
|
@ -507,7 +512,7 @@ func (s search) checkLibraries(proc process.Process, procname string) (matchedal
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) walkProcMemory(proc process.Process, procname string) (err error) {
|
||||
func (r *run) walkProcMemory(proc process.Process, procname string) (err error) {
|
||||
// find longest byte string to search for, which determines the buffer size
|
||||
bufsize := uint(4096)
|
||||
// find lowest offset, which determines start address
|
||||
|
@ -625,7 +630,7 @@ func (r Runner) walkProcMemory(proc process.Process, procname string) (err error
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) buildResults(t0 time.Time) (resStr string, err error) {
|
||||
func (r *run) buildResults(t0 time.Time) (resStr string, err error) {
|
||||
// in debug mode, we just panic
|
||||
if !debug {
|
||||
defer func() {
|
||||
|
@ -805,7 +810,7 @@ func (r Runner) buildResults(t0 time.Time) (resStr string, err error) {
|
|||
// only results that have at least one match are returned.
|
||||
// If foundOnly is not set, all results are returned, along with errors and
|
||||
// statistics.
|
||||
func (r Runner) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el searchResults
|
||||
stats statistics
|
||||
|
|
|
@ -24,7 +24,7 @@ type testParams struct {
|
|||
|
||||
func TestParameters(t *testing.T) {
|
||||
var (
|
||||
r Runner
|
||||
r run
|
||||
err error
|
||||
)
|
||||
var parameters = []testParams{
|
||||
|
@ -57,7 +57,7 @@ func TestParameters(t *testing.T) {
|
|||
|
||||
func TestFindGoTestProcess(t *testing.T) {
|
||||
var (
|
||||
r Runner
|
||||
r run
|
||||
s search
|
||||
)
|
||||
r.Parameters = *newParameters()
|
||||
|
@ -112,7 +112,7 @@ func TestSearches(t *testing.T) {
|
|||
{false, `{"searches":{"s1":{"names":["1983yrotewdshhhoiufhes7fd29"],"bytes":["ffffffffaaaabbbbcccceeee"],"options":{"matchall": true}}}}`},
|
||||
}
|
||||
for _, tp := range parameters {
|
||||
var r Runner
|
||||
var r run
|
||||
r.Parameters = *newParameters()
|
||||
err := json.Unmarshal([]byte(tp.params), &r.Parameters)
|
||||
if err != nil {
|
||||
|
|
|
@ -63,7 +63,7 @@ detailled doc at http://mig.mozilla.org/doc/module_memory.html
|
|||
// ParamsCreator implements an interactive parameters creation interface, which
|
||||
// receives user input, stores it into a Parameters structure, validates it,
|
||||
// and returns that structure as an interface. It is mainly used by the MIG Console
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
var err error
|
||||
p := newParameters()
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
@ -197,7 +197,7 @@ exit:
|
|||
// ParamsParser implements a command line parameters parser that takes a string
|
||||
// and returns a Parameters structure in an interface. It will display the module
|
||||
// help if the arguments string spell the work 'help'
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
names, libraries, bytes, contents flagParam
|
||||
|
|
|
@ -50,26 +50,8 @@ type Result struct {
|
|||
Errors []string `json:"errors"`
|
||||
}
|
||||
|
||||
// Stores details about the registration of a module
|
||||
type Registration struct {
|
||||
Runner func() interface{}
|
||||
}
|
||||
|
||||
// Available stores a list of activated module with their registration
|
||||
var Available = make(map[string]Registration)
|
||||
|
||||
// Register adds a module to the list of available modules
|
||||
func Register(name string, runner func() interface{}) {
|
||||
if _, exist := Available[name]; exist {
|
||||
panic("Register: a module named " + name + " has already been registered.\nAre you trying to import the same module twice?")
|
||||
}
|
||||
newmodule := &Registration{}
|
||||
newmodule.Runner = runner
|
||||
Available[name] = *newmodule
|
||||
}
|
||||
|
||||
// Moduler provides the interface to a Module
|
||||
type Moduler interface {
|
||||
// Runner provides the interface to an execution of a module
|
||||
type Runner interface {
|
||||
Run(io.Reader) string
|
||||
ValidateParameters() error
|
||||
}
|
||||
|
|
|
@ -6,25 +6,40 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type testModule struct {
|
||||
}
|
||||
|
||||
func (m *testModule) NewRun() Runner {
|
||||
return new(testRunner)
|
||||
}
|
||||
|
||||
type testRunner struct {
|
||||
Parameters params
|
||||
Results Result
|
||||
}
|
||||
|
||||
func (r *testRunner) ValidateParameters() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *testRunner) Run(in io.Reader) (out string) {
|
||||
return ""
|
||||
}
|
||||
|
||||
type params struct {
|
||||
SomeParam string `json:"someparam"`
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
// test simple registration
|
||||
Register("testing", func() interface{} {
|
||||
return new(testRunner)
|
||||
})
|
||||
Register("testing", new(testModule))
|
||||
if _, ok := Available["testing"]; !ok {
|
||||
t.Fatalf("testing module registration failed")
|
||||
}
|
||||
|
@ -38,9 +53,7 @@ func TestRegister(t *testing.T) {
|
|||
t.Fatalf("failed to panic on double registration of testing module")
|
||||
}
|
||||
}()
|
||||
Register("testing", func() interface{} {
|
||||
return new(testRunner)
|
||||
})
|
||||
Register("testing", new(testModule))
|
||||
}
|
||||
|
||||
func TestMakeMessage(t *testing.T) {
|
||||
|
|
|
@ -21,13 +21,18 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("netstat", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("netstat", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -79,7 +84,7 @@ type statistics struct {
|
|||
Totalhits float64 `json:"totalhits"`
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
for _, val := range r.Parameters.LocalMAC {
|
||||
err = validateMAC(val)
|
||||
if err != nil {
|
||||
|
@ -148,7 +153,7 @@ func validatePort(val string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (resStr string) {
|
||||
func (r *run) Run(in io.Reader) (resStr string) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// return error in json
|
||||
|
@ -314,7 +319,7 @@ func HasLocalIP(ipStr string) (found bool, elements []element, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, matchOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
|
|
@ -43,7 +43,7 @@ listeningport <port> search for an open socket on the local system listening on
|
|||
// ParamsCreator implements an interactive parameters creation interface, which
|
||||
// receives user input, stores it into a Parameters structure, validates it,
|
||||
// and returns that structure as an interface. It is mainly used by the MIG Console
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
fmt.Println("initializing netstat parameters creation")
|
||||
var err error
|
||||
var p params
|
||||
|
@ -159,7 +159,7 @@ const cmd_help string = `
|
|||
// ParamsParser implements a command line parameters parser that takes a string
|
||||
// and returns a Parameters structure in an interface. It will display the module
|
||||
// help if the arguments string spell the work 'help'
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
lm, nm, li, ni, ci, lp flagParam
|
||||
|
|
|
@ -44,7 +44,7 @@ icmp, tcp and udp ping. See doc at http://mig.mozilla.org/doc/module_ping.html
|
|||
}
|
||||
|
||||
// ParamsParser implements a command line parameter parser for the ping module
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
pa params
|
||||
|
@ -77,7 +77,7 @@ func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// ParamsCreator implements an interactive interface for the console
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
p params
|
||||
|
|
|
@ -25,13 +25,18 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("ping", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("ping", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -57,7 +62,7 @@ const (
|
|||
E_Timeout = "connection timed out"
|
||||
)
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
var (
|
||||
err error
|
||||
el elements
|
||||
|
@ -133,7 +138,7 @@ func (r Runner) Run(in io.Reader) (out string) {
|
|||
return r.buildResults(el)
|
||||
}
|
||||
|
||||
func (r *Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
// check if Protocol is a valid one that we support with this module
|
||||
switch r.Parameters.Protocol {
|
||||
case "icmp", "udp", "tcp":
|
||||
|
@ -182,7 +187,7 @@ func (r *Runner) ValidateParameters() (err error) {
|
|||
|
||||
// pingIcmp performs a ping to a destination. It select between ipv4 or ipv6 ping based
|
||||
// on the format of the destination ip.
|
||||
func (r Runner) pingIcmp() (err error) {
|
||||
func (r *run) pingIcmp() (err error) {
|
||||
var (
|
||||
icmpType icmp.Type
|
||||
network string
|
||||
|
@ -251,7 +256,7 @@ func (r Runner) pingIcmp() (err error) {
|
|||
|
||||
// pingTcp performs a straighfoward connection attempt on a destination ip:port and returns
|
||||
// an error if the attempt failed
|
||||
func (r Runner) pingTcp() (err error) {
|
||||
func (r *run) pingTcp() (err error) {
|
||||
conn, err := net.DialTimeout("tcp",
|
||||
fmt.Sprintf("%s:%d", r.Parameters.Destination, int(r.Parameters.DestinationPort)),
|
||||
time.Duration(r.Parameters.Timeout)*time.Second)
|
||||
|
@ -273,7 +278,7 @@ func (r Runner) pingTcp() (err error) {
|
|||
// Because UDP does not reply to connection requests, a lack of response may indicate that the
|
||||
// port is open, or that the packet got dropped. We chose to be optimistic and treat lack of
|
||||
// response (connection timeout) as an open port.
|
||||
func (r Runner) pingUdp() (err error) {
|
||||
func (r *run) pingUdp() (err error) {
|
||||
// Make it ip:port format
|
||||
destination := r.Parameters.Destination + ":" + fmt.Sprintf("%d", int(r.Parameters.DestinationPort))
|
||||
|
||||
|
@ -301,7 +306,7 @@ func (r Runner) pingUdp() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r Runner) buildResults(el elements) string {
|
||||
func (r *run) buildResults(el elements) string {
|
||||
r.Results.Elements = el
|
||||
if len(r.Results.Errors) == 0 {
|
||||
r.Results.Success = true
|
||||
|
@ -313,7 +318,7 @@ func (r Runner) buildResults(el elements) string {
|
|||
return string(jsonOutput[:])
|
||||
}
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
var el elements
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
|
|
|
@ -64,7 +64,7 @@ func loadOvalDefinitions(path string) (string, error) {
|
|||
return b.String(), nil
|
||||
}
|
||||
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
p := newParameters()
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for {
|
||||
|
@ -123,7 +123,7 @@ exit:
|
|||
return r.Parameters, r.ValidateParameters()
|
||||
}
|
||||
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
fs flag.FlagSet
|
||||
ovalDefs string
|
||||
|
|
|
@ -36,13 +36,18 @@ func endCounters() {
|
|||
stats.ExecRuntime = time.Now().Sub(counters.startTime).String()
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("pkg", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("pkg", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters Parameters
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -73,7 +78,7 @@ func makeOvalString(inbuf string) (string, error) {
|
|||
return string(ovalbuf), nil
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (resStr string) {
|
||||
func (r *run) Run(in io.Reader) (resStr string) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// return error in json
|
||||
|
@ -162,7 +167,7 @@ func (r Runner) Run(in io.Reader) (resStr string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
if r.Parameters.MaxConcurrentEval <= 0 || r.Parameters.MaxConcurrentEval > 10 {
|
||||
return fmt.Errorf("concurrent evaluation must be between > 0 and <= 10")
|
||||
}
|
||||
|
@ -200,7 +205,7 @@ func (r Runner) ValidateParameters() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
elem elements
|
||||
stats Statistics
|
||||
|
|
|
@ -22,7 +22,7 @@ func TestRegistration(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParameters(t *testing.T) {
|
||||
var r Runner
|
||||
var r run
|
||||
|
||||
validPayload := "H4sIAPiTeFUAA7PJL0vMiU9JTcvMyyzJzM8rVqjIzckrtlXKKCkpsNLXB0nr5WaWFKXq5Rel60f4+gQnZ6TmJoIldJH06Zoq2XHZ6KMbZ8cFAGdvQOxiAAAA"
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Contributor: Dustin J. Mitchell <dustin@mozilla.com>
|
||||
// Julien Vehent jvehent@mozilla.com [:ulfr]
|
||||
|
||||
package modules
|
||||
|
||||
// A mig module implements this interface
|
||||
type Moduler interface {
|
||||
NewRun() Runner
|
||||
}
|
||||
|
||||
// The set of registered modules
|
||||
var Available = make(map[string]Moduler)
|
||||
|
||||
// Register a new module as available
|
||||
func Register(name string, mod Moduler) {
|
||||
if _, exist := Available[name]; exist {
|
||||
panic("Register: a module named " + name + " has already been registered.\nAre you trying to import the same module twice?")
|
||||
}
|
||||
Available[name] = mod
|
||||
}
|
|
@ -17,17 +17,18 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// init is called by the Go runtime at startup. We use this function to
|
||||
// register the module in a global array of available modules, so the
|
||||
// agent knows we exist
|
||||
func init() {
|
||||
modules.Register("timedrift", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
// Runner gives access to the exported functions and structs of the module
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("timedrift", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -57,14 +58,14 @@ type ntpstats struct {
|
|||
Reachable bool `json:"reachable"`
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r *run) ValidateParameters() (err error) {
|
||||
if r.Parameters.Drift != "" {
|
||||
_, err = time.ParseDuration(r.Parameters.Drift)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r *run) Run(in io.Reader) (out string) {
|
||||
var (
|
||||
stats statistics
|
||||
el elements
|
||||
|
@ -233,7 +234,7 @@ func GetNetworkTime(host string) (t time.Time, latency string, err error) {
|
|||
}
|
||||
|
||||
// buildResults marshals the results
|
||||
func (r Runner) buildResults(el elements, stats statistics) string {
|
||||
func (r *run) buildResults(el elements, stats statistics) string {
|
||||
r.Results.Elements = el
|
||||
r.Results.Statistics = stats
|
||||
if len(r.Results.Errors) == 0 {
|
||||
|
@ -250,7 +251,7 @@ func (r Runner) buildResults(el elements, stats statistics) string {
|
|||
return string(jsonOutput[:])
|
||||
}
|
||||
|
||||
func (r Runner) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
func (r *run) PrintResults(result modules.Result, foundOnly bool) (prints []string, err error) {
|
||||
var (
|
||||
el elements
|
||||
stats statistics
|
||||
|
@ -313,7 +314,7 @@ If no drift is set, the module only returns local time.
|
|||
`, dash, dash)
|
||||
}
|
||||
|
||||
func (r Runner) ParamsCreator() (interface{}, error) {
|
||||
func (r *run) ParamsCreator() (interface{}, error) {
|
||||
fmt.Println("initializing timedrift parameters creation")
|
||||
var err error
|
||||
var p params
|
||||
|
@ -345,7 +346,7 @@ func (r Runner) ParamsCreator() (interface{}, error) {
|
|||
return r.Parameters, r.ValidateParameters()
|
||||
}
|
||||
|
||||
func (r Runner) ParamsParser(args []string) (interface{}, error) {
|
||||
func (r *run) ParamsParser(args []string) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
drift string
|
||||
|
|
|
@ -32,13 +32,18 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("upgrade", func() interface{} {
|
||||
return new(Runner)
|
||||
})
|
||||
type module struct {
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
func (m *module) NewRun() modules.Runner {
|
||||
return new(run)
|
||||
}
|
||||
|
||||
func init() {
|
||||
modules.Register("upgrade", new(module))
|
||||
}
|
||||
|
||||
type run struct {
|
||||
Parameters params
|
||||
Results modules.Result
|
||||
}
|
||||
|
@ -65,7 +70,7 @@ type statistics struct {
|
|||
DownloadSize int64 `json:"downloadsize"`
|
||||
}
|
||||
|
||||
func (r Runner) ValidateParameters() (err error) {
|
||||
func (r run) ValidateParameters() (err error) {
|
||||
locre := regexp.MustCompile(`^https?://`)
|
||||
checksumre := regexp.MustCompile(`^[a-zA-Z0-9]{64}$`)
|
||||
for k, v := range r.Parameters {
|
||||
|
@ -82,7 +87,7 @@ func (r Runner) ValidateParameters() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (r Runner) Run(in io.Reader) (out string) {
|
||||
func (r run) Run(in io.Reader) (out string) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
r.Results.Errors = append(r.Results.Errors, fmt.Sprintf("%v", e))
|
||||
|
@ -309,7 +314,7 @@ func moveBinary(binPath, version string) (linkloc string, err error) {
|
|||
|
||||
// buildResults transforms the ConnectedIPs map into a Results
|
||||
// map that is serialized in JSON and returned as a string
|
||||
func (r Runner) buildResults() string {
|
||||
func (r run) buildResults() string {
|
||||
var el elements
|
||||
el.OldPID = os.Getppid()
|
||||
r.Results.Elements = el
|
||||
|
|
|
@ -6,14 +6,11 @@ import (
|
|||
)
|
||||
|
||||
func CheckModuleRegistration(t *testing.T, module_name string) {
|
||||
registration, ok := modules.Available[module_name]
|
||||
mod, ok := modules.Available[module_name]
|
||||
if !ok {
|
||||
t.Fatalf("module %s not registered", module_name)
|
||||
}
|
||||
|
||||
modRunner := registration.Runner()
|
||||
if _, ok := modRunner.(modules.Moduler); !ok {
|
||||
t.Fatalf("module %s registration function does not return a Moduler",
|
||||
module_name)
|
||||
}
|
||||
// test getting a run instance (just don't fail!)
|
||||
mod.NewRun()
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче