beaker 2.7.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/HISTORY.md +121 -2
- data/lib/beaker/dsl.rb +2 -2
- data/lib/beaker/dsl/helpers.rb +13 -1429
- data/lib/beaker/dsl/helpers/facter_helpers.rb +48 -0
- data/lib/beaker/dsl/helpers/hiera_helpers.rb +71 -0
- data/lib/beaker/dsl/helpers/host_helpers.rb +506 -0
- data/lib/beaker/dsl/helpers/puppet_helpers.rb +698 -0
- data/lib/beaker/dsl/helpers/tk_helpers.rb +101 -0
- data/lib/beaker/dsl/helpers/web_helpers.rb +115 -0
- data/lib/beaker/dsl/install_utils.rb +8 -1570
- data/lib/beaker/dsl/install_utils/ezbake_utils.rb +256 -0
- data/lib/beaker/dsl/install_utils/module_utils.rb +237 -0
- data/lib/beaker/dsl/install_utils/pe_utils.rb +518 -0
- data/lib/beaker/dsl/install_utils/puppet_utils.rb +722 -0
- data/lib/beaker/dsl/outcomes.rb +0 -4
- data/lib/beaker/dsl/roles.rb +0 -3
- data/lib/beaker/dsl/structure.rb +127 -4
- data/lib/beaker/dsl/wrappers.rb +0 -4
- data/lib/beaker/host.rb +23 -0
- data/lib/beaker/host/unix/pkg.rb +4 -4
- data/lib/beaker/host_prebuilt_steps.rb +11 -5
- data/lib/beaker/hypervisor/vagrant.rb +1 -0
- data/lib/beaker/hypervisor/vmpooler.rb +38 -0
- data/lib/beaker/logger.rb +10 -4
- data/lib/beaker/network_manager.rb +5 -4
- data/lib/beaker/options/command_line_parser.rb +7 -0
- data/lib/beaker/shared.rb +2 -1
- data/lib/beaker/shared/semvar.rb +41 -0
- data/lib/beaker/test_suite.rb +20 -6
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/helpers/facter_helpers_spec.rb +59 -0
- data/spec/beaker/dsl/helpers/hiera_helpers_spec.rb +96 -0
- data/spec/beaker/dsl/helpers/host_helpers_spec.rb +413 -0
- data/spec/beaker/dsl/{helpers_spec.rb → helpers/puppet_helpers_spec.rb} +2 -611
- data/spec/beaker/dsl/helpers/tk_helpers_spec.rb +83 -0
- data/spec/beaker/dsl/helpers/web_helpers_spec.rb +60 -0
- data/spec/beaker/dsl/install_utils/module_utils_spec.rb +241 -0
- data/spec/beaker/dsl/install_utils/pe_utils_spec.rb +475 -0
- data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +523 -0
- data/spec/beaker/dsl/structure_spec.rb +108 -0
- data/spec/beaker/host_prebuilt_steps_spec.rb +44 -0
- data/spec/beaker/host_spec.rb +41 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +2 -1
- data/spec/beaker/logger_spec.rb +9 -2
- data/spec/beaker/network_manager_spec.rb +7 -1
- data/spec/beaker/options/command_line_parser_spec.rb +3 -2
- data/spec/beaker/shared/semvar_spec.rb +36 -0
- data/spec/beaker/test_suite_spec.rb +48 -0
- data/spec/mocks.rb +10 -0
- metadata +23 -5
- data/lib/beaker/dsl/ezbake_utils.rb +0 -259
- data/spec/beaker/dsl/install_utils_spec.rb +0 -1242
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
module DSL
|
5
|
+
module InstallUtils
|
6
|
+
# This module contains methods to assist in installing projects from source
|
7
|
+
# that use ezbake for packaging.
|
8
|
+
#
|
9
|
+
module EZBakeUtils
|
10
|
+
|
11
|
+
# @!group Public DSL Methods
|
12
|
+
|
13
|
+
# Installs leiningen project with given name and version on remote host.
|
14
|
+
#
|
15
|
+
# @param [Host] host A single remote host on which to install the
|
16
|
+
# specified leiningen project.
|
17
|
+
def install_from_ezbake host
|
18
|
+
ezbake_validate_support host
|
19
|
+
ezbake_tools_available?
|
20
|
+
install_ezbake_tarball_on_host host
|
21
|
+
ezbake_installsh host, "service"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Installs termini with given name and version on remote host.
|
25
|
+
#
|
26
|
+
# @param [Host] host A single remote host on which to install the
|
27
|
+
# specified leiningen project.
|
28
|
+
def install_termini_from_ezbake host
|
29
|
+
ezbake_validate_support host
|
30
|
+
ezbake_tools_available?
|
31
|
+
install_ezbake_tarball_on_host host
|
32
|
+
ezbake_installsh host, "termini"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Install a development version of ezbake into the local m2 repository
|
36
|
+
#
|
37
|
+
# This can be useful if you want to work on a development branch of
|
38
|
+
# ezbake that hasn't been released yet. Ensure your project dependencies
|
39
|
+
# in your development branch include a reference to the -SNAPSHOT
|
40
|
+
# version of the project for it to successfully pickup a pre-shipped
|
41
|
+
# version of ezbake.
|
42
|
+
#
|
43
|
+
# @param url [String] git url
|
44
|
+
# @param branch [String] git branch
|
45
|
+
def ezbake_dev_build url = "git@github.com:puppetlabs/ezbake.git",
|
46
|
+
branch = "master"
|
47
|
+
ezbake_dir = 'tmp/ezbake'
|
48
|
+
conditionally_clone url, ezbake_dir, branch
|
49
|
+
lp = ezbake_lein_prefix
|
50
|
+
|
51
|
+
Dir.chdir(ezbake_dir) do
|
52
|
+
ezbake_local_cmd "#{lp} install",
|
53
|
+
:throw_on_failure => true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @!endgroup
|
58
|
+
|
59
|
+
class << self
|
60
|
+
attr_accessor :config
|
61
|
+
end
|
62
|
+
|
63
|
+
# @!group Private helpers
|
64
|
+
|
65
|
+
# Test for support in one place
|
66
|
+
#
|
67
|
+
# @param [Host] host host to check for support
|
68
|
+
# @raise [RuntimeError] if OS is not supported
|
69
|
+
# @api private
|
70
|
+
def ezbake_validate_support host
|
71
|
+
variant, version, _, _ = host['platform'].to_array
|
72
|
+
unless variant =~ /^(fedora|el|centos|debian|ubuntu)$/
|
73
|
+
raise RuntimeError,
|
74
|
+
"No support for #{variant} within ezbake_utils ..."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Build, copy & unpack tarball on remote host
|
79
|
+
#
|
80
|
+
# @param [Host] host installation destination
|
81
|
+
# @api private
|
82
|
+
def install_ezbake_tarball_on_host host
|
83
|
+
if not ezbake_config
|
84
|
+
ezbake_stage
|
85
|
+
end
|
86
|
+
|
87
|
+
# Skip installation if the remote directory exists
|
88
|
+
result = on host, "test -d #{ezbake_install_dir}", :acceptable_exit_codes => [0, 1]
|
89
|
+
return if result.exit_code == 0
|
90
|
+
|
91
|
+
ezbake_staging_dir = File.join('target', 'staging')
|
92
|
+
Dir.chdir(ezbake_staging_dir) do
|
93
|
+
ezbake_local_cmd 'rake package:tar'
|
94
|
+
end
|
95
|
+
|
96
|
+
local_tarball = ezbake_staging_dir + "/pkg/" + ezbake_install_name + ".tar.gz"
|
97
|
+
remote_tarball = ezbake_install_dir + ".tar.gz"
|
98
|
+
scp_to host, local_tarball, remote_tarball
|
99
|
+
|
100
|
+
# untar tarball on host
|
101
|
+
on host, "tar -xzf " + remote_tarball
|
102
|
+
|
103
|
+
# Check to ensure directory exists
|
104
|
+
on host, "test -d #{ezbake_install_dir}"
|
105
|
+
end
|
106
|
+
|
107
|
+
LOCAL_COMMANDS_REQUIRED = [
|
108
|
+
['leiningen', 'lein --version', nil],
|
109
|
+
['lein-pprint', 'lein with-profile ci pprint :version',
|
110
|
+
'Must have lein-pprint installed under the :ci profile.'],
|
111
|
+
['java', 'java -version', nil],
|
112
|
+
['git', 'git --version', nil],
|
113
|
+
['rake', 'rake --version', nil],
|
114
|
+
]
|
115
|
+
|
116
|
+
# Checks given host for the tools necessary to perform
|
117
|
+
# install_from_ezbake.
|
118
|
+
#
|
119
|
+
# @raise [RuntimeError] if tool is not found
|
120
|
+
# @api private
|
121
|
+
def ezbake_tools_available?
|
122
|
+
LOCAL_COMMANDS_REQUIRED.each do |software_name, command, additional_error_message|
|
123
|
+
if not system command
|
124
|
+
error_message = "Must have #{software_name} installed on development system.\n"
|
125
|
+
if additional_error_message
|
126
|
+
error_message += additional_error_message
|
127
|
+
end
|
128
|
+
raise RuntimeError, error_message
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Return the ezbake config.
|
134
|
+
#
|
135
|
+
# @return [Hash] configuration for ezbake, usually from ezbake.rb
|
136
|
+
# @api private
|
137
|
+
def ezbake_config
|
138
|
+
EZBakeUtils.config
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns a leiningen prefix with local m2 repo capability
|
142
|
+
#
|
143
|
+
# @return [String] lein prefix command that uses a local build
|
144
|
+
# m2 repository.
|
145
|
+
# @api private
|
146
|
+
def ezbake_lein_prefix
|
147
|
+
# Get the absolute path to the local repo
|
148
|
+
m2_repo = File.join(Dir.pwd, 'tmp', 'm2-local')
|
149
|
+
|
150
|
+
'lein update-in : assoc :local-repo "\"' + m2_repo + '\"" --'
|
151
|
+
end
|
152
|
+
|
153
|
+
# Prepares a staging directory for the specified project.
|
154
|
+
#
|
155
|
+
# @api private
|
156
|
+
def ezbake_stage
|
157
|
+
# Install the PuppetDB jar into the local repository
|
158
|
+
ezbake_local_cmd "#{ezbake_lein_prefix} install",
|
159
|
+
:throw_on_failure => true
|
160
|
+
|
161
|
+
# Run ezbake stage
|
162
|
+
ezbake_local_cmd "#{ezbake_lein_prefix} with-profile ezbake ezbake stage",
|
163
|
+
:throw_on_failure => true
|
164
|
+
|
165
|
+
# Boostrap packaging, and grab configuration info from project
|
166
|
+
staging_dir = File.join('target','staging')
|
167
|
+
Dir.chdir(staging_dir) do
|
168
|
+
ezbake_local_cmd 'rake package:bootstrap'
|
169
|
+
|
170
|
+
load 'ezbake.rb'
|
171
|
+
ezbake = EZBake::Config
|
172
|
+
ezbake[:package_version] = `echo -n $(rake pl:print_build_param[ref] | tail -n 1)`
|
173
|
+
EZBakeUtils.config = ezbake
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Executes a local command using system, logging the prepared command
|
178
|
+
#
|
179
|
+
# @param [String] cmd command to execute
|
180
|
+
# @param [Hash] opts options
|
181
|
+
# @option opts [bool] :throw_on_failure If true, throws an
|
182
|
+
# exception if the exit code is non-zero. Defaults to false.
|
183
|
+
# @return [bool] true if exit == 0 false if otherwise
|
184
|
+
# @raise [RuntimeError] if :throw_on_failure is true and
|
185
|
+
# command fails
|
186
|
+
# @api private
|
187
|
+
def ezbake_local_cmd cmd, opts={}
|
188
|
+
opts = {
|
189
|
+
:throw_on_failure => false,
|
190
|
+
}.merge(opts)
|
191
|
+
|
192
|
+
logger.notify "localhost $ #{cmd}"
|
193
|
+
result = system cmd
|
194
|
+
if opts[:throw_on_failure] && result == false
|
195
|
+
raise RuntimeError, "Command failure #{cmd}"
|
196
|
+
end
|
197
|
+
result
|
198
|
+
end
|
199
|
+
|
200
|
+
# Retrieve the tarball installation name. This is the name of
|
201
|
+
# the tarball without the .tar.gz extension, and the name of the
|
202
|
+
# path where it will unpack to.
|
203
|
+
#
|
204
|
+
# @return [String] name of the tarball and directory
|
205
|
+
# @api private
|
206
|
+
def ezbake_install_name
|
207
|
+
ezbake = ezbake_config
|
208
|
+
project_package_version = ezbake[:package_version]
|
209
|
+
project_name = ezbake[:project]
|
210
|
+
"%s-%s" % [ project_name, project_package_version ]
|
211
|
+
end
|
212
|
+
|
213
|
+
# Returns the full path to the installed software on the remote host.
|
214
|
+
#
|
215
|
+
# This only returns the path, it doesn't work out if its installed or
|
216
|
+
# not.
|
217
|
+
#
|
218
|
+
# @return [String] path to the installation dir
|
219
|
+
# @api private
|
220
|
+
def ezbake_install_dir
|
221
|
+
"/root/#{ezbake_install_name}"
|
222
|
+
end
|
223
|
+
|
224
|
+
# A helper that wraps the execution of install.sh in the proper
|
225
|
+
# ezbake installation directory.
|
226
|
+
#
|
227
|
+
# @param [Host] host Host to run install.sh on
|
228
|
+
# @param [String] task Task to execute with install.sh
|
229
|
+
# @api private
|
230
|
+
def ezbake_installsh host, task=""
|
231
|
+
on host, "cd #{ezbake_install_dir}; bash install.sh #{task}"
|
232
|
+
end
|
233
|
+
|
234
|
+
# Only clone from given git URI if there is no existing git clone at the
|
235
|
+
# given local_path location.
|
236
|
+
#
|
237
|
+
# @param [String] upstream_uri git URI
|
238
|
+
# @param [String] local_path path to conditionally install to
|
239
|
+
# @param [String] branch to checkout
|
240
|
+
# @api private
|
241
|
+
def conditionally_clone upstream_uri, local_path, branch="origin/HEAD"
|
242
|
+
if ezbake_local_cmd "git --work-tree=#{local_path} --git-dir=#{local_path}/.git status"
|
243
|
+
ezbake_local_cmd "git --work-tree=#{local_path} --git-dir=#{local_path}/.git fetch origin"
|
244
|
+
ezbake_local_cmd "git --work-tree=#{local_path} --git-dir=#{local_path}/.git checkout #{branch}"
|
245
|
+
else
|
246
|
+
parent_dir = File.dirname(local_path)
|
247
|
+
FileUtils.mkdir_p(parent_dir)
|
248
|
+
ezbake_local_cmd "git clone #{upstream_uri} #{local_path}"
|
249
|
+
ezbake_local_cmd "git --work-tree=#{local_path} --git-dir=#{local_path}/.git checkout #{branch}"
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
module Beaker
|
2
|
+
module DSL
|
3
|
+
module InstallUtils
|
4
|
+
#
|
5
|
+
# This module contains methods to help install puppet modules
|
6
|
+
#
|
7
|
+
# To mix this is into a class you need the following:
|
8
|
+
# * a method *hosts* that yields any hosts implementing
|
9
|
+
# {Beaker::Host}'s interface to act upon.
|
10
|
+
# * a method *options* that provides an options hash, see {Beaker::Options::OptionsHash}
|
11
|
+
# * the module {Beaker::DSL::Roles} that provides access to the various hosts implementing
|
12
|
+
# {Beaker::Host}'s interface to act upon
|
13
|
+
# * the module {Beaker::DSL::Wrappers} the provides convenience methods for {Beaker::DSL::Command} creation
|
14
|
+
module ModuleUtils
|
15
|
+
|
16
|
+
# The directories in the module directory that will not be scp-ed to the test system when using
|
17
|
+
# `copy_module_to`
|
18
|
+
PUPPET_MODULE_INSTALL_IGNORE = ['.bundle', '.git', '.idea', '.vagrant', '.vendor', 'vendor', 'acceptance',
|
19
|
+
'bundle', 'spec', 'tests', 'log']
|
20
|
+
|
21
|
+
# Install the desired module on all hosts using either the PMT or a
|
22
|
+
# staging forge
|
23
|
+
#
|
24
|
+
# @see install_dev_puppet_module
|
25
|
+
def install_dev_puppet_module_on( host, opts )
|
26
|
+
if options[:forge_host]
|
27
|
+
with_forge_stubbed_on( host ) do
|
28
|
+
install_puppet_module_via_pmt_on( host, opts )
|
29
|
+
end
|
30
|
+
else
|
31
|
+
copy_module_to( host, opts )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
alias :puppet_module_install_on :install_dev_puppet_module_on
|
35
|
+
|
36
|
+
# Install the desired module on all hosts using either the PMT or a
|
37
|
+
# staging forge
|
38
|
+
#
|
39
|
+
# Passes options through to either `install_puppet_module_via_pmt_on`
|
40
|
+
# or `copy_module_to`
|
41
|
+
#
|
42
|
+
# @param opts [Hash]
|
43
|
+
#
|
44
|
+
# @example Installing a module from the local directory
|
45
|
+
# install_dev_puppet_module( :source => './', :module_name => 'concat' )
|
46
|
+
#
|
47
|
+
# @example Installing a module from a staging forge
|
48
|
+
# options[:forge_host] = 'my-forge-api.example.com'
|
49
|
+
# install_dev_puppet_module( :source => './', :module_name => 'concat' )
|
50
|
+
#
|
51
|
+
# @see install_puppet_module_via_pmt
|
52
|
+
# @see copy_module_to
|
53
|
+
def install_dev_puppet_module( opts )
|
54
|
+
block_on( hosts ) {|h| install_dev_puppet_module_on( h, opts ) }
|
55
|
+
end
|
56
|
+
alias :puppet_module_install :install_dev_puppet_module
|
57
|
+
|
58
|
+
# Install the desired module with the PMT on a given host
|
59
|
+
#
|
60
|
+
# @param opts [Hash]
|
61
|
+
# @option opts [String] :module_name The short name of the module to be installed
|
62
|
+
# @option opts [String] :version The version of the module to be installed
|
63
|
+
def install_puppet_module_via_pmt_on( host, opts = {} )
|
64
|
+
block_on host do |h|
|
65
|
+
version_info = opts[:version] ? "-v #{opts[:version]}" : ""
|
66
|
+
if opts[:source]
|
67
|
+
author_name, module_name = parse_for_modulename( opts[:source] )
|
68
|
+
modname = "#{author_name}-#{module_name}"
|
69
|
+
else
|
70
|
+
modname = opts[:module_name]
|
71
|
+
end
|
72
|
+
|
73
|
+
puppet_opts = {}
|
74
|
+
if host[:default_module_install_opts].respond_to? :merge
|
75
|
+
puppet_opts = host[:default_module_install_opts].merge( puppet_opts )
|
76
|
+
end
|
77
|
+
|
78
|
+
on h, puppet("module install #{modname} #{version_info}", puppet_opts)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Install the desired module with the PMT on all known hosts
|
83
|
+
# @see #install_puppet_module_via_pmt_on
|
84
|
+
def install_puppet_module_via_pmt( opts = {} )
|
85
|
+
install_puppet_module_via_pmt_on(hosts, opts)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Install local module for acceptance testing
|
89
|
+
# should be used as a presuite to ensure local module is copied to the hosts you want, particularly masters
|
90
|
+
# @param [Host, Array<Host>, String, Symbol] one_or_more_hosts
|
91
|
+
# One or more hosts to act upon,
|
92
|
+
# or a role (String or Symbol) that identifies one or more hosts.
|
93
|
+
# @option opts [String] :source ('./')
|
94
|
+
# The current directory where the module sits, otherwise will try
|
95
|
+
# and walk the tree to figure out
|
96
|
+
# @option opts [String] :module_name (nil)
|
97
|
+
# Name which the module should be installed under, please do not include author,
|
98
|
+
# if none is provided it will attempt to parse the metadata.json and then the Module file to determine
|
99
|
+
# the name of the module
|
100
|
+
# @option opts [String] :target_module_path (host['distmoduledir']/modules)
|
101
|
+
# Location where the module should be installed, will default
|
102
|
+
# to host['distmoduledir']/modules
|
103
|
+
# @option opts [Array] :ignore_list
|
104
|
+
# @option opts [String] :protocol
|
105
|
+
# Name of the underlying transfer method. Valid options are 'scp' or 'rsync'.
|
106
|
+
# @raise [ArgumentError] if not host is provided or module_name is not provided and can not be found in Modulefile
|
107
|
+
#
|
108
|
+
def copy_module_to(one_or_more_hosts, opts = {})
|
109
|
+
block_on one_or_more_hosts do |host|
|
110
|
+
opts = {:source => './',
|
111
|
+
:target_module_path => host['distmoduledir'],
|
112
|
+
:ignore_list => PUPPET_MODULE_INSTALL_IGNORE}.merge(opts)
|
113
|
+
ignore_list = build_ignore_list(opts)
|
114
|
+
target_module_dir = on( host, "echo #{opts[:target_module_path]}" ).stdout.chomp
|
115
|
+
source_path = File.expand_path( opts[:source] )
|
116
|
+
source_dir = File.dirname(source_path)
|
117
|
+
source_name = File.basename(source_path)
|
118
|
+
if opts.has_key?(:module_name)
|
119
|
+
module_name = opts[:module_name]
|
120
|
+
else
|
121
|
+
_, module_name = parse_for_modulename( source_path )
|
122
|
+
end
|
123
|
+
|
124
|
+
opts[:protocol] ||= 'scp'
|
125
|
+
case opts[:protocol]
|
126
|
+
when 'scp'
|
127
|
+
#move to the host
|
128
|
+
scp_to host, source_path, target_module_dir, {:ignore => ignore_list}
|
129
|
+
#rename to the selected module name, if not correct
|
130
|
+
cur_path = File.join(target_module_dir, source_name)
|
131
|
+
cur_path = File.join(target_module_dir, source_name)
|
132
|
+
new_path = File.join(target_module_dir, module_name)
|
133
|
+
if cur_path != new_path
|
134
|
+
# NOTE: this will need to be updated to handle powershell only windows SUTs
|
135
|
+
on host, "mv #{cur_path} #{new_path}"
|
136
|
+
end
|
137
|
+
when 'rsync'
|
138
|
+
rsync_to host, source, File.join(target_module_dir, module_name), {:ignore => ignore_list}
|
139
|
+
else
|
140
|
+
logger.debug "Unsupported transfer protocol, returning nil"
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
alias :copy_root_module_to :copy_module_to
|
146
|
+
|
147
|
+
#Recursive method for finding the module root
|
148
|
+
# Assumes that a Modulefile exists
|
149
|
+
# @param [String] possible_module_directory
|
150
|
+
# will look for Modulefile and if none found go up one level and try again until root is reached
|
151
|
+
#
|
152
|
+
# @return [String,nil]
|
153
|
+
def parse_for_moduleroot(possible_module_directory)
|
154
|
+
if File.exists?("#{possible_module_directory}/Modulefile") || File.exists?("#{possible_module_directory}/metadata.json")
|
155
|
+
possible_module_directory
|
156
|
+
elsif possible_module_directory === '/'
|
157
|
+
logger.error "At root, can't parse for another directory"
|
158
|
+
nil
|
159
|
+
else
|
160
|
+
logger.debug "No Modulefile or metadata.json found at #{possible_module_directory}, moving up"
|
161
|
+
parse_for_moduleroot File.expand_path(File.join(possible_module_directory,'..'))
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#Parse root directory of a module for module name
|
166
|
+
# Searches for metadata.json and then if none found, Modulefile and parses for the Name attribute
|
167
|
+
# @param [String] root_module_dir
|
168
|
+
# @return [String] module name
|
169
|
+
def parse_for_modulename(root_module_dir)
|
170
|
+
author_name, module_name = nil, nil
|
171
|
+
if File.exists?("#{root_module_dir}/metadata.json")
|
172
|
+
logger.debug "Attempting to parse Modulename from metadata.json"
|
173
|
+
module_json = JSON.parse(File.read "#{root_module_dir}/metadata.json")
|
174
|
+
if(module_json.has_key?('name'))
|
175
|
+
author_name, module_name = get_module_name(module_json['name'])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
if !module_name && File.exists?("#{root_module_dir}/Modulefile")
|
179
|
+
logger.debug "Attempting to parse Modulename from Modulefile"
|
180
|
+
if /^name\s+'?(\w+-\w+)'?\s*$/i.match(File.read("#{root_module_dir}/Modulefile"))
|
181
|
+
author_name, module_name = get_module_name(Regexp.last_match[1])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
if !module_name && !author_name
|
185
|
+
logger.debug "Unable to determine name, returning null"
|
186
|
+
end
|
187
|
+
return author_name, module_name
|
188
|
+
end
|
189
|
+
|
190
|
+
#Parse modulename from the pattern 'Auther-ModuleName'
|
191
|
+
#
|
192
|
+
# @param [String] author_module_name <Author>-<ModuleName> pattern
|
193
|
+
#
|
194
|
+
# @return [String,nil]
|
195
|
+
#
|
196
|
+
def get_module_name(author_module_name)
|
197
|
+
split_name = split_author_modulename(author_module_name)
|
198
|
+
if split_name
|
199
|
+
return split_name[:author], split_name[:module]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
#Split the Author-Name into a hash
|
204
|
+
# @param [String] author_module_attr
|
205
|
+
#
|
206
|
+
# @return [Hash<Symbol,String>,nil] :author and :module symbols will be returned
|
207
|
+
#
|
208
|
+
def split_author_modulename(author_module_attr)
|
209
|
+
result = /(\w+)-(\w+)/.match(author_module_attr)
|
210
|
+
if result
|
211
|
+
{:author => result[1], :module => result[2]}
|
212
|
+
else
|
213
|
+
nil
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Build an array list of files/directories to ignore when pushing to remote host
|
218
|
+
# Automatically adds '..' and '.' to array. If not opts of :ignore list is provided
|
219
|
+
# it will use the static variable PUPPET_MODULE_INSTALL_IGNORE
|
220
|
+
#
|
221
|
+
# @param opts [Hash]
|
222
|
+
# @option opts [Array] :ignore_list A list of files/directories to ignore
|
223
|
+
def build_ignore_list(opts = {})
|
224
|
+
ignore_list = opts[:ignore_list] || PUPPET_MODULE_INSTALL_IGNORE
|
225
|
+
if !ignore_list.kind_of?(Array) || ignore_list.nil?
|
226
|
+
raise ArgumentError "Ignore list must be an Array"
|
227
|
+
end
|
228
|
+
ignore_list << '.' unless ignore_list.include? '.'
|
229
|
+
ignore_list << '..' unless ignore_list.include? '..'
|
230
|
+
ignore_list
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
end
|