summaryrefslogtreecommitdiffstats
path: root/documentation/notcfengine.page
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-06-17 01:56:04 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-06-17 01:56:04 +0000
commit644fd4e5ff3cf3a31370be48c7d960e74204477d (patch)
tree98619c04b07ac461935505abc95ac2d533e10108 /documentation/notcfengine.page
parentf0907607347c26127dd566fbe5b19c8528d25f5d (diff)
downloadpuppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.tar.gz
puppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.tar.xz
puppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.zip
updating docs to work with webgen
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1293 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'documentation/notcfengine.page')
-rw-r--r--documentation/notcfengine.page222
1 files changed, 222 insertions, 0 deletions
diff --git a/documentation/notcfengine.page b/documentation/notcfengine.page
new file mode 100644
index 000000000..b96448e57
--- /dev/null
+++ b/documentation/notcfengine.page
@@ -0,0 +1,222 @@
+---
+inMenu: true
+title: Puppet vs. Cfengine
+---
+
+[Cfengine](http://www.cfengine.org) is currently the most widely deployed
+configuration management tool. In many ways, [Puppet](/projects/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.