summaryrefslogtreecommitdiffstats
path: root/documentation/structures.page
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/structures.page')
-rw-r--r--documentation/structures.page315
1 files changed, 315 insertions, 0 deletions
diff --git a/documentation/structures.page b/documentation/structures.page
new file mode 100644
index 000000000..5359330c2
--- /dev/null
+++ b/documentation/structures.page
@@ -0,0 +1,315 @@
+---
+inMenu: true
+---
+
+This is a brief overview of the language structures
+available for making site configurations in Puppet.
+For futher documentation, visit the [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](typedocs.html) 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
+
+Because ``include`` is a function, any normal value can be used, including
+variables and selectors:
+
+ include $operatingsystem, $hostname ? {
+ myhost => classA, default classB
+ }
+
+## 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 }
+ }
+
+
+
+The ``case`` statement 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).