wiki:HowToWriteAndDistributeNewModules
Last modified 3 years ago Last modified on 09/28/11 19:57:07

How To Write And Distribute New Modules

One of the neat things about Func is that it's infinitely extensible. Not only can you contribute code to func, but your program can also just drop a module file in /usr/lib/python$version/site-packages/func/modules (on each minion) and have them automatically be exerciseable both by Func's python API (see PythonApiExamples) and the command line.

Automatic module loading is exciting, because it means modules you write, however specific to your company or installation, can just work. They don't require building new func RPMs, or anything like that.

However, if your module is generally useful, it would be great if you could share it with the rest of the func community. We'll include some of these modules in the distribution, and link to others on the web site.

If you do want to package your own modules, distributing them as an RPM is probably a good idea.

Where Modules Go

/usr/lib/python$version/site-packages/func/minion/modules/*.py

Modules can also go into subdirs of that path. As long as those paths can act as python module paths (aka, init.py in the dirs)

For example:

modules/
       foobar/
       foobar/__init__.py
       foobar/blip.py

Could create a foobar.blip module, with methods called as foobar.blip.add() for example.

What Modules Look Like

For starters, you can look at any module that ships with Func to see what it looks like. The "test" module is the simplest.

#!/usr/bin/python

import func_module

class Test(func_module.FuncModule):

    version = "11.11.11"
    api_version = "0.0.1"
    description = "Just a very simple example module"

    def add(self, numb1, numb2):
        return numb1 + numb2

In Depth

Let's disect the Func Module

import func_module

class Test(func_module.FuncModule):

All Func modules extend from the same base class.

 version = "11.11.11"
 api_version = "0.0.1"
 description = "Just a very simple example module"

They have a constructor which always follows the same pattern... it lists which functions are exportable.

    def add(self, numb1, numb2):
        return numb1 + numb2

And they have functions. Functions should always return "simple" data types that can be easily serialized. So this means hashes ("dicts" in python parlance), lists/arrays/tuples, strings, ints, floats, etc.

We have the server configured to accept "None" also but in general, don't do this as XMLRPC clients in other languages may not support it.

Module Configuration

Module will read a configuration file in /etc/func/modules/CLASSNAME.conf where CLASSNAME is the name of the class thats derived from FuncModule class.

If the config file exists, the self.options reference will be a handle to a certmaster.config.BaseConfig derived local class. The values in the object can be accessed as attributes.

Each module needs to define a Config class thats subclassed from certmaster.config.BaseConfig. The class should define the attributes and types expected in the source file.

For example, from the test.py module:

    class Config(BaseConfig):
        example = Option('1')
        string_option = Option('some string here')
        int_option = IntOption(37)
        bool_option = BoolOption(True)
        float_option = FloatOption(3.14159)
        testvalue = 'this is a test. It is only a test'

The module can then use those options by reference the self.options.ATTRIBUTENAME. For example, self.options.testvalue in the above example is 'this is a test. It is only a test'

self.option vales can be set by setattr or setting the attributes directly. For example

     self.options.testvalue = 'this is something different'

To save a config file, the module can call self.save_config()

Creating a New Module

func comes with a command line application to make creation of new modules simple. Here is an example of it's usage:

[steve@tachikoman modules]$ func-create-module
Name: example
Description: An example module.

Leave blank to finish.
Method: echo
Method: time
Method: 
Your module is ready to be hacked on. Wrote out to example.py.

Here is the file that is created with the above input ...

[steve@tachikoman modules]$ cat example.py 
import func_module

class Example(func_module.FuncModule):

    # Update these if need be.
    version = "0.0.1"
    api_version = "0.0.1"
    description = "An example module."

    def self.echo(self):
        pass

    def self.time(self):
        pass

[steve@tachikoman modules]$ 

Summary

So, follow the above template, drop in the module python file in the modules directory, and it's as good as any module that came with func. Start scripting to it with the Python API, or use the command line. You're all set.