Community Open Promise Body Library


Next: , Previous: (dir), Up: (dir)

Cfengine-Open-Promise-Body-Library

COMPLETE TABLE OF CONTENTS

Summary of contents


Previous: Top, Up: Top

1 The Purpose Of This Handbook


Cfengine is built on promises. Promises were chosen as the model for Cfengine's configuration language, because they represent an expression of intention.

If you are using custom scripts to manage your systems, you are using recipes. Take a look at any cookbook and you will see that all recipes look the same: take flour, eggs, butter, sugar ... and you know nothing because you can make a hundred things from these steps. If you don't make clear your intention, it is very hard to know what the recipe is supposed to be: is it a cake, a waffle, a pastry?

The same is true in system administration. Recipes are not merely scripts, they encapsulate knowledge and experience. Their value is in communicating desired outcomes or states.

This library of standard components is like a cookbook that tells you only how to make basics well. It gives these basic skills names and therefore gives you a common vocabulary – you will put together these basics in creative ways to build your systems.



Please contribute to this guide by helping to develop a repertoire of basic skills and names. This collection should be comprehensive but parsimonious. Basics are only basics if they are few and carefully thought out. This is a work in progress and your experience is welcome.

This library will be moderated by Cfengine, and contributions and discussions ca n be made to the help-cfengine@cfengine.org mailing list.


Next: , Previous: The Purpose Of This Handbook, Up: The Purpose Of This Handbook

1.1 body acl access_generic(acl)

body acl access_generic(acl)
# default/inherited ACLs are left unchanged,
# applicable for both files and directories on all platforms
{
acl_method => "overwrite";
aces => { "@(acl)" };

windows::
acl_type => "ntfs";

!windows::
acl_type => "posix";
}



Next: , Previous: body acl access_generic, Up: The Purpose Of This Handbook

1.2 body acl ntfs(acl)

body acl ntfs(acl)
{
acl_type => "ntfs";
acl_method => "overwrite";
aces => { "@(acl)" };
}



Next: , Previous: body acl ntfs, Up: The Purpose Of This Handbook

1.3 body acl strict

body acl strict
# NOTE: May need to take ownership of file/dir
# to be sure no-one else is allowed access
{
acl_method => "overwrite";

windows::
aces => { "user:Administrator:rwx" };
!windows::
aces => { "user:root:rwx" };
}



Next: , Previous: body acl strict, Up: The Purpose Of This Handbook

1.4 body action bg(elapsed,expire)

body action bg(elapsed,expire)
{
ifelapsed   => "$(elapsed)";
expireafter => "$(expire)";
background  => "true";
}



Next: , Previous: body action bg, Up: The Purpose Of This Handbook

1.5 body action if_elapsed(x)

body action if_elapsed(x)
{
ifelapsed => "$(x)";
expireafter => "$(x)";
}



Next: , Previous: body action if_elapsed, Up: The Purpose Of This Handbook

1.6 body action ifwin_bg

body action ifwin_bg
{
windows::
background => "true";
}



Next: , Previous: body action ifwin_bg, Up: The Purpose Of This Handbook

1.7 body action immediate

body action immediate
{
ifelapsed => "0";
}



Next: , Previous: body action immediate, Up: The Purpose Of This Handbook

1.8 body action log_repaired(log,message)

body action log_repaired(log,message)
{
log_string => "$(sys.date), $(message)";
log_repaired => "$(log)";
}



Next: , Previous: body action log_repaired, Up: The Purpose Of This Handbook

1.9 body action log_verbose

body action log_verbose
{
log_level => "verbose";
}



Next: , Previous: body action log_verbose, Up: The Purpose Of This Handbook

1.10 body action measure_performance(x)

body action measure_performance(x)
{
measurement_class => "Detect changes in $(this.promiser)";
ifelapsed => "$(x)";
expireafter => "$(x)";
}



Next: , Previous: body action measure_performance, Up: The Purpose Of This Handbook

1.11 body action policy(p)

body action policy(p)
{
action_policy => "$(p)";
}


# Log a message to log=[/file|stdout]


Next: , Previous: body action policy, Up: The Purpose Of This Handbook

1.12 body action sample_rate(x)

body action sample_rate(x)
{
ifelapsed => "$(x)";
expireafter => "10";
}


Next: , Previous: body action sample_rate, Up: The Purpose Of This Handbook

1.13 body action warn_only

body action warn_only
{
action_policy => "warn";
ifelapsed => "60";
}



Next: , Previous: body action warn_only, Up: The Purpose Of This Handbook

1.14 body changes detect_all_change

body changes detect_all_change

# This is fierce, and will cost disk cycles

{
hash           => "best";
report_changes => "all";
update_hashes  => "yes";
}



Next: , Previous: body changes detect_all_change, Up: The Purpose Of This Handbook

1.15 body changes detect_content

body changes detect_content

# This is a cheaper alternative

{
hash           => "md5";
report_changes => "content";
update_hashes  => "yes";
}



Next: , Previous: body changes detect_content, Up: The Purpose Of This Handbook

1.16 body changes diff

body changes diff
# Generates diff report (Nova and above)
{
hash           => "sha256";
report_changes => "content";
report_diffs   => "true";
update_hashes  => "yes";
}



Next: , Previous: body changes diff, Up: The Purpose Of This Handbook

1.17 body changes diff_noupdate

body changes diff_noupdate
{
hash           => "sha256";
report_changes => "content";
report_diffs   => "true";
update_hashes  => "no";
}



Next: , Previous: body changes diff_noupdate, Up: The Purpose Of This Handbook

1.18 body changes noupdate

body changes noupdate
# Use on (small) files that should never change
{
hash           => "sha256";
report_changes => "content";
update_hashes  => "no";
}



Next: , Previous: body changes noupdate, Up: The Purpose Of This Handbook

1.19 body classes always(x)

body classes always(x)

# Define a class no matter what the outcome of the promise is

{
  promise_repaired => { "$(x)" };
  promise_kept => { "$(x)" };
  repair_failed => { "$(x)" };
  repair_denied => { "$(x)" };
  repair_timeout => { "$(x)" };
}

# agent bundles





Next: , Previous: body classes always, Up: The Purpose Of This Handbook

1.20 body classes cf2_if_else(yes,no)

body classes cf2_if_else(yes,no)

# meant to match cf2 semantics

{
promise_repaired => { "$(yes)" };
repair_failed    => { "$(no)" };
repair_denied    => { "$(no)" };
repair_timeout   => { "$(no)" };
}



Next: , Previous: body classes cf2_if_else, Up: The Purpose Of This Handbook

1.21 body classes cmd_repair(code,cl)

body classes cmd_repair(code,cl)
{
repaired_returncodes => { "$(code)" };
promise_repaired => { "$(cl)" };
}



Next: , Previous: body classes cmd_repair, Up: The Purpose Of This Handbook

1.22 body classes enumerate(x)

body classes enumerate(x)

#
# This is used by commercial editions to count 
# instances of jobs in a cluster
#

{
promise_repaired => { "mXC_$(x)" };
promise_kept => { "mXC_$(x)" };
persist_time => "15";
}



Next: , Previous: body classes enumerate, Up: The Purpose Of This Handbook

1.23 body classes if_else(yes,no)

body classes if_else(yes,no)

{
promise_kept     => { "$(yes)" };
promise_repaired => { "$(yes)" };
repair_failed    => { "$(no)" };
repair_denied    => { "$(no)" };
repair_timeout   => { "$(no)" };
}



Next: , Previous: body classes if_else, Up: The Purpose Of This Handbook

1.24 body classes if_notkept(x)

body classes if_notkept(x)
{
repair_failed   => { "$(x)" };
repair_denied   => { "$(x)" };
repair_timeout  => { "$(x)" };
}



Next: , Previous: body classes if_notkept, Up: The Purpose Of This Handbook

1.25 body classes if_ok(x)

body classes if_ok(x)
{
promise_repaired => { "$(x)" };
promise_kept => { "$(x)" };
}



Next: , Previous: body classes if_ok, Up: The Purpose Of This Handbook

1.26 body classes if_repaired(x)

body classes if_repaired(x)
{
promise_repaired => { "$(x)" };
}



Next: , Previous: body classes if_repaired, Up: The Purpose Of This Handbook

1.27 body classes state_repaired(x)

body classes state_repaired(x)
{
promise_repaired => { "$(x)" };
persist_time => "10";
}



Next: , Previous: body classes state_repaired, Up: The Purpose Of This Handbook

1.28 body contain in_dir(s)

body contain in_dir(s)
{
chdir => "$(s)";
}



Next: , Previous: body contain in_dir, Up: The Purpose Of This Handbook

1.29 body contain in_dir_shell(s)

body contain in_dir_shell(s)
{
chdir => "$(s)";
useshell => "true";
}



Next: , Previous: body contain in_dir_shell, Up: The Purpose Of This Handbook

1.30 body contain in_shell

body contain in_shell
{
useshell => "true";
}



Next: , Previous: body contain in_shell, Up: The Purpose Of This Handbook

1.31 body contain in_shell_and_silent

body contain in_shell_and_silent
{
useshell => "true";
no_output => "true";
}



Next: , Previous: body contain in_shell_and_silent, Up: The Purpose Of This Handbook

1.32 body contain in_shell_bg

body contain in_shell_bg
{
useshell => "true";
background => "true";
}



Next: , Previous: body contain in_shell_bg, Up: The Purpose Of This Handbook

1.33 body contain jail(owner,root,dir)

body contain jail(owner,root,dir)
{
exec_owner => "$(owner)";
useshell => "true";
chdir => "$(dir)";
chroot => "$(root)";
}





Next: , Previous: body contain jail, Up: The Purpose Of This Handbook

1.34 body contain setuid(x)

body contain setuid(x)
{
exec_owner => "$(x)";
useshell => "false";
}



Next: , Previous: body contain setuid, Up: The Purpose Of This Handbook

1.35 body contain setuid_sh(x)

body contain setuid_sh(x)
{
exec_owner => "$(x)";
useshell => "true";
}



Next: , Previous: body contain setuid_sh, Up: The Purpose Of This Handbook

1.36 body contain setuidgid_sh(owner,group)

body contain setuidgid_sh(owner,group)
{
exec_owner => "$(owner)";
exec_group => "$(group)";
useshell => "true";
}



Next: , Previous: body contain setuidgid_sh, Up: The Purpose Of This Handbook

1.37 body contain silent

body contain silent
{
no_output => "true";
}



Next: , Previous: body contain silent, Up: The Purpose Of This Handbook

1.38 body contain silent_in_dir(s)

body contain silent_in_dir(s)
{
chdir => "$(s)";
no_output => "true";
}



Next: , Previous: body contain silent_in_dir, Up: The Purpose Of This Handbook

1.39 body copy_from backup_local_cp(from)

body copy_from backup_local_cp(from)
# Local copy, keeping a backup of old versions
{
  source      => "$(from)";
  copy_backup => "timestamp";
}


# Copy only if the file does not already exist, i.e. seed the placement


Next: , Previous: body copy_from backup_local_cp, Up: The Purpose Of This Handbook

1.40 body copy_from local_cp(from)

body copy_from local_cp(from)
{
source      => "$(from)";
}



Next: , Previous: body copy_from local_cp, Up: The Purpose Of This Handbook

1.41 body copy_from local_dcp(from)

body copy_from local_dcp(from)
{
source      => "$(from)";
compare     => "digest";
}



Next: , Previous: body copy_from local_dcp, Up: The Purpose Of This Handbook

1.42 body copy_from no_backup_cp(from)

body copy_from no_backup_cp(from)
{
source      => "$(from)";
copy_backup => "false";
}



Next: , Previous: body copy_from no_backup_cp, Up: The Purpose Of This Handbook

1.43 body copy_from no_backup_dcp(from)

body copy_from no_backup_dcp(from)
{
source      => "$(from)";
copy_backup => "false";
compare     => "digest";
}



Next: , Previous: body copy_from no_backup_dcp, Up: The Purpose Of This Handbook

1.44 body copy_from no_backup_rcp(from,server)

body copy_from no_backup_rcp(from,server)
{
servers     => { "$(server)" };
source      => "$(from)";
compare     => "mtime";
copy_backup => "false";
}



Next: , Previous: body copy_from no_backup_rcp, Up: The Purpose Of This Handbook

1.45 body copy_from perms_cp(from)

body copy_from perms_cp(from)
{
source      => "$(from)";
preserve    => "true";
}


Next: , Previous: body copy_from perms_cp, Up: The Purpose Of This Handbook

1.46 body copy_from remote_cp(from,server)

body copy_from remote_cp(from,server)
{
servers     => { "$(server)" };
source      => "$(from)";
compare     => "mtime";
}



Next: , Previous: body copy_from remote_cp, Up: The Purpose Of This Handbook

1.47 body copy_from remote_dcp(from,server)

body copy_from remote_dcp(from,server)
{
servers     => { "$(server)" };
source      => "$(from)";
compare     => "digest";
}



Next: , Previous: body copy_from remote_dcp, Up: The Purpose Of This Handbook

1.48 body copy_from secure_cp(from,server)

body copy_from secure_cp(from,server)
{
source      => "$(from)";
servers     => { "$(server)" };
compare     => "digest";
encrypt     => "true";
verify      => "true";
}



Next: , Previous: body copy_from secure_cp, Up: The Purpose Of This Handbook

1.49 body copy_from seed_cp(from)

body copy_from seed_cp(from)
{
source      => "$(from)";
compare     => "exists";
}



Next: , Previous: body copy_from seed_cp, Up: The Purpose Of This Handbook

1.50 body copy_from sync_cp(from,server)

body copy_from sync_cp(from,server)
{
servers     => { "$(server)" };
source      => "$(from)";
purge       => "true";
preserve    => "true";
type_check  => "false";
}



Next: , Previous: body copy_from sync_cp, Up: The Purpose Of This Handbook

1.51 body delete tidy

body delete tidy

{
dirlinks => "delete";
rmdirs   => "true";
}



Next: , Previous: body delete tidy, Up: The Purpose Of This Handbook

1.52 body depth_search include_base

body depth_search include_base
{
include_basedir => "true";
}



Next: , Previous: body depth_search include_base, Up: The Purpose Of This Handbook

1.53 body depth_search recurse(d)

body depth_search recurse(d)

{
depth => "$(d)";
xdev  => "true";
}



Next: , Previous: body depth_search recurse, Up: The Purpose Of This Handbook

1.54 body depth_search recurse_ignore(d,list)

body depth_search recurse_ignore(d,list)
{
depth => "$(d)";
exclude_dirs => { @(list) };
}



Next: , Previous: body depth_search recurse_ignore, Up: The Purpose Of This Handbook

1.55 body edit_defaults empty

body edit_defaults empty
{
empty_file_before_editing => "true";
edit_backup => "false";
max_file_size => "300000";
}



Next: , Previous: body edit_defaults empty, Up: The Purpose Of This Handbook

1.56 body edit_defaults no_backup

body edit_defaults no_backup
{
edit_backup => "false";
}



Next: , Previous: body edit_defaults no_backup, Up: The Purpose Of This Handbook

1.57 body edit_defaults std_defs

body edit_defaults std_defs
{
empty_file_before_editing => "false";
edit_backup => "false";
max_file_size => "300000";
}



Next: , Previous: body edit_defaults std_defs, Up: The Purpose Of This Handbook

1.58 body edit_field col(split,col,newval,method)

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";
allow_blank_fields => "true";
}



Next: , Previous: body edit_field col, Up: The Purpose Of This Handbook

1.59 body edit_field line(split,col,newval,method)

body edit_field line(split,col,newval,method)
{
field_separator    => "$(split)";
select_field       => "$(col)";
value_separator    => " ";
field_value        => "$(newval)";
field_operation    => "$(method)";
extend_fields      => "true";
allow_blank_fields => "true";
}



Next: , Previous: body edit_field line, Up: The Purpose Of This Handbook

1.60 body edit_field quoted_var(newval,method)

body edit_field quoted_var(newval,method)
{
field_separator => "\"";
select_field    => "2";
value_separator  => " ";
field_value     => "$(newval)";
field_operation => "$(method)";
extend_fields => "false";
allow_blank_fields => "true";
}



Next: , Previous: body edit_field quoted_var, Up: The Purpose Of This Handbook

1.61 body file_select by_name(names)

body file_select by_name(names)
{
leaf_name  => { @(names)};
file_result => "leaf_name";
}



Next: , Previous: body file_select by_name, Up: The Purpose Of This Handbook

1.62 body file_select days_old(days)

body file_select days_old(days)
{
mtime       => irange(0,ago(0,0,"$(days)",0,0,0));
file_result => "mtime";
}



Next: , Previous: body file_select days_old, Up: The Purpose Of This Handbook

1.63 body file_select dirs

body file_select dirs
{
file_types  => { "dir" };
file_result => "file_types";
}



Next: , Previous: body file_select dirs, Up: The Purpose Of This Handbook

1.64 body file_select ex_list(names)

body file_select ex_list(names)
{
leaf_name  => { @(names)};
file_result => "!leaf_name";
}



Next: , Previous: body file_select ex_list, Up: The Purpose Of This Handbook

1.65 body file_select exclude(name)

body file_select exclude(name)
{
leaf_name  => { "$(name)"};
file_result => "!leaf_name";
}



Next: , Previous: body file_select exclude, Up: The Purpose Of This Handbook

1.66 body file_select name_age(name,days)

body file_select name_age(name,days)
{
leaf_name   => { "$(name)" };
mtime       => irange(0,ago(0,0,"$(days)",0,0,0));  
file_result => "mtime.leaf_name"; 
}



Next: , Previous: body file_select name_age, Up: The Purpose Of This Handbook

1.67 body file_select plain

body file_select plain
{
file_types  => { "plain" };
file_result => "file_types";
}


Next: , Previous: body file_select plain, Up: The Purpose Of This Handbook

1.68 body file_select size_range(from,to)

body file_select size_range(from,to)
{
search_size => irange("$(from)","$(to)");
file_result => "size";
}



Next: , Previous: body file_select size_range, Up: The Purpose Of This Handbook

1.69 body link_from linkchildren(tofile)

body link_from linkchildren(tofile)
{
source        => "$(tofile)";
link_type     => "symlink";
when_no_source  => "force";
link_children => "true";
when_linking_children => "if_no_such_file"; # "override_file";
}



Next: , Previous: body link_from linkchildren, Up: The Purpose Of This Handbook

1.70 body link_from ln_s(x)

body link_from ln_s(x)
{
link_type => "symlink";
source => "$(x)";
when_no_source => "force";
}



Next: , Previous: body link_from ln_s, Up: The Purpose Of This Handbook

1.71 body location after(str)

body location after(str)
{
before_after => "after";
select_line_matching => "$(str)";
}




Next: , Previous: body location after, Up: The Purpose Of This Handbook

1.72 body location start

body location start
{
before_after => "before";
}



Next: , Previous: body location start, Up: The Purpose Of This Handbook

1.73 body match_value scan_changing_file(line)

body match_value scan_changing_file(line)
{
select_line_matching => "$(line)";
track_growing_file => "false";
}



Next: , Previous: body match_value scan_changing_file, Up: The Purpose Of This Handbook

1.74 body match_value scan_log(line)

body match_value scan_log(line)
{
select_line_matching => "$(line)";
track_growing_file => "true";
}



Next: , Previous: body match_value scan_log, Up: The Purpose Of This Handbook

1.75 body mount nfs(server,source)

body mount nfs(server,source)
{
mount_type => "nfs";
mount_source => "$(source)";
mount_server => "$(server)";
edit_fstab => "true";
}




Next: , Previous: body mount nfs, Up: The Purpose Of This Handbook

1.76 body mount nfs_p(server,source,perm)

body mount nfs_p(server,source,perm)
{
mount_type => "nfs";
mount_source => "$(source)";
mount_server => "$(server)";
mount_options => {"$(perm)"};
edit_fstab => "true";
}



Next: , Previous: body mount nfs_p, Up: The Purpose Of This Handbook

1.77 body mount unmount

body mount unmount
{
mount_type => "nfs";
edit_fstab => "true";
unmount => "true";
}



Next: , Previous: body mount unmount, Up: The Purpose Of This Handbook

1.78 body package_method apt

body package_method apt
{
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex    => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "$(name)";

# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";

have_aptitude::
   package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
   package_list_update_command => "/usr/bin/aptitude update";
   package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes -q remove";
   package_update_command =>  "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
   package_verify_command =>  "/usr/bin/aptitude show";
   package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";

!have_aptitude::
   package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
   package_list_update_command => "/usr/bin/apt-get update";
   package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes -q remove";
   package_update_command =>  "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
   package_verify_command => "/usr/bin/dpkg -s";
   package_noverify_returncode => "1";
}



Next: , Previous: body package_method apt, Up: The Purpose Of This Handbook

1.79 body package_method dpkg_version(repo)

body package_method dpkg_version(repo)
{
package_changes => "individual";
package_list_command => "/usr/bin/dpkg -l";

# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";

package_list_name_regex    => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";

package_installed_regex => ".*"; # all reported are installed

package_file_repositories => { "$(repo)" };

debian.x86_64::
   package_name_convention => "$(name)_$(version)_amd64.deb";

debian.i686::
   package_name_convention => "$(name)_$(version)_i386.deb";

debian::
   package_add_command => "/usr/bin/dpkg --install";
   package_delete_command => "/usr/bin/dpkg --purge";
   package_update_command =>  "/usr/bin/dpkg --install";
}



Next: , Previous: body package_method dpkg_version, Up: The Purpose Of This Handbook

1.80 body package_method freebsd

body package_method freebsd
{
 package_changes => "individual";

 # Could use rpm for this
 package_list_command => "/usr/sbin/pkg_info";

 # Remember to escape special characters like |

 package_list_name_regex    => "([^\s]+)-.*";
 package_list_version_regex => "[^\s]+-([^\s]+).*";

 package_name_regex    => "([^\s]+)-.*";
 package_version_regex => "[^\s]+-([^\s]+).*";

 package_installed_regex => ".*";

 package_name_convention => "$(name)-$(version)";


package_add_command => "/usr/sbin/pkg_add -r";
package_delete_command => "/usr/sbin/pkg_delete";
}


 # Single bundle for all the similar managers simplifies promises


Next: , Previous: body package_method freebsd, Up: The Purpose Of This Handbook

1.81 body package_method generic

body package_method generic
{
SuSE::
 package_changes => "bulk";
 package_list_command => "/usr/bin/zypper packages";
 package_patch_list_command => "/usr/bin/zypper patches";
 package_installed_regex => "i.*";
 package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s]+).*";
 package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
 package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
 package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
 package_patch_name_regex    => "[^|]+\|\s+([^\s]+).*";
 package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
 package_name_convention => "$(name)";
 package_add_command => "/usr/bin/zypper --non-interactive install";
 package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
 package_update_command => "/usr/bin/zypper --non-interactive update";
 package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
 package_verify_command => "/usr/bin/zypper --non-interactive verify$";

redhat::
 package_changes => "bulk";
 package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
 package_patch_list_command => "/usr/bin/yum check-update";
 package_list_name_regex    => "^(\S+?)\s\S+?\s\S+$";
 package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
 package_list_arch_regex    => "^\S+?\s\S+?\s(\S+)$";
 package_installed_regex => ".*";
 package_name_convention => "$(name)";
 package_list_update_ifelapsed => "0";     # sometimes, caching is pretty disturbing
 package_patch_installed_regex => "^\s.*";
 package_patch_name_regex    => "([^.]+).*";
 package_patch_version_regex => "[^\s]\s+([^\s]+).*";
 package_patch_arch_regex    => "[^.]+\.([^\s]+).*";
 package_add_command    => "/usr/bin/yum -y install";
 package_update_command => "/usr/bin/yum -y update";
 package_delete_command => "/bin/rpm -e --nodeps --allmatches";
 package_verify_command => "/bin/rpm -V";

# package_changes => "bulk";
# package_list_command => "/usr/bin/yum list installed";
# package_patch_list_command => "/usr/bin/yum check-update";
# package_list_name_regex    => "([^.]+).*";
# package_list_version_regex => "[^\s]\s+([^\s]+).*";
# package_list_arch_regex    => "[^.]+\.([^\s]+).*";
# package_installed_regex => ".*(installed|\s+@).*";
# package_name_convention => "$(name).$(arch)";
# package_list_update_ifelapsed => "240";
# package_patch_installed_regex => "^\s.*";
# package_patch_name_regex    => "([^.]+).*";
# package_patch_version_regex => "[^\s]\s+([^\s]+).*";
# package_patch_arch_regex    => "[^.]+\.([^\s]+).*";
# package_add_command => "/usr/bin/yum -y install";
# package_delete_command => "/bin/rpm -e --nodeps";
# package_verify_command => "/bin/rpm -V";

debian::
 package_changes => "bulk";
 package_list_command => "/usr/bin/dpkg -l";
 package_list_name_regex    => "ii\s+([^\s]+).*";
 package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
 package_installed_regex => ".*"; # all reported are installed
 package_name_convention => "$(name)";
 package_list_update_ifelapsed => "240";		# 4 hours

debian.have_aptitude::
   package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
   package_list_update_command => "/usr/bin/aptitude update";
   package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes remove";
   package_update_command =>  "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
   package_verify_command =>  "/usr/bin/aptitude show";
   package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";

debian.!have_aptitude::
   package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
   package_list_update_command => "/usr/bin/apt-get update";
   package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes remove";
   package_update_command =>  "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
   package_verify_command => "/usr/bin/dpkg -s";
   package_noverify_returncode => "1";

freebsd::
 package_changes => "individual";
 package_list_command => "/usr/sbin/pkg_info";
 package_list_name_regex    => "([^\s]+)-.*";
 package_list_version_regex => "[^\s]+-([^\s]+).*";
 package_name_regex    => "([^\s]+)-.*";
 package_version_regex => "[^\s]+-([^\s]+).*";
 package_installed_regex => ".*";
 package_name_convention => "$(name)-$(version)";
 package_add_command => "/usr/sbin/pkg_add -r";
 package_delete_command => "/usr/sbin/pkg_delete";
}




Next: , Previous: body package_method generic, Up: The Purpose Of This Handbook

1.82 body package_method msi_explicit(repo)

body package_method msi_explicit(repo)
# use software name as promiser, e.g. "7-Zip", and explicitly
# specify any package_version and package_arch
{
package_changes => "individual";
package_file_repositories => { "$(repo)" };

package_installed_regex => ".*";
 
package_name_convention => "$(name)-$(version)-$(arch).msi";
package_delete_convention => "$(firstrepo)$(name)-$(version)-$(arch).msi";

package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
}



Next: , Previous: body package_method msi_explicit, Up: The Purpose Of This Handbook

1.83 body package_method msi_implicit(repo)

body package_method msi_implicit(repo)
# Use whole file name as promiser, e.g. "7-Zip-4.50-x86_64.msi",
# the name, version and arch is then deduced from the promiser
{
package_changes => "individual";
package_file_repositories => { "$(repo)" };

package_installed_regex => ".*";
 
package_name_convention => "$(name)-$(version)-$(arch).msi";
package_delete_convention => "$(firstrepo)$(name)-$(version)-$(arch).msi";

package_name_regex => "^(\S+)-(\d+\.?)+";
package_version_regex => "^\S+-((\d+\.?)+)";
package_arch_regex => "^\S+-[\d\.]+-(.*).msi";

package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
}



Next: , Previous: body package_method msi_implicit, Up: The Purpose Of This Handbook

1.84 body package_method rpm_version(repo)

body package_method rpm_version(repo)
{
package_changes => "individual";

package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";

# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";

package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";

package_installed_regex => "i.*";

package_file_repositories => { "$(repo)" };

package_name_convention => "$(name)-$(version).$(arch).rpm";

package_add_command => "/bin/rpm -ivh ";
package_update_command => "/bin/rpm -Uvh ";
package_delete_command => "/bin/rpm -e --nodeps";
package_noverify_regex => ".*[^\s].*";
}



Next: , Previous: body package_method rpm_version, Up: The Purpose Of This Handbook

1.85 body package_method solaris (pkgname, spoolfile, adminfile)

body package_method solaris (pkgname, spoolfile, adminfile)
{
package_changes => "individual";
package_list_command => "/usr/bin/pkginfo -l";
package_multiline_start    =>  "\s*PKGINST:\s+[^\s]+.*";
package_list_name_regex    => "\s*PKGINST:\s+([^\s]+).*";
package_list_version_regex => "\s*VERSION:\s+([^\s]+).*";
package_list_arch_regex    => "\s*ARCH:\s+([^\s]+)";
package_installed_regex => "\s*STATUS:\s*(completely|partially)\s+installed.*";
package_name_convention => "$(name)";
package_add_command => "/usr/sbin/pkgadd -n -a /tmp/$(adminfile) -d /tmp/$(spoolfile)";
package_delete_command => "/usr/sbin/pkgrm -n -a /tmp/$(adminfile)";
}


#
# The following bundle is part of a package setup for solaris, see unit examples
#


Next: , Previous: body package_method solaris, Up: The Purpose Of This Handbook

1.86 body package_method yum

body package_method yum
{
package_changes => "bulk";
package_list_command => "/usr/bin/yum list installed";
package_patch_list_command => "/usr/bin/yum check-update";

# Remember to escape special characters like |

package_list_name_regex    => "([^.]+).*";
package_list_version_regex => "[^\s]\s+([^\s]+).*";
package_list_arch_regex    => "[^.]+\.([^\s]+).*";

package_installed_regex => ".*(installed|\s+@).*";
package_name_convention => "$(name).$(arch)";

# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";

package_patch_installed_regex => "^\s.*";
package_patch_name_regex    => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex    => "[^.]+\.([^\s]+).*";

package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --nodeps";
package_verify_command => "/bin/rpm -V";
}



Next: , Previous: body package_method yum, Up: The Purpose Of This Handbook

1.87 body package_method yum_rpm

body package_method yum_rpm
# Contributed by Trond Hasle Amundsen

# More efficient package method for RedHat - uses rpm to list instead of yum
# Notes:
# - using $(name).$(arch) instead of $(name) for package_name_convention
#   causes uninstallation to fail.
# - using allmatches to remove for all architectures
#
{
  package_changes => "bulk";
  package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
  package_patch_list_command => "/usr/bin/yum check-update";

  package_list_name_regex    => "^(\S+?)\s\S+?\s\S+$";
  package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
  package_list_arch_regex    => "^\S+?\s\S+?\s(\S+)$";

  package_installed_regex => ".*";
  package_name_convention => "$(name)";

  package_patch_installed_regex => "^\s.*";
  package_patch_name_regex    => "([^.]+).*";
  package_patch_version_regex => "[^\s]\s+([^\s]+).*";
  package_patch_arch_regex    => "[^.]+\.([^\s]+).*";

  package_add_command    => "/usr/bin/yum -y install";
  package_update_command => "/usr/bin/yum -y update";
  package_delete_command => "/bin/rpm -e --nodeps --allmatches";
  package_verify_command => "/bin/rpm -V";
}


# The solaris package system is poorly designed, with too many different
# names to track. See the example in tests/units/unit_package_solaris.cf
# to see how to use this


Next: , Previous: body package_method yum_rpm, Up: The Purpose Of This Handbook

1.88 body package_method zypper

body package_method zypper

{
package_changes => "bulk";

package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";

# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";

package_patch_list_command => "/usr/bin/zypper patches";
package_installed_regex => "i.*";
package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";

package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex    => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";

package_name_convention => "$(name)";
package_add_command => "/usr/bin/zypper --non-interactive install";
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
package_update_command => "/usr/bin/zypper --non-interactive update";

package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
package_verify_command => "/usr/bin/zypper --non-interactive verify$";
}



Next: , Previous: body package_method zypper, Up: The Purpose Of This Handbook

1.89 body perms m(mode)

body perms m(mode)
{
mode   => "$(mode)";
}



Next: , Previous: body perms m, Up: The Purpose Of This Handbook

1.90 body perms mo(mode,user)

body perms mo(mode,user)
{
owners => { "$(user)" };
mode   => "$(mode)";
}



Next: , Previous: body perms mo, Up: The Purpose Of This Handbook

1.91 body perms mog(mode,user,group)

body perms mog(mode,user,group)
{
owners => { "$(user)" };
groups => { "$(group)" };
mode   => "$(mode)";
}



Next: , Previous: body perms mog, Up: The Purpose Of This Handbook

1.92 body perms og(u,g)

body perms og(u,g)
{
owners => { "$(u)" };
groups => { "$(g)" };
}



Next: , Previous: body perms og, Up: The Purpose Of This Handbook

1.93 body perms owner(user)

body perms owner(user)
{
owners => { "$(user)" };
}



Next: , Previous: body perms owner, Up: The Purpose Of This Handbook

1.94 body process_count any_count(cl)

body process_count any_count(cl)

{
match_range => "0,0";
out_of_range_define => { "$(cl)" };
}



Next: , Previous: body process_count any_count, Up: The Purpose Of This Handbook

1.95 body process_count check_range(name,lower,upper)

body process_count check_range(name,lower,upper)
{
match_range => irange("$(lower)","$(upper)");
out_of_range_define => { "$(name)_out_of_range" };
}



Next: , Previous: body process_count check_range, Up: The Purpose Of This Handbook

1.96 body process_select days_older_than(d)

body process_select days_older_than(d)
{
stime_range    => irange(ago(0,0,"$(d)",0,0,0),now);
process_result => "stime";
}



Next: , Previous: body process_select days_older_than, Up: The Purpose Of This Handbook

1.97 body process_select exclude_procs(x)

body process_select exclude_procs(x)
{
command => "$(x)";
process_result => "!command";
}



Next: , Previous: body process_select exclude_procs, Up: The Purpose Of This Handbook

1.98 body rename disable

body rename disable
{
disable => "true";
}



Next: , Previous: body rename disable, Up: The Purpose Of This Handbook

1.99 body rename rotate(level)

body rename rotate(level)
{
rotate => "$(level)";
}



Next: , Previous: body rename rotate, Up: The Purpose Of This Handbook

1.100 body rename to(file)

body rename to(file)
{
newname => "$(file)";
}



Next: , Previous: body rename to, Up: The Purpose Of This Handbook

1.101 body replace_with comment(c)

body replace_with comment(c)
{
replace_value => "$(c) $(match.1)";
occurrences => "all";
}



Next: , Previous: body replace_with comment, Up: The Purpose Of This Handbook

1.102 body replace_with uncomment

body replace_with uncomment
{
replace_value => "$(match.1)";
occurrences => "all";
}




Next: , Previous: body replace_with uncomment, Up: The Purpose Of This Handbook

1.103 body replace_with value(x)

body replace_with value(x)
{
replace_value => "$(x)";
occurrences => "all";
}



Next: , Previous: body replace_with value, Up: The Purpose Of This Handbook

1.104 body select_region INI_section(x)

body select_region INI_section(x)
{
select_start => "\[$(x)\]\s*";
select_end => "\[.*\]\s*";
}



Next: , Previous: body select_region INI_section, Up: The Purpose Of This Handbook

1.105 body service_method bootstart

body service_method bootstart
{
  service_autostart_policy => "boot_time";
  service_dependence_chain => "start_parent_services";
windows::
  service_type => "windows";
}



Next: , Previous: body service_method bootstart, Up: The Purpose Of This Handbook

1.106 body service_method force_deps

body service_method force_deps
{
  service_dependence_chain => "all_related";
windows::
  service_type => "windows";
}



Next: , Previous: body service_method force_deps, Up: The Purpose Of This Handbook

1.107 body volume min_free_space(free)

body volume min_free_space(free)
{
check_foreign  => "false";
freespace      => "$(free)";
sensible_size  => "10000";
sensible_count => "2";
}



Next: , Previous: body volume min_free_space, Up: The Purpose Of This Handbook

1.108 bundle agent cronjob(commands,user,hours,mins)

bundle agent cronjob(commands,user,hours,mins)

 # For adding lines to crontab for a user
 # methods:
 #  "cron" usebundle => cronjob("/bin/ls","mark","*","5,10");

{
vars:
  SuSE::
   "crontab" string => "/var/spool/cron/tabs";
  redhat|fedora::
   "crontab" string => "/var/spool/cron";
 !(SuSE|redhat|fedora)::
    "crontab" string => "/var/spool/cron/crontabs"; 

files:

!windows::
  "$(crontab)/$(user)" 

    comment => "A user's regular batch jobs are added to this file",
     create => "true",
  edit_line => append_if_no_line("$(mins) $(hours) * * * $(commands)"),
      perms => mo("644","$(user)"),
    classes => if_repaired("changed_crontab");

processes:

changed_crontab::
   "cron"
         comment => "Most crons need to be huped after file changes",
         signals => { "hup" };

}





Next: , Previous: bundle agent cronjob, Up: The Purpose Of This Handbook

1.109 bundle edit_line append_groups_starting(v)

bundle edit_line append_groups_starting(v)

 # For adding groups to /etc/group, needs
 # an array v[groupname] string => "line..."

{
vars:

  "index"        slist => getindices("$(v)");

classes:

  "add_$(index)" not => groupexists("$(index)");

insert_lines:

  "$($(v)[$(index)])",

         comment => "Append users into a group file format",
      ifvarclass => "add_$(index)";

}



Next: , Previous: bundle edit_line append_groups_starting, Up: The Purpose Of This Handbook

1.110 bundle edit_line append_if_no_line(str)

bundle edit_line append_if_no_line(str)
{
insert_lines:

 "$(str)"

     comment => "Append a line to the file if it doesn't already exist";
}



Next: , Previous: bundle edit_line append_if_no_line, Up: The Purpose Of This Handbook

1.111 bundle edit_line append_if_no_lines(list)

bundle edit_line append_if_no_lines(list)
{
insert_lines:

 "$(list)"

   comment => "Append lines to the file if they don't already exist";
}



Next: , Previous: bundle edit_line append_if_no_lines, Up: The Purpose Of This Handbook

1.112 bundle edit_line append_to_line_end(start,end)

bundle edit_line append_to_line_end(start,end)
#
# Lines starting with "$(start)" and not ending with "$(end)"
# will get appended with "$(end)", whitespaces will be left unmodified.
# For example, append_to_line_end("kernel", "vga=791") would replace
# "kernel /boot/vmlinuz root=/dev/sda7"
# with 
# "kernel /boot/vmlinuz root=/dev/sda7 resume=/dev/sda9 vga=791"
#
# WARNING: Be careful not to have multiple promises matching the same line,
#          which would result in the line growing indefinetively.
{
field_edits:

   "\s*$(start)\s.*"
      edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","append");
}



Next: , Previous: bundle edit_line append_to_line_end, Up: The Purpose Of This Handbook

1.113 bundle edit_line append_user_field(group,field,allusers)

bundle edit_line append_user_field(group,field,allusers)

 # For adding users to to a file like /etc/group
 # at field position "field", comma separated subfields

{
vars:

  "val" slist => { @(allusers) };

field_edits:

 "$(group):.*"

       comment => "Append users into a password file format",
    edit_field => col(":","$(field)","$(val)","alphanum");
}



Next: , Previous: bundle edit_line append_user_field, Up: The Purpose Of This Handbook

1.114 bundle edit_line append_users_starting(v)

bundle edit_line append_users_starting(v)

 # For adding to /etc/passwd or etc/shadow, needs
 # an array v[username] string => "line..."

{
vars:

  "index"        slist => getindices("$(v)");

classes:

  "add_$(index)" not => userexists("$(index)");

insert_lines:

  "$($(v)[$(index)])",

         comment => "Append users into a password file format",
      ifvarclass => "add_$(index)";
}



Next: , Previous: bundle edit_line append_users_starting, Up: The Purpose Of This Handbook

1.115 bundle edit_line comment_lines_containing(regex,comment)

bundle edit_line comment_lines_containing(regex,comment)

 # Comment lines of a file containing a regex

{
replace_patterns:
 
 "^(.*$(regex).*)$" 

     replace_with => comment("$(comment)"),
          comment => "Comment out lines in a file";
}
	 
	 


Next: , Previous: bundle edit_line comment_lines_containing, Up: The Purpose Of This Handbook

1.116 bundle edit_line comment_lines_matching(regex,comment)

bundle edit_line comment_lines_matching(regex,comment)

 # Comment lines of a file matching a regex

{
replace_patterns:
	 
 "^($(regex))$" 

     replace_with => comment("$(comment)"),
          comment => "Search and replace string";
}
	 
	 


Next: , Previous: bundle edit_line comment_lines_matching, Up: The Purpose Of This Handbook

1.117 bundle edit_line create_solaris_admin_file

bundle edit_line create_solaris_admin_file
{
insert_lines:
		
  "mail=
instance=unique
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
networktimeout=60
networkretries=3
authentication=quit
keystore=/var/sadm/security
proxy=
basedir=default";
}



Next: , Previous: bundle edit_line create_solaris_admin_file, Up: The Purpose Of This Handbook

1.118 bundle edit_line delete_lines_matching(regex)

bundle edit_line delete_lines_matching(regex)
{
delete_lines:

  "$(regex)"

     comment => "Delete lines matching regular expressions";
}



Next: , Previous: bundle edit_line delete_lines_matching, Up: The Purpose Of This Handbook

1.119 bundle edit_line expand_template(templatefile)

bundle edit_line expand_template(templatefile)

 # Read in the named text file and expand $(var)
 # inside the file

{
insert_lines:

   "$(templatefile)"

        insert_type => "file",
            comment => "Expand variables in the template file",
     expand_scalars => "true";
}


Next: , Previous: bundle edit_line expand_template, Up: The Purpose Of This Handbook

1.120 bundle edit_line insert_file(templatefile)

bundle edit_line insert_file(templatefile)
{
insert_lines:

   "$(templatefile)"
            comment => "Insert the template file into the file being edited",
        insert_type => "file";
}



Next: , Previous: bundle edit_line insert_file, Up: The Purpose Of This Handbook

1.121 bundle edit_line insert_lines(lines)




Next: , Previous: bundle edit_line insert_lines, Up: The Purpose Of This Handbook

1.122 bundle edit_line replace_line_end(start,end)

bundle edit_line replace_line_end(start,end)
#
# Lines starting with "$(start)" will get the ending given in "$(end)",
# whitespaces will be left unmodified.
# For example, replace_line_end("ftp", "2121/tcp") would replace
# "ftp             21/tcp"
# with 
# "ftp             2121/tcp"
{
field_edits:

   "\s*$(start)\s.*"
      edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","set");
}



Next: , Previous: bundle edit_line replace_line_end, Up: The Purpose Of This Handbook

1.123 bundle edit_line replace_or_add(pattern,line)

bundle edit_line replace_or_add(pattern,line)

 # Replace a pattern in a file with a single line.
 # If the pattern is not found, add the line to the file.
 # The pattern must match the whole line (it is automatically
 # anchored to the start and end of the line) to avoid
 # ambiguity.

{
vars:
  "cline" string => canonify("$(line)");

replace_patterns:
  "^(?!$(line))$(pattern)$"
  replace_with => value("$(line)"),
  classes => always("replace_done_$(cline)");

insert_lines:
  "$(line)"
    ifvarclass => "replace_done_$(cline)";
}



Next: , Previous: bundle edit_line replace_or_add, Up: The Purpose Of This Handbook

1.124 bundle edit_line resolvconf(search,list)

bundle edit_line resolvconf(search,list)

 # search is the search domains with space
 # list is an slist of nameserver addresses

{
delete_lines:

  "search.*"     comment => "Reset search lines from resolver";
  "nameserver.*" comment => "Reset nameservers in resolver";

insert_lines:

  "search $(search)"    comment => "Add search domains to resolver";
  "nameserver $(list)"  comment => "Add name servers to resolver";
}



Next: , Previous: bundle edit_line resolvconf, Up: The Purpose Of This Handbook

1.125 bundle edit_line set_config_values(v)

bundle edit_line set_config_values(v)

 # Sets the RHS of configuration items in the file of the form
 #   LHS RHS
 # If the line is commented out with #, it gets uncommented first.
 # Adds a new line if none exists.
 # The argument is the fully-qualified name of an associative array containing v[LHS]="rhs"

{
vars:
  "index" slist => getindices("$(v)");

  # Be careful if the index string contains funny chars
  "cindex[$(index)]" string => canonify("$(index)");

replace_patterns:
  # If the line is there, maybe commented out, uncomment and replace with
  # the correct value
  "^\s*($(index)\s+(?!$($(v)[$(index)])).*|# ?$(index)\s+.*)$"
    replace_with => value("$(index) $($(v)[$(index)])"),
    classes => always("replace_attempted_$(cindex[$(index)])");

insert_lines:
  "$(index) $($(v)[$(index)])"
    ifvarclass => "replace_attempted_$(cindex[$(index)])";

}



Next: , Previous: bundle edit_line set_config_values, Up: The Purpose Of This Handbook

1.126 bundle edit_line set_user_field(user,field,val)

bundle edit_line set_user_field(user,field,val)

 # Set the value of field number "field" in
 # a :-field formatted file like /etc/passwd

{
field_edits:

 "$(user):.*"

        comment => "Edit a user attribute in the password file",
     edit_field => col(":","$(field)","$(val)","set");
}



Next: , Previous: bundle edit_line set_user_field, Up: The Purpose Of This Handbook

1.127 bundle edit_line set_variable_values(v)

bundle edit_line set_variable_values(v)

 # Sets the RHS of variables in the file of the form
 #   LHS = RHS
 # Adds a new line if no LHS exists, repairs RHS values if one does exist
 #
 # To use:
 #   1) Define an array, where the keys are the LHS and the values are the RHS
 #        "stuff[lhs-1]" string => "rhs1";
 #        "stuff[lhs-2]" string => "rhs2";
 #   2) The parameter passed to the edit_line promise is the fully qualified
 #      name of the array (i.e., "bundlename.stuff") WITHOUT any "$" or "@"

{
vars:

  "index" slist => getindices("$(v)");

  # Be careful if the index string contains funny chars

  "cindex[$(index)]" string => canonify("$(index)");

field_edits:

  # match a line starting like the key = something

  "\s*$(index)\s*=.*"

     edit_field => col("=","2","$($(v)[$(index)])","set"),
        classes => if_ok("$(cindex[$(index)])_in_file"),
        comment => "Match a line starting like key = something";

insert_lines:

  "$(index)=$($(v)[$(index)])",

         comment => "Insert a variable definition",
      ifvarclass => "!$(cindex[$(index)])_in_file";
}


Next: , Previous: bundle edit_line set_variable_values, Up: The Purpose Of This Handbook

1.128 bundle edit_line set_variable_values2(file,v)

bundle edit_line set_variable_values2(file,v)
#
# Another implementation of set_variable_values.
# The input and output should be exactly the same (except the file name), 
# but in some Cfengine versions there are bugs, 
# so this bundle can be used as a workaround.
#
{
vars:

  "index" slist => getindices("$(v)");

  # Be careful if the index string contains funny chars

  "cindex[$(index)]" string => canonify("$(index)");

  "fieldc_$(cindex[$(index)])" int => getfields("$(index).*","$(file)","=","FIELD_$(cindex[$(index)])");

classes:
  "$(cindex[$(index)])_in_file" expression => strcmp("$(index)=$($(v)[$(index)])", "$(FIELD_$(index)[1])=$(FIELD_$(index)[2])");


delete_lines:  # delete any lhs when no match
  "$(index)=.*",
    ifvarclass => "!$(cindex[$(index)])_in_file";


insert_lines:

  "$(index)=$($(v)[$(index)])",

         comment => "Insert a variable definition",
      ifvarclass => "!$(cindex[$(index)])_in_file";

}



Next: , Previous: bundle edit_line set_variable_values2, Up: The Purpose Of This Handbook

1.129 bundle edit_line uncomment_lines_containing(regex,comment)

bundle edit_line uncomment_lines_containing(regex,comment)
	 
 # Uncomment lines of a file where the regex matches
 # the text after the comment string
	 
{
replace_patterns:
 
 "^$(comment)\s?(.*$(regex).*)$" 

    replace_with => uncomment,
         comment => "Uncomment a line containing a fragment";
}



Next: , Previous: bundle edit_line uncomment_lines_containing, Up: The Purpose Of This Handbook

1.130 bundle edit_line uncomment_lines_matching(regex,comment)

bundle edit_line uncomment_lines_matching(regex,comment)
	 
 # Uncomment lines of a file where the regex matches
 # the text after the comment string
	 
{
replace_patterns:
 
 "^$(comment)\s?($(regex))$" 

       replace_with => uncomment,
            comment => "Uncomment lines matching a regular expression";
}
	 


Previous: bundle edit_line uncomment_lines_matching, Up: The Purpose Of This Handbook

1.131 bundle edit_line warn_lines_matching(regex)

bundle edit_line warn_lines_matching(regex)
{
delete_lines:

  "$(regex)"  

   comment => "Warn about lines in a file",
    action => warn_only;
}


Table of Contents