A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.cfengine.com/latest/reference-masterfiles-policy-framework-lib-files.html below:

files.cf - CFEngine 3.26 Docs

See the files promises and edit_line bundles documentation for a comprehensive reference on the bundles, body types, and attributes used here.

file bodies control

Prototype: control

Description: Include policy files used by this policy file as part of inputs

Implementation:

code

body file control
{
      inputs => { @(files_common.inputs) };
}
edit_field bodies fstab_options

Prototype: fstab_options(newval, method)

Description: Edit the options field in a fstab format

Arguments:

This body edits the options field in the fstab file format. The method is a field_operation which can be append, prepend, set, delete, or alphanum. The newval option is OS-specific.

Example:

code

  # from the `fstab_options_editor`
  field_edits:
     "(?!#)\S+\s+$(mount)\s.+"
     edit_field => fstab_options($(option), $(method));

Implementation:

code

body edit_field fstab_options(newval, method)
{
      field_separator => "\s+";
      select_field    => "4";
      value_separator  => ",";
      field_value     => "$(newval)";
      field_operation => "$(method)";
}
quoted_var

Prototype: quoted_var(newval, method)

Description: Edit the quoted value of the matching line

Arguments:

Implementation:

code

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";
}
col

Prototype: col(split, col, newval, method)

Description: Edit tabluar data with comma-separated sub-values

Arguments:

Implementation:

code

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";
}
line

Prototype: line(split, col, newval, method)

Description: Edit tabular data with space-separated sub-values

Arguments:

Implementation:

code

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";
}
replace_with bodies text_between_match1_and_match2

Prototype: text_between_match1_and_match2(_text)

Description: Replace matched line with substituted string

Arguments:

Implementation:

code

body replace_with text_between_match1_and_match2( _text )
{
        replace_value => "$(match.1)$(_text)$(match.2)";
        occurrences => "all";
}
value

Prototype: value(x)

Description: Replace matching lines

Arguments:

Implementation:

code

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

Prototype: INI_section(x)

Description: Restrict the edit_line promise to the lines in section [x]

Arguments:

Implementation:

code

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

@if minimum_version(3.10)
      select_end_match_eof => "true";
@endif
}
edit_defaults bodies std_defs

Prototype: std_defs

Description: Standard definitions for edit_defaults Don't empty the file before editing starts and don't make a backup.

Implementation:

code

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

Prototype: empty

Description: Empty the file before editing

No backup is made

Implementation:

code

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

Prototype: no_backup

Description: Don't make a backup of the file before editing

Implementation:

code

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

Prototype: backup_timestamp

Description: Make a timestamped backup of the file before editing

Implementation:

code

body edit_defaults backup_timestamp
{
      empty_file_before_editing => "false";
      edit_backup => "timestamp";
      #max_file_size => "300000";
}
location bodies start

Prototype: start

Description: Editing occurs before the matched line

Implementation:

code

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

Prototype: after(str)

Description: Editing occurs after the line matching str

Arguments:

Implementation:

code

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

Prototype: before(str)

Description: Editing occurs before the line matching str

Arguments:

Implementation:

code

body location before(str)
{
      before_after => "before";
      select_line_matching => "$(str)";
}
replace_with bodies

Prototype: comment(c)

Description: Comment all lines matching the pattern by preprending c

Arguments:

Implementation:

code

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

Prototype: uncomment

Description: Uncomment all lines matching the pattern by removing anything outside the matching string

Implementation:

code

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

Prototype: secure_cp(from, server)

Description: Download a file from a remote server over an encrypted channel

Only copy the file if it is different from the local copy, and verify that the copy is correct.

Arguments:

Implementation:

code

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

Prototype: remote_cp(from, server)

Description: Download a file from a remote server.

Arguments:

Implementation:

code

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

Prototype: remote_dcp(from, server)

Description: Download a file from a remote server if it is different from the local copy.

Arguments:

See Also: local_dcp()

Implementation:

code

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

Prototype: local_cp(from)

Description: Copy a file if the modification time or creation time of the source file is newer (the default comparison mechanism).

Arguments:

Example:

code

bundle agent example
{
  files:
      "/tmp/file.bak"
        copy_from => local_cp("/tmp/file");
}

See Also: local_dcp()

Implementation:

code

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

Prototype: local_dcp(from)

Description: Copy a local file if the hash on the source file differs.

Arguments:

Example:

code

bundle agent example
{
  files:
      "/tmp/file.bak"
      copy_from => local_dcp("/tmp/file");
}

See Also: local_cp(), remote_dcp()

Implementation:

code

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

Prototype: perms_cp(from)

Description: Copy a local file and preserve file permissions on the local copy.

Arguments:

Implementation:

code

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

Prototype: perms_dcp(from)

Description: Copy a local file if it is different from the existing copy and preserve file permissions on the local copy.

Arguments:

Implementation:

code

body copy_from perms_dcp(from)
{
      source      => "$(from)";
      preserve    => "true";
      compare     => "digest";
}
backup_local_cp

Prototype: backup_local_cp(from)

Description: Copy a local file and keep a backup of old versions.

Arguments:

Implementation:

code

body copy_from backup_local_cp(from)
{
      source      => "$(from)";
      copy_backup => "timestamp";
}
seed_cp

Prototype: seed_cp(from)

Description: Copy a local file if the file does not already exist, i.e. seed the placement

Arguments:

Example:

code

bundle agent home_dir_init
{
  files:
      "/home/mark.burgess/."
      copy_from => seed_cp("/etc/skel"),
      depth_search => recurse(inf),
      file_select => all,
      comment => "We want to be sure that the home directory has files that are
                  present in the skeleton.";
}

Implementation:

code

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

Prototype: sync_cp(from, server)

Description: Synchronize a file with a remote server.

Arguments:

Example:

code

files:
  "/tmp/masterfiles/."
    copy_from => sync_cp( "/var/cfengine/masterfiles", $(sys.policy_server) ),
    depth_search => recurse(inf),
    file_select => all,
    comment => "Mirror masterfiles from the hub to a temporary directory";

See Also: dir_sync(), copyfrom_sync()

Implementation:

code

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

Prototype: no_backup_cp(from)

Description: Copy a local file and don't make any backup of the previous version

Arguments:

Implementation:

code

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

Prototype: no_backup_cp_compare(from, comparison)

Description: Copy a local file (from) based on comparison (comparison) and don't make any backup of the previous version

Arguments:

Implementation:

code

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

Prototype: no_backup_dcp(from)

Description: Copy a local file if contents have changed, and don't make any backup of the previous version

Arguments:

Implementation:

code

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

Prototype: no_backup_rcp(from, server)

Description: Download a file if it's newer than the local copy, and don't make any backup of the previous version

Arguments:

Implementation:

code

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

Prototype: ln_s(x)

Description: Create a symbolink link to x The link is created even if the source of the link does not exist.

Arguments:

Implementation:

code

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

Prototype: linkchildren(tofile)

Description: Create a symbolink link to tofile If the promiser is a directory, children are linked to the source, unless entries with identical names already exist. The link is created even if the source of the link does not exist.

Arguments:

Implementation:

code

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";
}
linkfrom

Prototype: linkfrom(source, type)

Description: Make any kind of link to a file

Arguments:

Implementation:

code

body link_from linkfrom(source, type)
{
      source => $(source);
      link_type => $(type);
}
perms bodies m

Prototype: m(mode)

Description: Set the file mode

Arguments:

Implementation:

code

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

#+begin_ENT-951
# Remove after 3.20 is not supported
        rxdirs => "true";
@if minimum_version(3.20)
        rxdirs => "false";
@endif
#+end
}
mo

Prototype: mo(mode, user)

Description: Set the file's mode and owners

Arguments:

Implementation:

code

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

#+begin_ENT-951
# Remove after 3.20 is not supported
        rxdirs => "true";
@if minimum_version(3.20)
        rxdirs => "false";
@endif
#+end
}
mog

Prototype: mog(mode, user, group)

Description: Set the file's mode, owner and group

Arguments:

Implementation:

code

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

#+begin_ENT-951
# Remove after 3.20 is not supported
        rxdirs => "true";
@if minimum_version(3.20)
        rxdirs => "false";
@endif
#+end
}
og

Prototype: og(u, g)

Description: Set the file's owner and group

Arguments:

Implementation:

code

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

Prototype: owner(user)

Description: Set the file's owner

Arguments:

Implementation:

code

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

Prototype: system_owned(mode)

Description: Set the file owner and group to the system default

Arguments:

Example:

code

files:
    "/etc/passwd" perms => system_owned("0644");

Implementation:

code

body perms system_owned(mode)
{
      mode   => "$(mode)";

#+begin_ENT-951
# Remove after 3.20 is not supported
        rxdirs => "true";
@if minimum_version(3.20)
        rxdirs => "false";
@endif
#+end

    !windows::
        owners => { "root" };

    windows::

      # NOTE: Setting owners will generate an error if the policy is not being
      # executed as the user who's ownership is being targeted. While it seems
      # that should typically be Administrator or SYSTEM, both are reported to
      # result in errors by users, thus owners is currently omitted for Windows.

      # ENT-9778
      groups => { "Administrators" };

    freebsd|openbsd|netbsd|darwin::
      groups => { "wheel" };

    linux::
      groups => { "root" };

    solaris::
      groups => { "sys" };

    aix::
      groups => { "system" };
}
acl bodies access_generic

Prototype: access_generic(acl)

Description: Set the aces of the access control as specified

Default/inherited ACLs are left unchanged. This body is applicable for both files and directories on all platforms.

Arguments:

Implementation:

code

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

    windows::
      acl_type => "ntfs";

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

Prototype: ntfs(acl)

Description: Set the aces on NTFS file systems, and overwrite existing ACLs.

This body requires CFEngine Enterprise.

Arguments:

Implementation:

code

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

Prototype: strict

Description: Limit file access via ACLs to users with administrator privileges, overwriting existing ACLs.

Note: May need to take ownership of file/dir to be sure no-one else is allowed access.

Implementation:

code

body acl strict
{
      acl_method => "overwrite";

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

Prototype: recurse(d)

Description: Search files and direcories recursively, up to the specified depth Directories on different devices are excluded.

Arguments:

Implementation:

code

body depth_search recurse(d)
{
      depth => "$(d)";
      xdev  => "true";
}
recurse_ignore

Prototype: recurse_ignore(d, list)

Description: Search files and directories recursively, but don't recurse into the specified directories

Arguments:

Implementation:

code

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

Prototype: include_base

Description: Search files and directories recursively, starting from the base directory.

Implementation:

code

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

Prototype: recurse_with_base(d)

Description: Search files and directories recursively up to the specified depth, starting from the base directory excluding directories on other devices.

Arguments:

Implementation:

code

body depth_search recurse_with_base(d)
{
      depth => "$(d)";
      xdev  => "true";
      include_basedir => "true";
}
delete bodies tidy

Prototype: tidy

Description: Delete the file and remove empty directories and links to directories

Implementation:

code

body delete tidy
{
      dirlinks => "delete";
      rmdirs   => "true";
}
rename bodies disable

Prototype: disable

Description: Disable the file

Implementation:

code

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

Prototype: rotate(level)

Description: Rotate and store up to level backups of the file

Arguments:

Implementation:

code

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

Prototype: to(file)

Description: Rename the file to file

Arguments:

Implementation:

code

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

Prototype: name_age(name, days)

Description: Select files that have a matching name and have not been modified for at least days

Arguments:

Implementation:

code

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";
}
days_old

Prototype: days_old(days)

Description: Select files that have not been modified for at least days

Arguments:

Implementation:

code

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

Prototype: size_range(from, to)

Description: Select files that have a size within the specified range

Arguments:

Implementation:

code

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

Prototype: bigger_than(size)

Description: Select files that are above a given size

Arguments:

Implementation:

code

body file_select bigger_than(size)
{
      search_size => irange("0","$(size)");
      file_result => "!size";
}
exclude

Prototype: exclude(name)

Description: Select all files except those that match name

Arguments:

Implementation:

code

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

Prototype: not_dir

Description: Select all files that are not directories

Implementation:

code

body file_select not_dir
{
      file_types => { "dir" };
      file_result => "!file_types";
}
plain

Prototype: plain

Description: Select plain, regular files

Implementation:

code

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

Prototype: dirs

Description: Select directories

Implementation:

code

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

Prototype: by_name(names)

Description: Select files that match names

Arguments:

Implementation:

code

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

Prototype: ex_list(names)

Description: Select all files except those that match names

Arguments:

Implementation:

code

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

Prototype: all

Description: Select all file system entries

Implementation:

code

body file_select all
{
      leaf_name => { ".*" };
      file_result => "leaf_name";
}
older_than

Prototype: older_than(years, months, days, hours, minutes, seconds)

Description: Select files older than the date-time specified

Arguments:

Generic older_than selection body, aimed to have a common definition handy for every case possible.

Implementation:

code

body file_select older_than(years, months, days, hours, minutes, seconds)
{
      mtime       => irange(0,ago("$(years)","$(months)","$(days)","$(hours)","$(minutes)","$(seconds)"));
      file_result => "mtime";
}
filetype_older_than

Prototype: filetype_older_than(filetype, days)

Description: Select files of specified type older than specified number of days

Arguments:

This body only takes a single filetype, see filetypes_older_than() if you want to select more than one type of file.

Implementation:

code

body file_select filetype_older_than(filetype, days)
{
      file_types => { "$(filetype)" };
      mtime      => irange(0,ago(0,0,"$(days)",0,0,0));
      file_result => "file_types.mtime";
}
filetypes_older_than

Prototype: filetypes_older_than(filetypes, days)

Description: Select files of specified types older than specified number of days

This body only takes a list of filetypes

Arguments:

See also: filetype_older_than()

Implementation:

code

body file_select filetypes_older_than(filetypes, days)
{
      file_types => { @(filetypes) };
      mtime      => irange(0,ago(0,0,"$(days)",0,0,0));
      file_result => "file_types.mtime";
}
symlinked_to

Prototype: symlinked_to(target)

Description: Select symlinks that point to $(target)

Arguments:

Implementation:

code

body file_select symlinked_to(target)
{
  file_types  => { "symlink" };
  issymlinkto => { "$(target)" };
  file_result => "issymlinkto";
}
changes bodies detect_all_change

Prototype: detect_all_change

Description: Detect all file changes using the best hash method

This is fierce, and will cost disk cycles

Implementation:

code

body changes detect_all_change
{
      hash           => "best";
      report_changes => "all";
      update_hashes  => "yes";
}
detect_all_change_using

Prototype: detect_all_change_using(hash)

Description: Detect all file changes using a given hash method

Detect all changes using a configurable hashing algorithm for times when you care about both content and file stats e.g. mtime

Arguments:

Implementation:

code

body changes detect_all_change_using(hash)
{
      hash           => "$(hash)";
      report_changes => "all";
      update_hashes  => "yes";
}
detect_content

Prototype: detect_content

Description: Detect file content changes using md5

This is a cheaper alternative

Implementation:

code

body changes detect_content
{
      hash           => "md5";
      report_changes => "content";
      update_hashes  => "yes";
}
detect_content_using

Prototype: detect_content_using(hash)

Description: Detect file content changes using a given hash algorithm.

For times when you only care about content, not file stats e.g. mtime

Arguments:

Implementation:

code

body changes detect_content_using(hash)
{
      hash           => "$(hash)";
      report_changes => "content";
      update_hashes  => "yes";
}
noupdate

Prototype: noupdate

Description: Detect content changes in (small) files that should never change

Implementation:

code

body changes noupdate
{
      hash           => "sha256";
      report_changes => "content";
      update_hashes  => "no";
}
diff

Prototype: diff

Description: Detect file content changes using sha256 and report the diff to CFEngine Enterprise

Implementation:

code

body changes diff
{
      hash           => "sha256";
      report_changes => "content";
      report_diffs   => "true";
      update_hashes  => "yes";
}
all_changes

Prototype: all_changes

Description: Detect all file changes using sha256 and report the diff to CFEngine Enterprise

Implementation:

code

body changes all_changes
{
      hash           => "sha256";
      report_changes => "all";
      report_diffs   => "true";
      update_hashes  => "yes";
}
diff_noupdate

Prototype: diff_noupdate

Description: Detect content changes in (small) files and report the diff to CFEngine Enterprise

Implementation:

code

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

Prototype: copyfrom_sync(f)

Description: Copy a directory or file with digest checksums, preserving attributes and purging leftovers

Arguments:

Implementation:

code

body copy_from copyfrom_sync(f)
{
      source => "$(f)";
      purge => "true";
      preserve => "true";
      type_check => "false";
      compare => "digest";
}
common bodies files_common

Prototype: files_common

Description: Enumerate policy files used by this policy file for inclusion to inputs

Implementation:

code

bundle common files_common
{
  vars:
      "inputs" slist => { "$(this.promise_dirname)/common.cf" };
}
edit_line bundles insert_before_if_no_line

Prototype: insert_before_if_no_line(before, string)

Description: Insert string before before if string is not found in the file

Arguments:

Implementation:

code

bundle edit_line insert_before_if_no_line(before, string)
{
  insert_lines:
      "$(string)"
        location => before($(before)),
        comment => "Prepend a line to the file if it doesn't already exist";
}
insert_file

Prototype: insert_file(templatefile)

Description: Reads the lines from templatefile and inserts those into the file being edited.

Arguments:

Implementation:

code

bundle edit_line insert_file(templatefile)
{
  insert_lines:

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

Prototype: lines_present(lines)

Description: Ensure lines are present in the file. Lines that do not exist are appended to the file

Arguments:

Example:

code

bundle agent example
{
 vars:
   "nameservers" slist => { "8.8.8.8", "8.8.4.4" };

 files:
     "/etc/resolv.conf" edit_line => lines_present( @(nameservers) );
     "/etc/ssh/sshd_config" edit_line => lines_present( "PermitRootLogin no" );
}

Implementation:

code

bundle edit_line lines_present(lines)
{
  insert_lines:

      "$(lines)"
        comment => "Append lines if they don't exist";
}
insert_lines

Prototype: insert_lines(lines)

Description: Alias for lines_present

Arguments:

Implementation:

code

bundle edit_line insert_lines(lines)
{
  insert_lines:

      "$(lines)"
        comment => "Append lines if they don't exist";
}
append_if_no_line

Prototype: append_if_no_line(lines)

Description: Alias for lines_present

Arguments:

Implementation:

code

bundle edit_line append_if_no_line(lines)
{
  insert_lines:

      "$(lines)"
        comment => "Append lines if they don't exist";
}
append_if_no_lines

Prototype: append_if_no_lines(lines)

Description: Alias for lines_present

Arguments:

Implementation:

code

bundle edit_line append_if_no_lines(lines)
{
  insert_lines:

      "$(lines)"
        comment => "Append lines if they don't exist";
}

Prototype: comment_lines_matching(regex, comment)

Description: Comment lines in the file that matching an anchored regex

Arguments:

Implementation:

code

bundle edit_line comment_lines_matching(regex,comment)
{
  replace_patterns:

      "^($(regex))$"

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

Prototype: contains_literal_string(string)

Description: Ensure the literal string is present in the promised file

Arguments:

Implementation:

code

bundle edit_line contains_literal_string(string)
{

   insert_lines:
     "$(string)"
       insert_type => "preserve_block",
       expand_scalars => "false",
       whitespace_policy => { "exact_match" };
}

Prototype: uncomment_lines_matching(regex, comment)

Description: Uncomment lines of the file where the regex matches the entire text after the comment string

Arguments:

Implementation:

code

bundle edit_line uncomment_lines_matching(regex,comment)
{
  replace_patterns:

      "^$(comment)\s?($(regex))$"

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

Prototype: comment_lines_containing(regex, comment)

Description: Comment lines of the file matching a regex

Arguments:

Implementation:

code

bundle edit_line comment_lines_containing(regex,comment)
{
  replace_patterns:

      "^((?!$(comment)).*$(regex).*)$"

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

Prototype: uncomment_lines_containing(regex, comment)

Description: Uncomment lines of the file where the regex matches parts of the text after the comment string

Arguments:

Implementation:

code

bundle edit_line uncomment_lines_containing(regex,comment)
{
  replace_patterns:

      "^$(comment)\s?(.*$(regex).*)$"

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

Prototype: delete_lines_matching(regex)

Description: Delete lines matching a regular expression

Arguments:

Implementation:

code

bundle edit_line delete_lines_matching(regex)
{
  delete_lines:

      "$(regex)"

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

Prototype: warn_lines_matching(regex)

Description: Warn about lines matching a regular expression

Arguments:

Implementation:

code

bundle edit_line warn_lines_matching(regex)
{
  delete_lines:

      "$(regex)"

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

Prototype: prepend_if_no_line(string)

Description: Prepend string if it doesn't exist in the file

Arguments:

See also:

Implementation:

code

bundle edit_line prepend_if_no_line(string)
{
  insert_lines:
      "$(string)"
      location => start,
      comment => "Prepend a line to the file if it doesn't already exist";
}
replace_line_end

Prototype: replace_line_end(start, end)

Description: Give lines starting with start 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"

Arguments:

Implementation:

code

bundle edit_line replace_line_end(start,end)
{
  field_edits:

      "\s*$(start)\s.*"
      comment => "Replace lines with $(this.start) and $(this.end)",
      edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","set");
}

Prototype: replace_uncommented_substrings(_comment, _find, _replace)

Description: Replace all occurrences of _find with _replace on lines that do not follow a _comment

Arguments:

Example:

code

bundle agent example_replace_uncommented_substrings
{
  files:
    "/tmp/file.txt"
      edit_line => replace_uncommented_substrings( "#", "ME", "YOU");
}

Notes:

History:

Implementation:

code

bundle edit_line replace_uncommented_substrings( _comment, _find, _replace )
{
  vars:
      "_reg_match_uncommented_lines_containing_find"
        string => "^([^$(_comment)]*)\Q$(_find)\E(.*$)";

  replace_patterns:
    "$(_reg_match_uncommented_lines_containing_find)"
      replace_with => text_between_match1_and_match2( $(_replace) );
}
append_to_line_end

Prototype: append_to_line_end(start, end)

Description: Append end to any lines beginning with start

end will be appended to all lines starting with start and not already ending 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 vga=791

WARNING: Be careful not to have multiple promises matching the same line, which would result in the line growing indefinitely.

Arguments:

Example:

code

 files:
     "/tmp/boot-options" edit_line => append_to_line_end("kernel", "vga=791");

Implementation:

code

bundle edit_line append_to_line_end(start,end)
{
  field_edits:

      "\s*$(start)\s.*"
      comment => "Append lines with $(this.start) and $(this.end)",
      edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","append");
}
regex_replace

Prototype: regex_replace(find, replace)

Description: Find exactly a regular expression and replace exactly the match with a string. You can think of this like a PCRE powered sed.

Arguments:

Implementation:

code

bundle edit_line regex_replace(find,replace)
{
  replace_patterns:

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

Prototype: resolvconf(search, list)

Description: Adds search domains and name servers to the system resolver configuration.

Use this bundle to modify resolv.conf. Existing entries for search and nameserver are replaced.

Arguments:

Implementation:

code

bundle edit_line resolvconf(search,list)
{
  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";
}
resolvconf_o

Prototype: resolvconf_o(search, list, options)

Description: Adds search domains, name servers and options to the system resolver configuration.

Use this bundle to modify resolv.conf. Existing entries for search, nameserver and options are replaced.

Arguments:

Implementation:

code

bundle edit_line resolvconf_o(search,list,options)
{
  delete_lines:

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

  insert_lines:

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

Prototype: manage_variable_values_ini(tab, sectionName)

Description: 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. Removes any variable value pairs not defined for the ini section.

Arguments:

See also: set_variable_values_ini()

Implementation:

code

bundle edit_line manage_variable_values_ini(tab, sectionName)
{
  vars:
      "index" slist => getindices("$(tab)[$(sectionName)]");

  delete_lines:
      ".*"
      select_region => INI_section(escape("$(sectionName)")),
      comment       => "Remove all entries in the region so there are no extra entries";

  insert_lines:
      "[$(sectionName)]"
      location => start,
      comment => "Insert lines";

      "$(index)=$($(tab)[$(sectionName)][$(index)])"
      select_region => INI_section(escape("$(sectionName)"));
}
set_variable_values_ini

Prototype: set_variable_values_ini(tab, sectionName)

Description: 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.

Arguments:

See also: manage_variable_values_ini()

Implementation:

code

bundle edit_line set_variable_values_ini(tab, sectionName)
{
  vars:
      "index" slist => getindices("$(tab)[$(sectionName)]");

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

  classes:
      "edit_$(cindex[$(index)])"     not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"),
      comment => "Create conditions to make changes";

  field_edits:

      # If the line is there, but commented out, first uncomment it
      "#+\s*$(index)\s*=.*"
      select_region => INI_section(escape("$(sectionName)")),
      edit_field => col("\s*=\s*","1","$(index)","set"),
      if => "edit_$(cindex[$(index)])";

      # match a line starting like the key something
      "\s*$(index)\s*=.*"
      edit_field => col("\s*=\s*","2","$($(tab)[$(sectionName)][$(index)])","set"),
      select_region => INI_section(escape("$(sectionName)")),
      classes => results("bundle", "set_variable_values_ini_not_$(cindex[$(index)])"),
      if => "edit_$(cindex[$(index)])";

  insert_lines:
      "[$(sectionName)]"
      location => start,
      comment => "Insert lines";

      "$(index)=$($(tab)[$(sectionName)][$(index)])"
      select_region => INI_section(escape("$(sectionName)")),
        if => "!(set_variable_values_ini_not_$(cindex[$(index)])_kept|set_variable_values_ini_not_$(cindex[$(index)])_repaired).edit_$(cindex[$(index)])";

}
insert_ini_section

Prototype: insert_ini_section(name, config)

Description: Inserts a INI section with content

code

# given an array "barray"
files:
    "myfile.ini" edit_line => insert_ini_section("foo", "barray");

Inserts a section in an INI file with the given configuration key-values from the array config.

Arguments:

Implementation:

code

bundle edit_line insert_ini_section(name, config)
{
  vars:
      # TODO: refactor once 3.7.x is EOL
      "indices" slist => getindices($(config));
      "k" slist => sort("indices", lex);

  insert_lines:
      "[$(name)]"
      location => start,
      comment => "Insert an ini section with values if not present";

      "$(k)=$($(config)[$(k)])"
      location => after("[$(name)]");
}
set_quoted_values

Prototype: set_quoted_values(v)

Description: Sets the RHS of variables in shell-like files of the form:

Adds a new line if no LHS exists, and replaces RHS values if one does exist. If the line is commented out with #, it gets uncommented first.

Arguments:

Example:

code

    vars:
       "stuff[lhs-1]" string => "rhs1";
       "stuff[lhs-2]" string => "rhs2";

    files:
       "myfile"
         edit_line => set_quoted_values(stuff)

See also: set_variable_values()

Implementation:

code

bundle edit_line set_quoted_values(v)
{
  meta:
      "tags"
      slist =>
      {
        "deprecated=3.6.0",
        "deprecation-reason=Generic reimplementation",
        "replaced-by=set_line_based"
      };

  vars:
      "index" slist => getindices("$(v)");
      # Be careful if the index string contains funny chars

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

  field_edits:
      # If the line is there, but commented out, first uncomment it
      "#+\s*$(index)\s*=.*"
      edit_field => col("=","1","$(index)","set");

      # match a line starting like the key = something
      "\s*$(index)\s*=.*"
      edit_field => col("=","2",'"$($(v)[$(index)])"',"set"),
      classes    => results("bundle", "$(cindex[$(index)])_in_file"),
      comment    => "Match a line starting like key = something";

  insert_lines:
      '$(index)="$($(v)[$(index)])"'
      comment    => "Insert a variable definition",
        if => "!($(cindex[$(index)])_in_file_kept|$(cindex[$(index)])_in_file_repaired)";
}
set_variable_values

Prototype: set_variable_values(v)

Description: Sets the RHS of variables in files of the form:

Adds a new line if no LHS exists, and replaces RHS values if one does exist. If the line is commented out with #, it gets uncommented first.

Arguments:

Example:

code

    vars:
       "stuff[lhs-1]" string => "rhs1";
       "stuff[lhs-2]" string => "rhs2";

    files:
       "myfile"
         edit_line => set_variable_values(stuff)

See also: set_quoted_values()

Implementation:

code

bundle edit_line set_variable_values(v)
{
  meta:
      "tags"
      slist =>
      {
        "deprecated=3.6.0",
        "deprecation-reason=Generic reimplementation",
        "replaced-by=set_line_based"
      };

  vars:

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

      # Be careful if the index string contains funny chars

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

  field_edits:

      # match a line starting like the key = something

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

      edit_field => col("\s*$(index)\s*=","2","$($(v)[$(index)])","set"),
      classes => results("bundle", "$(cv)_$(cindex[$(index)])_in_file"),
      comment => "Match a line starting like key = something";

  insert_lines:

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

      comment => "Insert a variable definition",
        if => "!($(cv)_$(cindex[$(index)])_in_file_kept|$(cv)_$(cindex[$(index)])_in_file_repaired)";
}
set_config_values

Prototype: set_config_values(v)

Description: Sets the RHS of configuration items in the file of the form:

If the line is commented out with #, it gets uncommented first.

Adds a new line if none exists.

Arguments:

Implementation:

code

bundle edit_line set_config_values(v)
{
  meta:
      "tags"
      slist =>
      {
        "deprecated=3.6.0",
        "deprecation-reason=Generic reimplementation",
        "replaced-by=set_line_based"
      };

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

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

      # Escape the value (had a problem with special characters and regex's)
      "ev[$(index)]" string => escape("$($(v)[$(index)])");

      # Do we have more than one line commented out?
      "index_comment_matches_$(cindex[$(index)])"
        int => countlinesmatching("^\s*#\s*($(index)\s+.*|$(index))$","$(edit.filename)");


  classes:
      # Check to see if this line exists
      "line_exists_$(cindex[$(index)])"
        expression => regline("^\s*($(index)\s.*|$(index))$","$(edit.filename)"),
        scope => "bundle";

      # if there's more than one comment, just add new (don't know who to use)
      "multiple_comments_$(cindex[$(index)])"
        expression => isgreaterthan("$(index_comment_matches_$(cindex[$(index)]))","1"),
        scope => "bundle";

  replace_patterns:
      # If the line is commented out, uncomment and replace with
      # the correct value
      "^\s*#\s*($(index)\s+.*|$(index))$"
        comment => "If we find a single commented entry we can uncomment it to
                    keep the settings near any inline documentation. If there
                    are multiple comments, then we don't try to replace them and
                    instead will later append the new value after the first
                    commented occurrence of $(index).",
        handle => "set_config_values_replace_commented_line",
        replace_with => value("$(index) $($(v)[$(index)])"),
                  if => "!line_exists_$(cindex[$(index)]).!replace_attempted_$(cindex[$(index)])_reached.!multiple_comments_$(cindex[$(index)])",
             classes => results("bundle", "uncommented_$(cindex[$(index)])");

      # If the line is there with the wrong value, replace with
      # the correct value
      "^\s*($(index)\s+(?!$(ev[$(index)])$).*|$(index))$"
           comment => "Correct the value $(index)",
      replace_with => value("$(index) $($(v)[$(index)])"),
           classes => results("bundle", "replace_attempted_$(cindex[$(index)])");

  insert_lines:
      # If the line doesn't exist, or there is more than one occurrence
      # of the LHS commented out, insert a new line and try to place it
      # after the commented LHS (keep new line with old comments)
      "$(index) $($(v)[$(index)])"
         comment => "Insert the value, marker exists $(index)",
        location => after("^\s*#\s*($(index)\s+.*|$(index))$"),
              if => "replace_attempted_$(cindex[$(index)])_reached.multiple_comments_$(cindex[$(index)])";

      # If the line doesn't exist and there are no occurrences
      # of the LHS commented out, insert a new line at the eof
      "$(index) $($(v)[$(index)])"
         comment => "Insert the value, marker doesn't exist $(index)",
              if => "replace_attempted_$(cindex[$(index)])_reached.!multiple_comments_$(cindex[$(index)])";

}
set_line_based

Prototype: set_line_based(v, sep, bp, kp, cp)

Description: Sets the RHS of configuration items in the file of the form:

Example usage for x=y lines (e.g. rsyncd.conf):

code

"myfile"
edit_line => set_line_based("test.config", "=", "\s*=\s*", ".*", "\s*#\s*");

Example usage for x y lines (e.g. sshd_config):

code

"myfile"
edit_line => set_line_based("test.config", " ", "\s+", ".*", "\s*#\s*");

If the line is commented out with $(cp), it gets uncommented first.

Adds a new line if none exists or if more than one commented-out possible matches exist.

Note: If the data structure being used for the first parameter is in the current bundle, you can use $(this.bundle).variable.

Originally set_config_values by Ed King.

Arguments:

Implementation:

code

bundle edit_line set_line_based(v, sep, bp, kp, cp)
{
  meta:
      "tags"
      slist =>
      {
        "replaces=set_config_values",
        "replaces=set_config_values_matching",
        "replaces=set_variable_values",
        "replaces=set_quoted_values",
        "replaces=maintain_key_values",
      };

  vars:
      "vkeys" slist => getindices("$(v)");
      "i" slist => grep($(kp), vkeys);

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

      # Escape the value (had a problem with special characters and regex's)
      "ev[$(i)]" string => escape("$($(v)[$(i)])");

      # Do we have more than one line commented out?
      "comment_matches_$(ci[$(i)])"
      int => countlinesmatching("^$(cp)($(i)$(bp).*|$(i))$",
                                $(edit.filename));


  classes:
      # 3.21.0 and greater know about a file being emptied before editing and
      # skip this check since it does not make sense.
@if minimum_version(3.21)
      # Check to see if this line exists
      "exists_$(ci[$(i)])"
      expression => regline("^\s*($(i)$(bp).*|$(i))$",
                            $(edit.filename)),
      unless => strcmp( "true", $(edit.empty_before_use) );
@endif

@if minimum_version(3.18)
    !(cfengine_3_18_0|cfengine_3_18_1|cfengine_3_18_2)::
      "exists_$(ci[$(i)])"
        expression => regline("^\s*($(i)$(bp).*|$(i))$",
                              $(edit.filename)),
        unless => strcmp( "true", $(edit.empty_before_use) );
@endif

    (cfengine_3_15|cfengine_3_16|cfengine_3_17|cfengine_3_18_0|cfengine_3_18_1|cfengine_3_18_2|cfengine_3_19|cfengine_3_20)::
      # Version 3.15.0 does not know about the before_version macro, so we keep the same behavior
      # TODO Remove after 3.21 is no longer supported. (3.15.0 was supported when 3.21 was released)
      # Check to see if this line exists
      "exists_$(ci[$(i)])"
        expression => regline("^\s*($(i)$(bp).*|$(i))$",
                              $(edit.filename));

    any::

      # if there's more than one comment, just add new (don't know who to use)
      "multiple_comments_$(ci[$(i)])"
      expression => isgreaterthan("$(comment_matches_$(ci[$(i)]))",
                                  "1");


  replace_patterns:
      # If the line is commented out, uncomment and replace with
      # the correct value
      "^$(cp)($(i)$(bp).*|$(i))$"
             comment => "Uncommented the value '$(i)'",
        replace_with => value("$(i)$(sep)$($(v)[$(i)])"),
                  if => "!exists_$(ci[$(i)]).!replace_attempted_$(ci[$(i)])_reached.!multiple_comments_$(ci[$(i)])",
             classes => results("bundle", "uncommented_$(ci[$(i)])");

      # If the line is there with the wrong value, replace with
      # the correct value
      "^\s*($(i)$(bp)(?!$(ev[$(i)])$).*|$(i))$"
           comment => "Correct the value '$(i)'",
      replace_with => value("$(i)$(sep)$($(v)[$(i)])"),
           classes => results("bundle", "replace_attempted_$(ci[$(i)])");

  insert_lines:
      # If the line doesn't exist, or there is more than one occurrence
      # of the LHS commented out, insert a new line and try to place it
      # after the commented LHS (keep new line with old comments)
      "$(i)$(sep)$($(v)[$(i)])"
         comment => "Insert the value, marker '$(i)' exists",
        location => after("^$(cp)($(i)$(bp).*|$(i))$"),
              if => "replace_attempted_$(ci[$(i)])_reached.multiple_comments_$(ci[$(i)])";

      # If the line doesn't exist and there are no occurrences
      # of the LHS commented out, insert a new line at the eof
      "$(i)$(sep)$($(v)[$(i)])"
         comment => "Insert the value, marker '$(i)' doesn't exist",
              if => "replace_attempted_$(ci[$(i)])_reached.!multiple_comments_$(ci[$(i)]).!exists_$(ci[$(i)])";

  reports:
    verbose_mode|EXTRA::
      "$(this.bundle): Line for '$(i)' exists" if => "exists_$(ci[$(i)])";
      "$(this.bundle): Line for '$(i)' does not exist" if => "!exists_$(ci[$(i)])";
}
set_config_values_matching

Prototype: set_config_values_matching(v, pat)

Description: Sets the RHS of configuration items in the file of the form

If the line is commented out with #, it gets uncommented first. Adds a new line if none exists.

Arguments:

Implementation:

code

bundle edit_line set_config_values_matching(v,pat)
{
  meta:
      "tags"
      slist =>
      {
        "deprecated=3.6.0",
        "deprecation-reason=Generic reimplementation",
        "replaced-by=set_line_based"
      };

  vars:
      "allparams" slist => getindices("$(v)");
      "index"     slist => grep("$(pat)", "allparams");

      # 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+.*)$"
      comment => "Correct the value",
      replace_with => value("$(index) $($(v)[$(index)])"),
      classes => results("bundle", "replace_attempted_$(cindex[$(index)])");

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

}
maintain_key_values

Prototype: maintain_key_values(v, sep)

Description: Sets the RHS of configuration items with an giving separator

Contributed by David Lee

Arguments:

Implementation:

code

bundle edit_line maintain_key_values(v,sep)
{
  meta:
      "tags"
      slist =>
      {
        "deprecated=3.6.0",
        "deprecation-reason=Generic reimplementation",
        "replaced-by=set_line_based"
      };

  vars:
      "index" slist => getindices("$(v)");
      # Be careful if the index string contains funny chars
      "cindex[$(index)]" string => canonify("$(index)");
      # Matching pattern for line (basically key-and-separator)
      "keypat[$(index)]" string => "\s*$(index)\s*$(sep)\s*";

      # Values may contain regexps. Escape them for replace_pattern matching.
      "ve[$(index)]" string => escape("$($(v)[$(index)])");

  classes:
      "$(cindex[$(index)])_key_in_file"
      comment => "Dynamic Class created if patterns matching",
      expression => regline("^$(keypat[$(index)]).*", "$(edit.filename)");

  replace_patterns:
      # For convergence need to use negative lookahead on value:
      # "key sep (?!value).*"
      "^($(keypat[$(index)]))(?!$(ve[$(index)])$).*"
      comment => "Replace definition of $(index)",
      replace_with => value("$(match.1)$($(v)[$(index)])");

  insert_lines:
      "$(index)$(sep)$($(v)[$(index)])"
      comment => "Insert definition of $(index)",
      if => "!$(cindex[$(index)])_key_in_file";
}
append_users_starting

Prototype: append_users_starting(v)

Description: For adding to /etc/passwd or etc/shadow

Arguments:

Note: To manage local users with CFEngine 3.6 and later, consider making users promises instead of modifying system files.

Implementation:

code

bundle edit_line append_users_starting(v)
{
  vars:

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

  classes:

      "add_$(index)"     not => userexists("$(index)"),
      comment => "Class created if user does not exist";

  insert_lines:

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

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

Prototype: append_groups_starting(v)

Description: For adding groups to /etc/group

Arguments:

Note: To manage local users with CFEngine 3.6 and later, consider making users promises instead of modifying system files.

Implementation:

code

bundle edit_line append_groups_starting(v)
{
  vars:

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

  classes:

      "add_$(index)"     not => groupexists("$(index)"),
      comment => "Class created if group does not exist";

  insert_lines:

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

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

}
set_colon_field

Prototype: set_colon_field(key, field, val)

Description: Set the value of field number field of the line whose first field is key to the value val, in a colon-separated file.

Arguments:

Implementation:

code

bundle edit_line set_colon_field(key,field,val)
{
  field_edits:

      "$(key):.*"

      comment => "Edit a colon-separated file, using the first field as a key",
      edit_field => col(":","$(field)","$(val)","set");
}
set_user_field

Prototype: set_user_field(user, field, val)

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

Arguments:

Note: To manage local users with CFEngine 3.6 and later, consider making users promises instead of modifying system files.

See also:

Implementation:

code

bundle edit_line set_user_field(user,field,val)
{
  field_edits:

      "$(user):.*"

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

Prototype: set_escaped_user_field(user, field, val)

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

Arguments:

Note: To manage local users with CFEngine 3.6 and later, consider making users promises instead of modifying system files.

See also:

Implementation:

code

bundle edit_line set_escaped_user_field(user,field,val)
{
  vars:
      "escaped_user"
        string => escape( "$(user)" );

  field_edits:

      "$(escaped_user):.*"

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

Prototype: append_user_field(group, field, allusers)

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

Arguments:

Note: To manage local users with CFEngine 3.6 and later, consider making users promises instead of modifying system files.

Implementation:

code

bundle edit_line append_user_field(group,field,allusers)
{
  field_edits:

      "$(group):.*"

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

Prototype: expand_template(templatefile)

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

Arguments:

Implementation:

code

bundle edit_line expand_template(templatefile)
{
  insert_lines:

      "$(templatefile)"

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

Prototype: replace_or_add(pattern, line)

Description: Replace a pattern in a file with a single line.

If the pattern is not found, add the line to the file.

Arguments:

Implementation:

code

bundle edit_line replace_or_add(pattern,line)
{
  vars:
      "cline" string => canonify("$(line)");
      "eline" string => escape("$(line)");

  replace_patterns:
      "^(?!$(eline)$)$(pattern)$"
      comment => "Replace a pattern here",
      replace_with => value("$(line)"),
      classes => results("bundle", "replace_$(cline)");

  insert_lines:
      "$(line)"
      if => "replace_$(cline)_reached";
}
converge

Prototype: converge(marker, lines)

Description: Converge lines marked with marker

Any content marked with marker is removed, then lines are inserted. Every line should contain marker.

Arguments:

Example:

code

bundle agent pam_d_su_include
#@brief Ensure /etc/pam.d/su has includes configured properly
{
  files:
    ubuntu::
      "/etc/pam.d/su"
        edit_line => converge( "@include", "@include common-auth

**Implementation:**


```cf3
bundle edit_line converge(marker, lines)
{
  vars:
      "regex" string => escape($(marker));

  delete_lines:
      ".*$(regex).*" comment => "Delete lines matching the marker";
  insert_lines:
      "$(lines)" comment => "Insert the given lines";
}
converge_prepend

Prototype: converge_prepend(marker, lines)

Description: Converge lines marked with marker to start of content

Any content marked with marker is removed, then lines are inserted at start of content. Every line should contain marker.

Arguments:

Example:

code

bundle agent pam_d_su_session
#@brief Ensure /etc/pam.d/su has session configured properly
{
  files:
    ubuntu::
      "/etc/pam.d/su"
        edit_line => converge_prepend( "session", "session       required   pam_env.so readenv=1 envfile=/etc/default/locale
session    optional   pam_mail.so nopen
session    required   pam_limits.so" );
}

History:

Implementation:

code

bundle edit_line converge_prepend(marker, lines)
{
  vars:
      "regex" string => escape($(marker));

  delete_lines:
      ".*$(regex).*" comment => "Delete lines matching the marker";
  insert_lines:
      "$(lines)" location => start, comment => "Insert the given lines";
}
fstab_option_editor

Prototype: fstab_option_editor(method, mount, option)

Description: Add or remove /etc/fstab options for a mount

This bundle edits the options field of a mount. The method is a field_operation which can be append, prepend, set, delete, or alphanum. The option is OS-specific.

Arguments:

Example:

code

 files:
     "/etc/fstab" edit_line => fstab_option_editor("delete", "/", "acl");
     "/etc/fstab" edit_line => fstab_option_editor("append", "/", "acl");

Implementation:

code

bundle edit_line fstab_option_editor(method, mount, option)
{
   field_edits:
      "(?!#)\S+\s+$(mount)\s.+"
      edit_field => fstab_options($(option), $(method));
}
agent bundles file_mustache

Prototype: file_mustache(mustache_file, json_file, target_file)

Description: Make a file from a Mustache template and a JSON file

Arguments:

Example:

code

methods:
     "m" usebundle => file_mustache("x.mustache", "y.json", "z.txt");

Implementation:

code

bundle agent file_mustache(mustache_file, json_file, target_file)
{
  files:
      "$(target_file)"
      create => "true",
      edit_template => $(mustache_file),
      template_data => readjson($(json_file), "100k"),
      template_method => "mustache";
}
file_mustache_jsonstring

Prototype: file_mustache_jsonstring(mustache_file, json_string, target_file)

Description: Make a file from a Mustache template and a JSON string

Arguments:

Example:

code

methods:
     "m" usebundle => file_mustache_jsonstring("x.mustache", '{ "x": "y" }', "z.txt");

Implementation:

code

bundle agent file_mustache_jsonstring(mustache_file, json_string, target_file)
{
  files:
      "$(target_file)"
      create => "true",
      edit_template => $(mustache_file),
      template_data => parsejson($(json_string)),
      template_method => "mustache";
}
file_tidy

Prototype: file_tidy(file)

Description: Remove a file

Arguments:

Example:

code

methods:
     "" usebundle => file_tidy("/tmp/z.txt");

Implementation:

code

bundle agent file_tidy(file)
{
  files:
      "$(file)" delete => tidy;

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): deleting $(file) with delete => tidy";
}
dir_sync

Prototype: dir_sync(from, to)

Description: Synchronize a directory entire, deleting unknown files

Arguments:

Example:

code

methods:
     "" usebundle => dir_sync("/tmp", "/var/tmp");

Implementation:

code

bundle agent dir_sync(from, to)
{
  files:
      "$(to)/."
      create => "true",
      depth_search => recurse("inf"),
      copy_from => copyfrom_sync($(from));

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): copying directory $(from) to $(to)";
}
file_copy

Prototype: file_copy(from, to)

Description: Copy a file

Arguments:

Example:

code

methods:
     "" usebundle => file_copy("/tmp/z.txt", "/var/tmp/y.txt");

Implementation:

code

bundle agent file_copy(from, to)
{
  files:
      "$(to)"
      copy_from => copyfrom_sync($(from));

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): copying file $(from) to $(to)";
}
file_make

Prototype: file_make(file, str)

Description: Make a file from a string

Arguments:

Example:

code

methods:
     "" usebundle => file_make("/tmp/z.txt", "Some text
and some more text here");

Implementation:

code

bundle agent file_make(file, str)
{
  vars:
      "len" int => string_length($(str));
    summarize::
      "summary" string => format("%s...%s",
                                string_head($(str), 18),
                                string_tail($(str), 18));
  classes:
      "summarize" expression => isgreaterthan($(len), 40);

  files:
      "$(file)"
      create => "true",
      edit_line => insert_lines($(str)),
      edit_defaults => empty;

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): creating $(file) with contents '$(str)'"
      if => "!summarize";

      "DEBUG $(this.bundle): creating $(file) with contents '$(summary)'"
      if => "summarize";
}
file_make_mog

Prototype: file_make_mog(file, str, mode, owner, group)

Description: Make a file from a string with mode, owner, group

Arguments:

Example:

code

methods:
     "" usebundle => file_make_mog("/tmp/z.txt", "Some text
and some more text here", "0644", "root", "root");

Implementation:

code

bundle agent file_make_mog(file, str, mode, owner, group)
{
  vars:
      "len" int => string_length($(str));
    summarize::
      "summary" string => format("%s...%s",
                                string_head($(str), 18),
                                string_tail($(str), 18));
  classes:
      "summarize" expression => isgreaterthan($(len), 40);

  files:
      "$(file)"
      create => "true",
      edit_line => insert_lines($(str)),
      perms => mog($(mode), $(owner), $(group)),
      edit_defaults => empty;

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): creating $(file) with contents '$(str)', mode '$(mode)', owner '$(owner)' and group '$(group)'"
      if => "!summarize";

      "DEBUG $(this.bundle): creating $(file) with contents '$(summary)', mode '$(mode)', owner '$(owner)' and group '$(group)'"
      if => "summarize";
}
file_make_mustache

Prototype: file_make_mustache(file, template, data)

Description: Make a file from a mustache template

Arguments:

Example:

code

vars:
  "state" data => datastate();

methods:
     "" usebundle => file_make_mustache( "/tmp/z.txt", "/tmp/z.mustache", @(state) );

Implementation:

code

bundle agent file_make_mustache(file, template, data)
{
  files:
      "$(file)"
        create => "true",
        edit_template => "$(template)",
        template_method => "mustache",
        template_data => @(data);

  reports:
      "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): rendering $(file) with template '$(template)'";
}
file_make_mustache_with_perms

Prototype: file_make_mustache_with_perms(file, template, data, mode, owner, group)

Description: Make a file from a mustache template

Arguments:

Example:

code

vars:
  "state" data => datastate();

methods:
     "" usebundle => file_make_mustache( "/tmp/z.txt", "/tmp/z.mustache", @(state),
                                         600, "root", "root" );

Implementation:

code

bundle agent file_make_mustache_with_perms(file, template, data, mode, owner, group)
{
  files:
      "$(file)"
        create => "true",
        edit_template => "$(template)",
        template_method => "mustache",
        perms => mog( $(mode), $(owner), $(group) ),
        template_data => @(data);

  reports:
      "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): rendering $(file) with template '$(template)'";
}
file_empty

Prototype: file_empty(file)

Description: Make an empty file

Arguments:

Example:

code

methods:
     "" usebundle => file_empty("/tmp/z.txt");

Implementation:

code

bundle agent file_empty(file)
{
  files:
      "$(file)"
      create => "true",
      edit_defaults => empty;

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): creating empty $(file) with 0 size";
}
file_hardlink

Prototype: file_hardlink(target, link)

Description: Make a hard link to a file

Arguments:

Example:

code

methods:
     "" usebundle => file_hardlink("/tmp/z.txt", "/tmp/z.link");

Implementation:

code

bundle agent file_hardlink(target, link)
{
  files:
      "$(link)"
      move_obstructions => "true",
      link_from => linkfrom($(target), "hardlink");

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): $(link) will be a hard link to $(target)";
}
file_link

Prototype: file_link(target, link)

Description: Make a symlink to a file

Arguments:

Example:

code

methods:
     "" usebundle => file_link("/tmp/z.txt", "/tmp/z.link");

Implementation:

code

bundle agent file_link(target, link)
{
  files:
      "$(link)"
      move_obstructions => "true",
      link_from => linkfrom($(target), "symlink");

  reports:
    "DEBUG|DEBUG_$(this.bundle)"::
      "DEBUG $(this.bundle): $(link) will be a symlink to $(target)";
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4