This document is under construction.
body common control { bundlesequence => { "testbundle" }; } ######################################################## body agent control { agentaccess => { "mark", "root" }; } ######################################################## bundle agent testbundle { files: "/home/mark/tmp" -> "me" changes => tripwire, depth_search => recurse("inf"), action => background; "/home/mark/LapTop/words" -> "you" changes => tripwire, depth_search => recurse("inf"); } ######################################################### body changes tripwire { hash => "md5"; report_changes => "content"; update_hashes => "true"; } ######################################################### body action background { background => "true"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; }
bundle agent garbage_collection { files: "$(sys.workdir)/outputs" delete => tidy, file_select => days_old("3"), depth_search => recurse("inf"); } ######################################################### body file_select days_old(days) # # we can build old "include", "exclude", and "ignore" # from these as standard patterns - these bodies can # form a library of standard patterns # { mtime => irange(ago(1,0,0,0,0,0),ago(0,0,$(days),0,0,0)); file_result => "mtime"; } ############################################ body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body delete tidy { dirlinks => "delete"; #keep/tidy/delete rmdirs => "true"; #none/all/sub }
######################################################## # # Simple test editfile # ######################################################## # # This assumes a file format like: # # [section 1] # # lines.... # # [section 2] # # lines... etc body common control { bundlesequence => { "testbundle" }; } ######################################################## bundle agent testbundle { vars: "1" string => "numerical backreference"; files: "/home/mark/tmp/cf3_test" create => "true", edit_line => AppendIfNoLine("cfengine tcp 5308","second"); } ######################################################## bundle edit_line AppendIfNoLine(parameter,two) { vars: "list" slist => { "1", "2", "3" }; "myscalar" string => "hitccokckckc"; insert_lines: "$(parameter) and $(two)-$(list)" location => "append"; "NEW Special-insert!!!" select_region => MySection("New section"); "set variable = value" select_region => MySection("New section"); "/home/mark/tmp/insert" insert_type => "file", expand_scalars => "true", select_region => MySection("New section"); delete_lines: "l.*"; "NEW.*" select_region => MySection("New section"); # Delete LinesStarting in file } ######################################################## body location append { # If not line to match, applies to whole text body before_after => "after"; } ######################################################## body location after(x) { # If not line to match, applies to whole text body #select_line_matching => "$(x)"; before_after => "after"; } ######################################################## body select_region MySection(x) { select_start => "\[$(x)\]"; select_end => "\[.*\]"; }
###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "testbundle" }; } ######################################################## bundle agent testbundle { vars: "userset" slist => { "one-x", "two-x", "three-x" }; files: # Make a copy of the password file "/home/mark/tmp/passwd" create => "true", edit_line => SetUserParam("mark","6","/set/this/shell"); "/home/mark/tmp/group" create => "true", edit_line => AppendUserParam("root","4","@(userset)"); commands: "/bin/echo" args => "$(userset)"; } ######################################################## bundle edit_line SetUserParam(user,field,val) { field_edits: "$(user).*" # Set field of the file to parameter edit_field => col(":","$(field)","$(val)","set"); } ######################################################## bundle edit_line AppendUserParam(user,field,allusers) { vars: "val" slist => { @(allusers) }; field_edits: "$(user).*" # Set field of the file to parameter edit_field => col(":","$(field)","$(val)","alphanum"); } ######################################## # Bodies ######################################## body edit_field col(split,col,newval,method) { field_separator => "$(split)"; select_field => "$(col)"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; }
###################################################################### # # Root password distribution # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "SetRootPassword" }; } ######################################################## bundle common g { vars: "secret_keys_dir" string => "/tmp"; } ######################################################## bundle agent SetRootPassword { files: "/var/cfengine/ppkeys/rootpw.txt" copy_from => scp("$(fqhost)-root.txt","master_host.example.org"); # or $(pw_class)-root.txt # Test this on a copy "/tmp/shadow" edit_line => SetRootPw; } ######################################################## bundle edit_line SetRootPw { vars: # Assume this file contains a single string of the form :passwdhash: # with : delimiters to avoid end of line/file problems "pw" int => readstringarray("rpw","$(sys.workdir)/ppkeys/rootpw.txt","#[^\n]*",":","1","200"); field_edits: "root.*" # Set field of the file to parameter edit_field => col(":","2","$(rpw[2])","set"); } ######################################################## bundle server passwords { vars: # Read a file of format # # classname: host1,host2,host4,IP-address,regex.*,etc # "pw_classes" int => readstringarray("acl","$(g.secret_keys_dir)/classes.txt","#[^\n]*",":","100","4000"); "each_pw_class" slist => getindices("acl"); access: "/secret/keys/$(each_pw_class)-root.txt" admit => splitstring("$(acl[$(each_pw_class)][1])" , ":" , "100"), ifencrypted => "true"; } ######################################## # Bodies ######################################## body edit_field col(split,col,newval,method) { field_separator => "$(split)"; select_field => "$(col)"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; } ######################################## body copy_from scp(from,server) { source => "$(from)"; compare => "digest"; encrypt => "true"; verify => "true"; }
Laptops do not need a lot of confguration support. IP addresses are set by DHCP and conditions are changeable. But you want to set your DNS search domains to familiar settings in spite of local DHCP configuration, and another useful trick is to keep a regular backup of disk changes on the local disk. This won't help against disk destruction, but it is a huge advantage when your user accidentally deletes files while travelling or offline.
####################################################### # # Laptop # ####################################################### body common control { bundlesequence => { "update", "garbage_collection", "main", "backup", }; inputs => { "update.cf", "site.cf", "library.cf" }; } ####################################################### body agent control { # if default runtime is 5 mins we need this for long jobs ifelapsed => "15"; } ####################################################### body monitor control { forgetrate => "0.7"; histograms => "true"; } ####################################################### body executor control { splaytime => "1"; mailto => "mark@iu.hio.no"; smtpserver => "localhost"; mailmaxlines => "30"; # Instead of a separate update script, now do this exec_command => "$(sys.workdir)/bin/cf-agent -f failsafe.cf && $(sys.workdir)/bin/cf-agent"; } ####################################################### # General site issues can be in bundles like this one ####################################################### bundle agent main { vars: "component" slist => { "cf-monitord", "cf-serverd" }; # - - - - - - - - - - - - - - - - - - - - - - - - files: "$(sys.resolv)" # test on "/tmp/resolv.conf" # create => "true", edit_line => resolver, edit_defaults => def; processes: "$(component)" restart_class => canonify("start_$(component)"); # - - - - - - - - - - - - - - - - - - - - - - - - commands: "$(sys.workdir)/bin/$(component)" ifvarclass => canonify("start_$(component)"); } ####################################################### # Backup ####################################################### bundle agent backup { files: "/home/backup" copy_from => cp("/home/mark"), depth_search => recurse("inf"), file_select => exclude_files, action => longjob; } ####################################################### # Garbage collection issues ####################################################### bundle agent garbage_collection { files: "$(sys.workdir)/outputs" delete => tidy, file_select => days_old("3"), depth_search => recurse("inf"); }
body common control { any:: bundlesequence => { "testbundle" }; } ############################################ bundle agent testbundle { files: "/home/mark/tmp/rotateme" rename => rotate("4"); } ############################################ body rename rotate(level) { rotate => "$(level)"; }
##################################################################### # Mount NFS ##################################################################### body common control { bundlesequence => { "mounts" }; } ##################################################################### bundle agent mounts { storage: # Assumes the filesystem has been exported "/mnt" mount => nfs("server.example.org","/home"); } ###################################################################### body mount nfs(server,source) { mount_type => "nfs"; mount_source => "$(source)"; mount_server => "$(server)"; edit_fstab => "true"; }
This counts to five by default. If we change ‘/bin/echo one’ to ‘/bin/echox one’, then the command will fail, causing us to skip five and go to six instead.
This shows how dependencies can be chained in spite of the order of promises in the bundle.
Normally the order of promises in a bundle is followed, within each promise type, and the types are ordered according to normal ordering.
#################################################### # # Counting by the numbers... # #################################################### body common control { bundlesequence => { "order" }; } #################################################### bundle agent order { vars: "list" slist => { "three", "four" }; commands: ok_later:: "/bin/echo five"; otherthing:: "/bin/echo six"; any:: "/bin/echo one" classes => d("ok_later","otherthing"); "/bin/echo two"; "/bin/echo $(list)"; preserved_class:: "/bin/echo seven"; } ############################################ body classes d(if,else) { promise_repaired => { "$(if)" }; repair_failed => { "$(else)" }; persist_time => "0"; }
####################################################### # # Postfix # ####################################################### body common control { any:: bundlesequence => { postfix }; } ####################################################### bundle agent postfix { vars: "prefix" string => "/etc"; "smtpserver" string => "localhost"; "mailrelay" string => "mailx.example.org"; files: "$(prefix)/main.cf" edit_line => prefix_postfix; "$(prefix)/sasl-passwd" create => "true", perms => system("0600","root"), edit_line => AppendIfNSL("$(smtpserver) _$(fqhost):chmsxrcynz4etzefabj9frejizhs22"); } ####################################################### # For the library ####################################################### bundle edit_line prefix_postfix { # # Value have the form NAME = "quoted space separated list" # vars: "ps[relayhost]" string => "[$(postfix.mailrelay)]:587"; "ps[mydomain]" string => "iu.hio.no"; "ps[smtp_sasl_auth_enable]" string => "yes"; "ps[smtp_sasl_password_maps]" string => "hash:/etc/postfix/sasl-passwd"; "ps[smtp_sasl_security_options]" string => ""; "ps[smtp_use_tls]" string => "yes"; "ps[default_privs]" string => "mailman"; "ps[inet_protocols]" string => "all"; "ps[inet_interfaces]" string => "127.0.0.1"; "parameter_name" slist => getindices("ps"); delete_lines: "$(parameter_name).*"; insert_lines: "$(parameter_name) = $(ps[$(parameter_name)])"; } ######################################################## bundle edit_line AppendIfNSL(parameter) { insert_lines: "$(parameter)"; # This is default } ######################################## # Library Bodies ######################################## body replace_with All(x) { replace_value => "$(x)"; occurrences => "all"; } ######################################################### body perms system(x,owner) { mode => "0640"; owners => { "$(owner)", "root" }; }
In cfengine 2 there is a separate action type for configuring the system resolver. In cfengine 3 this has been deprecated for this standard method using the basic functionality of cfengine. We write a reusable bundle using the editing features.
####################################################### # # Resolve conf # ####################################################### bundle common g # globals { vars: "searchlist" slist => { "search iu.hio.no", "search cfengine.com" }; "nameservers" slist => { "128.39.89.10", "128.39.74.16", "192.168.1.103" }; classes: # This sets a class if we are in the name server list "am_name_server" expression => reglist("@(nameservers)","$(sys.ipv4[eth1])"); } ####################################################### body common control { any:: bundlesequence => { "g", resolver(@(g.searchlist),@(g.nameservers)) }; } ####################################################### bundle agent resolver(s,n) { files: # When passing parameters down, we have to refer to # a source context "$(sys.resolv)" # test on "/tmp/resolv.conf" # create => "true", edit_line => doresolv("@(this.s)","@(this.n)"), edit_defaults => reconstruct; # or edit_defaults => modify } ####################################################### # For the library ####################################################### bundle edit_line doresolv(s,n) { vars: "line" slist => { @(s), @(n) }; insert_lines: "$(line)"; } ####################################################### body edit_defaults reconstruct { empty_file_before_editing => "true"; edit_backup => "false"; max_file_size => "100000"; } ####################################################### body edit_defaults modify { empty_file_before_editing => "false"; edit_backup => "false"; max_file_size => "100000"; }
Emulating the `tidy' feature of cfengine 2.
####################################################### # # Deleting files, like cf2 tidy age=0 r=inf # ####################################################### body common control { any:: bundlesequence => { "testbundle" }; } ############################################ bundle agent testbundle { files: "/tmp/test" delete => tidyfiles, file_select => zero_age, depth_search => recurse("inf"); } ######################################################### body depth_search recurse(d) { #include_basedir => "true"; depth => "$(d)"; } ######################################################### body delete tidy { dirlinks => "delete"; rmdirs => "false"; } ######################################################### body file_select zero_age # # we can build old "include", "exclude", and "ignore" # from these as standard patterns - these bodies can # form a library of standard patterns # { mtime => irange(ago(1,0,0,0,0,0),now); file_result => "mtime"; }
##################################################################### # Mount NFS ##################################################################### body common control { bundlesequence => { "mounts" }; } ##################################################################### bundle agent mounts { storage: # Assumes the filesystem has been exported "/mnt" mount => nfs("server.example.org","/home"); } ###################################################################### body mount nfs(server,source) { mount_type => "nfs"; mount_source => "$(source)"; mount_server => "$(server)"; edit_fstab => "true"; unmount => "true"; }
The problem of editing the correct modules into the list of standard modules for the Apache web server. This example is based on the standard configuration deployment of SuSE Linux. Simply provide the list of modules you want and another list that you don't want.
####################################################### # # Apache 2 reconfig - modelled on SuSE # ####################################################### body common control { any:: bundlesequence => { apache }; } ####################################################### bundle agent apache { files: SuSE:: "/etc/sysconfig/apache2" edit_line => fixapache; } ####################################################### # For the library ####################################################### bundle edit_line fixapache { vars: "add_modules" slist => { "dav", "dav_fs", "ssl", "php5", "dav_svn", "xyz", "superduper" }; "del_modules" slist => { "php3", "jk", "userdir", "imagemap", "alias" }; insert_lines: "APACHE_CONF_INCLUDE_FILES=\"/site/masterfiles/local-http.conf\""; field_edits: ##################################################################### # APACHE_MODULES="authz_host actions alias ..." ##################################################################### # Values have the form NAME = "quoted space separated list" "APACHE_MODULES=.*" # Insert module "columns" between the quoted RHS # using space separators edit_field => quotedvar("$(add_modules)","append"); "APACHE_MODULES=.*" # Delte module "columns" between the quoted RHS # using space separators edit_field => quotedvar("$(del_modules)","delete"); # if this line already exists, edit it } ######################################## # Bodies ######################################## body edit_field quotedvar(newval,method) { field_separator => "\""; select_field => "2"; value_separator => " "; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "false"; allow_blank_fields => "true"; }
Table of Contents