mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
Relocating extras into lib/ansible/modules/ after merge
This commit is contained in:
parent
c65ba07d2c
commit
011ea55a8f
596 changed files with 0 additions and 266 deletions
244
lib/ansible/modules/packaging/language/bower.py
Normal file
244
lib/ansible/modules/packaging/language/bower.py
Normal file
|
@ -0,0 +1,244 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2014, Michael Warkentin <mwarkentin@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: bower
|
||||
short_description: Manage bower packages with bower
|
||||
description:
|
||||
- Manage bower packages with bower
|
||||
version_added: 1.9
|
||||
author: "Michael Warkentin (@mwarkentin)"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The name of a bower package to install
|
||||
required: false
|
||||
offline:
|
||||
description:
|
||||
- Install packages from local cache, if the packages were installed before
|
||||
required: false
|
||||
default: no
|
||||
choices: [ "yes", "no" ]
|
||||
production:
|
||||
description:
|
||||
- Install with --production flag
|
||||
required: false
|
||||
default: no
|
||||
choices: [ "yes", "no" ]
|
||||
version_added: "2.0"
|
||||
path:
|
||||
description:
|
||||
- The base path where to install the bower packages
|
||||
required: true
|
||||
relative_execpath:
|
||||
description:
|
||||
- Relative path to bower executable from install path
|
||||
default: null
|
||||
required: false
|
||||
version_added: "2.1"
|
||||
state:
|
||||
description:
|
||||
- The state of the bower package
|
||||
required: false
|
||||
default: present
|
||||
choices: [ "present", "absent", "latest" ]
|
||||
version:
|
||||
description:
|
||||
- The version to be installed
|
||||
required: false
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Install "bootstrap" bower package.
|
||||
bower:
|
||||
name: bootstrap
|
||||
|
||||
- name: Install "bootstrap" bower package on version 3.1.1.
|
||||
bower:
|
||||
name: bootstrap
|
||||
version: '3.1.1'
|
||||
|
||||
- name: Remove the "bootstrap" bower package.
|
||||
bower:
|
||||
name: bootstrap
|
||||
state: absent
|
||||
|
||||
- name: Install packages based on bower.json.
|
||||
bower:
|
||||
path: /app/location
|
||||
|
||||
- name: Update packages based on bower.json to their latest version.
|
||||
bower:
|
||||
path: /app/location
|
||||
state: latest
|
||||
|
||||
# install bower locally and run from there
|
||||
- npm:
|
||||
path: /app/location
|
||||
name: bower
|
||||
global: no
|
||||
- bower:
|
||||
path: /app/location
|
||||
relative_execpath: node_modules/.bin
|
||||
'''
|
||||
|
||||
|
||||
class Bower(object):
|
||||
def __init__(self, module, **kwargs):
|
||||
self.module = module
|
||||
self.name = kwargs['name']
|
||||
self.offline = kwargs['offline']
|
||||
self.production = kwargs['production']
|
||||
self.path = kwargs['path']
|
||||
self.relative_execpath = kwargs['relative_execpath']
|
||||
self.version = kwargs['version']
|
||||
|
||||
if kwargs['version']:
|
||||
self.name_version = self.name + '#' + self.version
|
||||
else:
|
||||
self.name_version = self.name
|
||||
|
||||
def _exec(self, args, run_in_check_mode=False, check_rc=True):
|
||||
if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
|
||||
cmd = []
|
||||
|
||||
if self.relative_execpath:
|
||||
cmd.append(os.path.join(self.path, self.relative_execpath, "bower"))
|
||||
if not os.path.isfile(cmd[-1]):
|
||||
self.module.fail_json(msg="bower not found at relative path %s" % self.relative_execpath)
|
||||
else:
|
||||
cmd.append("bower")
|
||||
|
||||
cmd.extend(args)
|
||||
cmd.extend(['--config.interactive=false', '--allow-root'])
|
||||
|
||||
if self.name:
|
||||
cmd.append(self.name_version)
|
||||
|
||||
if self.offline:
|
||||
cmd.append('--offline')
|
||||
|
||||
if self.production:
|
||||
cmd.append('--production')
|
||||
|
||||
# If path is specified, cd into that path and run the command.
|
||||
cwd = None
|
||||
if self.path:
|
||||
if not os.path.exists(self.path):
|
||||
os.makedirs(self.path)
|
||||
if not os.path.isdir(self.path):
|
||||
self.module.fail_json(msg="path %s is not a directory" % self.path)
|
||||
cwd = self.path
|
||||
|
||||
rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)
|
||||
return out
|
||||
return ''
|
||||
|
||||
def list(self):
|
||||
cmd = ['list', '--json']
|
||||
|
||||
installed = list()
|
||||
missing = list()
|
||||
outdated = list()
|
||||
data = json.loads(self._exec(cmd, True, False))
|
||||
if 'dependencies' in data:
|
||||
for dep in data['dependencies']:
|
||||
dep_data = data['dependencies'][dep]
|
||||
if dep_data.get('missing', False):
|
||||
missing.append(dep)
|
||||
elif ('version' in dep_data['pkgMeta'] and
|
||||
'update' in dep_data and
|
||||
dep_data['pkgMeta']['version'] != dep_data['update']['latest']):
|
||||
outdated.append(dep)
|
||||
elif dep_data.get('incompatible', False):
|
||||
outdated.append(dep)
|
||||
else:
|
||||
installed.append(dep)
|
||||
# Named dependency not installed
|
||||
else:
|
||||
missing.append(self.name)
|
||||
|
||||
return installed, missing, outdated
|
||||
|
||||
def install(self):
|
||||
return self._exec(['install'])
|
||||
|
||||
def update(self):
|
||||
return self._exec(['update'])
|
||||
|
||||
def uninstall(self):
|
||||
return self._exec(['uninstall'])
|
||||
|
||||
|
||||
def main():
|
||||
arg_spec = dict(
|
||||
name=dict(default=None),
|
||||
offline=dict(default='no', type='bool'),
|
||||
production=dict(default='no', type='bool'),
|
||||
path=dict(required=True, type='path'),
|
||||
relative_execpath=dict(default=None, required=False, type='path'),
|
||||
state=dict(default='present', choices=['present', 'absent', 'latest', ]),
|
||||
version=dict(default=None),
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec=arg_spec
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
offline = module.params['offline']
|
||||
production = module.params['production']
|
||||
path = os.path.expanduser(module.params['path'])
|
||||
relative_execpath = module.params['relative_execpath']
|
||||
state = module.params['state']
|
||||
version = module.params['version']
|
||||
|
||||
if state == 'absent' and not name:
|
||||
module.fail_json(msg='uninstalling a package is only available for named packages')
|
||||
|
||||
bower = Bower(module, name=name, offline=offline, production=production, path=path, relative_execpath=relative_execpath, version=version)
|
||||
|
||||
changed = False
|
||||
if state == 'present':
|
||||
installed, missing, outdated = bower.list()
|
||||
if len(missing):
|
||||
changed = True
|
||||
bower.install()
|
||||
elif state == 'latest':
|
||||
installed, missing, outdated = bower.list()
|
||||
if len(missing) or len(outdated):
|
||||
changed = True
|
||||
bower.update()
|
||||
else: # Absent
|
||||
installed, missing, outdated = bower.list()
|
||||
if name in installed:
|
||||
changed = True
|
||||
bower.uninstall()
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
# Import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
if __name__ == '__main__':
|
||||
main()
|
225
lib/ansible/modules/packaging/language/bundler.py
Normal file
225
lib/ansible/modules/packaging/language/bundler.py
Normal file
|
@ -0,0 +1,225 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2015, Tim Hoiberg <tim.hoiberg@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION='''
|
||||
---
|
||||
module: bundler
|
||||
short_description: Manage Ruby Gem dependencies with Bundler
|
||||
description:
|
||||
- Manage installation and Gem version dependencies for Ruby using the Bundler gem
|
||||
version_added: "2.0.0"
|
||||
options:
|
||||
executable:
|
||||
description:
|
||||
- The path to the bundler executable
|
||||
required: false
|
||||
default: null
|
||||
state:
|
||||
description:
|
||||
- The desired state of the Gem bundle. C(latest) updates gems to the most recent, acceptable version
|
||||
required: false
|
||||
choices: [present, latest]
|
||||
default: present
|
||||
chdir:
|
||||
description:
|
||||
- The directory to execute the bundler commands from. This directoy
|
||||
needs to contain a valid Gemfile or .bundle/ directory
|
||||
required: false
|
||||
default: temporary working directory
|
||||
exclude_groups:
|
||||
description:
|
||||
- A list of Gemfile groups to exclude during operations. This only
|
||||
applies when state is C(present). Bundler considers this
|
||||
a 'remembered' property for the Gemfile and will automatically exclude
|
||||
groups in future operations even if C(exclude_groups) is not set
|
||||
required: false
|
||||
default: null
|
||||
clean:
|
||||
description:
|
||||
- Only applies if state is C(present). If set removes any gems on the
|
||||
target host that are not in the gemfile
|
||||
required: false
|
||||
choices: [yes, no]
|
||||
default: "no"
|
||||
gemfile:
|
||||
description:
|
||||
- Only applies if state is C(present). The path to the gemfile to use to install gems.
|
||||
required: false
|
||||
default: Gemfile in current directory
|
||||
local:
|
||||
description:
|
||||
- If set only installs gems from the cache on the target host
|
||||
required: false
|
||||
choices: [yes, no]
|
||||
default: "no"
|
||||
deployment_mode:
|
||||
description:
|
||||
- Only applies if state is C(present). If set it will only install gems
|
||||
that are in the default or production groups. Requires a Gemfile.lock
|
||||
file to have been created prior
|
||||
required: false
|
||||
choices: [yes, no]
|
||||
default: "no"
|
||||
user_install:
|
||||
description:
|
||||
- Only applies if state is C(present). Installs gems in the local user's cache or for all users
|
||||
required: false
|
||||
choices: [yes, no]
|
||||
default: "yes"
|
||||
gem_path:
|
||||
description:
|
||||
- Only applies if state is C(present). Specifies the directory to
|
||||
install the gems into. If C(chdir) is set then this path is relative to
|
||||
C(chdir)
|
||||
required: false
|
||||
default: RubyGems gem paths
|
||||
binstub_directory:
|
||||
description:
|
||||
- Only applies if state is C(present). Specifies the directory to
|
||||
install any gem bins files to. When executed the bin files will run
|
||||
within the context of the Gemfile and fail if any required gem
|
||||
dependencies are not installed. If C(chdir) is set then this path is
|
||||
relative to C(chdir)
|
||||
required: false
|
||||
default: null
|
||||
extra_args:
|
||||
description:
|
||||
- A space separated string of additional commands that can be applied to
|
||||
the Bundler command. Refer to the Bundler documentation for more
|
||||
information
|
||||
required: false
|
||||
default: null
|
||||
author: "Tim Hoiberg (@thoiberg)"
|
||||
'''
|
||||
|
||||
EXAMPLES='''
|
||||
# Installs gems from a Gemfile in the current directory
|
||||
- bundler:
|
||||
state: present
|
||||
executable: ~/.rvm/gems/2.1.5/bin/bundle
|
||||
|
||||
# Excludes the production group from installing
|
||||
- bundler:
|
||||
state: present
|
||||
exclude_groups: production
|
||||
|
||||
# Only install gems from the default and production groups
|
||||
- bundler:
|
||||
state: present
|
||||
deployment_mode: yes
|
||||
|
||||
# Installs gems using a Gemfile in another directory
|
||||
- bundler:
|
||||
state: present
|
||||
gemfile: ../rails_project/Gemfile
|
||||
|
||||
# Updates Gemfile in another directory
|
||||
- bundler:
|
||||
state: latest
|
||||
chdir: ~/rails_project
|
||||
'''
|
||||
|
||||
|
||||
def get_bundler_executable(module):
|
||||
if module.params.get('executable'):
|
||||
return module.params.get('executable').split(' ')
|
||||
else:
|
||||
return [ module.get_bin_path('bundle', True) ]
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
executable=dict(default=None, required=False),
|
||||
state=dict(default='present', required=False, choices=['present', 'latest']),
|
||||
chdir=dict(default=None, required=False, type='path'),
|
||||
exclude_groups=dict(default=None, required=False, type='list'),
|
||||
clean=dict(default=False, required=False, type='bool'),
|
||||
gemfile=dict(default=None, required=False, type='path'),
|
||||
local=dict(default=False, required=False, type='bool'),
|
||||
deployment_mode=dict(default=False, required=False, type='bool'),
|
||||
user_install=dict(default=True, required=False, type='bool'),
|
||||
gem_path=dict(default=None, required=False, type='path'),
|
||||
binstub_directory=dict(default=None, required=False, type='path'),
|
||||
extra_args=dict(default=None, required=False),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
executable = module.params.get('executable')
|
||||
state = module.params.get('state')
|
||||
chdir = module.params.get('chdir')
|
||||
exclude_groups = module.params.get('exclude_groups')
|
||||
clean = module.params.get('clean')
|
||||
gemfile = module.params.get('gemfile')
|
||||
local = module.params.get('local')
|
||||
deployment_mode = module.params.get('deployment_mode')
|
||||
user_install = module.params.get('user_install')
|
||||
gem_path = module.params.get('gem_path')
|
||||
binstub_directory = module.params.get('binstub_directory')
|
||||
extra_args = module.params.get('extra_args')
|
||||
|
||||
cmd = get_bundler_executable(module)
|
||||
|
||||
if module.check_mode:
|
||||
cmd.append('check')
|
||||
rc, out, err = module.run_command(cmd, cwd=chdir, check_rc=False)
|
||||
|
||||
module.exit_json(changed=rc != 0, state=state, stdout=out, stderr=err)
|
||||
|
||||
if state == 'present':
|
||||
cmd.append('install')
|
||||
if exclude_groups:
|
||||
cmd.extend(['--without', ':'.join(exclude_groups)])
|
||||
if clean:
|
||||
cmd.append('--clean')
|
||||
if gemfile:
|
||||
cmd.extend(['--gemfile', gemfile])
|
||||
if local:
|
||||
cmd.append('--local')
|
||||
if deployment_mode:
|
||||
cmd.append('--deployment')
|
||||
if not user_install:
|
||||
cmd.append('--system')
|
||||
if gem_path:
|
||||
cmd.extend(['--path', gem_path])
|
||||
if binstub_directory:
|
||||
cmd.extend(['--binstubs', binstub_directory])
|
||||
else:
|
||||
cmd.append('update')
|
||||
if local:
|
||||
cmd.append('--local')
|
||||
|
||||
if extra_args:
|
||||
cmd.extend(extra_args.split(' '))
|
||||
|
||||
rc, out, err = module.run_command(cmd, cwd=chdir, check_rc=True)
|
||||
|
||||
module.exit_json(changed='Installing' in out, state=state, stdout=out, stderr=err)
|
||||
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
if __name__ == '__main__':
|
||||
main()
|
239
lib/ansible/modules/packaging/language/composer.py
Normal file
239
lib/ansible/modules/packaging/language/composer.py
Normal file
|
@ -0,0 +1,239 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2014, Dimitrios Tydeas Mengidis <tydeas.dr@gmail.com>
|
||||
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: composer
|
||||
author:
|
||||
- "Dimitrios Tydeas Mengidis (@dmtrs)"
|
||||
- "René Moser (@resmo)"
|
||||
short_description: Dependency Manager for PHP
|
||||
version_added: "1.6"
|
||||
description:
|
||||
- Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you
|
||||
options:
|
||||
command:
|
||||
version_added: "1.8"
|
||||
description:
|
||||
- Composer command like "install", "update" and so on
|
||||
required: false
|
||||
default: install
|
||||
arguments:
|
||||
version_added: "2.0"
|
||||
description:
|
||||
- Composer arguments like required package, version and so on
|
||||
required: false
|
||||
default: null
|
||||
working_dir:
|
||||
description:
|
||||
- Directory of your project ( see --working-dir )
|
||||
required: true
|
||||
default: null
|
||||
aliases: [ "working-dir" ]
|
||||
prefer_source:
|
||||
description:
|
||||
- Forces installation from package sources when possible ( see --prefer-source )
|
||||
required: false
|
||||
default: "no"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "prefer-source" ]
|
||||
prefer_dist:
|
||||
description:
|
||||
- Forces installation from package dist even for dev versions ( see --prefer-dist )
|
||||
required: false
|
||||
default: "no"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "prefer-dist" ]
|
||||
no_dev:
|
||||
description:
|
||||
- Disables installation of require-dev packages ( see --no-dev )
|
||||
required: false
|
||||
default: "yes"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "no-dev" ]
|
||||
no_scripts:
|
||||
description:
|
||||
- Skips the execution of all scripts defined in composer.json ( see --no-scripts )
|
||||
required: false
|
||||
default: "no"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "no-scripts" ]
|
||||
no_plugins:
|
||||
description:
|
||||
- Disables all plugins ( see --no-plugins )
|
||||
required: false
|
||||
default: "no"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "no-plugins" ]
|
||||
optimize_autoloader:
|
||||
description:
|
||||
- Optimize autoloader during autoloader dump ( see --optimize-autoloader ). Convert PSR-0/4 autoloading to classmap to get a faster autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default.
|
||||
required: false
|
||||
default: "yes"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "optimize-autoloader" ]
|
||||
ignore_platform_reqs:
|
||||
version_added: "2.0"
|
||||
description:
|
||||
- Ignore php, hhvm, lib-* and ext-* requirements and force the installation even if the local machine does not fulfill these.
|
||||
required: false
|
||||
default: "no"
|
||||
choices: [ "yes", "no" ]
|
||||
aliases: [ "ignore-platform-reqs" ]
|
||||
requirements:
|
||||
- php
|
||||
- composer installed in bin path (recommended /usr/local/bin)
|
||||
notes:
|
||||
- Default options that are always appended in each execution are --no-ansi, --no-interaction and --no-progress if available.
|
||||
- We received reports about issues on macOS if composer was installed by Homebrew. Please use the official install method to avoid it.
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Downloads and installs all the libs and dependencies outlined in the /path/to/project/composer.lock
|
||||
- composer:
|
||||
command: install
|
||||
working_dir: /path/to/project
|
||||
|
||||
- composer:
|
||||
command: require
|
||||
arguments: my/package
|
||||
working_dir: /path/to/project
|
||||
|
||||
# Clone project and install with all dependencies
|
||||
- composer:
|
||||
command: create-project
|
||||
arguments: package/package /path/to/project ~1.0
|
||||
working_dir: /path/to/project
|
||||
prefer_dist: yes
|
||||
'''
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
# Let snippet from module_utils/basic.py return a proper error in this case
|
||||
pass
|
||||
|
||||
|
||||
def parse_out(string):
|
||||
return re.sub("\s+", " ", string).strip()
|
||||
|
||||
def has_changed(string):
|
||||
return "Nothing to install or update" not in string
|
||||
|
||||
def get_available_options(module, command='install'):
|
||||
# get all availabe options from a composer command using composer help to json
|
||||
rc, out, err = composer_command(module, "help %s --format=json" % command)
|
||||
if rc != 0:
|
||||
output = parse_out(err)
|
||||
module.fail_json(msg=output)
|
||||
|
||||
command_help_json = json.loads(out)
|
||||
return command_help_json['definition']['options']
|
||||
|
||||
def composer_command(module, command, arguments = "", options=[]):
|
||||
php_path = module.get_bin_path("php", True, ["/usr/local/bin"])
|
||||
composer_path = module.get_bin_path("composer", True, ["/usr/local/bin"])
|
||||
cmd = "%s %s %s %s %s" % (php_path, composer_path, command, " ".join(options), arguments)
|
||||
return module.run_command(cmd)
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
command = dict(default="install", type="str", required=False),
|
||||
arguments = dict(default="", type="str", required=False),
|
||||
working_dir = dict(aliases=["working-dir"], required=True),
|
||||
prefer_source = dict(default="no", type="bool", aliases=["prefer-source"]),
|
||||
prefer_dist = dict(default="no", type="bool", aliases=["prefer-dist"]),
|
||||
no_dev = dict(default="yes", type="bool", aliases=["no-dev"]),
|
||||
no_scripts = dict(default="no", type="bool", aliases=["no-scripts"]),
|
||||
no_plugins = dict(default="no", type="bool", aliases=["no-plugins"]),
|
||||
optimize_autoloader = dict(default="yes", type="bool", aliases=["optimize-autoloader"]),
|
||||
ignore_platform_reqs = dict(default="no", type="bool", aliases=["ignore-platform-reqs"]),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
# Get composer command with fallback to default
|
||||
command = module.params['command']
|
||||
if re.search(r"\s", command):
|
||||
module.fail_json(msg="Use the 'arguments' param for passing arguments with the 'command'")
|
||||
|
||||
arguments = module.params['arguments']
|
||||
available_options = get_available_options(module=module, command=command)
|
||||
|
||||
options = []
|
||||
|
||||
# Default options
|
||||
default_options = [
|
||||
'no-ansi',
|
||||
'no-interaction',
|
||||
'no-progress',
|
||||
]
|
||||
|
||||
for option in default_options:
|
||||
if option in available_options:
|
||||
option = "--%s" % option
|
||||
options.append(option)
|
||||
|
||||
options.extend(['--working-dir', os.path.abspath(module.params['working_dir'])])
|
||||
|
||||
option_params = {
|
||||
'prefer_source': 'prefer-source',
|
||||
'prefer_dist': 'prefer-dist',
|
||||
'no_dev': 'no-dev',
|
||||
'no_scripts': 'no-scripts',
|
||||
'no_plugins': 'no_plugins',
|
||||
'optimize_autoloader': 'optimize-autoloader',
|
||||
'ignore_platform_reqs': 'ignore-platform-reqs',
|
||||
}
|
||||
|
||||
for param, option in option_params.iteritems():
|
||||
if module.params.get(param) and option in available_options:
|
||||
option = "--%s" % option
|
||||
options.append(option)
|
||||
|
||||
if module.check_mode:
|
||||
options.append('--dry-run')
|
||||
|
||||
rc, out, err = composer_command(module, command, arguments, options)
|
||||
|
||||
if rc != 0:
|
||||
output = parse_out(err)
|
||||
module.fail_json(msg=output, stdout=err)
|
||||
else:
|
||||
# Composer version > 1.0.0-alpha9 now use stderr for standard notification messages
|
||||
output = parse_out(out + err)
|
||||
module.exit_json(changed=has_changed(output), msg=output, stdout=out+err)
|
||||
|
||||
# import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
if __name__ == '__main__':
|
||||
main()
|
239
lib/ansible/modules/packaging/language/cpanm.py
Normal file
239
lib/ansible/modules/packaging/language/cpanm.py
Normal file
|
@ -0,0 +1,239 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2012, Franck Cuny <franck@lumberjaph.net>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cpanm
|
||||
short_description: Manages Perl library dependencies.
|
||||
description:
|
||||
- Manage Perl library dependencies.
|
||||
version_added: "1.6"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The name of the Perl library to install. You may use the "full distribution path", e.g. MIYAGAWA/Plack-0.99_05.tar.gz
|
||||
required: false
|
||||
default: null
|
||||
aliases: ["pkg"]
|
||||
from_path:
|
||||
description:
|
||||
- The local directory from where to install
|
||||
required: false
|
||||
default: null
|
||||
notest:
|
||||
description:
|
||||
- Do not run unit tests
|
||||
required: false
|
||||
default: false
|
||||
locallib:
|
||||
description:
|
||||
- Specify the install base to install modules
|
||||
required: false
|
||||
default: false
|
||||
mirror:
|
||||
description:
|
||||
- Specifies the base URL for the CPAN mirror to use
|
||||
required: false
|
||||
default: false
|
||||
mirror_only:
|
||||
description:
|
||||
- Use the mirror's index file instead of the CPAN Meta DB
|
||||
required: false
|
||||
default: false
|
||||
installdeps:
|
||||
description:
|
||||
- Only install dependencies
|
||||
required: false
|
||||
default: false
|
||||
version_added: "2.0"
|
||||
version:
|
||||
description:
|
||||
- minimum version of perl module to consider acceptable
|
||||
required: false
|
||||
default: false
|
||||
version_added: "2.1"
|
||||
system_lib:
|
||||
description:
|
||||
- Use this if you want to install modules to the system perl include path. You must be root or have "passwordless" sudo for this to work.
|
||||
- This uses the cpanm commandline option '--sudo', which has nothing to do with ansible privilege escalation.
|
||||
required: false
|
||||
default: false
|
||||
version_added: "2.0"
|
||||
aliases: ['use_sudo']
|
||||
executable:
|
||||
description:
|
||||
- Override the path to the cpanm executable
|
||||
required: false
|
||||
default: null
|
||||
version_added: "2.1"
|
||||
notes:
|
||||
- Please note that U(http://search.cpan.org/dist/App-cpanminus/bin/cpanm, cpanm) must be installed on the remote host.
|
||||
author: "Franck Cuny (@franckcuny)"
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# install Dancer perl package
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
|
||||
# install version 0.99_05 of the Plack perl package
|
||||
- cpanm:
|
||||
name: MIYAGAWA/Plack-0.99_05.tar.gz
|
||||
|
||||
# install Dancer into the specified locallib
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
locallib: /srv/webapps/my_app/extlib
|
||||
|
||||
# install perl dependencies from local directory
|
||||
- cpanm:
|
||||
from_path: /srv/webapps/my_app/src/
|
||||
|
||||
# install Dancer perl package without running the unit tests in indicated locallib
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
notest: True
|
||||
locallib: /srv/webapps/my_app/extlib
|
||||
|
||||
# install Dancer perl package from a specific mirror
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
mirror: 'http://cpan.cpantesters.org/'
|
||||
|
||||
# install Dancer perl package into the system root path
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
system_lib: yes
|
||||
|
||||
# install Dancer if it's not already installed
|
||||
# OR the installed version is older than version 1.0
|
||||
- cpanm:
|
||||
name: Dancer
|
||||
version: '1.0'
|
||||
'''
|
||||
|
||||
def _is_package_installed(module, name, locallib, cpanm, version):
|
||||
cmd = ""
|
||||
if locallib:
|
||||
os.environ["PERL5LIB"] = "%s/lib/perl5" % locallib
|
||||
cmd = "%s perl -e ' use %s" % (cmd, name)
|
||||
if version:
|
||||
cmd = "%s %s;'" % (cmd, version)
|
||||
else:
|
||||
cmd = "%s;'" % cmd
|
||||
res, stdout, stderr = module.run_command(cmd, check_rc=False)
|
||||
if res == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _build_cmd_line(name, from_path, notest, locallib, mirror, mirror_only, installdeps, cpanm, use_sudo):
|
||||
# this code should use "%s" like everything else and just return early but not fixing all of it now.
|
||||
# don't copy stuff like this
|
||||
if from_path:
|
||||
cmd = cpanm + " " + from_path
|
||||
else:
|
||||
cmd = cpanm + " " + name
|
||||
|
||||
if notest is True:
|
||||
cmd = cmd + " -n"
|
||||
|
||||
if locallib is not None:
|
||||
cmd = cmd + " -l " + locallib
|
||||
|
||||
if mirror is not None:
|
||||
cmd = cmd + " --mirror " + mirror
|
||||
|
||||
if mirror_only is True:
|
||||
cmd = cmd + " --mirror-only"
|
||||
|
||||
if installdeps is True:
|
||||
cmd = cmd + " --installdeps"
|
||||
|
||||
if use_sudo is True:
|
||||
cmd = cmd + " --sudo"
|
||||
|
||||
return cmd
|
||||
|
||||
|
||||
def _get_cpanm_path(module):
|
||||
if module.params['executable']:
|
||||
return module.params['executable']
|
||||
else:
|
||||
return module.get_bin_path('cpanm', True)
|
||||
|
||||
|
||||
def main():
|
||||
arg_spec = dict(
|
||||
name=dict(default=None, required=False, aliases=['pkg']),
|
||||
from_path=dict(default=None, required=False, type='path'),
|
||||
notest=dict(default=False, type='bool'),
|
||||
locallib=dict(default=None, required=False, type='path'),
|
||||
mirror=dict(default=None, required=False),
|
||||
mirror_only=dict(default=False, type='bool'),
|
||||
installdeps=dict(default=False, type='bool'),
|
||||
system_lib=dict(default=False, type='bool', aliases=['use_sudo']),
|
||||
version=dict(default=None, required=False),
|
||||
executable=dict(required=False, type='path'),
|
||||
)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=arg_spec,
|
||||
required_one_of=[['name', 'from_path']],
|
||||
)
|
||||
|
||||
cpanm = _get_cpanm_path(module)
|
||||
name = module.params['name']
|
||||
from_path = module.params['from_path']
|
||||
notest = module.boolean(module.params.get('notest', False))
|
||||
locallib = module.params['locallib']
|
||||
mirror = module.params['mirror']
|
||||
mirror_only = module.params['mirror_only']
|
||||
installdeps = module.params['installdeps']
|
||||
use_sudo = module.params['system_lib']
|
||||
version = module.params['version']
|
||||
|
||||
changed = False
|
||||
|
||||
installed = _is_package_installed(module, name, locallib, cpanm, version)
|
||||
|
||||
if not installed:
|
||||
cmd = _build_cmd_line(name, from_path, notest, locallib, mirror, mirror_only, installdeps, cpanm, use_sudo)
|
||||
|
||||
rc_cpanm, out_cpanm, err_cpanm = module.run_command(cmd, check_rc=False)
|
||||
|
||||
if rc_cpanm != 0:
|
||||
module.fail_json(msg=err_cpanm, cmd=cmd)
|
||||
|
||||
if (err_cpanm.find('is up to date') == -1 and out_cpanm.find('is up to date') == -1):
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed, binary=cpanm, name=name)
|
||||
|
||||
# import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
424
lib/ansible/modules/packaging/language/maven_artifact.py
Normal file
424
lib/ansible/modules/packaging/language/maven_artifact.py
Normal file
|
@ -0,0 +1,424 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2014, Chris Schmidt <chris.schmidt () contrastsecurity.com>
|
||||
#
|
||||
# Built using https://github.com/hamnis/useful-scripts/blob/master/python/download-maven-artifact
|
||||
# as a reference and starting point.
|
||||
#
|
||||
# This module is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This software is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__author__ = 'cschmidt'
|
||||
|
||||
from lxml import etree
|
||||
import os
|
||||
import hashlib
|
||||
import sys
|
||||
import posixpath
|
||||
import urlparse
|
||||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.urls import *
|
||||
try:
|
||||
import boto3
|
||||
HAS_BOTO = True
|
||||
except ImportError:
|
||||
HAS_BOTO = False
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: maven_artifact
|
||||
short_description: Downloads an Artifact from a Maven Repository
|
||||
version_added: "2.0"
|
||||
description:
|
||||
- Downloads an artifact from a maven repository given the maven coordinates provided to the module. Can retrieve
|
||||
- snapshots or release versions of the artifact and will resolve the latest available version if one is not
|
||||
- available.
|
||||
author: "Chris Schmidt (@chrisisbeef)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- lxml
|
||||
- boto if using a S3 repository (s3://...)
|
||||
options:
|
||||
group_id:
|
||||
description:
|
||||
- The Maven groupId coordinate
|
||||
required: true
|
||||
artifact_id:
|
||||
description:
|
||||
- The maven artifactId coordinate
|
||||
required: true
|
||||
version:
|
||||
description:
|
||||
- The maven version coordinate
|
||||
required: false
|
||||
default: latest
|
||||
classifier:
|
||||
description:
|
||||
- The maven classifier coordinate
|
||||
required: false
|
||||
default: null
|
||||
extension:
|
||||
description:
|
||||
- The maven type/extension coordinate
|
||||
required: false
|
||||
default: jar
|
||||
repository_url:
|
||||
description:
|
||||
- The URL of the Maven Repository to download from.
|
||||
- Use s3://... if the repository is hosted on Amazon S3, added in version 2.2.
|
||||
required: false
|
||||
default: http://repo1.maven.org/maven2
|
||||
username:
|
||||
description:
|
||||
- The username to authenticate as to the Maven Repository. Use AWS secret key of the repository is hosted on S3
|
||||
required: false
|
||||
default: null
|
||||
aliases: [ "aws_secret_key" ]
|
||||
password:
|
||||
description:
|
||||
- The password to authenticate with to the Maven Repository. Use AWS secret access key of the repository is hosted on S3
|
||||
required: false
|
||||
default: null
|
||||
aliases: [ "aws_secret_access_key" ]
|
||||
dest:
|
||||
description:
|
||||
- The path where the artifact should be written to
|
||||
required: true
|
||||
default: false
|
||||
state:
|
||||
description:
|
||||
- The desired state of the artifact
|
||||
required: true
|
||||
default: present
|
||||
choices: [present,absent]
|
||||
timeout:
|
||||
description:
|
||||
- Specifies a timeout in seconds for the connection attempt
|
||||
required: false
|
||||
default: 10
|
||||
version_added: "2.3"
|
||||
validate_certs:
|
||||
description:
|
||||
- If C(no), SSL certificates will not be validated. This should only be set to C(no) when no other option exists.
|
||||
required: false
|
||||
default: 'yes'
|
||||
choices: ['yes', 'no']
|
||||
version_added: "1.9.3"
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Download the latest version of the JUnit framework artifact from Maven Central
|
||||
- maven_artifact:
|
||||
group_id: junit
|
||||
artifact_id: junit
|
||||
dest: /tmp/junit-latest.jar
|
||||
|
||||
# Download JUnit 4.11 from Maven Central
|
||||
- maven_artifact:
|
||||
group_id: junit
|
||||
artifact_id: junit
|
||||
version: 4.11
|
||||
dest: /tmp/junit-4.11.jar
|
||||
|
||||
# Download an artifact from a private repository requiring authentication
|
||||
- maven_artifact:
|
||||
group_id: com.company
|
||||
artifact_id: library-name
|
||||
repository_url: 'https://repo.company.com/maven'
|
||||
username: user
|
||||
password: pass
|
||||
dest: /tmp/library-name-latest.jar
|
||||
|
||||
# Download a WAR File to the Tomcat webapps directory to be deployed
|
||||
- maven_artifact:
|
||||
group_id: com.company
|
||||
artifact_id: web-app
|
||||
extension: war
|
||||
repository_url: 'https://repo.company.com/maven'
|
||||
dest: /var/lib/tomcat7/webapps/web-app.war
|
||||
'''
|
||||
|
||||
class Artifact(object):
|
||||
def __init__(self, group_id, artifact_id, version, classifier=None, extension='jar'):
|
||||
if not group_id:
|
||||
raise ValueError("group_id must be set")
|
||||
if not artifact_id:
|
||||
raise ValueError("artifact_id must be set")
|
||||
|
||||
self.group_id = group_id
|
||||
self.artifact_id = artifact_id
|
||||
self.version = version
|
||||
self.classifier = classifier
|
||||
|
||||
if not extension:
|
||||
self.extension = "jar"
|
||||
else:
|
||||
self.extension = extension
|
||||
|
||||
def is_snapshot(self):
|
||||
return self.version and self.version.endswith("SNAPSHOT")
|
||||
|
||||
def path(self, with_version=True):
|
||||
base = posixpath.join(self.group_id.replace(".", "/"), self.artifact_id)
|
||||
if with_version and self.version:
|
||||
return posixpath.join(base, self.version)
|
||||
else:
|
||||
return base
|
||||
|
||||
def _generate_filename(self):
|
||||
if not self.classifier:
|
||||
return self.artifact_id + "." + self.extension
|
||||
else:
|
||||
return self.artifact_id + "-" + self.classifier + "." + self.extension
|
||||
|
||||
def get_filename(self, filename=None):
|
||||
if not filename:
|
||||
filename = self._generate_filename()
|
||||
elif os.path.isdir(filename):
|
||||
filename = os.path.join(filename, self._generate_filename())
|
||||
return filename
|
||||
|
||||
def __str__(self):
|
||||
if self.classifier:
|
||||
return "%s:%s:%s:%s:%s" % (self.group_id, self.artifact_id, self.extension, self.classifier, self.version)
|
||||
elif self.extension != "jar":
|
||||
return "%s:%s:%s:%s" % (self.group_id, self.artifact_id, self.extension, self.version)
|
||||
else:
|
||||
return "%s:%s:%s" % (self.group_id, self.artifact_id, self.version)
|
||||
|
||||
@staticmethod
|
||||
def parse(input):
|
||||
parts = input.split(":")
|
||||
if len(parts) >= 3:
|
||||
g = parts[0]
|
||||
a = parts[1]
|
||||
v = parts[len(parts) - 1]
|
||||
t = None
|
||||
c = None
|
||||
if len(parts) == 4:
|
||||
t = parts[2]
|
||||
if len(parts) == 5:
|
||||
t = parts[2]
|
||||
c = parts[3]
|
||||
return Artifact(g, a, v, c, t)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class MavenDownloader:
|
||||
def __init__(self, module, base="http://repo1.maven.org/maven2"):
|
||||
self.module = module
|
||||
if base.endswith("/"):
|
||||
base = base.rstrip("/")
|
||||
self.base = base
|
||||
self.user_agent = "Maven Artifact Downloader/1.0"
|
||||
|
||||
def _find_latest_version_available(self, artifact):
|
||||
path = "/%s/maven-metadata.xml" % (artifact.path(False))
|
||||
xml = self._request(self.base + path, "Failed to download maven-metadata.xml", lambda r: etree.parse(r))
|
||||
v = xml.xpath("/metadata/versioning/versions/version[last()]/text()")
|
||||
if v:
|
||||
return v[0]
|
||||
|
||||
def find_uri_for_artifact(self, artifact):
|
||||
if artifact.version == "latest":
|
||||
artifact.version = self._find_latest_version_available(artifact)
|
||||
|
||||
if artifact.is_snapshot():
|
||||
path = "/%s/maven-metadata.xml" % (artifact.path())
|
||||
xml = self._request(self.base + path, "Failed to download maven-metadata.xml", lambda r: etree.parse(r))
|
||||
timestamp = xml.xpath("/metadata/versioning/snapshot/timestamp/text()")[0]
|
||||
buildNumber = xml.xpath("/metadata/versioning/snapshot/buildNumber/text()")[0]
|
||||
for snapshotArtifact in xml.xpath("/metadata/versioning/snapshotVersions/snapshotVersion"):
|
||||
if len(snapshotArtifact.xpath("classifier/text()")) > 0 and snapshotArtifact.xpath("classifier/text()")[0] == artifact.classifier and len(snapshotArtifact.xpath("extension/text()")) > 0 and snapshotArtifact.xpath("extension/text()")[0] == artifact.extension:
|
||||
return self._uri_for_artifact(artifact, snapshotArtifact.xpath("value/text()")[0])
|
||||
return self._uri_for_artifact(artifact, artifact.version.replace("SNAPSHOT", timestamp + "-" + buildNumber))
|
||||
|
||||
return self._uri_for_artifact(artifact, artifact.version)
|
||||
|
||||
def _uri_for_artifact(self, artifact, version=None):
|
||||
if artifact.is_snapshot() and not version:
|
||||
raise ValueError("Expected uniqueversion for snapshot artifact " + str(artifact))
|
||||
elif not artifact.is_snapshot():
|
||||
version = artifact.version
|
||||
if artifact.classifier:
|
||||
return posixpath.join(self.base, artifact.path(), artifact.artifact_id + "-" + version + "-" + artifact.classifier + "." + artifact.extension)
|
||||
|
||||
return posixpath.join(self.base, artifact.path(), artifact.artifact_id + "-" + version + "." + artifact.extension)
|
||||
|
||||
def _request(self, url, failmsg, f):
|
||||
url_to_use = url
|
||||
parsed_url = urlparse(url)
|
||||
if parsed_url.scheme=='s3':
|
||||
parsed_url = urlparse(url)
|
||||
bucket_name = parsed_url.netloc
|
||||
key_name = parsed_url.path[1:]
|
||||
client = boto3.client('s3',aws_access_key_id=self.module.params.get('username', ''), aws_secret_access_key=self.module.params.get('password', ''))
|
||||
url_to_use = client.generate_presigned_url('get_object',Params={'Bucket':bucket_name,'Key':key_name},ExpiresIn=10)
|
||||
|
||||
req_timeout = self.module.params.get('timeout')
|
||||
|
||||
# Hack to add parameters in the way that fetch_url expects
|
||||
self.module.params['url_username'] = self.module.params.get('username', '')
|
||||
self.module.params['url_password'] = self.module.params.get('password', '')
|
||||
self.module.params['http_agent'] = self.module.params.get('user_agent', None)
|
||||
|
||||
response, info = fetch_url(self.module, url_to_use, timeout=req_timeout)
|
||||
if info['status'] != 200:
|
||||
raise ValueError(failmsg + " because of " + info['msg'] + "for URL " + url_to_use)
|
||||
else:
|
||||
return f(response)
|
||||
|
||||
|
||||
def download(self, artifact, filename=None):
|
||||
filename = artifact.get_filename(filename)
|
||||
if not artifact.version or artifact.version == "latest":
|
||||
artifact = Artifact(artifact.group_id, artifact.artifact_id, self._find_latest_version_available(artifact),
|
||||
artifact.classifier, artifact.extension)
|
||||
|
||||
url = self.find_uri_for_artifact(artifact)
|
||||
if not self.verify_md5(filename, url + ".md5"):
|
||||
response = self._request(url, "Failed to download artifact " + str(artifact), lambda r: r)
|
||||
if response:
|
||||
f = open(filename, 'w')
|
||||
# f.write(response.read())
|
||||
self._write_chunks(response, f, report_hook=self.chunk_report)
|
||||
f.close()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def chunk_report(self, bytes_so_far, chunk_size, total_size):
|
||||
percent = float(bytes_so_far) / total_size
|
||||
percent = round(percent * 100, 2)
|
||||
sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" %
|
||||
(bytes_so_far, total_size, percent))
|
||||
|
||||
if bytes_so_far >= total_size:
|
||||
sys.stdout.write('\n')
|
||||
|
||||
def _write_chunks(self, response, file, chunk_size=8192, report_hook=None):
|
||||
total_size = response.info().getheader('Content-Length').strip()
|
||||
total_size = int(total_size)
|
||||
bytes_so_far = 0
|
||||
|
||||
while 1:
|
||||
chunk = response.read(chunk_size)
|
||||
bytes_so_far += len(chunk)
|
||||
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
file.write(chunk)
|
||||
if report_hook:
|
||||
report_hook(bytes_so_far, chunk_size, total_size)
|
||||
|
||||
return bytes_so_far
|
||||
|
||||
def verify_md5(self, file, remote_md5):
|
||||
if not os.path.exists(file):
|
||||
return False
|
||||
else:
|
||||
local_md5 = self._local_md5(file)
|
||||
remote = self._request(remote_md5, "Failed to download MD5", lambda r: r.read())
|
||||
return local_md5 == remote
|
||||
|
||||
def _local_md5(self, file):
|
||||
md5 = hashlib.md5()
|
||||
f = open(file, 'rb')
|
||||
for chunk in iter(lambda: f.read(8192), ''):
|
||||
md5.update(chunk)
|
||||
f.close()
|
||||
return md5.hexdigest()
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
group_id = dict(default=None),
|
||||
artifact_id = dict(default=None),
|
||||
version = dict(default="latest"),
|
||||
classifier = dict(default=None),
|
||||
extension = dict(default='jar'),
|
||||
repository_url = dict(default=None),
|
||||
username = dict(default=None,aliases=['aws_secret_key']),
|
||||
password = dict(default=None, no_log=True,aliases=['aws_secret_access_key']),
|
||||
state = dict(default="present", choices=["present","absent"]), # TODO - Implement a "latest" state
|
||||
timeout = dict(default=10, type='int'),
|
||||
dest = dict(type="path", default=None),
|
||||
validate_certs = dict(required=False, default=True, type='bool'),
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
parsed_url = urlparse(module.params["repository_url"])
|
||||
except AttributeError as e:
|
||||
module.fail_json(msg='url parsing went wrong %s' % e)
|
||||
|
||||
if parsed_url.scheme=='s3' and not HAS_BOTO:
|
||||
module.fail_json(msg='boto3 required for this module, when using s3:// repository URLs')
|
||||
|
||||
group_id = module.params["group_id"]
|
||||
artifact_id = module.params["artifact_id"]
|
||||
version = module.params["version"]
|
||||
classifier = module.params["classifier"]
|
||||
extension = module.params["extension"]
|
||||
repository_url = module.params["repository_url"]
|
||||
repository_username = module.params["username"]
|
||||
repository_password = module.params["password"]
|
||||
state = module.params["state"]
|
||||
dest = module.params["dest"]
|
||||
|
||||
if not repository_url:
|
||||
repository_url = "http://repo1.maven.org/maven2"
|
||||
|
||||
#downloader = MavenDownloader(module, repository_url, repository_username, repository_password)
|
||||
downloader = MavenDownloader(module, repository_url)
|
||||
|
||||
try:
|
||||
artifact = Artifact(group_id, artifact_id, version, classifier, extension)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg=e.args[0])
|
||||
|
||||
prev_state = "absent"
|
||||
if os.path.isdir(dest):
|
||||
dest = posixpath.join(dest, artifact_id + "-" + version + "." + extension)
|
||||
if os.path.lexists(dest) and downloader.verify_md5(dest, downloader.find_uri_for_artifact(artifact) + '.md5'):
|
||||
prev_state = "present"
|
||||
else:
|
||||
path = os.path.dirname(dest)
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
if prev_state == "present":
|
||||
module.exit_json(dest=dest, state=state, changed=False)
|
||||
|
||||
try:
|
||||
if downloader.download(artifact, dest):
|
||||
module.exit_json(state=state, dest=dest, group_id=group_id, artifact_id=artifact_id, version=version, classifier=classifier, extension=extension, repository_url=repository_url, changed=True)
|
||||
else:
|
||||
module.fail_json(msg="Unable to download the artifact")
|
||||
except ValueError as e:
|
||||
module.fail_json(msg=e.args[0])
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
295
lib/ansible/modules/packaging/language/npm.py
Normal file
295
lib/ansible/modules/packaging/language/npm.py
Normal file
|
@ -0,0 +1,295 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2013, Chris Hoffman <christopher.hoffman@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: npm
|
||||
short_description: Manage node.js packages with npm
|
||||
description:
|
||||
- Manage node.js packages with Node Package Manager (npm)
|
||||
version_added: 1.2
|
||||
author: "Chris Hoffman (@chrishoffman)"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The name of a node.js library to install
|
||||
required: false
|
||||
path:
|
||||
description:
|
||||
- The base path where to install the node.js libraries
|
||||
required: false
|
||||
version:
|
||||
description:
|
||||
- The version to be installed
|
||||
required: false
|
||||
global:
|
||||
description:
|
||||
- Install the node.js library globally
|
||||
required: false
|
||||
default: no
|
||||
choices: [ "yes", "no" ]
|
||||
executable:
|
||||
description:
|
||||
- The executable location for npm.
|
||||
- This is useful if you are using a version manager, such as nvm
|
||||
required: false
|
||||
ignore_scripts:
|
||||
description:
|
||||
- Use the --ignore-scripts flag when installing.
|
||||
required: false
|
||||
choices: [ "yes", "no" ]
|
||||
default: no
|
||||
version_added: "1.8"
|
||||
production:
|
||||
description:
|
||||
- Install dependencies in production mode, excluding devDependencies
|
||||
required: false
|
||||
choices: [ "yes", "no" ]
|
||||
default: no
|
||||
registry:
|
||||
description:
|
||||
- The registry to install modules from.
|
||||
required: false
|
||||
version_added: "1.6"
|
||||
state:
|
||||
description:
|
||||
- The state of the node.js library
|
||||
required: false
|
||||
default: present
|
||||
choices: [ "present", "absent", "latest" ]
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
description: Install "coffee-script" node.js package.
|
||||
- npm:
|
||||
name: coffee-script
|
||||
path: /app/location
|
||||
|
||||
description: Install "coffee-script" node.js package on version 1.6.1.
|
||||
- npm:
|
||||
name: coffee-script
|
||||
version: '1.6.1'
|
||||
path: /app/location
|
||||
|
||||
description: Install "coffee-script" node.js package globally.
|
||||
- npm:
|
||||
name: coffee-script
|
||||
global: yes
|
||||
|
||||
description: Remove the globally package "coffee-script".
|
||||
- npm:
|
||||
name: coffee-script
|
||||
global: yes
|
||||
state: absent
|
||||
|
||||
description: Install "coffee-script" node.js package from custom registry.
|
||||
- npm:
|
||||
name: coffee-script
|
||||
registry: 'http://registry.mysite.com'
|
||||
|
||||
description: Install packages based on package.json.
|
||||
- npm:
|
||||
path: /app/location
|
||||
|
||||
description: Update packages based on package.json to their latest version.
|
||||
- npm:
|
||||
path: /app/location
|
||||
state: latest
|
||||
|
||||
description: Install packages based on package.json using the npm installed with nvm v0.10.1.
|
||||
- npm:
|
||||
path: /app/location
|
||||
executable: /opt/nvm/v0.10.1/bin/npm
|
||||
state: present
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
# Let snippet from module_utils/basic.py return a proper error in this case
|
||||
pass
|
||||
|
||||
|
||||
class Npm(object):
|
||||
def __init__(self, module, **kwargs):
|
||||
self.module = module
|
||||
self.glbl = kwargs['glbl']
|
||||
self.name = kwargs['name']
|
||||
self.version = kwargs['version']
|
||||
self.path = kwargs['path']
|
||||
self.registry = kwargs['registry']
|
||||
self.production = kwargs['production']
|
||||
self.ignore_scripts = kwargs['ignore_scripts']
|
||||
|
||||
if kwargs['executable']:
|
||||
self.executable = kwargs['executable'].split(' ')
|
||||
else:
|
||||
self.executable = [module.get_bin_path('npm', True)]
|
||||
|
||||
if kwargs['version']:
|
||||
self.name_version = self.name + '@' + str(self.version)
|
||||
else:
|
||||
self.name_version = self.name
|
||||
|
||||
def _exec(self, args, run_in_check_mode=False, check_rc=True):
|
||||
if not self.module.check_mode or (self.module.check_mode and run_in_check_mode):
|
||||
cmd = self.executable + args
|
||||
|
||||
if self.glbl:
|
||||
cmd.append('--global')
|
||||
if self.production:
|
||||
cmd.append('--production')
|
||||
if self.ignore_scripts:
|
||||
cmd.append('--ignore-scripts')
|
||||
if self.name:
|
||||
cmd.append(self.name_version)
|
||||
if self.registry:
|
||||
cmd.append('--registry')
|
||||
cmd.append(self.registry)
|
||||
|
||||
#If path is specified, cd into that path and run the command.
|
||||
cwd = None
|
||||
if self.path:
|
||||
if not os.path.exists(self.path):
|
||||
os.makedirs(self.path)
|
||||
if not os.path.isdir(self.path):
|
||||
self.module.fail_json(msg="path %s is not a directory" % self.path)
|
||||
cwd = self.path
|
||||
|
||||
rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)
|
||||
return out
|
||||
return ''
|
||||
|
||||
def list(self):
|
||||
cmd = ['list', '--json']
|
||||
|
||||
installed = list()
|
||||
missing = list()
|
||||
data = json.loads(self._exec(cmd, True, False))
|
||||
if 'dependencies' in data:
|
||||
for dep in data['dependencies']:
|
||||
if 'missing' in data['dependencies'][dep] and data['dependencies'][dep]['missing']:
|
||||
missing.append(dep)
|
||||
elif 'invalid' in data['dependencies'][dep] and data['dependencies'][dep]['invalid']:
|
||||
missing.append(dep)
|
||||
else:
|
||||
installed.append(dep)
|
||||
if self.name and self.name not in installed:
|
||||
missing.append(self.name)
|
||||
#Named dependency not installed
|
||||
else:
|
||||
missing.append(self.name)
|
||||
|
||||
return installed, missing
|
||||
|
||||
def install(self):
|
||||
return self._exec(['install'])
|
||||
|
||||
def update(self):
|
||||
return self._exec(['update'])
|
||||
|
||||
def uninstall(self):
|
||||
return self._exec(['uninstall'])
|
||||
|
||||
def list_outdated(self):
|
||||
outdated = list()
|
||||
data = self._exec(['outdated'], True, False)
|
||||
for dep in data.splitlines():
|
||||
if dep:
|
||||
# node.js v0.10.22 changed the `npm outdated` module separator
|
||||
# from "@" to " ". Split on both for backwards compatibility.
|
||||
pkg, other = re.split('\s|@', dep, 1)
|
||||
outdated.append(pkg)
|
||||
|
||||
return outdated
|
||||
|
||||
|
||||
def main():
|
||||
arg_spec = dict(
|
||||
name=dict(default=None),
|
||||
path=dict(default=None, type='path'),
|
||||
version=dict(default=None),
|
||||
production=dict(default='no', type='bool'),
|
||||
executable=dict(default=None, type='path'),
|
||||
registry=dict(default=None),
|
||||
state=dict(default='present', choices=['present', 'absent', 'latest']),
|
||||
ignore_scripts=dict(default=False, type='bool'),
|
||||
)
|
||||
arg_spec['global'] = dict(default='no', type='bool')
|
||||
module = AnsibleModule(
|
||||
argument_spec=arg_spec,
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
path = module.params['path']
|
||||
version = module.params['version']
|
||||
glbl = module.params['global']
|
||||
production = module.params['production']
|
||||
executable = module.params['executable']
|
||||
registry = module.params['registry']
|
||||
state = module.params['state']
|
||||
ignore_scripts = module.params['ignore_scripts']
|
||||
|
||||
if not path and not glbl:
|
||||
module.fail_json(msg='path must be specified when not using global')
|
||||
if state == 'absent' and not name:
|
||||
module.fail_json(msg='uninstalling a package is only available for named packages')
|
||||
|
||||
npm = Npm(module, name=name, path=path, version=version, glbl=glbl, production=production, \
|
||||
executable=executable, registry=registry, ignore_scripts=ignore_scripts)
|
||||
|
||||
changed = False
|
||||
if state == 'present':
|
||||
installed, missing = npm.list()
|
||||
if len(missing):
|
||||
changed = True
|
||||
npm.install()
|
||||
elif state == 'latest':
|
||||
installed, missing = npm.list()
|
||||
outdated = npm.list_outdated()
|
||||
if len(missing):
|
||||
changed = True
|
||||
npm.install()
|
||||
if len(outdated):
|
||||
changed = True
|
||||
npm.update()
|
||||
else: #absent
|
||||
installed, missing = npm.list()
|
||||
if name in installed:
|
||||
changed = True
|
||||
npm.uninstall()
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
# import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
240
lib/ansible/modules/packaging/language/pear.py
Normal file
240
lib/ansible/modules/packaging/language/pear.py
Normal file
|
@ -0,0 +1,240 @@
|
|||
#!/usr/bin/python -tt
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2012, Afterburn <http://github.com/afterburn>
|
||||
# (c) 2013, Aaron Bull Schaefer <aaron@elasticdog.com>
|
||||
# (c) 2015, Jonathan Lestrelin <jonathan.lestrelin@gmail.com>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'version': '1.0'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: pear
|
||||
short_description: Manage pear/pecl packages
|
||||
description:
|
||||
- Manage PHP packages with the pear package manager.
|
||||
version_added: 2.0
|
||||
author:
|
||||
- "'jonathan.lestrelin' <jonathan.lestrelin@gmail.com>"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of the package to install, upgrade, or remove.
|
||||
required: true
|
||||
|
||||
state:
|
||||
description:
|
||||
- Desired state of the package.
|
||||
required: false
|
||||
default: "present"
|
||||
choices: ["present", "absent", "latest"]
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Install pear package
|
||||
- pear:
|
||||
name: Net_URL2
|
||||
state: present
|
||||
|
||||
# Install pecl package
|
||||
- pear:
|
||||
name: pecl/json_post
|
||||
state: present
|
||||
|
||||
# Upgrade package
|
||||
- pear:
|
||||
name: Net_URL2
|
||||
state: latest
|
||||
|
||||
# Remove packages
|
||||
- pear:
|
||||
name: Net_URL2,pecl/json_post
|
||||
state: absent
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
def get_local_version(pear_output):
|
||||
"""Take pear remoteinfo output and get the installed version"""
|
||||
lines = pear_output.split('\n')
|
||||
for line in lines:
|
||||
if 'Installed ' in line:
|
||||
installed = line.rsplit(None, 1)[-1].strip()
|
||||
if installed == '-': continue
|
||||
return installed
|
||||
return None
|
||||
|
||||
def get_repository_version(pear_output):
|
||||
"""Take pear remote-info output and get the latest version"""
|
||||
lines = pear_output.split('\n')
|
||||
for line in lines:
|
||||
if 'Latest ' in line:
|
||||
return line.rsplit(None, 1)[-1].strip()
|
||||
return None
|
||||
|
||||
def query_package(module, name, state="present"):
|
||||
"""Query the package status in both the local system and the repository.
|
||||
Returns a boolean to indicate if the package is installed,
|
||||
and a second boolean to indicate if the package is up-to-date."""
|
||||
if state == "present":
|
||||
lcmd = "pear info %s" % (name)
|
||||
lrc, lstdout, lstderr = module.run_command(lcmd, check_rc=False)
|
||||
if lrc != 0:
|
||||
# package is not installed locally
|
||||
return False, False
|
||||
|
||||
rcmd = "pear remote-info %s" % (name)
|
||||
rrc, rstdout, rstderr = module.run_command(rcmd, check_rc=False)
|
||||
|
||||
# get the version installed locally (if any)
|
||||
lversion = get_local_version(rstdout)
|
||||
|
||||
# get the version in the repository
|
||||
rversion = get_repository_version(rstdout)
|
||||
|
||||
if rrc == 0:
|
||||
# Return True to indicate that the package is installed locally,
|
||||
# and the result of the version number comparison
|
||||
# to determine if the package is up-to-date.
|
||||
return True, (lversion == rversion)
|
||||
|
||||
return False, False
|
||||
|
||||
|
||||
def remove_packages(module, packages):
|
||||
remove_c = 0
|
||||
# Using a for loop incase of error, we can report the package that failed
|
||||
for package in packages:
|
||||
# Query the package first, to see if we even need to remove
|
||||
installed, updated = query_package(module, package)
|
||||
if not installed:
|
||||
continue
|
||||
|
||||
cmd = "pear uninstall %s" % (package)
|
||||
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
|
||||
|
||||
if rc != 0:
|
||||
module.fail_json(msg="failed to remove %s" % (package))
|
||||
|
||||
remove_c += 1
|
||||
|
||||
if remove_c > 0:
|
||||
|
||||
module.exit_json(changed=True, msg="removed %s package(s)" % remove_c)
|
||||
|
||||
module.exit_json(changed=False, msg="package(s) already absent")
|
||||
|
||||
|
||||
def install_packages(module, state, packages):
|
||||
install_c = 0
|
||||
|
||||
for i, package in enumerate(packages):
|
||||
# if the package is installed and state == present
|
||||
# or state == latest and is up-to-date then skip
|
||||
installed, updated = query_package(module, package)
|
||||
if installed and (state == 'present' or (state == 'latest' and updated)):
|
||||
continue
|
||||
|
||||
if state == 'present':
|
||||
command = 'install'
|
||||
|
||||
if state == 'latest':
|
||||
command = 'upgrade'
|
||||
|
||||
cmd = "pear %s %s" % (command, package)
|
||||
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
|
||||
|
||||
if rc != 0:
|
||||
module.fail_json(msg="failed to install %s" % (package))
|
||||
|
||||
install_c += 1
|
||||
|
||||
if install_c > 0:
|
||||
module.exit_json(changed=True, msg="installed %s package(s)" % (install_c))
|
||||
|
||||
module.exit_json(changed=False, msg="package(s) already installed")
|
||||
|
||||
|
||||
def check_packages(module, packages, state):
|
||||
would_be_changed = []
|
||||
for package in packages:
|
||||
installed, updated = query_package(module, package)
|
||||
if ((state in ["present", "latest"] and not installed) or
|
||||
(state == "absent" and installed) or
|
||||
(state == "latest" and not updated)):
|
||||
would_be_changed.append(package)
|
||||
if would_be_changed:
|
||||
if state == "absent":
|
||||
state = "removed"
|
||||
module.exit_json(changed=True, msg="%s package(s) would be %s" % (
|
||||
len(would_be_changed), state))
|
||||
else:
|
||||
module.exit_json(change=False, msg="package(s) already %s" % state)
|
||||
|
||||
|
||||
def exe_exists(program):
|
||||
for path in os.environ["PATH"].split(os.pathsep):
|
||||
path = path.strip('"')
|
||||
exe_file = os.path.join(path, program)
|
||||
if os.path.isfile(exe_file) and os.access(exe_file, os.X_OK):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
name = dict(aliases=['pkg']),
|
||||
state = dict(default='present', choices=['present', 'installed', "latest", 'absent', 'removed'])),
|
||||
required_one_of = [['name']],
|
||||
supports_check_mode = True)
|
||||
|
||||
if not exe_exists("pear"):
|
||||
module.fail_json(msg="cannot find pear executable in PATH")
|
||||
|
||||
p = module.params
|
||||
|
||||
# normalize the state parameter
|
||||
if p['state'] in ['present', 'installed']:
|
||||
p['state'] = 'present'
|
||||
elif p['state'] in ['absent', 'removed']:
|
||||
p['state'] = 'absent'
|
||||
|
||||
if p['name']:
|
||||
pkgs = p['name'].split(',')
|
||||
|
||||
pkg_files = []
|
||||
for i, pkg in enumerate(pkgs):
|
||||
pkg_files.append(None)
|
||||
|
||||
if module.check_mode:
|
||||
check_packages(module, pkgs, p['state'])
|
||||
|
||||
if p['state'] in ['present', 'latest']:
|
||||
install_packages(module, p['state'], pkgs)
|
||||
elif p['state'] == 'absent':
|
||||
remove_packages(module, pkgs)
|
||||
|
||||
# import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue