Sharing task code
Multiple tasks can share common files between them. Tasks can additionally pull library code from other modules.
To create a task that includes additional files pulled from modules, include the files property in your metadata as an array of paths. A path consists of:
- the module name
- one of the following directories within the module:
files
— Most helper files. This prevents the file from being treated as a task or added to the PuppetRuby loadpath.tasks
— Helper files that can be called as tasks on their own.lib
— Ruby code that might be reused by types, providers, or Puppet functions.
- the remaining path to a file or directory; directories must include
a trailing slash
/
All path separators must be forward slashes. An example would
be stdlib/lib/puppet/
.
The files
property can be included both as a top-level metadata property, and as
a property of an implementation, for
example:
{ "implementations": [ {"name": "sql_linux.sh", "requirements": ["shell"], "files": ["mymodule/files/lib.sh"]}, {"name": "sql_windows.ps1", "requirements": ["powershell"], "files": ["mymodule/files/lib.ps1"]} ], "files": ["emoji/files/emojis/"] }
When a task includes the files
property, all files listed in the top-level property and
in the specific implementation chosen for a target are copied to a temporary directory on that
target. The directory structure of the specified files is preserved such that paths specified
with the files
metadata option are available to tasks prefixed with _installdir
. The task executable
itself is located in its module location under the _installdir
as well, so other files can be found at ../../mymodule/files/
relative to the task
executable's location.
For example, you can create a task and metadata in a module at ~/.puppetlabs/bolt/site-modules/mymodule/tasks/task.{json,rb}
.
Metadata
{ "files": ["multi_task/files/rb_helper.rb"] }
File resource
multi_task/files/rb_helper.rb
def useful_ruby { helper: "ruby" } end
Task
#!/usr/bin/env ruby require 'json' params = JSON.parse(STDIN.read) require_relative File.join(params['_installdir'], 'multi_task', 'files', 'rb_helper.rb') # Alternatively use relative path # require_relative File.join(__dir__, '..', '..', 'multi_task', 'files', 'rb_helper.rb') puts useful_ruby.to_json
Output
Started on localhost... Finished on localhost: { "helper": "ruby" } Successful on 1 node: localhost Ran on 1 node in 0.12 seconds
Task helpers
To help with writing tasks, Bolt includes python_task_helper and ruby_task_helper. It also makes a useful demonstration of including code from another module.
Python example
Create task and metadata in a module at ~/.puppetlabs/bolt/site-modules/mymodule/tasks/task.{json,py}
.
Metadata
{ "files": ["python_task_helper/files/task_helper.py"], "input_method": "stdin" }
Task
#!/usr/bin/env python import os, sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python_task_helper', 'files')) from task_helper import TaskHelper class MyTask(TaskHelper): def task(self, args): return {'greeting': 'Hi, my name is '+args['name']} if __name__ == '__main__': MyTask().run()
Output
$ bolt task run mymodule::task -n localhost name='Julia' Started on localhost... Finished on localhost: { "greeting": "Hi, my name is Julia" } Successful on 1 node: localhost Ran on 1 node in 0.12 seconds
Ruby example
Create task and metadata in a new module at ~/.puppetlabs/bolt/site-modules/mymodule/tasks/mytask.{json,rb}
.
Metadata
{ "files": ["ruby_task_helper/files/task_helper.rb"], "input_method": "stdin" }
Task
#!/usr/bin/env ruby require_relative '../../ruby_task_helper/files/task_helper.rb' class MyTask < TaskHelper def task(name: nil, **kwargs) { greeting: "Hi, my name is #{name}" } end end MyTask.run if __FILE__ == $0
Output
$ bolt task run mymodule::mytask -n localhost name="Robert'); DROP TABLE Students;--" Started on localhost... Finished on localhost: { "greeting": "Hi, my name is Robert'); DROP TABLE Students;--" } Successful on 1 node: localhost Ran on 1 node in 0.12 seconds