# salt.modules.aptpkg

Support for APT (Advanced Packaging Tool)

Important

If you feel that Salt should be using this module to manage packages on a minion, and it is using a different module (or gives an error similar to 'pkg.install' is not available), see here.

For repository management, the `python-apt` package must be installed.

class salt.modules.aptpkg.SourceEntry(line, file=None)
  repo_line()

    Return the repo line for the sources file

  str()

class salt.modules.aptpkg.SourcesList
  add(type, uri, dist, orig_comps, architectures, signedby)
  add_file(file)

    Add the lines of a file to self.list

  remove(source)

    remove a source from the list of sources

  save()

    write all of the sources from the list of sources to the file.

salt.modules.aptpkg.add_repo_key(path=None, text=None, keyserver=None, keyid=None, saltenv='base', aptkey=True, keydir=None, keyfile=None)

  New in version 2017.7.0.

  Add a repo key using `apt-key add`.

  Parameters:

    - path (str) -- The path of the key file to import.

    - text (str) -- The key data to import, in string form.

    - keyserver (str) -- The server to download the repo key specified by the keyid.

    - keyid (str) -- The key id of the repo key to add.

    - saltenv (str) -- The environment the key file resides in.

    - aptkey (bool) -- Use the binary apt-key.

    - keydir (str) -- The directory path to save keys. The default directory is /etc/apt/keyrings/ which is the recommended path for adding third party keys. This argument is only used when aptkey is False.

    - keyfile (str) -- The name of the key to add. This is only required when aptkey is False and you are using a keyserver. This argument is only used when aptkey is False.

  Returns:

    A boolean representing whether the repo key was added.

  Return type:

    bool

  Warning

  The apt-key binary is deprecated and will last be available in Debian 11 and Ubuntu 22.04. It is recommended to use aptkey=False when using this module.

  CLI Examples:

      salt '*' pkg.add_repo_key 'salt://apt/sources/test.key'

      salt '*' pkg.add_repo_key text="'$KEY1'"

      salt '*' pkg.add_repo_key keyserver='keyserver.example' keyid='0000AAAA'

salt.modules.aptpkg.autoremove(list_only=False, purge=False)

  New in version 2015.5.0.

  Remove packages not required by another package using `apt-get autoremove`.

  list_onlyFalse

    Only retrieve the list of packages to be auto-removed, do not actually perform the auto-removal.

  purgeFalse

    Also remove package config data when autoremoving packages.

    New in version 2015.8.0.

  CLI Example:

      salt '*' pkg.autoremove
      salt '*' pkg.autoremove list_only=True
      salt '*' pkg.autoremove purge=True

salt.modules.aptpkg.available_version(*names, **kwargs)

  This function is an alias of `latest_version`.

  > Return the latest version of the named package available for upgrade or installation. If more than one package name is specified, a dict of name/version pairs is returned.

  > If the latest version of a given package is already installed, an empty string will be returned for that package.

  > A specific repo can be requested using the `fromrepo` keyword argument.

  > cache_valid_time

  > > New in version 2016.11.0.

  > > Skip refreshing the package database if refresh has already occurred within <value> seconds

  > CLI Example:

  >     salt '*' pkg.latest_version <package name>
  >     salt '*' pkg.latest_version <package name> fromrepo=unstable
  >     salt '*' pkg.latest_version <package1> <package2> <package3> ...

salt.modules.aptpkg.del_repo(repo, **kwargs)

  Delete a repo from the sources.list / sources.list.d

  If the .list file is in the sources.list.d directory and the file that the repo exists in does not contain any other repo configuration, the file itself will be deleted.

  The repo passed in must be a fully formed repository definition string.

  CLI Examples:

      salt '*' pkg.del_repo "myrepo definition"

salt.modules.aptpkg.del_repo_key(name=None, aptkey=True, keydir=None, **kwargs)

  New in version 2015.8.0.

  Remove a repo key using `apt-key del`

  name

    Repo from which to remove the key. Unnecessary if `keyid` is passed.

  keyid

    The KeyID of the GPG key to remove

  keyid_ppaFalse

    If set to `True`, the repo's GPG key ID will be looked up from ppa.launchpad.net and removed.

    Note

    Setting this option to `True` requires that the `name` param also be passed.

  aptkey

    Use the binary apt-key.

  keydir

    The directory path to save keys. The default directory is /etc/apt/keyrings/ which is the recommended path for adding third party keys.

  Warning

  The apt-key binary is deprecated and will last be available in Debian 11 and Ubuntu 22.04. It is recommended to use aptkey=False when using this module.

  CLI Examples:

      salt '*' pkg.del_repo_key keyid=0123ABCD
      salt '*' pkg.del_repo_key name='ppa:foo/bar' keyid_ppa=True

salt.modules.aptpkg.expand_repo_def(**kwargs)

  Take a repository definition and expand it to the full pkg repository dict that can be used for comparison. This is a helper function to make the Debian/Ubuntu apt sources sane for comparison in the pkgrepo states.

  This is designed to be called from pkgrepo states and will have little use being called on the CLI.

salt.modules.aptpkg.file_dict(*packages, **kwargs)

  List the files that belong to a package, grouped by package. Not specifying any packages will return a list of _every_ file on the system's package database (not generally recommended).

  CLI Examples:

      salt '*' pkg.file_dict httpd
      salt '*' pkg.file_dict httpd postfix
      salt '*' pkg.file_dict

salt.modules.aptpkg.file_list(*packages, **kwargs)

  List the files that belong to a package. Not specifying any packages will return a list of _every_ file on the system's package database (not generally recommended).

  CLI Examples:

      salt '*' pkg.file_list httpd
      salt '*' pkg.file_list httpd postfix
      salt '*' pkg.file_list

salt.modules.aptpkg.get_repo(repo, **kwargs)

  Display a repo from the sources.list / sources.list.d

  The repo passed in needs to be a complete repo entry.

  CLI Examples:

      salt '*' pkg.get_repo "myrepo definition"

salt.modules.aptpkg.get_repo_keys(aptkey=True, keydir=None)

  New in version 2017.7.0.

  List known repo key details. :param bool aptkey: Use the binary apt-key. :param str keydir: The directory path to save keys. The default directory is /etc/apt/keyrings/ which is the recommended path for adding third party keys. This argument is only used when aptkey is False.

  Returns:

    A dictionary containing the repo keys.

  Return type:

    dict

  CLI Examples:

      salt '*' pkg.get_repo_keys

salt.modules.aptpkg.get_selections(pattern=None, state=None)

  View package state from the dpkg database.

  Returns a dict of dicts containing the state, and package names:

      {'<host>':
          {'<state>': ['pkg1',
                       ...
                      ]
          },
          ...
      }

  CLI Example:

      salt '*' pkg.get_selections
      salt '*' pkg.get_selections 'python-*'
      salt '*' pkg.get_selections state=hold
      salt '*' pkg.get_selections 'openssh*' state=hold

salt.modules.aptpkg.hold(name=None, pkgs=None, sources=None, **kwargs)

  New in version 2014.7.0.

  Set package in 'hold' state, meaning it will not be upgraded.

  name

    The name of the package, e.g., 'tmux'

    CLI Example:

        salt '*' pkg.hold <package name>

  pkgs

    A list of packages to hold. Must be passed as a python list.

    CLI Example:

        salt '*' pkg.hold pkgs='["foo", "bar"]'

salt.modules.aptpkg.info_installed(*names, **kwargs)

  Return the information of the named package(s) installed on the system.

  New in version 2015.8.1.

  names

    The names of the packages for which to return information.

  failhard

    Whether to throw an exception if none of the packages are installed. Defaults to True.

    New in version 2016.11.3.

  CLI Example:

      salt '*' pkg.info_installed <package1>
      salt '*' pkg.info_installed <package1> <package2> <package3> ...
      salt '*' pkg.info_installed <package1> failhard=false

salt.modules.aptpkg.install(name=None, refresh=False, fromrepo=None, skip_verify=False, debconf=None, pkgs=None, sources=None, reinstall=False, downloadonly=False, ignore_epoch=False, **kwargs)

  Changed in version 2015.8.12,2016.3.3,2016.11.0: On minions running systemd>=205, systemd-run(1) is now used to isolate commands which modify installed packages from the `salt-minion` daemon's control group. This is done to keep systemd from killing any apt-get/dpkg commands spawned by Salt when the `salt-minion` service is restarted. (see `KillMode` in the systemd.kill(5) manpage for more information). If desired, usage of systemd-run(1) can be suppressed by setting a `config option` called `systemd.scope`, with a value of `False` (no quotes).

  Install the passed package, add refresh=True to update the dpkg database.

  name

    The name of the package to be installed. Note that this parameter is ignored if either "pkgs" or "sources" is passed. Additionally, please note that this option can only be used to install packages from a software repository. To install a package file manually, use the "sources" option.

    32-bit packages can be installed on 64-bit systems by appending the architecture designation (`:i386`, etc.) to the end of the package name.

    CLI Example:

        salt '*' pkg.install <package name>

  refresh

    Whether or not to refresh the package database before installing.

  cache_valid_time

  > New in version 2016.11.0.

  > Skip refreshing the package database if refresh has already occurred within <value> seconds

  fromrepo

    Specify a package repository to install from (e.g., `apt-get -t unstable install somepackage`)

  skip_verify

    Skip the GPG verification check (e.g., `--allow-unauthenticated`, or `--force-bad-verify` for install from package file).

  debconf

    Provide the path to a debconf answers file, processed before installation.

  version

    Install a specific version of the package, e.g. 1.2.3~0ubuntu0. Ignored if "pkgs" or "sources" is passed.

    Changed in version 2018.3.0: version can now contain comparison operators (e.g. `>1.2.3`, `<=2.0`, etc.)

  reinstallFalse

    Specifying reinstall=True will use `apt-get install --reinstall` rather than simply `apt-get install` for requested packages that are already installed.

    If a version is specified with the requested package, then `apt-get install --reinstall` will only be used if the installed version matches the requested version.

    New in version 2015.8.0.

  ignore_epochFalse

    Only used when the version of a package is specified using a comparison operator (e.g. `>4.1`). If set to `True`, then the epoch will be ignored when comparing the currently-installed version to the desired version.

    New in version 2018.3.0.

  Multiple Package Installation Options:

  pkgs

    A list of packages to install from a software repository. Must be passed as a python list.

    CLI Example:

        salt '*' pkg.install pkgs='["foo", "bar"]'
        salt '*' pkg.install pkgs='["foo", {"bar": "1.2.3-0ubuntu0"}]'

  sources

    A list of DEB packages to install. Must be passed as a list of dicts, with the keys being package names, and the values being the source URI or local path to the package. Dependencies are automatically resolved and marked as auto-installed.

    32-bit packages can be installed on 64-bit systems by appending the architecture designation (`:i386`, etc.) to the end of the package name.

    Changed in version 2014.7.0.

    CLI Example:

        salt '*' pkg.install sources='[{"foo": "salt://foo.deb"},{"bar": "salt://bar.deb"}]'

  force_yes

    Passes `--force-yes` to the apt-get command. Don't use this unless you know what you're doing.

    New in version 0.17.4.

  install_recommends

    Whether to install the packages marked as recommended. Default is True.

    New in version 2015.5.0.

  only_upgrade

    Only upgrade the packages, if they are already installed. Default is False.

    New in version 2015.5.0.

  force_conf_new

    Always install the new version of any configuration files.

    New in version 2015.8.0.

  Returns a dict containing the new package names and versions:

      {'<package>': {'old': '<old-version>',
                     'new': '<new-version>'}}

salt.modules.aptpkg.latest_version(*names, **kwargs)

  Return the latest version of the named package available for upgrade or installation. If more than one package name is specified, a dict of name/version pairs is returned.

  If the latest version of a given package is already installed, an empty string will be returned for that package.

  A specific repo can be requested using the `fromrepo` keyword argument.

  cache_valid_time

  > New in version 2016.11.0.

  > Skip refreshing the package database if refresh has already occurred within <value> seconds

  CLI Example:

      salt '*' pkg.latest_version <package name>
      salt '*' pkg.latest_version <package name> fromrepo=unstable
      salt '*' pkg.latest_version <package1> <package2> <package3> ...

salt.modules.aptpkg.list_downloaded(root=None, **kwargs)

  New in version 3000?.

  List prefetched packages downloaded by apt in the local disk.

  root

    operate on a different root directory.

  CLI Example:

      salt '*' pkg.list_downloaded

salt.modules.aptpkg.list_pkgs(versions_as_list=False, removed=False, purge_desired=False, **kwargs)

  List the packages currently installed in a dict:

      {'<package_name>': '<version>'}

  removed

    If `True`, then only packages which have been removed (but not purged) will be returned.

  purge_desired

    If `True`, then only packages which have been marked to be purged, but can't be purged due to their status as dependencies for other installed packages, will be returned. Note that these packages will appear in installed

    Changed in version 2014.1.1: Packages in this state now correctly show up in the output of this function.

  CLI Example:

      salt '*' pkg.list_pkgs
      salt '*' pkg.list_pkgs versions_as_list=True

salt.modules.aptpkg.list_repo_pkgs(*args, **kwargs)

  New in version 2017.7.0.

  Returns all available packages. Optionally, package names (and name globs) can be passed and the results will be filtered to packages matching those names.

  This function can be helpful in discovering the version or repo to specify in a `pkg.installed` state.

  The return data will be a dictionary mapping package names to a list of version numbers, ordered from newest to oldest. For example:

      {
          'bash': ['4.3-14ubuntu1.1',
                   '4.3-14ubuntu1'],
          'nginx': ['1.10.0-0ubuntu0.16.04.4',
                    '1.9.15-0ubuntu1']
      }

  CLI Examples:

      salt '*' pkg.list_repo_pkgs
      salt '*' pkg.list_repo_pkgs foo bar baz

salt.modules.aptpkg.list_repos(**kwargs)

  Lists all repos in the sources.list (and sources.lists.d) files

  CLI Example:

      salt '*' pkg.list_repos
      salt '*' pkg.list_repos disabled=True

salt.modules.aptpkg.list_upgrades(refresh=True, dist_upgrade=True, **kwargs)

  List all available package upgrades.

  refresh

    Whether to refresh the package database before listing upgrades. Default: True.

  cache_valid_time

  > New in version 2016.11.0.

  > Skip refreshing the package database if refresh has already occurred within <value> seconds

  dist_upgrade

    Whether to list the upgrades using dist-upgrade vs upgrade. Default is to use dist-upgrade.

  CLI Example:

      salt '*' pkg.list_upgrades

salt.modules.aptpkg.mod_repo(repo, saltenv='base', aptkey=True, **kwargs)

  Modify one or more values for a repo. If the repo does not exist, it will be created, so long as the definition is well formed. For Ubuntu the `ppa:<project>/repo` format is acceptable. `ppa:` format can only be used to create a new repository.

  The following options are available to modify a repo definition:

  architectures

    A comma-separated list of supported architectures, e.g. `amd64` If this option is not set, all architectures (configured in the system) will be used.

  comps

    A comma separated list of components for the repo, e.g. `main`

  file

    A file name to be used

  keyserver

    Keyserver to get gpg key from

  keyid

    Key ID or a list of key IDs to load with the `keyserver` argument

  key_url

    URL to a GPG key to add to the APT GPG keyring

  key_text

    GPG key in string form to add to the APT GPG keyring

    New in version 2018.3.0.

  consolidateFalse

    If `True`, will attempt to de-duplicate and consolidate sources

  comments

    Sometimes you want to supply additional information, but not as enabled configuration. All comments provided here will be joined into a single string and appended to the repo configuration with a comment marker (#) before it.

    New in version 2015.8.9.

  refreshTrue

    Enable or disable (True or False) refreshing of the apt package database. The previous `refresh_db` argument was deprecated in favor of `refresh``. The `refresh_db` argument will still continue to work to ensure backwards compatibility, but please change to using the preferred `refresh`.

  Note

  Due to the way keys are stored for APT, there is a known issue where the key won't be updated unless another change is made at the same time. Keys should be properly added on initial configuration.

  CLI Examples:

      salt '*' pkg.mod_repo 'myrepo definition' uri=http://new/uri
      salt '*' pkg.mod_repo 'myrepo definition' comps=main,universe

salt.modules.aptpkg.normalize_name(name)

  Strips the architecture from the specified package name, if necessary.

  CLI Example:

      salt '*' pkg.normalize_name zsh:amd64

salt.modules.aptpkg.owner(*paths, **kwargs)

  New in version 2014.7.0.

  Return the name of the package that owns the file. Multiple file paths can be passed. Like `pkg.version`, if a single path is passed, a string will be returned, and if multiple paths are passed, a dictionary of file/package name pairs will be returned.

  If the file is not owned by a package, or is not present on the minion, then an empty string will be returned for that path.

  CLI Example:

      salt '*' pkg.owner /usr/bin/apachectl
      salt '*' pkg.owner /usr/bin/apachectl /usr/bin/basename

salt.modules.aptpkg.parse_arch(name)

  Parse name and architecture from the specified package name.

  CLI Example:

      salt '*' pkg.parse_arch zsh:amd64

salt.modules.aptpkg.purge(name=None, pkgs=None, **kwargs)

  Changed in version 2015.8.12,2016.3.3,2016.11.0: On minions running systemd>=205, systemd-run(1) is now used to isolate commands which modify installed packages from the `salt-minion` daemon's control group. This is done to keep systemd from killing any apt-get/dpkg commands spawned by Salt when the `salt-minion` service is restarted. (see `KillMode` in the systemd.kill(5) manpage for more information). If desired, usage of systemd-run(1) can be suppressed by setting a `config option` called `systemd.scope`, with a value of `False` (no quotes).

  Remove packages via `apt-get purge` along with all configuration files.

  name

    The name of the package to be deleted.

  Multiple Package Options:

  pkgs

    A list of packages to delete. Must be passed as a python list. The `name` parameter will be ignored if this option is passed.

  New in version 0.16.0.

  Returns a dict containing the changes.

  CLI Example:

      salt '*' pkg.purge <package name>
      salt '*' pkg.purge <package1>,<package2>,<package3>
      salt '*' pkg.purge pkgs='["foo", "bar"]'

salt.modules.aptpkg.refresh_db(cache_valid_time=0, failhard=False, **kwargs)

  Updates the APT database to latest packages based upon repositories

  Returns a dict, with the keys being package databases and the values being the result of the update attempt. Values can be one of the following:

  - `True`: Database updated successfully

  - `False`: Problem updating database

  - `None`: Database already up-to-date

  cache_valid_time

  > New in version 2016.11.0.

  > Skip refreshing the package database if refresh has already occurred within <value> seconds

  failhard

  > If False, return results of Err lines as `False` for the package database that encountered the error. If True, raise an error with a list of the package databases that encountered errors.

  CLI Example:

      salt '*' pkg.refresh_db

salt.modules.aptpkg.remove(name=None, pkgs=None, **kwargs)

  Changed in version 2015.8.12,2016.3.3,2016.11.0: On minions running systemd>=205, systemd-run(1) is now used to isolate commands which modify installed packages from the `salt-minion` daemon's control group. This is done to keep systemd from killing any apt-get/dpkg commands spawned by Salt when the `salt-minion` service is restarted. (see `KillMode` in the systemd.kill(5) manpage for more information). If desired, usage of systemd-run(1) can be suppressed by setting a `config option` called `systemd.scope`, with a value of `False` (no quotes).

  Remove packages using `apt-get remove`.

  name

    The name of the package to be deleted.

  Multiple Package Options:

  pkgs

    A list of packages to delete. Must be passed as a python list. The `name` parameter will be ignored if this option is passed.

  New in version 0.16.0.

  Returns a dict containing the changes.

  CLI Example:

      salt '*' pkg.remove <package name>
      salt '*' pkg.remove <package1>,<package2>,<package3>
      salt '*' pkg.remove pkgs='["foo", "bar"]'

salt.modules.aptpkg.services_need_restart(**kwargs)

  New in version 3003.

  List services that use files which have been changed by the package manager. It might be needed to restart them.

  Requires checkrestart from the debian-goodies package.

  CLI Examples:

      salt '*' pkg.services_need_restart

salt.modules.aptpkg.set_selections(path=None, selection=None, clear=False, saltenv='base')

  Change package state in the dpkg database.

  The state can be any one of, documented in `dpkg(1)`:

  - install

  - hold

  - deinstall

  - purge

  This command is commonly used to mark specific packages to be held from being upgraded, that is, to be kept at a certain version. When a state is changed to anything but being held, then it is typically followed by `apt-get -u dselect-upgrade`.

  Note: Be careful with the `clear` argument, since it will start with setting all packages to deinstall state.

  Returns a dict of dicts containing the package names, and the new and old versions:

      {'<host>':
          {'<package>': {'new': '<new-state>',
                         'old': '<old-state>'}
          },
          ...
      }

  CLI Example:

      salt '*' pkg.set_selections selection='{"install": ["netcat"]}'
      salt '*' pkg.set_selections selection='{"hold": ["openssh-server", "openssh-client"]}'
      salt '*' pkg.set_selections salt://path/to/file
      salt '*' pkg.set_selections salt://path/to/file clear=True

salt.modules.aptpkg.show(*names, **kwargs)

  New in version 2019.2.0.

  Runs an `apt-cache show` on the passed package names, and returns the results in a nested dictionary. The top level of the return data will be the package name, with each package name mapping to a dictionary of version numbers to any additional information returned by `apt-cache show`.

  filter

    An optional comma-separated list (or quoted Python list) of case-insensitive keys on which to filter. This allows one to restrict the information returned for each package to a smaller selection of pertinent items.

  refreshFalse

    If `True`, the apt cache will be refreshed first. By default, no refresh is performed.

  CLI Examples:

      salt myminion pkg.show gawk
      salt myminion pkg.show 'nginx-*'
      salt myminion pkg.show 'nginx-*' filter=description,provides

salt.modules.aptpkg.unhold(name=None, pkgs=None, sources=None, **kwargs)

  New in version 2014.7.0.

  Set package current in 'hold' state to install state, meaning it will be upgraded.

  name

    The name of the package, e.g., 'tmux'

    CLI Example:

        salt '*' pkg.unhold <package name>

  pkgs

    A list of packages to unhold. Must be passed as a python list.

    CLI Example:

        salt '*' pkg.unhold pkgs='["foo", "bar"]'

salt.modules.aptpkg.upgrade(refresh=True, dist_upgrade=False, **kwargs)

  Changed in version 2015.8.12,2016.3.3,2016.11.0: On minions running systemd>=205, systemd-run(1) is now used to isolate commands which modify installed packages from the `salt-minion` daemon's control group. This is done to keep systemd from killing any apt-get/dpkg commands spawned by Salt when the `salt-minion` service is restarted. (see `KillMode` in the systemd.kill(5) manpage for more information). If desired, usage of systemd-run(1) can be suppressed by setting a `config option` called `systemd.scope`, with a value of `False` (no quotes).

  Upgrades all packages via `apt-get upgrade` or `apt-get dist-upgrade` if `dist_upgrade` is `True`.

  Returns a dictionary containing the changes:

      {'<package>':  {'old': '<old-version>',
                      'new': '<new-version>'}}

  dist_upgrade

    Whether to perform the upgrade using dist-upgrade vs upgrade. Default is to use upgrade.

    New in version 2014.7.0.

  refreshTrue

    If `True`, the apt cache will be refreshed first. By default, this is `True` and a refresh is performed.

  cache_valid_time

  > New in version 2016.11.0.

  > Skip refreshing the package database if refresh has already occurred within <value> seconds

  download_only (or downloadonly)

    Only download the packages, don't unpack or install them. Use downloadonly to be in line with yum and zypper module.

    New in version 2018.3.0.

  force_conf_new

    Always install the new version of any configuration files.

    New in version 2015.8.0.

  allow_downgrades

    Allow apt to downgrade packages without a prompt.

    New in version 3005.

  CLI Example:

      salt '*' pkg.upgrade

salt.modules.aptpkg.upgrade_available(name, **kwargs)

  Check whether or not an upgrade is available for a given package

  CLI Example:

      salt '*' pkg.upgrade_available <package name>

salt.modules.aptpkg.version(*names, **kwargs)

  Returns a string representing the package version or an empty string if not installed. If more than one package name is specified, a dict of name/version pairs is returned.

  CLI Example:

      salt '*' pkg.version <package name>
      salt '*' pkg.version <package1> <package2> <package3> ...

salt.modules.aptpkg.version_cmp(pkg1, pkg2, ignore_epoch=False, **kwargs)

  Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem making the comparison.

  ignore_epochFalse

    Set to `True` to ignore the epoch when comparing versions

    New in version 2015.8.10,2016.3.2.

  CLI Example:

      salt '*' pkg.version_cmp '0.2.4-0ubuntu1' '0.2.4.1-0ubuntu1'