File: //usr/lib/python2.7/site-packages/salt/states/chocolatey.py
# -*- coding: utf-8 -*-
'''
Manage Chocolatey package installs
.. versionadded:: 2016.3.0
.. note::
Chocolatey pulls data from the Chocolatey internet database to determine
current versions, find available versions, etc. This is normally a slow
operation and may be optimized by specifying a local, smaller chocolatey
repo.
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt libs
import salt.utils.data
import salt.utils.versions
from salt.exceptions import SaltInvocationError
def __virtual__():
'''
Load only if chocolatey is loaded
'''
return 'chocolatey' if 'chocolatey.install' in __salt__ else False
def installed(name, version=None, source=None, force=False, pre_versions=False,
install_args=None, override_args=False, force_x86=False,
package_args=None, allow_multiple=False):
'''
Installs a package if not already installed
Args:
name (str):
The name of the package to be installed. Required.
version (str):
Install a specific version of the package. Defaults to latest
version. If the version is different to the one installed then the
specified version will be installed. Default is None.
source (str):
Chocolatey repository (directory, share or remote URL, feed).
Defaults to the official Chocolatey feed. Default is None.
force (bool):
Reinstall the current version of an existing package. Do not use
with ``allow_multiple``. Default is False.
pre_versions (bool):
Include pre-release packages. Default is False.
install_args (str):
Install arguments you want to pass to the installation process, i.e
product key or feature list. Default is None.
override_args (bool):
Set to True if you want to override the original install arguments
(for the native installer) in the package and use your own. When
this is set to False install_args will be appended to the end of the
default arguments. Default is False.
force_x86 (bool):
Force x86 (32bit) installation on 64 bit systems. Default is False.
package_args (str):
Arguments you want to pass to the package. Default is None.
allow_multiple (bool):
Allow mulitiple versions of the package to be installed. Do not use
with ``force``. Does not work with all packages. Default is False.
.. versionadded:: 2017.7.0
.. code-block:: yaml
Installsomepackage:
chocolatey.installed:
- name: packagename
- version: '12.04'
- source: 'mychocolatey/source'
- force: True
'''
if force and allow_multiple:
raise SaltInvocationError(
'Cannot use \'force\' in conjunction with \'allow_multiple\'')
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
# Get list of currently installed packages
pre_install = __salt__['chocolatey.list'](local_only=True)
# Determine action
# Package not installed
if name.lower() not in [package.lower() for package in pre_install.keys()]:
if version:
ret['changes'] = {name: 'Version {0} will be installed'.format(version)}
else:
ret['changes'] = {name: 'Latest version will be installed'}
# Package installed
else:
version_info = __salt__['chocolatey.version'](name=name,
check_remote=True,
source=source)
full_name = name
for pkg in version_info:
if name.lower() == pkg.lower():
full_name = pkg
installed_version = version_info[full_name]['installed'][0]
if version:
if salt.utils.versions.compare(
ver1=installed_version, oper="==", ver2=version):
if force:
ret['changes'] = {
name: 'Version {0} will be reinstalled'.format(version)}
ret['comment'] = 'Reinstall {0} {1}'.format(full_name, version)
else:
ret['comment'] = '{0} {1} is already installed'.format(name, version)
if __opts__['test']:
ret['result'] = None
return ret
else:
if allow_multiple:
ret['changes'] = {
name: 'Version {0} will be installed side by side with '
'Version {1} if supported'.format(version, installed_version)
}
ret['comment'] = (
'Install {0} {1} side-by-side with {0} {2}'.format(
full_name, version, installed_version
)
)
else:
ret['changes'] = {
name: 'Version {0} will be installed over Version {1}'.format(version, installed_version)
}
ret['comment'] = 'Install {0} {1} over {0} {2}'.format(
full_name, version, installed_version
)
force = True
else:
version = installed_version
if force:
ret['changes'] = {
name: 'Version {0} will be reinstalled'.format(version)}
ret['comment'] = 'Reinstall {0} {1}'.format(full_name, version)
else:
ret['comment'] = '{0} {1} is already installed'.format(name, version)
if __opts__['test']:
ret['result'] = None
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'The installation was tested'
return ret
# Install the package
result = __salt__['chocolatey.install'](name=name,
version=version,
source=source,
force=force,
pre_versions=pre_versions,
install_args=install_args,
override_args=override_args,
force_x86=force_x86,
package_args=package_args,
allow_multiple=allow_multiple)
if 'Running chocolatey failed' not in result:
ret['result'] = True
else:
ret['result'] = False
if not ret['result']:
ret['comment'] = 'Failed to install the package {0}'.format(name)
# Get list of installed packages after 'chocolatey.install'
post_install = __salt__['chocolatey.list'](local_only=True)
ret['changes'] = salt.utils.data.compare_dicts(pre_install, post_install)
return ret
def uninstalled(name, version=None, uninstall_args=None, override_args=False):
'''
Uninstalls a package
name
The name of the package to be uninstalled
version
Uninstalls a specific version of the package. Defaults to latest
version installed.
uninstall_args
A list of uninstall arguments you want to pass to the uninstallation
process i.e product key or feature list
override_args
Set to true if you want to override the original uninstall arguments (
for the native uninstaller)in the package and use your own.
When this is set to False uninstall_args will be appended to the end of
the default arguments
.. code-block:: yaml
Removemypackage:
chocolatey.uninstalled:
- name: mypackage
- version: '21.5'
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
# Get list of currently installed packages
pre_uninstall = __salt__['chocolatey.list'](local_only=True)
# Determine if package is installed
if name.lower() in [package.lower() for package in pre_uninstall.keys()]:
try:
ret['changes'] = {
name: '{0} version {1} will be removed'.format(
name, pre_uninstall[name][0]
)
}
except KeyError:
ret['changes'] = {name: '{0} will be removed'.format(name)}
else:
ret['comment'] = 'The package {0} is not installed'.format(name)
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'The uninstall was tested'
return ret
# Uninstall the package
result = __salt__['chocolatey.uninstall'](name,
version,
uninstall_args,
override_args)
if 'Running chocolatey failed' not in result:
ret['result'] = True
else:
ret['result'] = False
if not ret['result']:
ret['comment'] = 'Failed to uninstall the package {0}'.format(name)
# Get list of installed packages after 'chocolatey.uninstall'
post_uninstall = __salt__['chocolatey.list'](local_only=True)
ret['changes'] = salt.utils.data.compare_dicts(pre_uninstall, post_uninstall)
return ret
def upgraded(name,
version=None,
source=None,
force=False,
pre_versions=False,
install_args=None,
override_args=False,
force_x86=False,
package_args=None):
'''
Upgrades a package. Will install the package if not installed.
.. versionadded:: 2018.3.0
Args:
name (str):
The name of the package to be installed. Required.
version (str):
Install a specific version of the package. Defaults to latest
version. If the version is greater than the one installed then the
specified version will be installed. Default is ``None``.
source (str):
Chocolatey repository (directory, share or remote URL, feed).
Defaults to the official Chocolatey feed. Default is ``None``.
force (bool):
``True`` will reinstall an existing package with the same version.
Default is ``False``.
pre_versions (bool):
``True`` will nclude pre-release packages. Default is ``False``.
install_args (str):
Install arguments you want to pass to the installation process, i.e
product key or feature list. Default is ``None``.
override_args (bool):
``True`` will override the original install arguments (for the
native installer) in the package and use those specified in
``install_args``. ``False`` will append install_args to the end of
the default arguments. Default is ``False``.
force_x86 (bool):
``True`` forces 32bit installation on 64 bit systems. Default is
``False``.
package_args (str):
Arguments you want to pass to the package. Default is ``None``.
.. code-block:: yaml
upgrade_some_package:
chocolatey.upgraded:
- name: packagename
- version: '12.04'
- source: 'mychocolatey/source'
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
# Get list of currently installed packages
pre_install = __salt__['chocolatey.list'](local_only=True)
# Determine if there are changes
# Package not installed
if name.lower() not in [package.lower() for package in pre_install.keys()]:
if version:
ret['changes'][name] = 'Version {0} will be installed'.format(version)
ret['comment'] = 'Install version {0}'.format(version)
else:
ret['changes'][name] = 'Latest version will be installed'
ret['comment'] = 'Install latest version'
# Package installed
else:
version_info = __salt__['chocolatey.version'](name, check_remote=True)
# Get the actual full name out of version_info
full_name = name
for pkg in version_info:
if name.lower() == pkg.lower():
full_name = pkg
installed_version = version_info[full_name]['installed'][0]
# If version is not passed, use available... if available is available
if not version:
if 'available' in version_info[full_name]:
version = version_info[full_name]['available'][0]
if version:
# If installed version and new version are the same
if salt.utils.versions.compare(
ver1=installed_version,
oper="==",
ver2=version):
if force:
ret['changes'][name] = 'Version {0} will be reinstalled'.format(version)
ret['comment'] = 'Reinstall {0} {1}'.format(full_name, version)
else:
ret['comment'] = '{0} {1} is already installed'.format(
name, installed_version
)
else:
# If installed version is older than new version
if salt.utils.versions.compare(
ver1=installed_version, oper="<", ver2=version):
ret['changes'][name] = 'Version {0} will be upgraded to Version {1}'.format(
installed_version, version
)
ret['comment'] = 'Upgrade {0} {1} to {2}'.format(
full_name, installed_version, version
)
# If installed version is newer than new version
else:
ret['comment'] = (
'{0} {1} (newer) is already installed'.format(
name, installed_version
)
)
# Catch all for a condition where version is not passed and there is no
# available version
else:
ret['comment'] = 'No version found to install'
# Return if there are no changes to be made
if not ret['changes']:
return ret
# Return if running in test mode
if __opts__['test']:
ret['result'] = None
return ret
# Install the package
result = __salt__['chocolatey.upgrade'](name=name,
version=version,
source=source,
force=force,
pre_versions=pre_versions,
install_args=install_args,
override_args=override_args,
force_x86=force_x86,
package_args=package_args)
if 'Running chocolatey failed' not in result:
ret['comment'] = 'Package {0} upgraded successfully'.format(name)
ret['result'] = True
else:
ret['comment'] = 'Failed to upgrade the package {0}'.format(name)
ret['result'] = False
# Get list of installed packages after 'chocolatey.install'
post_install = __salt__['chocolatey.list'](local_only=True)
# Prior to this, ret['changes'] would have contained expected changes,
# replace them with the actual changes now that we have completed the
# installation.
ret['changes'] = salt.utils.data.compare_dicts(pre_install, post_install)
return ret