copy relative symbolic links

53 views
Skip to first unread message

Merlin Mittelbach

unread,
Mar 23, 2018, 7:51:44 AM3/23/18
to help-cfengine
Hello,
I am trying to copy this directory with its children from the policy server to the remote host:

lrwxrwxrwx 1 root root   17  1. Feb 18:00 1e09d511.0 -> ./rootcert_g2.pem
lrwxrwxrwx 1 root root   14  1. Feb 18:00 4e18c148.0 -> ./rootcert.pem
lrwxrwxrwx 1 root root   24  1. Feb 18:00 6107e209.0 -> ./intermediatecacert.pem
lrwxrwxrwx 1 root root   15  1. Feb 18:00 6ab64010.0 -> ./cacert_g2.pem
lrwxrwxrwx 1 root root   12  1. Feb 18:00 760ed126.0 -> ./cacert.pem
lrwxrwxrwx 1 root root   14  1. Feb 18:00 812e17de.0 -> ./rootcert.pem
lrwxrwxrwx 1 root root   27  1. Feb 18:00 8dcb65b2.0 -> ./intermediatecacert_g2.pem
lrwxrwxrwx 1 root root   24  1. Feb 18:00 aaa0e946.0 -> ./intermediatecacert.pem
-rw-r--r-- 1 root root 2,0K  6. Feb 10:49 cacert_g2.pem
-rw-r--r-- 1 root root 1,9K  6. Feb 10:49 cacert.pem
lrwxrwxrwx 1 root root   12  1. Feb 18:00 ec9ca246.0 -> ./cacert.pem
-rw-r--r-- 1 root root 1,8K  6. Feb 10:49 intermediatecacert_g2.pem
-rw-r--r-- 1 root root 1,7K  6. Feb 10:49 intermediatecacert.pem
-rw-r--r-- 1 root root 1,4K  6. Feb 10:49 rootcert_g2.pem
-rw-r--r-- 1 root root 1,3K  6. Feb 10:49 rootcert.pem


My copy_from body looks like this:

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


Unfortunately the links aren't copied, but resolved and the resulting file is copied. I tried to play around with the copylink_patterns and linkcopy_patterns.
Any hint how to do this?
Cheers Merlin.

Aleksey Tsalolikhin

unread,
Mar 23, 2018, 8:09:56 AM3/23/18
to Merlin Mittelbach, help-cfengine
I'm on the go now but I'll mention there are a few attributes the deal with links on the following page: https://docs.cfengine.com/docs/3.10/reference-promise-types-files.html#copylink_patterns

--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengin...@googlegroups.com.
To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

Nick Anderson

unread,
Mar 23, 2018, 9:10:19 AM3/23/18
to Aleksey Tsalolikhin, Merlin Mittelbach, help-cfengine

Hi Merlin,

I don't think that you need copylink_patterns, it defines a list of regular expressions matching files that should be copied instead of linked, which is the opposite of what you want.

There is also linkcopy_patterns which is a list of regular expressions matching filenames that should be symlinked and not copied. You can use this to create a symlink mirror locally. Also not what you are looking for.

What version of CFEngine are you running? I am able to copy a file tree
recursively and preserve symlinks. Note that I am using depth_search, and file_select in my files type promise to mirror the directory. Also I am only testing this locally, should be straight forward to convert into a remote copy.

mkdir -p /tmp/source/
echo "Hello world" > /tmp/source/file.txt
cd /tmp/source
ln -s file symlink
ls -al /tmp/source
bundle agent main
{
  files:
      "/tmp/dest/." create => "true";

      "/tmp/dest/."
        copy_from => sync_including_symlinks( "/tmp/source/." ),
        depth_search => recurse(inf), # Search the entire directory tree down
        file_select => all,           # Select all files
        move_obstructions => "true";  # Move things so you can ensure links
                                      # and dirs are proper mirrors
  reports:
    "CFEngine $(sys.cf_version)";
    "$(with)" with => execresult( "ls -al /tmp/dest/", useshell);
}

body copy_from sync_including_symlinks( source_path )
{
  source      => "$(source_path)";
  compare     => "digest";
  verify      => "true";
  purge       => "true";
  copy_backup => "false"; # Don't make .cfsaved files

  # no-op when using TLS (3.7.0 and newer)
  # encrypt     => "true";

  # I am doing a local copy 
  # servers     => { "$(server)" };
}

# Duplicated inline from the stdlib
body file_select all
# @brief Select all file system entries
{
      leaf_name => { ".*" };
      file_result => "leaf_name";
}
body depth_search recurse(d)
# @brief Search files and direcories recursively, up to the specified depth
# Directories on different devices are included.
#
# @param d The maximum search depth
{
      depth => "$(d)";
      xdev  => "true";
}

After running the policy we get a mirror that looks like this:

R: CFEngine 3.11.0
R: total 4568
drwxr-xr-x   2 nickanderson nickanderson    4096 Mar 23 08:02 .
drwxrwxrwt+ 30 root         root         4665344 Mar 23 08:05 ..
-rw-rw-r--   1 nickanderson nickanderson      12 Mar 23 08:02 file.txt
lrwxrwxrwx   1 nickanderson nickanderson       8 Mar 23 08:02 symlink -> file.txt


Nick Anderson
Doer of things, CFEngine

Merlin Mittelbach

unread,
Mar 23, 2018, 9:46:45 AM3/23/18
to help-cfengine
@Aleksey Tsalolikhin
I tried that without success.

@Nick
I tried that. But it is only working for a local copy. Did you try to copy the directory via the cf-serverd?
Btw I am on v3.11.0 as well.

Cheers

Nick Anderson

unread,
Mar 23, 2018, 11:28:04 AM3/23/18
to help-cfengine
Indeed, when i make it a remote copy, the relative symlink is not preserved. It is converged to a plain file.


```
 verbose: file_select result 'leaf_name' on '/tmp/source/./symlink' was 'true'
 verbose: '/tmp/dest/./symlink' wasn't at destination (copying)
    info: Copying from '192.168.33.2:/tmp/source/./symlink'
 verbose: Copying remote file '192.168.33.2:/tmp/source/./symlink', expecting 12 bytes
 verbose: Copy of regular file succeeded '/tmp/source/./symlink' to '/tmp/dest/./symlink.cfnew'
 verbose: Final verification of transmission ...
 verbose: New file '/tmp/dest/./symlink.cfnew' transmitted correctly - verified
 verbose: Additional promise info: version 'CFEngine Promises.cf 3.10.3' source path '/var/cfengine/inputs/services/main.cf' at line 31
 verbose: File permissions on '/tmp/dest/./symlink' as promised
 verbose: Additional promise info: version 'CFEngine Promises.cf 3.10.3' source path '/var/cfengine/inputs/services/main.cf' at line 31
 verbose: Updated file from '192.168.33.2:/tmp/source/./symlink'
```

Nick Anderson

unread,
Mar 23, 2018, 11:50:29 AM3/23/18
to help-cfengine

Merlin Mittelbach

unread,
Apr 5, 2018, 3:34:26 AM4/5/18
to help-cfengine
Thanks for your help. I work around that problem by just creating the links by hand.
But I am looking forward to see that issue fixed.
Cheers

Marco Marongiu

unread,
Apr 9, 2018, 10:39:20 AM4/9/18
to help-c...@googlegroups.com


On 05/04/18 09:34, Merlin Mittelbach wrote:
> Thanks for your help. I work around that problem by just creating the
> links by hand.

Couldn't you use a commands promise for that then?
Reply all
Reply to author
Forward
0 new messages