diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-06-07 18:14:00 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-06-07 18:14:00 +0000 |
commit | 1a93e6d6d8c253da985262f7adfeb533570ec17f (patch) | |
tree | 6de993ce4db8fa738ccff5255610d8a8a10bc7b6 | |
parent | d84827e09510bd069f912fc3d1c30a38355a054a (diff) | |
download | puppet-1a93e6d6d8c253da985262f7adfeb533570ec17f.tar.gz puppet-1a93e6d6d8c253da985262f7adfeb533570ec17f.tar.xz puppet-1a93e6d6d8c253da985262f7adfeb533570ec17f.zip |
copying all documentation from the plone site
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1237 980ebf18-57e1-0310-9a29-db15c13687c0
-rw-r--r-- | documentation/big-picture.rst | 242 | ||||
-rw-r--r-- | documentation/creating-a-puppet-type.rst | 381 | ||||
-rw-r--r-- | documentation/fromsvn.rst | 78 | ||||
-rw-r--r-- | documentation/fsconfigref.rst | 85 | ||||
-rw-r--r-- | documentation/howitworks.rst | 277 | ||||
-rw-r--r-- | documentation/index.rst | 155 | ||||
-rw-r--r-- | documentation/installation.rst | 304 | ||||
-rw-r--r-- | documentation/introduction.rst | 315 | ||||
-rw-r--r-- | documentation/languagetutorial.rst | 150 | ||||
-rw-r--r-- | documentation/notcfengine.rst | 220 | ||||
-rw-r--r-- | documentation/puppetd-executable-reference.rst | 289 | ||||
-rw-r--r-- | documentation/rails-puppet-manager.rst | 64 | ||||
-rw-r--r-- | documentation/security.rst | 59 | ||||
-rw-r--r-- | documentation/structures.rst | 322 | ||||
-rw-r--r-- | documentation/testing.rst | 82 | ||||
-rw-r--r-- | documentation/typedocs.rst | 1232 |
16 files changed, 4255 insertions, 0 deletions
diff --git a/documentation/big-picture.rst b/documentation/big-picture.rst new file mode 100644 index 000000000..f4965082c --- /dev/null +++ b/documentation/big-picture.rst @@ -0,0 +1,242 @@ +Big picture +=========== +Puppet is a **declarative language** for expressing system configuration, a +**client and server** for distributing it, and a **library** for realizing the +configuration. + +Rather than approaching server management by automating current techniques, +Puppet reframes the problem by providing a language to express the +relationships between servers, the services they provide, and the primitive +objects that compose those services. Rather than handling the detail of how +to achieve a certain configuration or provide a given service, Puppet users +can simply express their desired configuration using the abstractions they're +used to handling, like ``service`` and ``node``, and Puppet is responsible for +either achieving the configuration or providing the user enough information to +fix any encountered problems. + +This document is a supplement to the Introduction_ and it is assumed that +readers are familiar with the contents of that document. + +Less Detail, More Information +============================= + +A correct configuration must obviously provide the appropriate details, but a +configuration tool should understand that the details are generally the easy +part. The hard part of system configuration is understanding the +complex relationships between services and the objects that comprise those +services. One of the primary goals of Puppet is to allow users to push the +details into lower levels of the configuration and pull the relationships into +the foreground. + +For instance, take a typical Apache web server deployment. Puppet allows one +to encapsulate all of the primitives necessary for successful deployment into +one reusable object, and that object can even be abstractedt to support +multiple apache versions. Here's how a simple apache definition might look +for a Debian server (Debian uses ``apache`` for 1.x versions and ``apache2`` +for 2.x versions):: + + define apache(version, conf, user, group) { + # abstract across apache1 and apache2 + $name = $version ? { + 1 => "apache", + 2 => "apache2" + } + package{ $name: + install => true + } + + file { $conf: + user => $user, + group => $group, + source => $conf + } + + # we want the service to restart if the config file changes + # or if the package gets upgraded + service { $name: + running => true, + requires => [file[$conf], package[$name]] + } + } + +Now, with this configuration, one can easily set multiple servers up to run +different versions of apache. The key benefit here is that the information +necessary to run apache correctly is separated from the decision to do so on a +given host. For example:: + + # import our apache definition file + import "apache" + + node server1 { + # use a locally-available config file + apache { + version => 1, + conf => "/nfs/configs/apache/server1.conf", + user => www-data, + group => www-data + } + } + + node server 2 { + # use a config that we pull from elsewhere + apache { + version => 2, + conf => "http://configserver/configs/server2/httpd.conf" + user => www-data, + group => www-data + } + } + +Notice that our node configuration only specifies 1) that a given server is +running Apache, and 2) the information necessary to differentiate this +instance of apache from another instance. If a given detail is going to be +the same for all apache instances (such as the fact that the service should be +running and that it should be restarted if the configuration file changes), +then that detail does not have to be specified every time an Apache instance +is configured. + +Describing Configuration +======================== + +Puppet's declarative language separates the "what" of the configuration from +the "how". + +Language Example: Class Hierarchy using Inherit +----------------------------------------------- + +A Site Configuration is made of high level declarative statements about policy. +A Policy of having all hosts monitored (to ensure uptime, report +performance/load, or audit log files) can be implmented with inheritance (as +with "server_host") or with composition (as in workstation).:: + + define monitored_component (report_server) { + #(registers w/ monitoring software).... + } + class monitored_host { + $report_server = "somehost.domain.com" + monitored_component { "mon_comp" : + report_server => $report_server + } + } + class server_host inherits monitored_host { + #(other definitions/classes specific to servers).... + } + #... or ... + class workstation_host { + $alt_report_server = "someotherhost.domain.com" + monitored_component ( "workstation_mon" : + report_server => $alt_report_server + #(other definitions specific to workstations).... + } + +Language Example: Type Composition using Function Definitions +------------------------------------------------------------- + +The following example describes the services (objects) and relationships +(definitions) for a simple web site.:: + + define webserver (port, htmldoc, default-config-file) { + #...(configures httpd to serve files at path "htmldoc")... + } + define firewall_port (external-port, internal-port) { + #...(stores the port aspects for a "firewall" object to + #later build a firewall config)... + } + +By defining the Webserver/Firewall objects, the details of behavior not +relevant to a simple website (such as the default configuration of a httpd +server or the process of registering the firewall port aspect can be enclosed +in an abstraction. + +One model for a Simple website defines the relationship between two components: +a webserver to respond to the HTTP requests, and a firewall to limit traffic +and protect the webserver host. They require two parameters: The external port +to receive HTTP requests, and the collection of files that the webserver will +offer as webpages.:: + + define simple_web_site_service (external-port,data-filepath) { + $internal-port = 80 + $default_config_file = "...httpd.conf" + webserver { "simple_webserver" : + port => $internal-port + htmldoc => $data-filepath, + default-config-file => $default-config-file } + + firewall_port { "simple_firewall_port" : + external-port => $external-port, + internal-port => $internal-port } + + requires ( simple_webserver, simple_firewall_port ) + } + +This definition of the service declares the components as related objects. The +Web Site Service requires a webserver and an open port on the firewall +component. + +As this configuration is deployed to different operating systems (RedHat linux, +solaris, etc.), the appropriate webserver, web-data, firewall object class can +be called by the Puppet framework. The lower level details of how each OS +specific component implements its configuration is separate from site policy. + +You can read more about the Puppet language in the Introduction_. (Add link to +user manual, when it's written) + + +Distributing Configuration +========================== + +The Puppet framework Library consists of a client and server. + +(picture/diagram: client, server, site-config -> host-config) + +A Puppet server is aware of the full configuration. As some component's +configuration aspects depend on the configuration of other components (e.g. the +firewall config includes the ports used by webservers), generating +configuration for a component requires being aware of full configuration. + +A Puppet client that runs on a specific host (or perhaps the same host as its +Puppet Server) is generally only concerned with the components to be configured +on that host. + +Puppet Clients normally request or "pull" configuration from their server. The +Server processes the configuration request for the host using a pre-generated +tree model of the classes and definitions from the site-config. + +When configuration needs to be "pushed" to the clients, the Server can be asked +to attempt to trigger each client to request "pull" a new host configuration. + +Example: Puppet server, library + +You can read more about the Puppet language in the Introduction_. (Add link to +user manual, when it's written) + + +Realizing the Configuration +=========================== + +The Puppet Client Library contains the component knowledge of how to reach +desired states and configurations for several objects: File, Package, etc. + +Example: Puppet Client, library:: + + ...todo: file: transfer, mode, ownership... + +You can read more about the Puppet language in the Introduction_. +(Add link to user manual, when it's written) + +Some components such as the webserver and firewall, from the simple-website +example, require additional code to reach "closure". "Closure" is when the +component is entirely responsible for implementing its own configuration. + +Much as database applications abstract the mechanics of storing, indexing, and +searching their data, a component ideally should abstract the specifics of how +to store, confirm, and implement its requested configuration. + +To learn more, review other Puppet Documentation_ and sample Configurations_. + + +.. _Introduction: intro + +.. _Documentation: /projects/puppet/documentation/ + +.. _Configurations: /svn/manifests/ diff --git a/documentation/creating-a-puppet-type.rst b/documentation/creating-a-puppet-type.rst new file mode 100644 index 000000000..bcc854711 --- /dev/null +++ b/documentation/creating-a-puppet-type.rst @@ -0,0 +1,381 @@ +Organizational Principles +========================= +I won't claim that the terminology currently in place is great, but it's +what's there, so bear with me. + +Puppet types are basically container classes; they do not directly do any work +themselves, usually, but rather serve to collect other classes that can work. +The three types of classes that a type can contain are Parameters_, +MetaParameters_, and States_. + +Types are created by calling the ``newtype`` method on ``Puppet::Type``, with +the name of the type as the only required argument (you can optionally specify +a parent class; otherwise, Puppet::Type is used as the parent class), and you +must also provide a block of code used to define the type:: + + Puppet::Type.newtype(:database) do + ... the code ... + end + +A normal type would define multiple states_ and zero or more parameters_. +Once these are defined, you just put the type into ``lib/puppet/type`` +anywhere in Ruby's search path, and Puppet will autoload the type when you use +it in the language. + +All types should also provide inline documention in the ``@doc`` class +instance variable. The text format is in `Restructured Text`_. + +Parameters +---------- +These are usually simple attributes that can be used to modify function, but +they don't directly do any work themselves. Parameters are defined inside the +block passed to ``newtype``, using the ``newparam`` method:: + + + Puppet::Type.newtype(:database) do + newparam(:color) do + desc "Specify the color you want your database to be." + + newvalues(:red, :green, :blue, :purple) + end + end + +The ``desc`` method provides documentation for your parameter. This +documentation is used by ``puppetdoc`` to create the `Type Reference`_. + +The ``newvalues`` method is optional; if you use it, then only those values +(in string or symbol form) will be considered valid values, and they will +always be converted to symbols for easier testing. + +At least one of your parameters must be the **namevar**, specified using the +``isnamevar`` method. This is a too-magical parameter in Puppet; this is the +attribute that is considered to uniquely identify a given instance, such as a +file's path or a user's name. If a separate name is not provided, then this +value is returned by the ``name`` method on a type instance, but you can +specify both a name and the namevar, although it can be confusing internally:: + + file { sshconfig: + path => "/etc/ssh/ssh_config", + source => "/nfs/path/to/my/ssh/config" + } + +This would have ``file.name`` returning ``sshconfig`` and ``file[:path]`` +returning ``/etc/ssh/ssh_config``. This is confusing enough that it's best to +always use the namevar and not the ``name`` method. + +You can specify regexes in addition to literal values; matches against regexes +always happen after equality comparisons against literal values, and those +matches are not converted to symbols. For instance, given the following +definition:: + + newparam(:color) do + desc "Your color, and stuff." + + newvalues(:blue, :red, /.+/) + end + +If you provide "blue" as the value, then your parameter will get set to +``:blue``, but if you provide "green", then it will get set to "green". + +Currently, you set parameters by treating the containing object as a hash:: + + db[:color] = :blue + +If the parameter already exists, then 'value=' is called on the object, with +the value you provide. If it does not exist, then the object is created and +put into the type instance's ``@parameters`` hash, indexed by parameter name. +The parameter object gets its ``@parent`` instance variable set so that it +points back to the containing type instance. + +You can similarly retrieve the parameter:: + + puts db[:color] + +Within the type instance itself (i.e., in instance methods), you can use these +same methods to set and retrieve the values, or you can call the ``value`` +methods directly, once the object exists:: + + # Create the param + self[:color] = :blue + color = @parameters[:color].value + @parameters[:color].value = :red + +Validation and Munging +++++++++++++++++++++++ +If your parameter does not have a defined list of values, or you need to +convert the values in some way, you can use the ``validate`` and ``munge`` +hooks:: + + newparam(:color) do + desc "Your color, and stuff." + + newvalues(:blue, :red, /.+/) + + validate do |value| + if value == "green" + raise ArgumentError, + "Everyone knows green databases don't have enough RAM" + else + super + end + end + + munge do |value| + case value + when :mauve, :violet # are these colors really any different? + :purple + else + super + end + end + end + +These should probably not be methods you call on the type and should just be +instance methods you define, but it's not a big deal either way. The default +``validate`` method looks for values defined using ``newvalues`` and if there +are any values defined it accepts only those values (this is exactly how +allowed values are validated). The default ``munge`` method converts any +values that are specifically allowed into symbols. If you override either of +these methods, note that you lose this value handling and symbol conversion, +which you'll have to call ``super`` for. + +Values are always validated before they're munged. + +Lastly, validation and munging *only* happen when a value is assigned. They +have no role to play at all during use of a given value, only during +assignment. + +MetaParameters +-------------- +These are just like parameters in all but two ways. First, they are defined +using the ``newmetaparam`` method, and second, when defined they are valid for +all types, not just a single type. See the end of type.rb for examples. + +You should never define any of these in an average custom type; if you need a +new MetaParameter, contact the main developers about getting it added to the +core. + +States +------ +States are what usually do the actual work on the system. These are actually +a subclass of parameters, but with much more functionality. Without +exception, every state needs to define at least two methods: ``retrieve`` and +``sync``. + +The Variables ++++++++++++++ +The ``retrieve`` and ``sync`` methods work in tandem with two important +instance variables, ``@is`` and ``@should``. The first should reflect the +current state of the, um, state (I already admitted the nomenclature is bad), +and it should be in whatever form your class expects -- symbol, array, +whatever. The second reflects what the current state, um, should be, and it +is *always* an array. + +Because there are two variables that contain values, assignment to states is a +bit odd. By default, ``@should`` is used when you use the indexing methods:: + + file[:owner] = "root" + +This sets ``@should`` to be ``["owner"]``. You would not normally set the +``@is`` variable from outside the instance, but sometimes it's necessary:: + + file.is = [:owner, "root"] + +Because ``@should`` is always an array but most states can't actually use +an array, the ``should`` accessor method only returns the first value in the +array. If you do want to use the whole array (i.e., you consume all of the +values, not just the first), then you have to override the ``should`` method +to return the whole array. You'll see why in a minute. + +I should probably explain why ``@should`` is always an array: You can always +specify multiple values for any state, and by default, if the current state is +in that list of values, then no work is done. That is, given the following +definition:: + + file { "/etc/sudoers": + owner => root, group => [wheel, root], mode => 440 + } + +If the group is currently ``wheel`` or ``root``, then the file is considered +in sync. + +The Methods ++++++++++++ + +``retrieve`` is used to get the current value of the state on the machine. +For instance, here is a trivialized version of how to retrieve a File's +owner:: + + newstate(:owner) do + def retrieve + @is = File.stat(@parent[:path]).mode + end + end + +It's critical that you set the ``@is`` instance variable on the state. +Puppet should really just set the variable for you based on the return value, +but, well, it doesn't do that right. One important aspect of ``retrieve`` is +that it should not modify the system in any way; if someone runs their +configuration in ``noop`` mode, then ``retrieve`` is still called, so it's +important that it not modify the state of the system. + +The other critical method is ``sync``, which actually modifies the machine:: + + newstate(:owner) do + def retrieve + @is = File.stat(@parent[:path]).uid + end + + def sync + File.chown(self.should, nil, @parent[:path]) + + return :file_changed + end + end + +Note this ``return`` here; sync operations are expected to return an event if +they do any work, and this event is used to trigger subscribing objects. If +you return nil, then Puppet will assume you didn't do any work. At this point +the events themselves are meaningless, but at some point users will be able to +subscribe to specific events, rather than all events from a given object. + +There's a third method, ``insync?``, which you will not normally override but +is important to understand. This method is used to determine if your state is +in sync, and thus if any work needs to be done. The default method looks a +lot like this:: + + def insync? + @should.include?(@is) + end + +Notice that we're checking to see if our current value is anywhere in the +``@should`` list. + +State Values +++++++++++++ +Just like parameters, you can define allowed values for states, but there's +one significant change: With state values, you have to specify the code that +will achieve that state. Here is a trivialized version of ``ensure`` state on +files:: + + newstate(:ensure) do + newvalue(:file) do + @parent.write { |f| f.puts "" } # make an empty file + return :file_created + end + + newvalue(:directory) do + Dir.mkdir(@parent[:path]) + return :directory_created + end + + newvalue(:absent) do + File.unlink(@parent) + return :file_deleted + end + + # Allow users to treat these equivalently. + aliasvalue(:present, :file) + end + +You similarly must provide code when you specify a regular expression. This +value specification mechanism gives you the same validation and munging that +parameters have while allowing you to cleanly separate your code for each +allowed value. See the existing types for examples of this, although not all +states have a defined value list, and this mechanism was created long after +most of the types were created and they have not all been updated to use it. + +Behind the scenese, puppet creates a ``set_<value>`` method, named for each +allowed value, and the default ``sync`` method just looks at the ``should`` +value here, tries to find an appropriate method, and calls it if it finds +one. In this example, files have ``set_file``, ``set_directory``, and +``set_absent`` methods, and ``sync`` calls them according to the output of +``should``. + +All of these are convenience methods, of course; you can have a single opaque +all-powerful ``sync`` method, you don't have to split it up using values. + +Process +======= +Now that you have an idea of how types are constructed, let's look at the +process of applying one or more type instances. + +Dependency Sorting +------------------ +I'll ignore the process of turning Puppet manifests into types; that's handled +in the `How It Works`_ document. The collection of objects are always +contained in a top-level instance of the ``component`` type (this is an +unfortunate hold-over from some flawed design ideas in the early development +of Puppet -- expect it to change internally at some point). + +When work is begun, ``evaluate`` is called on the component (usually by +client/master.rb); this method does a topological sort based on dependency +information on all contained objects (components can contain other components, +so it's a recursive sort), creates a new transaction, and adds the now-sorted +flat list of objects to the transaction. + +Transactions +------------ +Once the transaction has all of the objects, ``evaluate`` is called on it. +This method is the heart of action in Puppet; it's relatively short, but +determines all of the actual function in a given run. + +It iterates across the sorted list of objects, finding all objects that are +scheduled to run (which, by default, is all of them) and that match the tag +list if there are any tags specified (you can specify tags to ``puppetd`` +which will cause it to only run objects that have those tags). For each of +those found objects, the transaction calls ``evaluate`` on the object, which +in turn calls ``statechanges`` on the object. + +``statechanges`` iterates across each instantiated state (i.e., file objects +have many states, but only those states for which you've provided a value have +instances in a given file object's ``@states`` variables), looking for +out-of-sync states. The states are checked in the order they're defined; this +often does not matter, but for classes like ``file`` it matters a lot. For +each state that's out of sync, a ``StateChange`` object is created; it's +basically an organizational class that knows how to sync a state and log the +work it's doing. + +There's one exception to this "all states are checked" rule: If the instance +has an ``ensure`` state and that state is out of sync, then Puppet assumes +that the object is entirely missing or will be entirely removed and that the +``ensure`` state knows how to do that. This allows Puppet to create just one +log message when creating a new object (as opposed to, say, one each for the +file contents, the mode, the owner, and the group) and provides better +modeling for object creation and destruction. However, it does mean that if +you provide this state it needs to be able to completely create the object on +its own; this often just means syncing all of the other out-of-sync states +once the object exists. + +The type instance's ``evaluate`` method returns to the transaction the list of +collected state change objects. Once the transaction has all of the changes, +it iterates across each one, calling ``forward`` on them (yes, there's a +``backward`` that can revert the change) and collecting events from each +change. + +Until recently, Puppet collected all of the events (which contain references +to the object that generated them) and triggered any subscriptions at the end +of the run, but now events are managed so that they're triggered inline. + +Once all of an object's states are in sync, the transaction looks for events +that the object is subscribed to and triggers any found subscriptions. + +That's pretty much it. The ``transaction`` class is pretty short, but it's +also pretty complicated. Fortunately, you should be able to ignore it just +about entirely; define your states in the order you want them applied, make +sure your ``ensure`` state can completely create or destroy the object, and +return events if you made a change. Other than that, you should not have to +think about transactions or how they work. + +Conclusion +========== +That's all you need for your type. See the existing types for different ways +to treat this. You can create methods on your type and call those methods +from the state (like packages do), or put enough complexity into each state +that they end up in their own file (like files do). + +Comments on this document are appreciated. + +.. _type reference: typedocs +.. _restructured text: http://docutils.sourceforge.net/rst.html +.. _how it works: howitworks diff --git a/documentation/fromsvn.rst b/documentation/fromsvn.rst new file mode 100644 index 000000000..4780faf27 --- /dev/null +++ b/documentation/fromsvn.rst @@ -0,0 +1,78 @@ +Puppet is currently implemented in Ruby and uses standard Ruby libraries. You should be able to run Puppet on any Unix-style host with Ruby. Windows support is planned but not currently available. + +Before you Begin +---------------- + +Make sure your host has Ruby version 1.8.2:: + + $ ruby -v + +Make sure you have Subverion:: + + $ svn --version -q + +Get the Source +-------------- + +Puppet currently relies on another ReductiveLabs tool, Facter. Create a working +directory and download them both:: + + $ SETUP_DIR=~/svn + $ mkdir -p $SETUP_DIR + $ cd $SETUP_DIR + $ svn checkout https://reductivelabs.com/svn/facter + $ svn checkout https://reductivelabs.com/svn/puppet + + +Make it Available +----------------- + +Last, we need to put the puppet binaries into our path and make the Puppet and +Facter libraries available to Ruby:: + + $ PATH=$PATH:$SETUP_DIR/facter/bin:$SETUP_DIR/puppet/trunk/bin + $ RUBYLIB=$SETUP_DIR/facter/lib:$SETUP_DIR/puppet/trunk/lib + $ export PATH RUBYLIB + +Facter changes far less often than Puppet and it is very minimal (a single +library file and a single executable), so it is probably worth just installing +it:: + + $ cd facter/trunk + $ sudo ruby ./install.rb + +Test it Works +------------- +Now you can test that it is working. The best way to do that is described in +the testing_ guide, and involves writing a short site manifest. Another +option is to run through all of the unit tests that ship with Puppet:: + + $ cd $SETUP_DIR/puppet/trunk/test + $ ./test + +This tends to take a long time, however, and is probably only useful if you +already know there's a problem and want to report a bug or if you are planning +on doing development. It is worth noting that some of these tests necessarily +modify your system, so unless you know what you are doing, **it is unadvisable +to run them as root**, and certainly not on a production system. + +Help with Installing +-------------------- +You can build your first Puppet script by using this Simple Example_. + +You can see more documentation about installation of Puppet and its +prerequisites by looking at Bootstrap-Install_ guide. + + +More documentation +------------------ + +You can learn more about Puppet by reading the Documentation_. + +.. _Documentation: /projects/puppet/documentation/ + +.. _Example: https://reductivelabs.com/svn/manifests/project-www/README-www.rst + +.. _Bootstrap-Install: https://reductivelabs.com/svn/manifests/project-test/bootstrap-install.rst + +.. _testing: testing diff --git a/documentation/fsconfigref.rst b/documentation/fsconfigref.rst new file mode 100644 index 000000000..cd2b30868 --- /dev/null +++ b/documentation/fsconfigref.rst @@ -0,0 +1,85 @@ +FileServer +========== + +Puppet comes with both a client and server for copying files around. The file +serving function is provided as part of the central Puppet daemon, +``puppetmasterd``, and the client function is used through the ``source`` +attribute of ``file`` objects:: + + # copy a remove file to /etc/sudoers + file { "/etc/sudoers": + mode => 440, + owner => root, + group => root, + source => "puppet://server/module/sudoers" + } + +As the example implies, Puppet's fileserving function abstracts local +filesystem topology by supporting fileservice "modules". You specify a path +to serve and a name for the path, and clients request it by name instead of by +path. This provides the ability to conceal from the client unnecessary +details like the local filesystem configuration. + +File Format +============= +The default location for the file service is ``/etc/puppet/fileserver.conf``; +this can be changed using the ``--fsconfig`` flag to ``puppetmasterd``. +The format of the file is almost exactly like that of rsync_, although it does +not yet support nearly the functionality of rsync. The configuration file +resembles INI-style files, but it is not exactly the same:: + + [module] + path /path/to/files + allow *.domain.com + deny *.wireless.domain.com + +These three options represent the only options currently available in the +configuration file. The module name somewhat obviously goes in the brackets. +While the path is the only required option, the default security configuration +is to deny all access, so if no ``allow`` lines are specified, the module will +be configured but available to no one. + +Security +======== +There are two aspects to securing the Puppet file server: Allowing specific +access, and denying specific access. By default no access is allowed. There +are three ways to specify a class of clients who are allowed or denied access: +By IP address, by name, or a global allow using ``*``. + +Priority +-------- +All ``deny`` statements are parsed before all ``allow`` statements, so if any +``deny`` statements match a host, then that host will be denied, and if no +``allow`` statements match a host, it will be denied. + +Host Names +---------- +Host names can be specified using either a complete hostname, or specifying an +entire domain using the ``*`` wildcard:: + + [export] + path /export + allow host.domain1.com + allow *.domain2.com + deny badhost.domain2.com + +IP Addresses +------------ +IP address can be specified similarly to host names, using either complete IP +addresses or wildcarded addresses, but you can also use CIDR-style notation:: + + [export] + path /export + allow 127.0.0.1 + allow 192.168.0.* + allow 192.168.1.0/24 + +Global allow +------------ +Specifying a single wildcard will let anyone into a module:: + + [export] + path /export + allow * + +.. _rsync: http://samba.anu.edu.au/rsync/ diff --git a/documentation/howitworks.rst b/documentation/howitworks.rst new file mode 100644 index 000000000..730d4b04e --- /dev/null +++ b/documentation/howitworks.rst @@ -0,0 +1,277 @@ +Introduction +============ +The goal of this document is to describe how a manifest you write in Puppet +gets converted to work being done on the system. This process is relatively +complex, but you seldom need to know many of the details; this document only +exists for those who are pushing the boundaries of what Puppet can do or who +don't understand why they are seeing a particular error. It can also help +those who are hoping to extend Puppet beyond its current abilities. + +High Level +========== +When looked at coarsely, Puppet has three main phases of execution -- +compiling, instantiation, and configuration. + +Compiling +--------- +Here is where we convert from a text-based manifest into the actual code we'll +be executing. Any code not meant for the host in question is ignored, and any +code that is meant for that host is fully interpolated, meaning that variables +are expanded and all of the results are literal strings. + +The only connection between the compiling phase and the library of Puppet +elements is that all resulting elements are verified that the referenced type +is valid and that all specified attributes are valid for that type. There is +no value validation at this point. + +In a networked setup, this phase happens entirely on the server. The output +of this phase is a collection of very simplistic elements that closely +resemble basic hashes and arrays. + +Instantiation +------------- +This phase converts the simple hashes and arrays into Puppet library objects. +Because this phase requires so much information about the client in order to +work correctly (e.g., what type of packaging is used, what type of services, +etc.), this phase happens entirely on the client. + +The conversion from the simpler format into literal Puppet objects allows +those objects to do greater validation on the inputs, and this is where most +of the input validation takes place. If you specified a valid attribute but +an invalid value, this is where you will find it out, meaning that you will +find it out when the config is instantiated on the client, not (unfortunately) +on the server. + +The output of this phase is the machine's entire configuration in memory and +in a form capable of modifying the local system. + +Configuration +------------- +This is where the Puppet library elements actually modify the system. Each of +them compares their specified state to the state on the machine and make any +modifications that are necessary. If the machine exactly matches the +specified configuration, then no work is done. + +The output of this phase is a correctly configured machine, in one pass. + +Lower Level +=========== +These three high level phases can each be broken down into more steps. + +Compile Phase 1: Parsing +------------------------ +:Inputs: Manifests written in the Puppet language +:Outputs: Parse trees (instances of AST_ objects) +:Entry: `Puppet::Parser::Parser#parse`_ + +At this point, all Puppet manifests start out as text documents, and it's the +parser's job to understand those documents. The parser (defined in +``parser/grammar.ra`` and ``parser/lexer.rb``) does very little work -- it +converts from text to a format that maps directly back to the text, building +parse trees that are essentially equivalent to the text itself. The only +validation that takes place here is syntactic. + +This phase takes place immediately for all uses of Puppet. Whether you are +using nodes or no nodes, whether you are using the standalone puppet +interpreter or the client/server system, parsing happens as soon as Puppet +starts. + +Compile Phase 2: Interpreting +----------------------------- +:Inputs: Parse trees (instances of AST_ objects) and client information + (collection of facts output by Facter_) +:Outputs: Trees of TransObject_ and TransBucket_ instances (from + transportable.rb) +:Entry: `Puppet::Parser::AST#evaluate`_ +:Exit: `Puppet::Parser::Scope#to_trans`_ + +Most configurations will rely on client information to make decisions. When +the Puppet client starts, it loads the Facter_ library, collects all of the +facts that it can, and passes those facts to the interpreter. When you use +Puppet over a network, these facts are passed over the network to the server +and the server uses them to compile the client's configuration. + +This step of passing information to the server enables the server to make +decisions about the client based on things like operating system and hardware +architecture, and it also enables the server to insert information about the +client into the configuration, information like IP address and MAC address. + +The interpreter_ combines the parse trees and the client information into a +tree of simple transportable_ objects which maps roughly to the configuration +as defined in the manifests -- it is still a tree, but it is a tree of classes +and the elements contained in those classes. + +Nodes vs. No Nodes +'''''''''''''''''' +When you use Puppet, you have the option of using `node elements`_ or not. If +you do not use node elements, then the entire configuration is interpreted +every time a client connects, from the top of the parse tree down. In this +case, you must have some kind of explicit selection mechanism for specifying +which code goes with which node. + +If you do use nodes, though, the interpreter precompiles everything except the +node-specific code. When a node connects, the interpreter looks for the code +associated with that node name (retrieved from the Facter facts) and compiles +just that bit on demand. + +Configuration Transport +----------------------- +:Inputs: Transportable_ objects +:Outputs: Transportable_ objects +:Entry: `Puppet::Server::Master#getconfig`_ +:Exit: `Puppet::Client::MasterClient#getconfig`_ + +If you are using the stand-alone puppet executable, there is no configuration +transport because the client and server are in the same process. If you are +using the networked puppetd client and puppetmasterd server, though, the +configuration must be sent to the client once it is entirely compiled. + +Puppet currently converts the Transportable objects to YAML_, which it then +CGI-escapes and sends over the wire using XMLRPC over HTTPS. The client +receives the configuration, unescapes it, caches it to disk in case the server +is not available on the next run, and then uses YAML to convert it back to +normal Ruby Transportable objects. + +Instantiation Phase +------------------- +:Inputs: Transportable_ objects +:Outputs: `Puppet::Type`_ instances +:Entry: `Puppet::Client::MasterClient#getconfig`_ +:Exit: `Puppet::Type#finalize`_ + +To create Puppet library objects (all of which are instances of `Puppet::Type`_ +subclasses), ``to_trans`` is called on the top-level transportable object. +All container objects get converted to `Puppet::Type::Component`_ instances, +and all normal objects get converted into the appropriate Puppet type +instance. + +This is where all input validation takes place and often where values get +converted into more usable forms. For instance, filesystems always return +user IDs, not user names, so Puppet objects convert them appropriately. +(Incidentally, sometimes Puppet is creating the user that it's chowning a file +to, so whenever possible it ignores validation errors until the last minute.) + +The last phase of instantiation is the *finalization* phase. One of the goals +of the Puppet language is to make file order matter as little as possible; +this means that a Puppet object needs to be able to require other objects +listed later in the manifest, which means that the required object will be +instantiated after the requiring object. So, the finalization phase is used +to actually handle all of these requirements -- Puppet objects use their +references to objects and verify that the objects actually exist. + +Configuration Phase 1: Comparison +--------------------------------- +:Inputs: `Puppet::Type`_ instances +:Outputs: `Puppet::StateChange`_ objects collected in a `Puppet::Transaction`_ + instance +:Entry: `Puppet::Client::MasterClient#apply`_ +:Exit: `Puppet::Type::Component#evaluate`_ + +Before Puppet does any work at all, it compares its entire configuration to +the state on disk (or in memory, or whatever). To do this, it recursively +iterates across the tree of `Puppet::Type`_ instances (which, again, still +roughly maps to the class structure defined in the manifest) and calls +``evaluate``. + +Things are a bit messier than this in real life, but the summary is that +``evaluate`` retrieves the state of each object, compares that state to the +desired state, and creates a Puppet::StateChange object for every individual +bit that's out of sync (e.g., if a file has the wrong owner and wrong mode, +then each of those are in separate StateChange instances). The end result of +evaluating the whole tree is a collection of StateChange objects for every bit +that's out of sync, all sorted in order of dependencies so that objects are +always fixed before the objects that depend on them. + +The top-level component (which is also responsible for this sorting) creates a +Puppet::Transaction instance and inserts these changes into it. + +Notes About Recursion +''''''''''''''''''''' +Recursion muddies this phase considerably. While it's tempting to merely +handle recursion in the instantiation phase, the state on disk can (and will) +change between runs, so the configured state and the on-disk state must be +compared on every run (and it is assumed that ``puppetd`` will be a +long-running process that only does instantiation once but does configuration +many times). + +This means that there might still be objects that don't exist at the end of +instantiation but do exist at the end of comparison. In particular, when +doing recursive file copies from a remote machine, Puppet creates an object in +memory to map to every remote file, and that recursive object creation would +not make sense at instantiation time, only at comparison time. + +This might introduce some strangenesses, though, and it is expected that this +could cause interesting-in-a-not-particularly-good-way edge cases. + +Configuration Phase 2: Syncing +------------------------------ +:Inputs: `Puppet::Transaction`_ instance containing `Puppet::StateChange`_ + instances +:Outputs: Completely configured operating system +:Entry: `Puppet::Type::Component#evaluate`_ +:Exit: `Puppet::Transaction#evaluate`_ + +The transaction's job is just to execute each change. The changes themselves +are responsible for logging everything that happens (one of the reasons that +all work is done by StateChange objects rather than just letting the objects +do it is to guarantee that every modification is logged). This execution is +done by calling ``go`` on each change in turn, and if the change does any work +then it produces an event of some kind. These events are collected until all +changes have been executed. + +Once the transaction is complete, all of the events are checked to see if +there are any callbacks associated with them. Puppet currently only supports +one type of callback and one way of specifying them: Calling ``refresh`` on +objects based on that object subscribing to another object. For instance, +take the following snippet:: + + file { "/etc/ssh/sshd.conf": + source => "puppet://puppet/config/sshd.conf" + } + + service { sshd: + running => true, + subscribe => file["/etc/ssh/sshd.conf"] + } + +If the local file is out of sync with the remote file, then a StateChange +instance is created reflecting this. When that change is executed, it creates +a ``file_changed`` event. Because of the above subscription, the callback +associated with this event is to call ``refresh`` on the ``sshd`` service; for +services, ``refresh`` is equivalent to restarting, to sshd is restarted. In +this way, Puppet elements can react to changes that it makes to the system. + +While transactions are fully capable of moving both forward and backward +(e.g., if a transaction encountered an error, it could back out all of its +changes), there are currently no hooks within Puppet itself to specify when +and why that would happen. If this is a critical feature for you or you have +a brilliant way to go about creating it, I would love to hear it, but it is +currently a back-burner goal. + +Conclusion +========== +That's the entire flow of how a Puppet manifest becomes a complete +configuration. There is more to the Puppet system, such as FileBuckets, but +those are more support staff rather than the main attraction. + +.. _facter: /projects/facter +.. _node elements: /projects/puppet/documentation/structures#nodes +.. _yaml: http://www.yaml.org/ +.. _Puppet::Parser::Parser#parse: /downloads/puppet/apidocs/classes/Puppet/Parser/Parser.html +.. _Puppet::Parser::AST#evaluate: /downloads/puppet/apidocs/classes/Puppet/Parser/AST.html +.. _Puppet::Parser::Scope#to_trans: /downloads/puppet/apidocs/classes/Puppet/Parser/Scope.html +.. _AST: /downloads/puppet/apidocs/classes/Puppet/Parser/AST.html +.. _TransObject: /downloads/puppet/apidocs/classes/Puppet/TransObject.html +.. _TransBucket: /downloads/puppet/apidocs/classes/Puppet/TransBucket.html +.. _Puppet::Server::Master#getconfig: /downloads/puppet/apidocs/classes/Puppet/Server/Master.html +.. _Puppet::Client::MasterClient#getconfig: /downloads/puppet/apidocs/classes/Puppet/Client/MasterClient.html +.. _Transportable: /downloads/puppet/apidocs/classes/Puppet/TransBucket.html +.. _Puppet::StateChange: /downloads/puppet/apidocs/classes/Puppet/StateChange.html +.. _Puppet::Transaction: /downloads/puppet/apidocs/classes/Puppet/Transaction.html +.. _Puppet::Client::MasterClient#apply: /downloads/puppet/apidocs/classes/Puppet/Client/MasterClient.html +.. _Puppet::Type::Component#evaluate: /downloads/puppet/apidocs/classes/Puppet/Type/Component.html +.. _Puppet::Type::Component: /downloads/puppet/apidocs/classes/Puppet/Type/Component.html +.. _Puppet::Transaction#evaluate: /downloads/puppet/apidocs/classes/Puppet/Transaction.html +.. _interpreter: /downloads/puppet/apidocs/classes/Puppet/Parser/Interpreter.html +.. _Puppet::Type: /downloads/puppet/apidocs/classes/Puppet/Type.html +.. _Puppet::Type#finalize: /downloads/puppet/apidocs/classes/Puppet/Type.html diff --git a/documentation/index.rst b/documentation/index.rst new file mode 100644 index 000000000..acec2a5f2 --- /dev/null +++ b/documentation/index.rst @@ -0,0 +1,155 @@ +.. contents:: Table of Contents + +How to Use This Guide +===================== +This guide is largely a pointer to smaller, more focused guides, although it +includes unique information when no appropriate smaller guide exists. + +Introduction to Puppet +======================= + +Puppet is a declarative *language* for expressing system configuration, a +*client and server* for distributing it, and a *library* for realizing the +configuration. + +The Puppet Introduction_ covers the basic architecture and design goals, +including whether and why you should be using Puppet on your network. + +.. _Introduction: intro + + +Installation +=============== +There is an `Installation Guide`_ meant for installation of Puppet across a +network. + +There are also complete examples that can be used as a starting point. +`Project WWW`_ is a complete example of a single-node manifest that builds a +web service, and `Project SOHO`_ is a complete example of a networked web +service creator. + +There is also a guide for `using Puppet from source`_, and one for +`testing Puppet`_, to get an idea of what you can do without making a full +deployment. + +.. _installation guide: installation +.. _Project WWW: /svn/manifests/project-www +.. _Project SOHO: /svn/manifests/project-soho +.. _using puppet from source: fromsvn +.. _testing puppet: testing + +The Big Picture +=============== + +It is still somewhat incomplete, there is a `Big Picture`_ document describing +Puppet's general philosophy without focusing on the specific. This is a great +place to start if you're wondering why Puppet exists and what separates it +from other `Configuration Management`_ tools. + +.. _Big Picture: big-picture +.. _Configuration Management: http://config.sage.org + +Command Line Executables +========================== + +This section will eventually have links to full man-pages for each executable, +but for now the man pages can be found by running the respective executable +with the '--help' flag (this requires the Rdoc::usage module, which is +often missing). + +However, most arguments for the executables are in the form of configuration +parameters used internally in the library. All of the executables are +written to accept any of these configuration parameters, and they +are all defined in the `Puppet Executable Reference`_. + +puppet + Stand alone Puppet Site Manifest Script evaluator. Parses, evaluates, + and implements a Site Manifest locally. + +puppetmasterd + Puppet Site Manifest Server Daemon. Runs on each host + serving/providing configurations to Puppet client hosts. + +puppetd + Puppet Client Host Configuration Daemon. Runs on each host whose + configuration is managed by Puppet. Requests a Host Specific Manifest + from a Puppet Manifest Server and implements it locally. + +puppetca + SSL Certificate Authority Server used for receiving cerification + requests from puppet clients. Puppet Client Hosts are required to have + their SSL certs signed by their Puppet Manifest Server's Authority + before they can be authenticated and authorized to recieve + configurations. + +puppetdoc + Command line tool for printing Puppet Default and Local Type Library + reference documentation. This is really only used internally. + +.. _Puppet Executable Reference: puppet-executable-reference + +Type and Language Reference +============================== +The Puppet reference is split into two pieces: + +* `Language Tutorial`_ + + A simple description of how the Puppet language functions, with multiple + examples. + +* `Type Reference`_ + + A reference of all available Puppet Types. The types defined in this + reference represent the total ability of Puppet to manage your system -- if + an object is not in this reference, then Puppet cannot currently manage it. + +* `Language Reference`_ + + A reference to all available language structures within Puppet. This + reference presents the limits of and options for expressibility within + Puppet. + +.. _Language Tutorial: languagetutorial +.. _Type Reference: typedocs +.. _Language Reference: structures + +API Documentation +================= +Until I have time to write tutorials on how to extend Puppet, you might find +some benefit in perusing the `API docs`_. They're woefully incomplete as of +the end of 2005, but I'll be updating them over time. + +.. _api docs: /downloads/puppet/apidocs + +Configuration +================ +Most Puppet configuration is currently done directly through the executables +through the use of command-line flags, although this should largely migrate to +configuration files before 1.0. As such, the man pages for the respective +executables is the appropriate place to look for documentation on +configuration (e.g., ``puppetmasterd`` for serving and ``puppetd`` for the +client). + +There are some guides already, though: + +* `File Serving Configuration`_ + +* `Puppet Certificates and Security`_ + +.. _File Serving Configuration: fsconfigref +.. _Puppet Certificates and Security: security + +Additional Documentation +======================== +While the above links represent the standard, recommended documentation, there +is additional information available for those who are interested: + +* `Example Manifests`_ + +* `Puppet Internals`_ + +* `How Cfengine compares to Puppet`_ + +.. _Example Manifests: /svn/manifests +.. _Puppet Internals: howitworks +.. _How Cfengine compares to Puppet: notcfengine diff --git a/documentation/installation.rst b/documentation/installation.rst new file mode 100644 index 000000000..be60b360b --- /dev/null +++ b/documentation/installation.rst @@ -0,0 +1,304 @@ +Getting the Files +================= + +You will need to install Puppet on all machines that will use it, including +both clients and servers. + +There are packages_ available for some platforms, but for the rest +you will have to install using the tarball_ or GEMs_. + +Prerequisites +------------- +The only prerequisite for Puppet that doesn't come as part of the Ruby +standard library is facter_, which is also developed_ by Reductive Labs. + +All other prerequisites for Puppet are Ruby libraries, and they should all +come with any standard Ruby 1.8.2 install. The other prerequisites, should +your OS not come with the complete standard library, are: + +* ``base64`` +* ``cgi`` +* ``digest/md5`` +* ``etc`` +* ``fileutils`` +* ``ipaddr`` +* ``openssl`` +* ``strscan`` +* ``syslog`` +* ``uri`` +* ``webrick`` +* ``webrick/https`` +* ``xmlrpc`` + +Ruby +'''' +I recommend using whatever Ruby comes with your system, since that's what I've +tested against in most cases and it's most likely to work correctly. If you +feel the particular need to build it manually, you can get the source from +`the Ruby site`_. + + +Red Hat ++++++++ +If you are building on Red Hat (at least on version 3), you +apparently must build it with ``CPPFLAGS=-I/usr/kerberos/include/``, else you +will have all kinds of unreasonable problems (thanks to Mario Martelli for +tracking that one down). + +Solaris ++++++++ +I have had mixed results with the Ruby packages from both Sunfreeware_ and +BlastWave_. It might almost be easier to compile it manually for Solaris, but +Ruby 1.8.3 from Sunfreeware seems to be working right now. + +If you get segfaults, core dumps, or 'library missing ciphers' errors, that is +almost definitely a problem with that specific ruby package, not Puppet or +Ruby itself. + +Debian and Ubuntu ++++++++++++++++++ +The package maintainer for Ruby on these platforms has decided to split +the Ruby standard library into many packages. According to Eric Hollensbe, +this is the package dependency list for Puppet on Debian: + +* ruby +* irb +* ri +* rdoc +* libxmlrpc-ruby +* libopenssl-ruby +* libstrscan-ruby +* libsyslog-ruby +* libwebrick-ruby + +.. _sunfreeware: http://sunfreeware.com +.. _blastwave: http://blastwave.org + +.. _the ruby site: http://ruby-lang.org/ + +Facter +'''''' + +First install facter. Like Puppet, there are packages_ available for +some platforms, but you might have to use the tarball:: + + # get the latest tarball + wget http://reductivelabs.com/downloads/facter/facter-latest.tgz + + # untar and install it + gzip -d -c facter-latest.tgz | tar xf - + cd facter-* + sudo ruby install.rb # or become root and run install.rb + +There are also gems available in the download_ directory. + +Install Puppet +-------------- + +Using the same mechanism, install the puppet libraries and executables:: + + # get the latest tarball + wget http://reductivelabs.com/downloads/puppet/puppet-latest.tgz + + # untar and install it + gzip -d -c puppet-latest.tgz | tar xf - + cd puppet-* + sudo ruby install.rb # or become root and run install.rb + +Alternative: Using RubyGems +----------------------------- +You can also use Reductive Labs' Gems server to install Facter and Puppet:: + + gem install --remote --source http://reductivelabs.com/downloads facter + gem install --remote --source http://reductivelabs.com/downloads puppet + +For more information on RubyGems, see the `Gems User Guide`_. + +Alternative alternative: Native Packages +----------------------------------------- +It is our goal to provide as many native packages as possible, but it's been +slow going. Until I have official native packages, David Lutterkort used spec +and init files from Duane Griffin to create native RPMs that should work on +Red Hat Enterprise 4 and Fedora Core 4. You can get them from his +`yum repository`_. + +There are also `Debian packages`_, although they are not quite as well +maintained as the RPMs. + +.. _yum repository: http://people.redhat.com/~dlutter/yum/ +.. _debian packages: /downloads/packages/Debian + +Building the Server +=================== + +Create Your Site Manifest +------------------------- + +Because the Puppet language is declarative, it does not make as much sense to +speak of "executing" Puppet programs, or to describe them as "scripts". We +choose to use the word *manifest* to describe Puppet programs, and we speak of +*applying* those manifests to the local system. Thus, a *manifest* is a text +document written in the Puppet language and meant to result in a desired +configuration. + +Puppet is written with the assumption that you will have one central manifest +capable of configuring your entire network, which we call the *site manifest*. +You could have multiple, separate site manifests if you wanted, but at this +point each of them would need their own servers. + +For more information on how to create the site manifest, see the +`Language Reference`_ and the `Library Reference`_. + +Puppet will look for your site manifest in ``/etc/puppet/manifests/site.pp``, +so create ``/etc/puppet/manifests`` and add your manifest, along with any +files it includes, to that directory. It is highly recommended that you use +some kind of `version control`_ on your manifests. + +Example Manifests +''''''''''''''''''' +The site manifest can be as simple or as complicated as you want. A good +starting point is to make sure that your sudoers file has the appropriate +permissions:: + + # site.pp + file { "/etc/sudoers": + owner => root, group => root, mode => 440 + } + +If you want to get more complicated, it's a good idea to split your +manifest into multiple files. For instance, you could split it based on +operating systems (e.g., Solaris and Red Hat) and server classes (e.g., +'webserver' and 'logserver'). I also find it useful to have a set of +functions, in an external file included first:: + + # site.pp + + # import the functions + import "functions.pp" + + # import all of the os classes, like redhat.pp and solaris.pp + import "os/*" + + # import all of the server classes, like webserver.pp + import "classes/*" + +Here's an example of a generically useful function I use; it encapsulates the +source of files that I copy from a central server, and just saves a little +typing:: + + # functions.pp + + define remotefile(owner = root, group = root, mode, source, backup = false, recurse = false) { + file { + $name: + mode => $mode, + owner => $owner, + group => $group, + backup => $backup, + source => "puppet://$server/dist/$source" + } + } + +You would use the function like this:: + + remotefile { "/etc/sudoers": + mode => 440, source => "apps/sudo/sudoers" + } + +Start the Central Daemon +------------------------ +Most sites should only need a single central server. Reductive Labs will +soon publish a document describing how to build puppet architectures with +failover capabilities and achitectures that are capable of handling large +loads, but for now only a single server is supported. + +Decide which machine you want to be your central server; this is where you +will be starting ``puppetmasterd``. + +The best way to start any daemon is using your local server's service +management system, often in the form of ``init`` scripts. Eventually Puppet +will ship with an appropriate script for each platform, but in the meantime +you can either create your own, using an existing script as an example, or +simply run without one (not recommended for production environments). + +The daemon should start just fine with no arguments:: + + /usr/bin/puppetmasterd + +It will automatically create all necessary certificates, directories, and +files. If you want the daemon to also function as a file server, so your +clients can copy files from it, you will need to create a +`fileserver configuration file`_. + +If you are still only testing, and do not have node definitions in your +site manifest (such as with the above example manifest) , tell +``puppetmasterd`` not to look for them:: + + /usr/bin/puppetmasterd --nonodes + +Verifying Installation +====================== +To verify that your daemon is working as expected, pick a single client to use +as a testbed. Once Puppet is installed on that machine, run a single client +against the central server to verify that everything is working appropriately. +You should start the first client in verbose mode, with the ``--waitforcert`` +flag enabled:: + + puppetd --server myserver.domain.com --waitforcert 60 --test + +The default server for ``puppetd`` is ``puppet``, so you could just create a +CNAME of that to whatever server is running ``puppetmasterd``. + +Adding the ``--test`` flag here is equivalent to adding ``--verbose --onetime +--no-usecacheonfailure``. This causes ``puppetd`` to stay in the foreground, +print extra output, only run once and then exit, and to just exit if the +remote configuration fails to compile (by default, ``puppetd`` will use a +cached configuration if there is a problem with the remote manifests). + +In running the client, you should see a message that the client did not +receive a certificate (this message will repeat every 60 seconds with the +above command). This is normal, since your server is not autosigning +certificates as a security precaution. On your server, list the waiting +certificates:: + + puppetca --list + +You should see the name of the test client. Now go ahead and sign the +certificate:: + + puppetca --sign mytestclient.domain.com + +Within 60 seconds, your test client should receive its certificate from the +server, receive its configuration, apply it locally, and exit normally. + +Finishing Installation +====================== +There are already init scripts available for some platforms (notably, Red Hat +versions, thanks to David Lutterkort's work on the RPMs_), but for +not-yet-supported platforms, you will need to create an init script that can +start and stop ``puppetd``. The process creates a PID file in its run +directory (``/var/puppet/run``, by default), so you can use that to stop it. + +The process will log to syslog by default. + +Beta Notes +========== +There are some important notes to keep in mind about using the beta of +Puppet: + +* Files are currently automatically reread when they are changed, within a + timeout of 60 seconds. +* Patches are not only welcome, they're encouraged. + +.. _developed: /projects/facter +.. _download: /downloads +.. _version control: http://svnbook.red-bean.com/ +.. _fileserver configuration file: fsconfigref +.. _Gems User Guide: http://docs.rubygems.org/read/book/1 +.. _Language Reference: structures +.. _Library Reference: typedocs + +.. _packages: /downloads/packages +.. _tarball: /downloads/puppet +.. _gems: /downloads/gems +.. _rpms: /downloads/rpm diff --git a/documentation/introduction.rst b/documentation/introduction.rst new file mode 100644 index 000000000..2614b4d46 --- /dev/null +++ b/documentation/introduction.rst @@ -0,0 +1,315 @@ +Introduction +============ +Puppet is a system configuration tool. It has a library for managing the +system, a language for specifying the configuration you want, and a set of +clients and servers for communicating the configuration and other information. + +The library is entirely responsible for all action, and the language is +entirely responsible for expressing configuration choices. Everything is +developed so that the language operations can take place centrally on a single +server (or bank of servers), and all library operations will take place on each +individual client. Thus, there is a clear demarcation between language +operations and library operations, as this document will mention. + +Setup +===== +The vast majority of Puppet architectures will look like a star, with a +central server running `puppetmasterd`, and each client node running +`puppetd`, contacting that central server. Your central manifest, which +contains the configuration for all of your nodes, needs to be on the central +server, most likely at `/etc/puppet/manifests/site.pp`. + +Start the `puppetmasterd` daemon, and then tell your clients to contact that +server by specifying `-s <servername>` as arguments to `puppetd`, replacing +"<servername>" with the name of the server. Alternatively, `puppetd` defaults +to looking for a server named "puppet", so you can just create a CNAME for +your server, so that it answers to "puppet". + +It is a good idea to run both the server and client in verbose mode, enabled +with the `-v` flag, until you are sure everything is working. As each new +client connects, you will need to run `puppetca --list` to list the +certificates waiting to be signed, and then `puppetca --sign <name>`, +replacing "<name>" with the name of the client whose certificate you want to +sign. You can turn on autosigning by creating `/etc/puppet/autosign.conf` and +put the hosts, domains, or IP addresses or ranges that you want to sign in +there. + +Language +======== +The language is declarative, and is modeled somewhat after cfengine's concept +of actions, action instances, and instance parameters. Here is how a file +element would look in puppet:: + + file { "/etc/passwd": + owner => root, + group => root, + mode => 644 + } + +Each instance of a low-level element like ``file`` must have a name parameter +defined, because that is how you uniquely refer to the element you are +managing. Any string that doesn't match ``\w+`` or ``\d+`` needs to be quoted +(e.g., file names). + +There are two ways for types to be available in the language: They'll either +be ``primitive types`` included in the Puppet framework itself, or they'll be +``defined types`` resulting from definitions or server classes. + +Definitions +----------- +Because experience with cfengine showed that objects of different types are +often related, puppet focuses on making creation of associations between +objects of any type easier than making many objects of the same type. The +fundamental unit of association is a 'definition': :: + + # currently, the variables don't have '$' attached in the definition prototype + # this might change + define sudo(source,group) { + package { sudo: + version => "1.6.7" + } + file { "/etc/sudoers": + source => $source, # parameterization; copy the file from where? + mode => 440 # the 'file' type converts this appropriately to + # octal + } + file { "/usr/sbin/sudo": + owner => root, + group => $group + } + } + +A definition has its own scope, so variables defined within it are only +available within the definition itself. + +This definition can now be treated as a type:: + + sudo { + group => root, + source => "http://fileserver/files/sudoers?v=production" + } + +One significant difference between definitions and types is that types +generally have many associated parameters, most of which are optional, while a +given definition will (at this point) always require all parameters. You can +manage as little or as much of a file as you want, for instance, but once you +wrap it in a definition you have to pass every specified parameter to instances +of the definition. + +It is appropriate to think of definitions as declarative functions; referring +to the name of a definition results in the associated declarative code being +executed with the provided parameters. + +I will likely soon add the ability to provide defaults to definition +parameters; any other feature requests are welcome. + +Classes +------- +In addition to definitions, the language supports server classes. At this +point, the only syntactical or functional difference between the two is that +server classes can have a parent class:: + + class base { + sudo { ... } # an existing definition + } + + class server inherits base { + ssh { ... } # an existing definition + } + + if $hostname == "myhost" { + server{} # the braces are mandatory at this point + } elsif $hostname == "otherhost" { + base{} + } + +The classes also support parameterization, just like definitions. Notice that +the mechanism for associating nodes with servers is stupid. I considered the +following syntax:: + + node host { + server {} + } + +But that doesn't seem much better. Again, recommendations are accepted. + +Having a parent class means that that parent's objects are all operated on +before any of the subclass's are. So, in this case, each member of 'server' +would first verify 'sudo' is set up correctly and then check 'ssh'. + +Variables +--------- +Because it is assumed that strings will be used far more than variables, simple +strings don't have be quoted or otherwise marked, but variables must have the +``$`` attached:: + + $group = "root" + + file { "/etc/sudoers": + group => $group + } + +Strings and booleans (``true`` and ``false``) are the only data types; even +numbers are converted to strings. Arrays are supported, although their +behaviour has not been characterized for all cases. One particular use of +arrays is for implicit iteration:: + + $files = ["/etc/passwd","/etc/group","/etc/fstab"] + + file { $files: + owner => root, + group => root + } + +This implicitly iterates across the file list and performs all of the +appropriate checks. + +Currently, ``puppet`` collects as much information as it can (using the +``Facter`` library) and sets all of it as top-level variables. So, you can +expect variables like ``$operatingsystem`` and ``$ipaddress``. + +Also, because ``puppet`` is a declarative language, reassigning a variable +within the same scope is currently an error. The language is written such that +this could be disabled (please let me know if you need this feature), but it is +currently always enabled. You can override defaults in a lower scope:: + + $var = default + + define test { + $var = override + ... + } + +It is expected that parameter passing to definitions will be the primary +mechanism for variable assignment, so it seems unlikely that this limitation +will cause much trouble. + +Importing +--------- +Files can be imported using the ``import`` command:: + + import "filename" + +There is currently no search path or anything; files are looked for in the same +directory as the file doing the importing. Each file should have its own +lexical scope, but I haven't yet figured out how to do that. + +Control Structures +------------------ +There are currently two basic control structures, one meant to return a value +and the other just a normal 'if/elsif/else' structure. + +Selectors ++++++++++ +One of the primary goals of Puppet is to simplify building a single +configuration that works across multiple machines and machine classes. One +mechanism for this is currently called a 'selector'; it is similar to the +trinary operator ``:?``:: + + $value = $variable ? { + value1 => setvalue1, + value2 => setvalue2, + default => other + } + +This sets the variable ``$value`` depending on the value of ``$variable``. If +it is ``value1``, then ``$value`` gets set to ``setvalue1``, else the value +gets set to ``other``. + +The brackets can be in either part of the expression, or not at all:: + + $value = $variable ? "value1" => "setvalue1" + +A selector that doesn't match a value is a compile error. + +These structures are useful for simplistic abstraction across platforms:: + + file { "/etc/sudoers": + owner => root, + group => $operatingsystem ? { + SunOS => root, + Linux => root, + FreeBSD => wheel + } + } + +If +++ +Puppet currently supports a normal If/Elsif/Else structure, and each statement +introduces a new lexical scope. Things that can be tested are currently +extremely limited (just simple comparisons, e.g., '==', '<=', etc.); it should +be easy to add &&, ||, and parentheticals for extended tests, but I don't yet +know how I'll handling testing more complex expressions. + +I expect that this structure will go away, to be replaced with a more +declarative structure. + +Library +======= +This section discusses some aspects of the internals of the Puppet library. +This information can be useful but is not critical for use and understanding +of Puppet. + +The library is composed of two fundamental types of objects: Types and states +(yes, the terminology is atrocious). States are things that can be configured +to change one aspect of an object (e.g., a file's owner), types are essentially +named collections of states. So, there is a File type, and it is a collection +of all of the states available to modify files. + +In addition to states, which necessarily modify 'the bits on disk', as it were, +types can also have non-state parameters which modify how that type instance +behaves:: + + file { "/bin": + owner => bin, + recurse => true + } + +The ``recurse`` parameter to ``file`` does not modify the system itself, it +modifies how the ``file`` type manages ``/bin``. + +Not all types as expressed in the language are types defined in the library; +some language types are actually definitions or server classes. Types that +are defined in the language itself are termed ``primitive types`` or just +``primitives``, and types that generate other types are termed ``metatypes``. + +At this point, all types have a unique name (within the current scope, but it +probably should actually be global). This name is set using a class instance +variable: :: + + # in the library + class Mytype < Puppet::Type + @name = :mytype + ... + end + + # in the language + mytype { "yay": ... } + +The states similarly have unique names, although this uniqueness is only +per-type. When a type is defined, all states and parameters are also listed as +class instance variables; states are listed by class, and parameters with +symbols. Here is the File type declaration: :: + + @states = [ + Puppet::State::FileCreate, + Puppet::State::FileUID, + Puppet::State::FileGroup, + Puppet::State::FileMode, + Puppet::State::FileSetUID + ] + + @parameters = [ + :path, + :recurse + ] + +Puppet::Type gets notified of a subclass, and it iterates over the states +retrieving each name and making a hash from the name to the class. + +Lastly, each type must either provide a state or parameter of ':name', or it +must set '@namevar' so that the system knows what is considered the name: :: + + @namevar = :path + +With this declaration, ``file { "/tmp/file": }`` is basically equivalent to ``file { path => "/tmp/file" }``. diff --git a/documentation/languagetutorial.rst b/documentation/languagetutorial.rst new file mode 100644 index 000000000..018eb4151 --- /dev/null +++ b/documentation/languagetutorial.rst @@ -0,0 +1,150 @@ +Elements and Organization +========================= +The entire purpose of the Puppet language is to result in Puppet elements that +directly model elements on each client being managed. Because different +clients have different lists of elements, and some clients vary in the +configuration of specific elements, Puppet's language supports various +abstraction, selection, and overriding capabilities. + +Naming +============= +For simple elements, we just specify the element type, name, and parameters:: + + file { "/etc/passwd": + owner => root, + group => root, + mode => 644 + } + +Any machine on which this snippet is executed will use it to verify that the +``passwd`` file is configured as specified. The Puppet language treats the +field before the colon as the name of the object, so in this case the name is +``/etc/passwd``, which works fine for this file since both the path and the +details are essentially always the same on all systems. + +For files that vary across systems, it makes sense to create a *symbolic name* +for your element:: + + file { sshdconfig: + path => $operatingsystem ? { + solaris => "/usr/local/etc/ssh/sshd_config", + default => "/etc/ssh/sshd_config" + }, + owner => root, + group => root, + mode => 644 + } + +Here we create a symbolic name instead of using the path as the name, and now +we can refer to that element by name elsewhere in the manifest:: + + service { sshd: + subscribe => file[sshdconfig] + } + +This will cause the ``sshd`` service to get restarted when the ``sshdconfig`` +file changes. + +It's important to note here that the language doesn't actually know anything +about the objects it is managing; it knows the name and the type, and it has a +list of parameters, but those parameters mean nothing in the language. If you +provide a symbolic name to a given element, you should always use that single +name, because otherwise the language will assume you are managing separate +elements, which might result in an error in the library:: + + file { sshdconfig: + path => "/usr/local/etc/ssh/sshd_config", + owner => root + } + + file { "/usr/local/etc/ssh/sshd_config": + owner => sshd + } + +The Puppet parser does not know that these element specifications will attempt +to manage the same element, because they have different names. This will +result in an error on the client when the second element tries to instantiate +and it is found to conflict with the first element. + +Assignment +========== +Puppet has a declarative language, which means that its scoping and assignment +rules are somewhat different than a normal imperative language. The primary +difference is that you cannot change the value of a variable within a single +scope, because that would rely on file order to determine the value of the +variable. This will result in an error:: + + $user = root + file { "/etc/passwd": + owner => $user + } + $user = bin + file { "/bin": + owner => $user, + recurse => true + } + +You will almost always find that you can avoid resetting variable values using +the builtin conditionals_:: + + $group = $operatingsystem ? { + solaris => sysadmin, + default => wheel + } + +This is only one assignment, so no errors. + +Overriding +========== +Puppet provides a separate scope for every class and component, and scope +trees are created as a manifest is parsed. Take the following configuration:: + + class base { + file { "/etc/issue": + source => "puppet://server/module/common/issue" + } + } + + class sub inherits base { + file { "/etc/issue": + source => "puppet://server/module/mysite/issue" + } + } + +This creates two distinct scopes, one for each class. The ``sub`` class +overrides the specification of ``/etc/issue``, because it's in a lower scope, +and when this manifest is applied, the latter location is used as the source +for the file. This allows you to subclass a class and slightly change its +behaviour. + +Defaults +======== +Puppet elements are normally specified using a lower-case element type. You +can specify default values for a given type using the capitalized form of the +element type, though:: + + Exec { path => "/usr/bin:/bin:/usr/sbin:/sbin" } + + import "classes/*.pp" + + node mynode { + include $operatingsystem + } + +The first statement in this snippet provides a default value for 'exec' +elements, which require either fully qualified paths or a path in which to +look for the executable. This way you can specify a single default path for +your entire configuration, and then override that value as necessary. + +This can be used for any element type. For instance, CentOS defaults to using +``rpm`` for its package type, but you can easily change that to ``yum``:: + + case $operatingsystem { + centos: { + Package { type => yum } + } + } + + ... + +.. _conditionals: /projects/puppet/documentation/structures#conditionals diff --git a/documentation/notcfengine.rst b/documentation/notcfengine.rst new file mode 100644 index 000000000..1fb3ba002 --- /dev/null +++ b/documentation/notcfengine.rst @@ -0,0 +1,220 @@ +Cfengine_ is currently the most widely deployed configuration management tool. +In many ways, Puppet_ can be thought of as a next-generation version of +cfengine, in that many of puppet's design goals are specifically derived from +experience with cfengine and are meant to overcome many of cfengine's +weaknesses. + +This document summarizes the primary advances that Puppet makes over +cfengine's current state. + +Abstraction +----------- +Cfengine is a great way to scale common administrative practices -- you can +move from using SSH and a for loop to using Cfengine pretty smoothly. +However, there is just as much complexity present in either form. You still +have to handle file contents, and you still have to manage operating system +differences yourself -- you have to know whether it's ``useradd`` or +``adduser``, whether it's ``init`` or Sun's ``SMF``, and what the format of the +filesystem tab is. + +Puppet's primary goal is to provide enough abstraction so that you do not have +to know those details. You can speak in terms of users, services, or +filesystems, and Puppet will translate them to the appropriate commands on +each system. Puppet administrators are free to focus on the complexity of +their networks, rather than being forced to also handle that complexity plus +the complexity of the differences between the operating systems. + +Dedication +---------- +Puppet will be supported by an organization dedicated to creating +the best system automation software, and I expect to have a staff of at +least a few people dedicated to development, support, consulting, and custom +development. Constrast this with cfengine, which is supported by a professor +whose primary use for the software is in research into anomalies. + +Cfengine's author is only now starting to invest on community involvement in +its development; while its author has always accepted patches from the +community, he has been hesitant to provide standard project features like a +version repository and a bug database and as a result cfengine's large user +base has not resulted in a large development community. + +Because Reductive Labs is a commercial enterprise dependent on customer +satisfaction for its survival, our customers will have a large say in how best +to develop Puppet, and we'll be doing everything we can to develop a strong +community just as dedicated to Puppet and server automation as we are. Our +goal is also to have multiple developers dedicated full time to Puppet +development, which should significantly accelerate feature development +compared to cfengine. + +Language Power +-------------- +While the two languages are superficially similar, the puppet language already +supports two critical features that cfengine forces you to hack around. +Puppet supports building higher level objects out of a set of low-level +objects including the ability to parameterize, and has a built-in ability to +express relationships between objects. For instance, here is how you might +define an 'apache' component:: + + define apache(docroot,htmlsource,configfile) { + # make sure the package is installed + package { apache: version => "2.0.51", installed => true } + + # pull down the data to serve + file { $docroot: source => $htmlsource } + + # and the config file + file { "/etc/apache/httpd.conf": source => $configfile } + + # restart the apache service if the package is reinstalled or if + # the config file changes; notice no need for 'define' statements + # or AddInstallable calls + service { apache: running => true, + requires => [ package[apache], file["/etc/apache/httpd.conf"] ] + } + } + + # You could now have different versions of this: + + apache { + docroot => "/var/wwwprod", + htmlsource => "nfs://fileserver/web/wwwprod", + configfile => "https://webserver/web/prod.conf" + } + + apache { + docroot => "/var/wwwdev", + htmlsource => "http://tmpserver/web/wwwdev", + configfile => "https://webserver/web/dev.conf" + } + +This simple level of abstraction already puts you far beyond what cfengine +can do. The initial goal is to provide ample power to express the true +complexity of a network configuration, but just as importantly we want to +support code sharing. There has been essentially zero success in sharing +configurations within the cfengine community because of how difficult basic +abstraction is with cfengine, so one of my primary goals with the language was +to make abstraction, within a network or across one, downright easy. + +Decoupling +---------- +Puppet is being written with all components decoupled from each other, using +clean and preferably industry-standard interfaces between them. Adding a new +action to cfengine requires modification of the entire functional stack +from the lexer and parser through to the backing library, while adding a new +type to Puppet can be as simple as dropping a ruby script into the right +directory. + +Puppet also uses the industry-standard XMLRPC protocol for communication +between Puppet clients and servers, so the protocol is easy to study and +either end could be replaced by another service if desired. + +Interactivity +------------- +Puppet is being designed to make it easy to get information back +out of it. For instance, it will be easy to figure out how many changes +happened on a given node, even in a given time frame and of a given type, +without having to parse log files or something. When puppet +ships, it will ship with a small add-on that will automatically graph all +of this info in RRD files so that you can just enable this and +automatically get graphs of change rates on your network. + +Development Methodology +----------------------- +Reductive Labs is a big believer in enhancing developer productivity. Puppet +is being written in Ruby because it is a high-level language that is easy to +use yet provides significant productivity enhancements over low-level +languages like C. Reductive Labs also strongly believes that unreadable code +is bad code; if you can't easily follow a code path in Puppet, then you've +found a bug. Lastly, we assiduosly unit test our code. We're always looking +for more ways to test our code, and every bug we quash gets turned into a unit +test so we know we'll never release that bug again. + +Examples +-------- +I've got some small configurations that exemplify some of the differences. +Here's how a simple centralized Apache configuration would look in the two +languages, for instance. The two manifests just download Apache's +configuration from a central server, restarting Apache if the files change at +all, and also making sure that Apache is always running. + +Here's how it looks in puppet:: + + # This would normally be in a separate file, e.g., classes/apache.pp + class apacheserver { + # Download the config from a central $server + file { "/etc/apache": + source => "puppet://server.domain.com/source/apache", + recurse => true, + owner => root, + group => root + } + + # Check that apache is running, and mark it to restart if + # the config files change + service { apache: + running => true, + subscribe => file["/etc/apache"] + } + } + + # Node "nodename" is an apache server + node nodename { + include apacheserver + } + +And here's how the same configuration looks in cfengine:: + + control: + # this class is necessary later + AddInstallable = ( restart_apache ) + + groups: + # Mark which nodes are apache servers + apacheserver = ( nodename ) + + # copy the files down from the central server, setting 'restart_apache' + # if any files changed + copy: + apacheserver:: + /source/apache + dest=/etc/apache server=$(server) owner=root group=root + define=restart_apache + + # Make sure the process is running + processes: + apacheserver:: + "apache" restart "/etc/init.d/apache startssl" + + # restart apache if the appropriate class is set + shellcommands: + apacheserver.restart_apache:: + "/etc/init.d/apache restart" + +There are a few specific items worth noting in this comparison: + +* The cfengine configuration is a bit inside out, in that each + statement has to mention the class associated with the work in question + (assuming you have multiple classes in your configuration). This encourages + you to organize your configuration based on the type of work being done + (e.g., copying or shellcommands), rather than the reason you're doing the + work (i.e., it's all for the Apache server). + +* The cfengine configuration uses the dynamically defined class + 'restart_Apache' to mark the relationship between the Apache configuration + files and the running Apache process, rather than allowing you to just + directly specify a relationship. + +* The cfengine configuration also separates the management of the Apache + process into two statements, one for starting if it happens to not be + running and one for restarting if the files change, whereas Puppet is able + to handle both functions in one statement. + +* The cfengine configuration requires at least two forward references (that + is, references to portions of the configuration that are further on). The + 'restart_apache' class must be set as 'AddInstallable' before it is used + anywhere, and the 'apacheserver' class must be set before any code is + associated with it. Neither of these is a big deal in small doses, but it + can get quite complicated as the configuration matures. + +.. _cfengine: http://www.cfengine.org +.. _puppet: /projects/puppet diff --git a/documentation/puppetd-executable-reference.rst b/documentation/puppetd-executable-reference.rst new file mode 100644 index 000000000..bfed7e856 --- /dev/null +++ b/documentation/puppetd-executable-reference.rst @@ -0,0 +1,289 @@ +=========================== +Puppet Executable Reference +=========================== + +Every Puppet executable (with the exception of ``puppetdoc``) accepts all of +these arguments, but not all of the arguments make sense for every executable. +Each argument has a section listed with it in parentheses; often, that section +will map to an executable (e.g., ``puppetd``), in which case it probably only +makes sense for that one executable. If ``puppet`` is listed as the section, +it is most likely an option that is valid for everyone. + +This will not always be the case. I have tried to be as thorough as possible +in the descriptions of the arguments, so it should be obvious whether an +argument is approprite or not. + +* **autosign** (*ca*) + + Whether to enable autosign. Valid values are true (which autosigns any key request, and is a very bad idea), false (which never autosigns any key request), and the path to a file, which uses that configuration file to determine which keys to sign. + +* **bucketdir** (*filebucket*) + + Where FileBucket files are stored. + +* **ca_days** (*ca*) + + How long a certificate should be valid. + +* **ca_md** (*ca*) + + The type of hash used in certificates. + +* **cacert** (*ca*) + + The CA certificate. + +* **cadir** (*ca*) + + The root directory for the certificate authority. + +* **cakey** (*ca*) + + The CA private key. + +* **capass** (*ca*) + + Where the CA stores the password for the private key + +* **caprivatedir** (*ca*) + + Where the CA stores private certificate information. + +* **capub** (*ca*) + + The CA public key. + +* **certdir** (*certificates*) + + The certificate directory. + +* **classfile** (*puppetd*) + + The file in which puppetd stores a list of the classes associated with the retrieved configuratiion. Can be loaded in the separate ``puppet`` executable using the ``--loadclasses`` option. + +* **color** (*puppet*) + + Whether to use ANSI colors when logging to the console. + +* **confdir** (*puppet*) + + The main Puppet configuration directory. + +* **config** (*puppetdoc*) + + The configuration file for puppetdoc. + +* **csrdir** (*ca*) + + Where the CA stores certificate requests + +* **fileserverconfig** (*fileserver*) + + Where the fileserver configuration is stored. + +* **genconfig** (*puppet*) + + Whether to just print a configuration to stdout and exit. Only makes sense when used interactively. Takes into account arguments specified on the CLI. + +* **genmanifest** (*puppet*) + + Whether to just print a manifest to stdout and exit. Only makes sense when used interactively. Takes into account arguments specified on the CLI. + +* **group** (*puppetmasterd*) + + The group puppetmasterd should run as. + +* **httplog** (*puppetd*) + + Where the puppetd web server logs. + +* **ignoreschedules** (*puppetd*) + + Boolean; whether puppetd should ignore schedules. This is useful for initial puppetd runs. + +* **keylength** (*ca*) + + The bit length of keys. + +* **ldapattrs** (*ldap*) + + The LDAP attributes to use to define Puppet classes. Values should be comma-separated. + +* **ldapbase** (*ldap*) + + The search base for LDAP searches. It's impossible to provide a meaningful default here, although the LDAP libraries might have one already set. Generally, it should be the 'ou=Hosts' branch under your main directory. + +* **ldapnodes** (*ldap*) + + Whether to search for node configurations in LDAP. + +* **ldapparentattr** (*ldap*) + + The attribute to use to define the parent node. + +* **ldappassword** (*ldap*) + + The password to use to connect to LDAP. + +* **ldapport** (*ldap*) + + The LDAP port. Only used if ``ldapnodes`` is enabled. + +* **ldapserver** (*ldap*) + + The LDAP server. Only used if ``ldapnodes`` is enabled. + +* **ldapstring** (*ldap*) + + The search string used to find an LDAP node. + +* **ldapuser** (*ldap*) + + The user to use to connect to LDAP. Must be specified as a full DN. + +* **localconfig** (*puppetd*) + + Where puppetd caches the local configuration. An extension indicating the cache format is added automatically. + +* **lockdir** (*puppet*) + + Where lock files are kept. + +* **logdir** (*puppet*) + + The Puppet log directory. + +* **manifest** (*puppetmasterd*) + + The entry-point manifest for puppetmasterd. + +* **manifestdir** (*puppetmasterd*) + + Where puppetmasterd looks for its manifests. + +* **masterhttplog** (*puppetmasterd*) + + Where the puppetmasterd web server logs. + +* **masterlog** (*puppetmasterd*) + + Where puppetmasterd logs. This is generally not used, since syslog is the default log destination. + +* **masterport** (*puppetmasterd*) + + Which port puppetmasterd listens on. + +* **mkusers** (*puppet*) + + Whether to create the necessary user and group that puppetd will run as. + +* **noop** (*puppetd*) + + Whether puppetd should be run in noop mode. + +* **paramcheck** (*ast*) + + Whether to validate parameters during parsing. + +* **parseonly** (*puppetmasterd*) + + Just check the syntax of the manifests. + +* **passfile** (*certificates*) + + Where puppetd stores the password for its private key. Generally unused. + +* **privatedir** (*certificates*) + + Where the client stores private certificate information. + +* **privatekeydir** (*certificates*) + + The private key directory. + +* **publickeydir** (*certificates*) + + The public key directory. + +* **puppetdlockfile** (*puppetd*) + + A lock file to temporarily stop puppetd from doing anything. + +* **puppetdlog** (*puppetd*) + + The log file for puppetd. This is generally not used. + +* **puppetport** (*puppetd*) + + Which port puppetd listens on. + +* **req_bits** (*ca*) + + The bit length of the certificates. + +* **rrddir** (*metrics*) + + The directory where RRD database files are stored. + +* **rrdgraph** (*metrics*) + + Whether RRD information should be graphed. + +* **rundir** (*puppet*) + + Where Puppet PID files are kept. + +* **runinterval** (*puppetd*) + + How often puppetd applies the client configuration; in seconds + +* **serial** (*ca*) + + Where the serial number for certificates is stored. + +* **server** (*puppetd*) + + The server to which server puppetd should connect + +* **signeddir** (*ca*) + + Where the CA stores signed certificates. + +* **ssldir** (*puppet*) + + Where SSL certificates are kept. + +* **statedir** (*puppet*) + + The directory where Puppet state is stored. Generally, this directory can be removed without causing harm (although it might result in spurious service restarts). + +* **statefile** (*puppet*) + + Where puppetd and puppetmasterd store state associated with the running configuration. In the case of puppetmasterd, this file reflects the state discovered through interacting with clients. + +* **tags** (*transaction*) + + Tags to use to find objects. If this is set, then only objects tagged with the specified tags will be applied. Values must be comma-separated. + +* **typecheck** (*ast*) + + Whether to validate types during parsing. + +* **usecacheonfailure** (*puppetd*) + + Whether to use the cached configuration when the remote configuration will not compile. This option is useful for testing new configurations, where you want to fix the broken configuration rather than reverting to a known-good one. + +* **user** (*puppetmasterd*) + + The user puppetmasterd should run as. + +* **vardir** (*puppet*) + + Where Puppet stores dynamic and growing data. + + + +---------------- + + +*This page autogenerated on Tue Apr 11 18:37:26 CDT 2006* diff --git a/documentation/rails-puppet-manager.rst b/documentation/rails-puppet-manager.rst new file mode 100644 index 000000000..6cc0b6b8c --- /dev/null +++ b/documentation/rails-puppet-manager.rst @@ -0,0 +1,64 @@ +I have begun work on a simplistic web-based Puppet manager based on Rails_, +called PuppetShow. It's in a very primitive state -- including having no +authentication, so use at your own risk -- but it's a good proof of concept. + +To get it working, first check out the code_. Then set up your apache config +to serve it. This is what mine looks like:: + + <VirtualHost 192.168.0.101:80 192.168.0.102:80 192.168.0.3:80> + ServerAdmin luke@madstop.com + SetEnv RAILS_ENV development + ServerName puppet.madstop.com + ServerAlias puppet + DocumentRoot /var/lib/puppetshow/public + ErrorLog /var/lib/puppetshow/log/apache.log + + <Directory /var/lib/puppetshow/public/> + Options ExecCGI FollowSymLinks + AddHandler cgi-script .cgi + AllowOverride all + Order allow,deny + Allow from all + </Directory> + </VirtualHost> + +Now we just need to get the puppet internal stuff working. We could use +either ``rake`` or Puppet to do this, but for whatever reason I decided to use +Puppet. I've created a ``setup.pp`` file in the root of the tree, so you just +need to modify that as appropriate (in particular, I have a Facter lib that +sets ``$home`` for me, so you'll probably need to set that), then run:: + + sudo puppet -v setup.pp + +At that point you should have a functional app. Like I said, there's no +navigation at all, so you need to know what's out there. The first thing you +need to do is start a daemon that this app can connect to. Pick your victim, +create a namespace auth file (defaults to +``/etc/puppet/namespaceauth.conf``):: + + [fileserver] + allow *.madstop.com + + [puppetmaster] + allow *.madstop.com + + [pelementserver] + allow puppet.madstop.com + +Then start your client:: + + puppetd -v --listen --no-client + +Here we're telling it to start the listening daemon but not to run the config. +You can obviously use whatever options you want, though. + +Now you should be able to just go to your app. At this point, you need to +know the name of the machine you want to connect to and the name of a type to +look at. Say you're connecting to culain (my workstation's name), and you +want to look at users; this would be your URL: +http://puppet.domain.com/remote/culain/user/list + +Replace as appropriate for your site. + +.. _rails: http://rubyonrails.org +.. _code: https://reductivelabs.com/svn/puppetshow diff --git a/documentation/security.rst b/documentation/security.rst new file mode 100644 index 000000000..19c72b929 --- /dev/null +++ b/documentation/security.rst @@ -0,0 +1,59 @@ +Overview +======== +Puppet relies on standards wherever possible. In the case of security, it uses +standard SSL certificates for client and server verification. Because of the +cost of buying signed certificates for every client and the complexity of +managing your own certificate authority (CA), Puppet includes its own CA. +This CA has been optimized for use with Puppet but could also be used to +generate certificates for other purposes. The primary goal in certificate +management within Puppet has been to keep it simple, and wherever possible to +not make it even noticeable. + +Certificates +============ + +Authentication +-------------- +Certificates are the only method of authentication -- if a client's +certificate can be verified using standard SSL verification mechanisms, then +it is considered authenticated. + +Client Certificate Generation +----------------------------- +The Puppet server, ``puppetmasterd``, is normally also the CA. Clients who +do not yet have signed certificates will automatically generate a key pair and +a certificate request, and then will connect to the server and provide it +with the certificate request. If the server has ``autosign`` turned on (which +is not necessarily recommended), then the autosign configuration file (which +defaults to ``/etc/puppet/autosign.conf``) is checked for whether the client's +name matches any contents. For instance, take the following configuration +file:: + + hostname.domain.com + *.secure.domain.com + +This configuration would autosign certificate requests for +``hostname.domain.com`` and any hosts coming from ``*.secure.domain.com``. + +This configuration file is read each time a signature is asked for, so changes +to it can be short-lived and will be immediately noticed. + +Server-Side Certificate Management +---------------------------------- +In the normal case, certificate auto-signing will be disabled. In these +cases, certificates will have to be signed using the ``puppetca`` utility. +Prior to the 1.0 release it is expected that there will be email notification +of certificate requests waiting to be signed, but for now either the logs +must be watched or ``puppetca --list`` can be used list waiting requests. + +Once a request arrives, ``puppetca --sign <hostname>`` can be used to sign the +request. Adding the ``--all`` flag will sign all outstanding requests. + +Access and Authorization +======================== +Puppet currently has few network functions, so security has so far been +treated by them individually. It is expected that there will be some +system-wide security hooks prior to the 1.0 release, but the certificate +authentication already provides significant security. + +Recommendations on approaches are heartily recommended. diff --git a/documentation/structures.rst b/documentation/structures.rst new file mode 100644 index 000000000..1c5818d5b --- /dev/null +++ b/documentation/structures.rst @@ -0,0 +1,322 @@ +This is a brief overview of the language structures +available for making site configurations in Puppet. +For futher documentation, visit the `Puppet homepage`_. + +.. _puppet homepage: /projects/puppet + +Types +----- +The basic unit of configuration in Puppet are ``types``. Types model objects +on the computer being managed, and each builtin type has attributes that +determine the final type configuration:: + + file { "/etc/passwd": owner => root, mode => 644 } + package { apache: install => true } + +Puppet also provides facilities for defining new types as collections of +existing types (see Components_ below), but there is no syntactic difference +between using builtin types like ``file`` and ``package`` and using defined +types. Any operation or syntax that succeeds for builtin types should also +work for defined types. + +See the `Type Reference`_ for the documentation for the +Puppet Library's primitive types. + +Assignment +----------- + +``$variable = value`` + +Variables available in the current scope are referenced +by preceding them with the ``$`` character. + +Once assigned, variables cannot be reassigned. However, +within a sub-scope a new assignment can be made for a +variable name for that sub-scope and any further +sub-scopes created within it:: + + $x = foo + $y = bar + $z = "$x$y" + +Bringing Config files together +------------------------------ + +:: + + import "filename" + +Starts the parsing of the file specified and creates any specified definitions +and classes at the current scope. Currently files are only searched for +within the same directory as the file doing the importing. + +Files can also be imported using globbing, as implemented by Ruby's +``Dir.glob`` method:: + + import "classes/*" + import "packages/[a-z]*" + +Scope +----- + +Generally speaking, any language structure that involves curly braces creates +a new scope inside those braces. This currently includes server and class +definitions and if/then/else structures. Each file should also introduce its +own scope but currently does not. + +Once assigned, variables cannot be reassigned within the same scope. However, +within a sub-scope a new assignment can be made for a variable name for that +sub-scope and any further scopes created within it:: + + $var = value + + # override $var + define testing { + $var = othervalue + } + +Service and class definitions are scoped just as variable assignments are. +Functions defined and Classes created within a scope will not be available +outside the scope in which they are created:: + + define testing { + file { "/etc/passwd": owner => root } + } + + class osx { + # override the existing testing definition + define testing { + file { "/etc/other": owner => root } + } + } + +The evaluation by Puppet of following example would be result in the copying +of ``/file_repository/test-httpd.conf`` to ``/etc/httpd/conf/httpd.conf``:: + + $filename = "/etc/apache/httpd.conf" + + class webserver { + $filename = "/etc/httpd/conf/httpd.conf" + define httpd_service (config_file) { + file { $filename : source => $config_file } + } + httpd_service { "test_httpd" : + config_file => "/file_repository/test-httpd.conf" + } + } + + webserver {} + +Components +---------- + +``define <name>(<param1>,<param2>,...) {...}`` + +Definition of fuctions allows the composition of lower level types into higher +level types. + +Parameters of defined functions can be referenced within the definition scope, +similarly to variables, by preceding their names with the ``$`` character:: + + define svnserve(source, path, user = false, password = false) { + file { $path: + create => directory, + owner => root, + group => root + } + $svncmd = $user ? { + false => "/usr/bin/svn co --non-interactive $source/$name .", + default => "/usr/bin/svn co --non-interactive --username $user --password '$password' $source/$name ." + } + exec { $svncmd: + cwd => $path, + require => file[$path], + creates => "$path/.svn" + } + } + + svnserve { dist: + source => "https://reductivelabs.com/svn", + path => "/dist", + user => "puppet", + password => "password" + } + + svnserve { "dist/config/apps/puppet": + source => "https://reductivelabs.com/svn", + path => "/etc/puppet", + user => "puppet", + password => "password" + } + +Note that calling components results in a unique instance of all contained +objects. In the above case, each of the calls to ``svnserver`` results in an +``exec`` and a ``file`` instance. So, it's important that all of your +components are written that they support this. + +A good rule of thumb is that you should only include statements in your +components that have variables in their names. If a statement doesn't +have a variable in the name, then you are likely to result in a situation +where multiple components will try to manage the same instance, which will +result in an error at run time. + +Server Classes +-------------- + +``class <class_name> [inherits <super_class_name>] { ... }`` + +Class definitions allow the specification of a hierarchy of server classes; a +host that is a member of a subclass will apply the configuration from the +subclass and all parent classes. The primary difference between classes and +components is that classes are singletons -- there will only ever be a single +instance of a given class on a given server. Thus, if you have a server which +is a member of three different classes, each of which share the same parent +class, then you will get one instance of the parent class and one instance of +each of the subclasses. + +:: + + # really simple example + class solaris { + file { + "/etc/passwd": owner => root, group => root, mode => 644; + "/etc/shadow": owner => root, group => root, mode => 440 + } + } + + class solworkstation inherits solaris { + file { + "/etc/sudoers": owner => root, group => root, mode => 440; + "/bin/sudo": owner => root, group => root, mode => 4111 + } + } + + include solworkstation + +The ``include`` syntax is syntactically equivalent to specifying a class +with no arguments. The above statement is equivalent to this statement:: + + solworkstation {} + +Subclassing ++++++++++++ +The primary benefit of using subclasses instead of just including the parent +class is that the subclass can override elements in the parent class:: + + class unix { + file { "/etc/sudoers": + owner => root, + group => root, + mode => 440 + } + } + + class bsd inherits unix { + file { "/etc/sudoers": + group => wheel + } + } + +Including the ``unix`` class sets the group to ``root``, but including the +``bsd`` class overrides the vale to ``wheel``. + +Using Classes Outside of Puppet ++++++++++++++++++++++++++++++++ +This isn't really a "language" thing, but it seemed the best place to document +this. + +All classes set on a Puppet client are stored in an external file (usually +``/etc/puppet/classes.txt``, but can be modified with the ``classfile`` +argument or setting). This means other tools can easily read in the classes +that Puppet sets and use them for their own logic. + +There is also (as of 0.15.4) a new command to set arbitrary classes that do +not have any code associated with them:: + + class freebsd { + tag unix, bsd + } + + class redhat { + tag unix, sysv + } + +These classes will then be written to the classes.txt file like all others, +even though there is no code associated with them. The syntax is just like +``include``, so you can use variables, also:: + + tag $operatingsystem + +Nodes +----- + +``node <hostname> { ... }`` + +Node definitions specify the configuration to apply to a specific node. By +default they are looked for by ``puppetmasterd`` but not by ``puppet``. See +the documentation for each to enable or disable them. + +Any code outside of a node definition will be applied to all nodes, while any +code inside will only apply to the specified node or nodes:: + + class webserver { ... } + class dbserver { ... } + + file { "/etc/sudoers": mode => 440 } # apply to everyone + + node host1, host2 { + include webserver + } + node host3, host4 { + include dbserver + } + +Nodes can also inherit from other nodes, so it's easy to apply defaults:: + + node base { + include $operatingsystem + } + + node kirby inherits base { + include webserver + } + +Conditionals +------------ +Puppet currently supports two types of conditionals: in-statement and around +statements. We call the in-statement conditionals ``selectors``, as they are +essentially a select-style operator, which support the use of ``default`` to +specify a default value:: + + define testing(os) { + owner = $os ? { + sunos => adm, + redhat => bin, + default => root + } + file { "/some/file": owner => $owner } + } + + + +``case`` provides the ability to conditionally apply +types:: + + case $operatingsystem { + sunos: { solaris {} } # apply the solaris class + redhat: { redhat {} } # apply the redhat class + default: { generic {} } # apply the generic class + } + +Reserved words +-------------- +Generally, any word that the syntax uses for special meaning is probably also +a reserved word, meaning you cannot use it for variable or type names. Thus, +words like ``true``, ``define``, ``inherits``, and ``class`` are all reserved. + +Comments +-------- +Puppet supports sh-style comments; they can either be on their own line or at +the end of a line (see the Conditionals_ example above). + +.. _type reference: /projects/puppet/documentation/typedocs diff --git a/documentation/testing.rst b/documentation/testing.rst new file mode 100644 index 000000000..fb0a1a870 --- /dev/null +++ b/documentation/testing.rst @@ -0,0 +1,82 @@ +If you want to just test-drive Puppet, making the least commitment possible, +you can run it directly from the checked-out source_, against a configuration +in a temporary directory. + +The default Puppet configuration directory (where it looks for its manifests, +and where it stores certificates and logs) is ``/etc/puppet`` if you are +running the executables as root or ``~/.puppet`` otherwise. All of the +executables accept a ``--confdir <directory>`` flag to change this directory. + +I often use my local Subversion sandbox for testing (i.e., I have my Puppet +configuration stored in Subversion and checked out in my home directory, and I +just test Puppet directly against this configuration). Normally Puppet would +make the configuration directory for you, but the server needs the ``site.pp`` +to exist, so you need to create the ``manifests`` subdirectory:: + + $ mkdir -p /var/tmp/puppet/manifests + $ vi /var/tmp/puppet/manifests/site.pp + <create file> + +Alternatively, you can just specify the manifest itself:: + + $ sudo puppetmasterd --verbose --manifest ~/svn/puppet/manifests/site.pp + +I also always at least run the daemons in verbose mode while testing. First +start the central daemon:: + + $ sudo puppetmasterd --verbose --confdir /var/tmp/puppet + +By default, ``puppetmasterd`` looks for node definitions along these lines:: + + node mymachine { + include $operatingsystem + } + +You can put any valid Puppet code in the structure, but the important +point is that the node definitions need to be there or you need to tell +``puppetmasterd`` they are not there by using the ``--nonodes`` argument. If +you are trying to write a config that works for both ``puppet`` (the +stand-alone executable) and ``puppetd`` (the client to ``puppetmasterd``), +then you should create the config without nodes and use the ``--nonodes`` +argument. + +Once you have the manifest, start the client, pointing it at the local server, +running in noop mode the first time:: + + $ sudo puppetd --verbose --confdir /var/tmp/puppet --server localhost --noop --onetime + +This will connect to the server, retrieve the current machine's configuration, +and run it. In noop mode, this should work for any user, but if you run it as +a normal user you might get some errors if you are not in noop mode (e.g., +normal users cannot use 'chown'). + +Note that your ``site.pp`` file should have a node_ definition for the host +connecting; otherwise you will get an error complaining of no configuration for +that host. It is possible to skip this requirement -- see the ``--help`` +output of ``puppetmasterd`` for details. + +Configuration Testing +--------------------- +Once you're successfully running the daemons, there are other useful flags you +can use to make your life easier. First is the '--test' flag for ``puppetd`, +which is the equivalent of running with +``--onetime --verbose --no-usecacheonfailure``, which means the puppet client +will exit after the first run and will not use the cached configuration if the +central one is broken somehow (this is useful for those cases where you +accidentally cause a parsing error in the config). + +Also, you can narrow down what portion of the configuration you are testing by +using '--tag'. For instance, say you are running this on a machine that is an +ldapserver, namedserver, and webserver, and you're adding ntpserver to the +list of classes being evaluated. Rather than sitting through the entire +config every run, just apply the ntpserver elements:: + + $ sudo puppet --server localhost --test --tag ntpserver + +Every element in Puppet is tagged with the class or definition enclosing that +element, all the way up to the base of the configuration, and it is also +tagged with the host name. So if 'classA' includes 'classB' which creates +'fileC', then 'fileC' will be tagged with both classes. + +.. _node: structures#nodes +.. _source: fromsvn diff --git a/documentation/typedocs.rst b/documentation/typedocs.rst new file mode 100644 index 000000000..0c35274eb --- /dev/null +++ b/documentation/typedocs.rst @@ -0,0 +1,1232 @@ +============== +Type Reference +============== + + + +--------------- +Meta-Parameters +--------------- + +Metaparameters are parameters that work with any element; they are part of the +Puppet framework itself rather than being part of the implementation of any +given instance. Thus, any defined metaparameter can be used with any instance +in your manifest, including defined components. + + +- **alias** + Creates an alias for the object. Puppet uses this internally when you + provide a symbolic name:: + + file { sshdconfig: + path => $operatingsystem ? { + solaris => "/usr/local/etc/ssh/sshd_config", + default => "/etc/ssh/sshd_config" + }, + source => "..." + } + + service { sshd: + subscribe => file[sshdconfig] + } + + When you use this feature, the parser sets ``sshdconfig`` as the name, + and the library sets that as an alias for the file so the dependency + lookup for ``sshd`` works. You can use this parameter yourself, + but note that only the library can use these aliases; for instance, + the following code will not work:: + + file { "/etc/ssh/sshd_config": + owner => root, + group => root, + alias => sshdconfig + } + + file { sshdconfig: + mode => 644 + } + + There's no way here for the Puppet parser to know that these two stanzas + should be affecting the same file. + + See the `language tutorial <http://reductivelabs.com/projects/puppet/documentation/languagetutorial>`__ for more information. + +- **check** + States which should have their values retrieved + but which should not actually be modified. This is currently used + internally, but will eventually be used for querying, so that you + could specify that you wanted to check the install state of all + packages, and then query the Puppet client daemon to get reports + on all packages. +- **loglevel** + Sets the level that information will be logged. + The log levels have the biggest impact when logs are sent to + syslog (which is currently the default). Valid values are ``debug``, ``info``, ``notice``, ``warning``, ``err``, ``alert``, ``emerg``, ``crit``, ``verbose``. +- **noop** + Boolean flag indicating whether work should actually + be done. *true*/**false** +- **require** + One or more objects that this object depends on. + This is used purely for guaranteeing that changes to required objects + happen before the dependent object. For instance:: + + # Create the destination directory before you copy things down + file { "/usr/local/scripts": + ensure => directory + } + + file { "/usr/local/scripts/myscript": + source => "puppet://server/module/myscript", + mode => 755, + require => file["/usr/local/scripts"] + } + + Note that Puppet will autorequire everything that it can, and + there are hooks in place so that it's easy for elements to add new + ways to autorequire objects, so if you think Puppet could be + smarter here, let us know. + + In fact, the above code was redundant -- Puppet will autorequire + any parent directories that are being managed; it will + automatically realize that the parent directory should be created + before the script is pulled down. + + Currently, exec_ elements will autorequire their CWD (if it is + specified) plus any fully qualified paths that appear in the + command. For instance, if you had an ``exec`` command that ran + the ``myscript`` mentioned above, the above code that pulls the + file down would be automatically listed as a requirement to the + ``exec`` code, so that you would always be running againts the + most recent version. +- **schedule** + On what schedule the object should be managed. You must create a + schedule_ object, and then reference the name of that object to use + that for your schedule:: + + schedule { daily: + period => daily, + range => "2-4" + } + + exec { "/usr/bin/apt-get update": + schedule => daily + } + + The creation of the schedule object does not need to appear in the + configuration before objects that use it. +- **subscribe** + One or more objects that this object depends on. Changes in the + subscribed to objects result in the dependent objects being + refreshed (e.g., a service will get restarted). For instance:: + + class nagios { + file { "/etc/nagios/nagios.conf": + source => "puppet://server/module/nagios.conf", + alias => nagconf # just to make things easier for me + } + + service { nagios: + running => true, + subscribe => file[nagconf] + } + } +- **tag** + Add the specified tags to the associated element. While all elements + are automatically tagged with as much information as possible + (e.g., each class and component containing the element), it can + be useful to add your own tags to a given element. + + Tags are currently useful for things like applying a subset of a + host's configuration:: + + puppetd --test --tag mytag + + This way, when you're testing a configuration you can run just the + portion you're testing. + +----- +Types +----- + +- *namevar* is the parameter used to uniquely identify a type instance. + This is the parameter that gets assigned when a string is provided before + the colon in a type declaration. In general, only developers will need to + worry about which parameter is the ``namevar``. + + In the following code:: + + file { "/etc/passwd": + owner => root, + group => root, + mode => 644 + } + + "/etc/passwd" is considered the name of the file object (used for things like + dependency handling), and because ``path`` is the namevar for ``file``, that + string is assigned to the ``path`` parameter. + +- *parameters* determine the specific configuration of the instance. They either + directly modify the system (internally, these are called states) or they affect + how the instance behaves (e.g., adding a search path for ``exec`` instances + or determining recursion on ``file`` instances). + + + + +---------------- + + +cron +======== +Installs and manages cron jobs. All fields except the command +and the user are optional, although specifying no periodic +fields would result in the command being executed every +minute. While the name of the cron job is not part of the actual +job, it is used by Puppet to store and retrieve it. + +If you specify a cron job that matches an existing job in every way +except name, then the jobs will be considered equivalent and the +new name will be permanently associated with that job. Once this +association is made and synced to disk, you can then manage the job +normally (e.g., change the schedule of the job). + +Example:: + + cron { logrotate: + command => "/usr/sbin/logrotate", + user => root, + hour => 2, + minute => 0 + } + + + +Cron Parameters +'''''''''''''''''''''''''''''' +- **command** + The command to execute in the cron job. The environment + provided to the command varies by local system rules, and it is + best to always provide a fully qualified command. The user's + profile is not sourced when the command is run, so if the + user's environment is desired it should be sourced manually. + + All cron parameters support ``absent`` as a value; this will + remove any existing values for that field. +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **hour** + The hour at which to run the cron job. Optional; + if specified, must be between 0 and 23, inclusive. +- **minute** + The minute at which to run the cron job. + Optional; if specified, must be between 0 and 59, inclusive. +- **month** + The month of the year. Optional; if specified + must be between 1 and 12 or the month name (e.g., December). +- **monthday** + The day of the month on which to run the + command. Optional; if specified, must be between 1 and 31. +- **name** + The symbolic name of the cron job. This name + is used for human reference only and is generated automatically + for cron jobs found on the system. This generally won't + matter, as Puppet will do its best to match existing cron jobs + against specified jobs (and Puppet adds a comment to cron jobs it + adds), but it is at least possible that converting from + unmanaged jobs to managed jobs might require manual + intervention. + + The names can only have alphanumeric characters plus the '-' + character. +- **user** + The user to run the command as. This user must + be allowed to run cron jobs, which is not currently checked by + Puppet. + + The user defaults to whomever Puppet is running as. +- **weekday** + The weekday on which to run the command. + Optional; if specified, must be between 0 and 6, inclusive, with + 0 being Sunday, or must be the name of the day (e.g., Tuesday). + + + +---------------- + + +exec +======== +Executes external commands. It is critical that all commands +executed using this mechanism can be run multiple times without +harm, i.e., they are *idempotent*. One useful way to create idempotent +commands is to use the *creates* parameter. + +It is worth noting that ``exec`` is special, in that it is not +currently considered an error to have multiple ``exec`` instances +with the same name. This was done purely because it had to be this +way in order to get certain functionality, but it complicates things. +In particular, you will not be able to use ``exec`` instances that +share their commands with other instances as a dependency, since +Puppet has no way of knowing which instance you mean. + +For example:: + + # defined in the production class + exec { "make": + cwd => "/prod/build/dir", + path => "/usr/bin:/usr/sbin:/bin" + } + + . etc. . + + # defined in the test class + exec { "make": + cwd => "/test/build/dir", + path => "/usr/bin:/usr/sbin:/bin" + } + +Any other type would throw an error, complaining that you had +the same instance being managed in multiple places, but these are +obviously different images, so ``exec`` had to be treated specially. + +It is recommended to avoid duplicate names whenever possible. + +There is a strong tendency to use ``exec`` to do whatever work Puppet +can't already do; while this is obviously acceptable (and unavoidable) +in the short term, it is highly recommended to migrate work from ``exec`` +to real Puppet element types as quickly as possible. If you find that +you are doing a lot of work with ``exec``, please at least notify +us at Reductive Labs what you are doing, and hopefully we can work with +you to get a native element type for the work you are doing. In general, +it is a Puppet bug if you need ``exec`` to do your work. + + +Exec Parameters +'''''''''''''''''''''''''''''' +- **command** (*namevar*) + The actual command to execute. Must either be fully qualified + or a search path for the command must be provided. If the command + succeeds, any output produced will be logged at the instance's + normal log level (usually ``notice``), but if the command fails + (meaning its return code does not match the specified code) then + any output is logged at the ``err`` log level. +- **creates** + A file that this command creates. If this + parameter is provided, then the command will only be run + if the specified file does not exist. + + :: + + exec { "tar xf /my/tar/file.tar": + cwd => "/var/tmp", + creates => "/var/tmp/myfile", + path => ["/usr/bin", "/usr/sbin"] + } + +- **cwd** + The directory from which to run the command. If + this directory does not exist, the command will fail. +- **group** + The group to run the command as. This seems to work quite + haphazardly on different platforms -- it is a platform issue + not a Ruby or Puppet one, since the same variety exists when + running commnands as different users in the shell. +- **logoutput** + Whether to log output. Defaults to logging output at the + loglevel for the ``exec`` element. Values are **true**, *false*, + and any legal log level. Valid values are ``true``, ``false``, ``debug``, ``info``, ``notice``, ``warning``, ``err``, ``alert``, ``emerg``, ``crit``. +- **onlyif** + If this parameter is set, then this +exec+ will only run if + the command returns 0. For example:: + + exec { "logrotate": + path => "/usr/bin:/usr/sbin:/bin", + onlyif => "test `du /var/log/messages | cut -f1` -gt 100000" + } + + This would run +logrotate+ only if that test returned true. + + Note that this command follows the same rules as the main command, + which is to say that it must be fully qualified if the path is not set. +- **path** + The search path used for command execution. + Commands must be fully qualified if no path is specified. Paths + can be specified as an array or as a colon-separated list. +- **refreshonly** + The command should only be run as a + refresh mechanism for when a dependent object is changed. It only + makes sense to use this option when this command depends on some + other object; it is useful for triggering an action:: + + # Pull down the main aliases file + file { "/etc/aliases": + source => "puppet://server/module/aliases" + } + + # Rebuild the database, but only when the file changes + exec { newaliases: + path => ["/usr/bin", "/usr/sbin"], + subscribe => file["/etc/aliases"], + refreshonly => true + } + + Note that only ``subscribe`` can trigger actions, not ``require``, + so it only makes sense to use ``refreshonly`` with ``subscribe``. Valid values are ``true``, ``false``. +- **returns** + The expected return code. An error will be returned if the + executed command returns something else. Defaults to 0. +- **unless** + If this parameter is set, then this +exec+ will run unless + the command returns 0. For example:: + + exec { "/bin/echo root >> /usr/lib/cron/cron.allow": + path => "/usr/bin:/usr/sbin:/bin", + unless => "grep root /usr/lib/cron/cron.allow 2>/dev/null" + } + + This would add +root+ to the cron.allow file (on Solaris) unless + +grep+ determines it's already there. + + Note that this command follows the same rules as the main command, + which is to say that it must be fully qualified if the path is not set. +- **user** + The user to run the command as. Note that if you + use this then any error output is not currently captured. This + is because of a bug within Ruby. + + + +---------------- + + +file +======== +Manages local files, including setting ownership and +permissions, creation of both files and directories, and +retrieving entire files from remote servers. As Puppet matures, it +expected that the ``file`` element will be used less and less to +manage content, and instead native elements will be used to do so. + +If you find that you are often copying files in from a central +location, rather than using native elements, please contact +Reductive Labs and we can hopefully work with you to develop a +native element to support what you are doing. + + +File Parameters +'''''''''''''''''''''''''''''' +- **backup** + Whether files should be backed up before + being replaced. If a filebucket_ is specified, files will be + backed up there; else, they will be backed up in the same directory + with a ``.puppet-bak`` extension. + + To use filebuckets, you must first create a filebucket in your + configuration:: + + filebucket { main: + server => puppet + } + + ``puppetmasterd`` creates a filebucket by default, so you can + usually back up to your main server with this configuration. Once + you've described the bucket in your configuration, you can use + it in any file:: + + file { "/my/file": + source => "/path/in/nfs/or/something", + backup => main + } + + This will back the file up to the central server. + + At this point, the only benefits to doing so are that you do not + have backup files lying around on each of your machines, a given + version of a file is only backed up once, and you can restore + any given file manually, no matter how old. Eventually, + transactional support will be able to automatically restore + filebucketed files. +- **checksum** + How to check whether a file has changed. **md5**/*lite-md5*/ + *time*/*mtime* Valid values are ``md5lite``, ``time``, ``timestamp``, ``mtime``, ``nosum``, ``md5``. Values can also match ``(?-mix:^\{md5|md5lite|timestamp|mtime|time\})``. +- **content** + Specify the contents of a file as a string. Newlines, tabs, and spaces + can be specified using the escaped syntax (e.g., \n for a newline). The + primary purpose of this parameter is to provide a kind of limited + templating:: + + define resolve(nameserver1, nameserver2, domain, search) { + $str = "search $search + domain $domain + nameserver $nameserver1 + nameserver $nameserver2 + " + + file { "/etc/resolv.conf": + content => $str + } + } + + Yes, it's very primitive, and it's useless for larger files, but it + is mostly meant as a stopgap measure for simple cases. +- **ensure** + Whether to create files that don't currently exist. + Possible values are *absent*, *present* (equivalent to *file*), + *file*, and *directory*. Specifying 'absent' will delete the file, + although currently this will not recursively delete directories. + + Anything other than those values will be considered to be a symlink. + For instance, the following text creates a link:: + + # Useful on solaris + file { "/etc/inetd.conf": + ensure => "/etc/inet/inetd.conf" + } + + You can make relative links:: + + # Useful on solaris + file { "/etc/inetd.conf": + ensure => "inet/inetd.conf" + } + + If you need to make a relative link to a file named the same + as one of the valid values, you must prefix it with ``./`` or + something similar. + + You can also make recursive symlinks, which will create a + directory structure that maps to the target directory, + with directories corresponding to each directory + and links corresponding to each file. Valid values are ``link``, ``absent`` (also called ``false``), ``directory``, ``file`` (also called ``present``). Values can also match ``(?-mix:.)``. +- **group** + Which group should own the file. Argument can be either group + name or group ID. +- **ignore** + A parameter which omits action on files matching + specified patterns during recursion. Uses Ruby's builtin globbing + engine, so shell metacharacters are fully supported, e.g. ``[a-z]*``. + Matches that would descend into the directory structure are ignored, + e.g., ``*/*``. +- **linkmaker** + An internal parameter used by the *symlink* + type to do recursive link creation. +- **links** + How to handle links during file actions. During file copying, + ``follow`` will copy the target file instead of the link, ``manage`` + will copy the link itself, and ``ignore`` will just pass it by. + When not copying, ``manage`` and ``ignore`` behave equivalently + (because you cannot really ignore links entirely during local + recursion), and ``follow`` will manage the file to which the + link points. Valid values are ``follow``, ``manage``, ``ignore``. +- **mode** + Mode the file should be. Currently relatively limited: + you must specify the exact mode the file should be. +- **owner** + To whom the file should belong. Argument can be user name or + user ID. +- **path** (*namevar*) + The path to the file to manage. Must be fully qualified. +- **recurse** + Whether and how deeply to do recursive + management. Valid values are ``true``, ``false``, ``inf``. Values can also match ``(?-mix:^[0-9]+$)``. +- **source** + Copy a file over the current file. Uses ``checksum`` to + determine when a file should be copied. Valid values are either + fully qualified paths to files, or URIs. Currently supported URI + types are *puppet* and *file*. + + This is one of the primary mechanisms for getting content into + applications that Puppet does not directly support and is very + useful for those configuration files that don't change much across + sytems. For instance:: + + class sendmail { + file { "/etc/mail/sendmail.cf": + source => "puppet://server/module/sendmail.cf" + } + } + + See the `fileserver docs`_ for information on how to configure + and use file services within Puppet. + + +.. _fileserver docs: /projects/puppet/documentation/fsconfigref + +- **target** + The target for creating a link. Currently, symlinks are the + only type supported. Valid values are ``notlink``. Values can also match ``(?-mix:.)``. +- **type** + A read-only state to check the file type. + + + +---------------- + + +filebucket +============== +A repository for backing up files. If no filebucket is +defined, then files will be backed up in their current directory, +but the filebucket can be either a host- or site-global repository +for backing up. It stores files and returns the MD5 sum, which +can later be used to retrieve the file if restoration becomes +necessary. A filebucket does not do any work itself; instead, +it can be specified as the value of *backup* in a **file** object. + +Currently, filebuckets are only useful for manual retrieval of +accidentally removed files (e.g., you look in the log for the md5 +sum and retrieve the file with that sum from the filebucket), but +when transactions are fully supported filebuckets will be used to +undo transactions. + + +Filebucket Parameters +'''''''''''''''''''''''''''''' +- **name** + The name of the filebucket. +- **path** + The path to the local filebucket. If this is + not specified, then the bucket is remote and *server* must be + specified. +- **port** + The port on which the remote server is listening. + Defaults to the normal Puppet port, 8140. +- **server** + The server providing the filebucket. If this is + not specified, then the bucket is local and *path* must be + specified. + + + +---------------- + + +group +========= +Manage groups. This type can only create groups. Group +membership must be managed on individual users. This element type +uses the prescribed native tools for creating groups and generally +uses POSIX APIs for retrieving information about them. It does +not directly modify /etc/group or anything. + +For most platforms, the tools used are ``groupadd`` and its ilk; +for Mac OS X, NetInfo is used. This is currently unconfigurable, +but if you desperately need it to be so, please contact us. + + +Group Parameters +'''''''''''''''''''''''''''''' +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **gid** + The group ID. Must be specified numerically. If not + specified, a number will be picked, which can result in ID + differences across systems and thus is not recommended. The + GID is picked according to local system standards. +- **name** + The group name. While naming limitations vary by + system, it is advisable to keep the name to the degenerate + limitations, which is a maximum of 8 characters beginning with + a letter. + + + +---------------- + + +host +======== +Installs and manages host entries. For most systems, these +entries will just be in /etc/hosts, but some systems (notably OS X) +will have different solutions. + + +Host Parameters +'''''''''''''''''''''''''''''' +- **alias** + Any alias the host might have. Multiple values must be + specified as an array. Note that this state has the same name + as one of the metaparams; using this state to set aliases will + make those aliases available in your Puppet scripts and also on + disk. +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **ip** + The host's IP address. +- **name** + The host name. + + + +---------------- + + +mount +========= +Manages mounted mounts, including putting mount +information into the mount table. + + +Mount Parameters +'''''''''''''''''''''''''''''' +- **atboot** + Whether to mount the mount at boot. Not all platforms + support this. +- **blockdevice** + The the device to fsck. This is state is only valid + on Solaris, and in most cases will default to the correct + value. +- **device** + The device providing the mount. This can be whatever + device is supporting by the mount, including network + devices or devices specified by UUID rather than device + path, depending on the operating system. +- **dump** + Whether to dump the mount. Not all platforms + support this. +- **ensure** + Create, remove, or mount a filesystem mount. Valid values are ``mounted``, ``absent``, ``present``. +- **fstype** + The mount type. Valid values depend on the + operating system. +- **options** + Mount options for the mounts, as they would + appear in the fstab. +- **pass** + The pass in which the mount is checked. +- **path** (*namevar*) + The mount path for the mount. + + + +---------------- + + +package +=========== +Manage packages. There is a basic dichotomy in package +support right now: Some package types (e.g., yum and apt) can +retrieve their own package files, while others (e.g., rpm and +sun) cannot. For those package formats that cannot retrieve +their own files, you can use the ``source`` parameter to point to +the correct file. + +Puppet will automatically guess the packaging format that you are +using based on the platform you are on, but you can override it +using the ``type`` parameter; obviously, if you specify that you +want to use ``rpm`` then the ``rpm`` tools must be available. + + +Package Parameters +'''''''''''''''''''''''''''''' +- **adminfile** + A file containing package defaults for installing packages. + This is currently only used on Solaris. The value will be + validated according to system rules, which in the case of + Solaris means that it should either be a fully qualified path + or it should be in /var/sadm/install/admin. +- **category** + A read-only parameter set by the package. +- **description** + A read-only parameter set by the package. +- **ensure** + What state the package should be in. + *latest* only makes sense for those packaging formats that can + retrieve new packages on their own and will throw an error on + those that cannot. Valid values are ``absent``, ``latest``, ``present`` (also called ``installed``). +- **instance** + A read-only parameter set by the package. +- **name** + The package name. This is the name that the packaging + system uses internally, which is sometimes (especially on Solaris) + a name that is basically useless to humans. If you want to + abstract package installation, then you can use aliases to provide + a common name to packages:: + + # In the 'openssl' class + $ssl = $operationgsystem ? { + solaris => SMCossl, + default => openssl + } + + # It is not an error to set an alias to the same value as the + # object name. + package { $ssl: + ensure => installed, + alias => openssl + } + + . etc. . + + $ssh = $operationgsystem ? { + solaris => SMCossh, + default => openssh + } + + # Use the alias to specify a dependency, rather than + # having another selector to figure it out again. + package { $ssh: + ensure => installed, + alias => openssh, + require => package[openssl] + } + +- **platform** + A read-only parameter set by the package. +- **responsefile** + A file containing any necessary answers to questions asked by + the package. This is currently only used on Solaris. The + value will be validated according to system rules, but it should + generally be a fully qualified path. +- **root** + A read-only parameter set by the package. +- **source** + From where to retrieve the package. +- **status** + A read-only parameter set by the package. +- **type** + The package format. You will seldom need to specify this -- + Puppet will discover the appropriate format for your platform. +- **vendor** + A read-only parameter set by the package. +- **version** + For some platforms this is a read-only parameter set by the + package, but for others, setting this parameter will cause + the package of that version to be installed. It just depends + on the features of the packaging system. + + + +---------------- + + +port +======== +Installs and manages port entries. For most systems, these +entries will just be in /etc/services, but some systems (notably OS X) +will have different solutions. + + +Port Parameters +'''''''''''''''''''''''''''''' +- **alias** + Any aliases the port might have. Multiple values must be + specified as an array. Note that this state has the same name as + one of the metaparams; using this state to set aliases will make + those aliases available in your Puppet scripts and also on disk. +- **description** + The port description. +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **name** + The port name. +- **number** + The port number. +- **protocols** + The protocols the port uses. Valid values are *udp* and *tcp*. + Most services have both protocols, but not all. If you want + both protocols, you must specify that; Puppet replaces the + current values, it does not merge with them. If you specify + multiple protocols they must be as an array. + + + +---------------- + + +schedule +============ +Defined schedules for Puppet. The important thing to understand +about how schedules are currently implemented in Puppet is that they +can only be used to stop an element from being applied, they never +guarantee that it is applied. + +Every time Puppet applies its configuration, it will collect the +list of elements whose schedule does not eliminate them from +running right then, but there is currently no system in place to +guarantee that a given element runs at a given time. If you +specify a very restrictive schedule and Puppet happens to run at a +time within that schedule, then the elements will get applied; +otherwise, that work may never get done. + +Thus, it behooves you to use wider scheduling (e.g., over a couple of +hours) combined with periods and repetitions. For instance, if you +wanted to restrict certain elements to only running once, between +the hours of two and 4 AM, then you would use this schedule:: + + schedule { maint: + range => "2 - 4", + period => daily, + repeat => 1 + } + +With this schedule, the first time that Puppet runs between 2 and 4 AM, +all elements with this schedule will get applied, but they won't +get applied again between 2 and 4 because they will have already +run once that day, and they won't get applied outside that schedule +because they will be outside the scheduled range. + +Puppet automatically creates a schedule for each valid period with the +same name as that period (e.g., hourly and daily). Additionally, +a schedule named *puppet* is created and used as the default, +with the following attributes:: + + schedule { puppet: + period => hourly, + repeat => 2 + } + +This will cause elements to be applied every 30 minutes by default. + + + +Schedule Parameters +'''''''''''''''''''''''''''''' +- **name** + The name of the schedule. This name is used to retrieve the + schedule when assigning it to an object:: + + schedule { daily: + period => daily, + range => [2, 4] + } + + exec { "/usr/bin/apt-get update": + schedule => daily + } + +- **period** + The period of repetition for an element. Choose from among + a fixed list of *hourly*, *daily*, *weekly*, and *monthly*. + The default is for an element to get applied every time that + Puppet runs, whatever that period is. + + Note that the period defines how often a given element will get + applied but not when; if you would like to restrict the hours + that a given element can be applied (e.g., only at night during + a maintenance window) then use the ``range`` attribute. + + If the provided periods are not sufficient, you can provide a + value to the *repeat* attribute, which will cause Puppet to + schedule the affected elements evenly in the period the + specified number of times. Take this schedule:: + + schedule { veryoften: + period => hourly, + repeat => 6 + } + + This can cause Puppet to apply that element up to every 10 minutes. + + At the moment, Puppet cannot guarantee that level of + repetition; that is, it can run up to every 10 minutes, but + internal factors might prevent it from actually running that + often (e.g., long-running Puppet runs will squash conflictingly + scheduled runs). + + See the ``periodmatch`` attribute for tuning whether to match + times by their distance apart or by their specific value. Valid values are ``hourly``, ``daily``, ``weekly``, ``monthly``. +- **periodmatch** + Whether periods should be matched by number (e.g., the two times + are in the same hour) or by distance (e.g., the two times are + 60 minutes apart). *number*/**distance** Valid values are ``number``, ``distance``. +- **range** + The earliest and latest that an element can be applied. This + is always a range within a 24 hour period, and hours must be + specified in numbers between 0 and 23, inclusive. Minutes and + seconds can be provided, using the normal colon as a separator. + For instance:: + + schedule { maintenance: + range => "1:30 - 4:30" + } + + This is mostly useful for restricting certain elements to being + applied in maintenance windows or during off-peak hours. +- **repeat** + How often the application gets repeated in a given period. + Defaults to 1. + + + +---------------- + + +service +=========== +Manage running services. Service support unfortunately varies +widely by platform -- some platforms have very little if any +concept of a running service, and some have a very codified and +powerful concept. Puppet's service support will generally be able +to make up for any inherent shortcomings (e.g., if there is no +'status' command, then Puppet will look in the process table for a +command matching the service name), but the more information you +can provide the better behaviour you will get. Or, you can just +use a platform that has very good service support. + + +Service Parameters +'''''''''''''''''''''''''''''' +- **binary** + The path to the daemon. This is only used for + systems that do not support init scripts. This binary will be + used to start the service if no ``start`` parameter is + provided. +- **enable** + Whether a service should be enabled to start at boot. + This state behaves quite differently depending on the platform; + wherever possible, it relies on local tools to enable or disable + a given service. *true*/*false*/*runlevels* Valid values are ``true``, ``false``. +- **ensure** + Whether a service should be running. **true**/*false* Valid values are ``running`` (also called ``true``), ``stopped`` (also called ``false``). +- **hasstatus** + Declare the the service's init script has a + functional status command. Based on testing, it was found + that a large number of init scripts on different platforms do + not support any kind of status command; thus, you must specify + manually whether the service you are running has such a + command (or you can specify a specific command using the + ``status`` parameter). + + If you do not specify anything, then the service name will be + looked for in the process table. +- **name** + The name of the service to run. This name + is used to find the service in whatever service subsystem it + is in. +- **path** + The search path for finding init scripts. +- **pattern** + The pattern to search for in the process table. + This is used for stopping services on platforms that do not + support init scripts, and is also used for determining service + status on those service whose init scripts do not include a status + command. + + If this is left unspecified and is needed to check the status + of a service, then the service name will be used instead. + + The pattern can be a simple string or any legal Ruby pattern. +- **restart** + Specify a *restart* command manually. If left + unspecified, the service will be stopped and then started. +- **running** + A place-holder parameter that wraps ``ensure``, because + ``running`` is deprecated. You should use ``ensure`` instead + of this, but using this will still work, albeit with a + warning. +- **start** + Specify a *start* command manually. Most service subsystems + support a ``start`` command, so this will not need to be + specified. +- **status** + Specify a *status* command manually. If left + unspecified, the status method will be determined + automatically, usually by looking for the service in the + process table. +- **stop** + Specify a *stop* command manually. +- **type** + The service type. For most platforms, it does not make + sense to set this parameter, as the default is based on + the builtin service facilities. The service types available are: + + * ``base``: You must specify everything. + * ``init``: Assumes ``start`` and ``stop`` commands exist, but you + must specify everything else. + * ``debian``: Debian's own specific version of ``init``. + * ``smf``: Solaris 10's new Service Management Facility. + Valid values are ``base``, ``init``, ``debian``, ``redhat``, ``smf``. + + + +---------------- + + +sshkey +========== +Installs and manages host entries. For most systems, these +entries will just be in /etc/hosts, but some systems (notably OS X) +will have different solutions. + + +Sshkey Parameters +'''''''''''''''''''''''''''''' +- **alias** + Any alias the host might have. Multiple values must be + specified as an array. Note that this state has the same name + as one of the metaparams; using this state to set aliases will + make those aliases available in your Puppet scripts and also on + disk. +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **key** + The key itself; generally a long string of hex digits. +- **name** + The host name. +- **type** + The encryption type used. Probably ssh-dss or ssh-rsa. + + + +---------------- + + +symlink +=========== +Create symbolic links to existing files. **This type is deprecated; +use file_ instead.** + + +Symlink Parameters +'''''''''''''''''''''''''''''' +- **ensure** + Create a link to another file. Currently only symlinks + are supported, and attempts to replace normal files with + links will currently fail, while existing but incorrect symlinks + will be removed. +- **path** (*namevar*) + The path to the file to manage. Must be fully qualified. +- **recurse** + If target is a directory, recursively create + directories (using `file`'s `source` parameter) and link all + contained files. For instance:: + + # The Solaris Blastwave repository installs everything + # in /opt/csw; link it into /usr/local + symlink { "/usr/local": + ensure => "/opt/csw", + recurse => true + } + + + Note that this does not link directories -- any directories + are created in the destination, and any files are linked over. + + + +---------------- + + +tidy +======== +Remove unwanted files based on specific criteria. + + +Tidy Parameters +'''''''''''''''''''''''''''''' +- **age** + Tidy files whose age is equal to or greater than + the specified number of days. +- **backup** + Whether files should be backed up before + being replaced. If a filebucket_ is specified, files will be + backed up there; else, they will be backed up in the same directory + with a ``.puppet-bak`` extension. + + To use filebuckets, you must first create a filebucket in your + configuration:: + + filebucket { main: + server => puppet + } + + ``puppetmasterd`` creates a filebucket by default, so you can + usually back up to your main server with this configuration. Once + you've described the bucket in your configuration, you can use + it in any file:: + + file { "/my/file": + source => "/path/in/nfs/or/something", + backup => main + } + + This will back the file up to the central server. + + At this point, the only benefits to doing so are that you do not + have backup files lying around on each of your machines, a given + version of a file is only backed up once, and you can restore + any given file manually, no matter how old. Eventually, + transactional support will be able to automatically restore + filebucketed files. +- **path** (*namevar*) + The path to the file or directory to manage. Must be fully + qualified. +- **recurse** + If target is a directory, recursively descend + into the directory looking for files to tidy. +- **rmdirs** + Tidy directories in addition to files; that is, remove + directories whose age is older than the specified criteria. +- **size** + Tidy files whose size is equal to or greater than + the specified size. Unqualified values are in kilobytes, but + *b*, *k*, and *m* can be appended to specify *bytes*, *kilobytes*, + and *megabytes*, respectively. Only the first character is + significant, so the full word can also be used. +- **type** + Set the mechanism for determining age. + **atime**/*mtime*/*ctime*. + + + +---------------- + + +user +======== +Manage users. Currently can create and modify users, but +cannot delete them. Theoretically all of the parameters are +optional, but if no parameters are specified the comment will +be set to the user name in order to make the internals work out +correctly. + +This element type uses the prescribed native tools for creating +groups and generally uses POSIX APIs for retrieving information +about them. It does not directly modify /etc/passwd or anything. + +For most platforms, the tools used are ``useradd`` and its ilk; +for Mac OS X, NetInfo is used. This is currently unconfigurable, +but if you desperately need it to be so, please contact us. + + +User Parameters +'''''''''''''''''''''''''''''' +- **comment** + A description of the user. Generally is a user's full name. +- **ensure** + The basic state that the object should be in. Valid values are ``absent``, ``present``. +- **gid** + The user's primary group. Can be specified numerically or + by name. +- **groups** + The groups of which the user is a member. The primary + group should not be listed. Multiple groups should be + specified as an array. +- **home** + The home directory of the user. The directory must be created + separately and is not currently checked for existence. +- **membership** + Whether specified groups should be treated as the only groups + of which the user is a member or whether they should merely + be treated as the minimum membership list. Valid values are ``inclusive``, ``minimum``. +- **name** + User name. While limitations are determined for + each operating system, it is generally a good idea to keep to + the degenerate 8 characters, beginning with a letter. +- **shell** + The user's login shell. The shell must exist and be + executable. +- **uid** + The user ID. Must be specified numerically. For new users + being created, if no user ID is specified then one will be + chosen automatically, which will likely result in the same user + having different IDs on different systems, which is not + recommended. + + + +---------------- + + +*This page autogenerated on Wed May 10 11:09:04 CDT 2006* |