From 9a1918c62875fde93267213631fc8852a704f31e Mon Sep 17 00:00:00 2001
From: Tim Hoiberg <tim.hoiberg@gmail.com>
Date: Wed, 13 May 2015 19:40:50 +1000
Subject: [PATCH] Adding module to manage Ruby Gem dependencies via Bundler

---
 packaging/language/bundler.py | 199 ++++++++++++++++++++++++++++++++++
 1 file changed, 199 insertions(+)
 create mode 100644 packaging/language/bundler.py

diff --git a/packaging/language/bundler.py b/packaging/language/bundler.py
new file mode 100644
index 00000000000..877d09dbea5
--- /dev/null
+++ b/packaging/language/bundler.py
@@ -0,0 +1,199 @@
+#!/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/>.
+#
+
+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
+'''
+
+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=yes
+
+# Installs gems using a Gemfile in another directory
+- bunlder: 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),
+				exclude_groups=dict(default=None, required=False, type='list'),
+				clean=dict(default=False, required=False, type='bool'),
+				gemfile=dict(default=None, required=False),
+				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),
+				binstub_directory=dict(default=None, required=False),
+				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_install_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 *
+main()
\ No newline at end of file