Objects matching the expression 'type'
- #293 groups for users type are not sorted before comparing to the existing groups setting (groups, type, user)
- #539 Defined types cannot have titles (title, type)
- #727 mount "ensure" parameter's documentation unclear (mount, type)
- #757 interface type does not allow changing of target (interface, type)
- #769 Mount Type Mounts Device Multiple Times (double, mount, twice, two, type)
- #770 per module lib directory patch (define, lib, module, patch, type)
- #777 interface type recreates all interfaces on every puppetd restart (interface, type)
- #1140 Refresh support for package type (package, refresh, type)
- #1144 Update to type/cron.rb documentation (cron, type)
- NagiosReference (nagios, type)
- PracticalTypes So you want to create a custom type. Good for you. There should be more of them in the world. However, it can be really daunting to create a type, as the existing types are mostly very complex, with talk of providers, munging, and all the rest of it. Funnily enough, most of the types we might want to create are a hell of a lot simpler than the pre-existing ones, and don't need the majority of the complexity that Puppet's type model provides. This document is a lighter introduction to writing types than the more official docs. It simplifies the model down to the bare minimum needed to implement a wide range of simple (but still useful) types. Hopefully you can get up to speed with writing simple types, and then move on to more difficult concepts later once you need them. Building a mental model ----------------------- It's important to know roughly how Puppet does what it does with types before writing one, so we'll start with a bit of explanation about how Puppet works with types. There's two important things that Puppet asks each resource during a Puppet run: "Are you up to date?" and "Please modify the system to bring yourself up to date". The work that gets done by your type can be many and varied, but it all must fit into this question / action model. For an example of this, consider the simple task of appending a line to a file if it doesn't already exist. The question "are you up to date?" is handled by just looking through the file to see if the line exists. Modifying the system just involves appending the line to the file. If you can describe what you want to do with your type in these terms, you're a long way towards being able to write your type. Simple Beginnings: Defining the type ------------------------------------ There's a bunch of stuff you have to do to define any type in the Puppet system -- scaffolding, if you like. A simple template looks like this:: module Puppet newtype(:append_if_no_such_line) do end end Here we're defining a type named append_if_no_such_line, which isn't going to do anything. We'll fill in the blanks later. Where should you be putting this code? It's important that the file be named after your type: a type named append_if_no_such_line must be put in a file named append_if_no_such_line.rb. If you put it in any other file, Puppet won't recognise it and your type won't get used (probably resulting in errors in your manifest). What about the directory to put the file into? Puppet will look for types in a puppet/type directory anywhere in the Ruby load path and in the libdir you've defined. (If you don't know where your libdir setting points to, you can run puppetd --genconfig to get all your config variables and see what it's set to). Since you don't want to be copying a type definition file to every machine under Puppet control, you can use pluginsync to get the copying done automatically. Setting that up is beyond the scope of this article; see Creating Custom Types for info on the pluginsync mechanism. Variables: how to know what to do --------------------------------- It would be a very rare type indeed that didn't need to be configured in some way. Puppet's way of defining variables that can be set in the manifest is with "parameters". You define these in your type, and then you can specify values for them in your manifests. Continuing with our append_if_no_such_line example, we have two parameters of interest -- the file we want to mangle, and the line we want to append. So let's define those now:: module Puppet newtype(:append_if_no_such_line) do newparam(:file) newparam(:line) end end Defining parameters is pretty easy, huh? We've missed one thing in our type above, a parameter that every type needs but which we don't think about very often. Any thoughts? It's the parameter which defines the "title" of each individual resource, often called the "name". In theory, you can call this anything you like, but there's complications if you call it anything other than "name", so we'll just call it that and move on:: module Puppet newtype(:append_if_no_such_line) do newparam(:name) newparam(:file) newparam(:line) end end Documentation is Critical ------------------------- I'm going to take a little pause here and talk about documenting your type. It's important to document your type so others can use it. Unfortunately, Puppet uses it's own slightly weird structure for documentation, by setting variables in various places, rather than just using rdoc comments. Oh well. To document the type itself, you need to set the @doc variable at the type level with a documentation string:: module Puppet newtype(:append_if_no_such_line) do @doc (type, types)