Skip to content

link

link makes sure a symbolic link exists and points where you say, or that it does not exist. It reads the link with readlink, creates or repoints it with ln -sfn, and removes it with rm -f. Use it for the classic "enabled" links (sites-enabled/app), for a current link between releases, and to put a program on the PATH.

New in 0.2.0

Minimal example

link "/etc/nginx/sites-enabled/app", to: "/etc/nginx/sites-available/app"

Options

Option Type Default Description
to String required Where the link points. Stored as given: a relative target such as "releases/2" is relative to the link's directory. The target does not have to exist.
state :present or :absent :present :absent removes the link.
force true or false false Replace a regular file that is where the link should be. Without it, a file in the way is an error.
notifies [:action, "type[name]"], optionally with :immediately, or a list of them none Actions to run on other resources when this one changes. See Notifications.
subscribes [:action, "type[name]"], optionally with :immediately, or a list of them none Actions to run on this resource when another one changes.
tags Symbol, String, or an Array of them none Tags for running part of a recipe with --tags and --skip-tags. See Tags.

The link's directory must exist; declare it with a directory resource first if it does not. A directory where the link should be is always an error, even with force: true.

Scenarios

examples/resources/link/recipe.rb
# Two releases of an application side by side, and a link that says which
# one is live: deploying another release is a change to the link.
directory "/srv/app/releases/1"
directory "/srv/app/releases/2"
file "/srv/app/releases/2/console", content: "#!/bin/sh\necho \"release 2\"\n", mode: "0755"
link "/srv/app/current", to: "releases/2"

# A command on the PATH that runs whichever release is live.
link "/usr/local/bin/app-console", to: "/srv/app/current/console"

# A link that must not exist.
link "/usr/local/bin/old-console", state: :absent
$ sudo sadame apply examples/resources/link
sadame 0.5.1 apply on local (Debian GNU/Linux 12 (bookworm))

changed    directory[/srv/app/releases/1]
           state: absent -> present
changed    directory[/srv/app/releases/2]
           state: absent -> present
changed    file[/srv/app/releases/2/console]
           state: absent -> present
           mode: 0755
           --- /dev/null
           +++ /srv/app/releases/2/console (desired)
           @@ -0,0 +1,2 @@
           +#!/bin/sh
           +echo "release 2"
changed    link[/srv/app/current]
           state: absent -> present
           to: releases/2
changed    link[/usr/local/bin/app-console]
           state: absent -> present
           to: /srv/app/current/console
unchanged  link[/usr/local/bin/old-console]

Summary
  changed      5  directory[/srv/app/releases/1]
                  directory[/srv/app/releases/2]
                  file[/srv/app/releases/2/console]
                  link[/srv/app/current]
                  link[/usr/local/bin/app-console]
  unchanged    1
  failed       0
  skipped      0
  notified     0

Finished in 0.29s.

$ readlink /srv/app/current /usr/local/bin/app-console
releases/2
/srv/app/current/console

$ app-console
release 2

Someone pointed it at the old release

$ sudo ln -sfn releases/1 /srv/app/current

$ sudo sadame drift examples/resources/link
sadame 0.5.1 drift on local (Debian GNU/Linux 12 (bookworm))

~ link[/srv/app/current]
    to: releases/1 -> releases/2

Drift: 1 of 6 resources differs from the recipe.

$ sudo sadame apply examples/resources/link
sadame 0.5.1 apply on local (Debian GNU/Linux 12 (bookworm))

unchanged  directory[/srv/app/releases/1]
unchanged  directory[/srv/app/releases/2]
unchanged  file[/srv/app/releases/2/console]
changed    link[/srv/app/current]
           to: releases/1 -> releases/2
unchanged  link[/usr/local/bin/app-console]
unchanged  link[/usr/local/bin/old-console]

Summary
  changed      1  link[/srv/app/current]
  unchanged    5
  failed       0
  skipped      0
  notified     0

Finished in 0.22s.

A link that enables a configuration can notify the service that reads it:

link "/etc/nginx/sites-enabled/app",
     to: "/etc/nginx/sites-available/app",
     notifies: [:reload, "service[nginx]"]

Common mistakes

  • A file in the way. A path that exists as a regular file fails with "is a regular file, not a symbolic link". Add force: true when replacing it is what you want, as for /etc/resolv.conf.
  • Relative targets. to: "releases/2" is relative to the link's directory, not to the directory you run sadame from. sadame compares the target as written: to: "/srv/app/releases/2" and to: "releases/2" are different links, even when they lead to the same place.
  • Expecting the link to create its directory. ln fails when the directory does not exist.

See also

  • file and directory for what the link points to.
  • service for services that read linked configuration.