r10k 0.0.9 → 1.0.0rc1
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.
- data/bin/r10k +1 -1
- data/lib/r10k.rb +0 -4
- data/lib/r10k/cli.rb +9 -5
- data/lib/r10k/cli/deploy.rb +108 -0
- data/lib/r10k/cli/environment.rb +5 -1
- data/lib/r10k/cli/environment/deploy.rb +6 -28
- data/lib/r10k/cli/environment/list.rb +6 -10
- data/lib/r10k/cli/environment/stale.rb +6 -16
- data/lib/r10k/cli/module.rb +5 -1
- data/lib/r10k/cli/module/deploy.rb +5 -32
- data/lib/r10k/cli/module/list.rb +6 -27
- data/lib/r10k/cli/puppetfile.rb +76 -0
- data/lib/r10k/cli/synchronize.rb +8 -24
- data/lib/r10k/cli/version.rb +22 -0
- data/lib/r10k/deployment.rb +55 -26
- data/lib/r10k/deployment/config.rb +69 -0
- data/lib/r10k/{config → deployment/config}/loader.rb +9 -5
- data/lib/r10k/deployment/environment.rb +88 -0
- data/lib/r10k/deployment/source.rb +79 -0
- data/lib/r10k/errors.rb +3 -5
- data/lib/r10k/execution.rb +43 -0
- data/lib/r10k/git/cache.rb +131 -0
- data/lib/r10k/git/errors.rb +34 -0
- data/lib/r10k/git/repository.rb +74 -0
- data/lib/r10k/git/working_dir.rb +142 -0
- data/lib/r10k/logging.rb +6 -2
- data/lib/r10k/module.rb +10 -13
- data/lib/r10k/module/forge.rb +35 -22
- data/lib/r10k/module/git.rb +18 -8
- data/lib/r10k/puppetfile.rb +107 -0
- data/lib/r10k/task.rb +13 -0
- data/lib/r10k/task/deployment.rb +151 -0
- data/lib/r10k/task/environment.rb +29 -0
- data/lib/r10k/task/module.rb +18 -0
- data/lib/r10k/task/puppetfile.rb +99 -0
- data/lib/r10k/task_runner.rb +72 -0
- data/lib/r10k/util/purgeable.rb +50 -0
- data/lib/r10k/version.rb +1 -1
- data/spec/unit/deployment/environment_spec.rb +19 -0
- data/spec/unit/git/cache_spec.rb +37 -0
- data/spec/unit/git/working_dir_spec.rb +15 -0
- data/spec/unit/module/forge_spec.rb +95 -0
- data/spec/unit/module_spec.rb +29 -0
- metadata +79 -44
- data/lib/r10k/action.rb +0 -7
- data/lib/r10k/action/environment.rb +0 -74
- data/lib/r10k/action/module.rb +0 -36
- data/lib/r10k/cli/cache.rb +0 -32
- data/lib/r10k/config.rb +0 -46
- data/lib/r10k/deployment/environment_collection.rb +0 -75
- data/lib/r10k/librarian.rb +0 -31
- data/lib/r10k/librarian/dsl.rb +0 -20
- data/lib/r10k/root.rb +0 -98
- data/lib/r10k/synchro/git.rb +0 -226
data/lib/r10k/librarian.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'r10k'
|
2
|
-
require 'r10k/module'
|
3
|
-
|
4
|
-
class R10K::Librarian
|
5
|
-
|
6
|
-
attr_reader :forge
|
7
|
-
|
8
|
-
def initialize(puppetfile)
|
9
|
-
@puppetfile = puppetfile
|
10
|
-
@modules = []
|
11
|
-
@forge = 'forge.puppetlabs.com'
|
12
|
-
end
|
13
|
-
|
14
|
-
def load
|
15
|
-
dsl = R10K::Librarian::DSL.new(self)
|
16
|
-
dsl.instance_eval(File.read(@puppetfile), @puppetfile)
|
17
|
-
|
18
|
-
@modules
|
19
|
-
end
|
20
|
-
|
21
|
-
# This method only exists because people tried being excessively clever.
|
22
|
-
def set_forge(forge)
|
23
|
-
@forge = forge
|
24
|
-
end
|
25
|
-
|
26
|
-
def add_module(name, args)
|
27
|
-
@modules << [name, args]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
require 'r10k/librarian/dsl'
|
data/lib/r10k/librarian/dsl.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'r10k/librarian'
|
2
|
-
|
3
|
-
class R10K::Librarian::DSL
|
4
|
-
|
5
|
-
def initialize(librarian)
|
6
|
-
@librarian = librarian
|
7
|
-
end
|
8
|
-
|
9
|
-
def mod(name, args = [])
|
10
|
-
@librarian.add_module(name, args)
|
11
|
-
end
|
12
|
-
|
13
|
-
def forge(location)
|
14
|
-
@librarian.set_forge(location)
|
15
|
-
end
|
16
|
-
|
17
|
-
def method_missing(method, *args)
|
18
|
-
raise NoMethodError, "unrecognized declaration '#{method}'"
|
19
|
-
end
|
20
|
-
end
|
data/lib/r10k/root.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'r10k'
|
2
|
-
require 'r10k/module'
|
3
|
-
require 'r10k/synchro/git'
|
4
|
-
require 'r10k/logging'
|
5
|
-
|
6
|
-
class R10K::Root
|
7
|
-
|
8
|
-
include R10K::Logging
|
9
|
-
|
10
|
-
# @!attribute [r] name
|
11
|
-
# The directory name of this root
|
12
|
-
attr_reader :name
|
13
|
-
|
14
|
-
# @!attribute [r] basedir
|
15
|
-
# The basedir to clone the root into
|
16
|
-
attr_reader :basedir
|
17
|
-
|
18
|
-
# @!attribute [r] remote
|
19
|
-
# The location of the remote git repository
|
20
|
-
attr_reader :remote
|
21
|
-
|
22
|
-
# @!attribute [r] ref
|
23
|
-
# The git ref to instantiate into the basedir
|
24
|
-
attr_reader :ref
|
25
|
-
|
26
|
-
def initialize(hash)
|
27
|
-
parse_initialize_hash(hash)
|
28
|
-
end
|
29
|
-
|
30
|
-
def sync!(options = {})
|
31
|
-
synchro = R10K::Synchro::Git.new(@remote)
|
32
|
-
recursive_needed = !(synchro.cloned?(full_path))
|
33
|
-
synchro.sync(full_path, @ref, options)
|
34
|
-
|
35
|
-
sync_modules!(options) if recursive_needed
|
36
|
-
end
|
37
|
-
|
38
|
-
def sync_modules!(options = {})
|
39
|
-
modules.each do |mod|
|
40
|
-
mod.sync!(options)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def modules
|
45
|
-
librarian = R10K::Librarian.new("#{full_path}/Puppetfile")
|
46
|
-
|
47
|
-
module_data = librarian.load
|
48
|
-
|
49
|
-
@modules = module_data.map do |mod|
|
50
|
-
name = mod[0]
|
51
|
-
args = mod[1]
|
52
|
-
R10K::Module.new(name, "#{full_path}/modules", args)
|
53
|
-
end
|
54
|
-
rescue Errno::ENOENT
|
55
|
-
logger.warn "#{self}: #{full_path} does not exist, cannot enumerate modules."
|
56
|
-
[]
|
57
|
-
end
|
58
|
-
|
59
|
-
def full_path
|
60
|
-
@full_path ||= File.expand_path(File.join @basedir, @name)
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def parse_initialize_hash(hash)
|
66
|
-
if hash['name']
|
67
|
-
@name = hash.delete('name')
|
68
|
-
elsif hash['ref']
|
69
|
-
@name = hash['ref']
|
70
|
-
else
|
71
|
-
raise "Unable to resolve directory name from options #{hash.inspect}"
|
72
|
-
end
|
73
|
-
|
74
|
-
# XXX This could be metaprogrammed, but it seems like the road to madness.
|
75
|
-
|
76
|
-
if hash['basedir']
|
77
|
-
@basedir = hash.delete('basedir')
|
78
|
-
else
|
79
|
-
raise "'basedir' is a required value for #{self.class}.new"
|
80
|
-
end
|
81
|
-
|
82
|
-
if hash['remote']
|
83
|
-
@remote = hash.delete('remote')
|
84
|
-
else
|
85
|
-
raise "'remote' is a required value for #{self.class}.new"
|
86
|
-
end
|
87
|
-
|
88
|
-
if hash['ref']
|
89
|
-
@ref = hash.delete('ref')
|
90
|
-
else
|
91
|
-
raise "'ref' is a required value for #{self.class}.new"
|
92
|
-
end
|
93
|
-
|
94
|
-
unless hash.empty?
|
95
|
-
raise "#{self.class}.new only expects keys ['name', 'basedir', 'remote', 'ref'], got #{hash.keys.inspect}"
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
data/lib/r10k/synchro/git.rb
DELETED
@@ -1,226 +0,0 @@
|
|
1
|
-
require 'r10k'
|
2
|
-
require 'r10k/errors'
|
3
|
-
require 'r10k/logging'
|
4
|
-
|
5
|
-
require 'systemu'
|
6
|
-
require 'fileutils'
|
7
|
-
|
8
|
-
module R10K::Synchro; end
|
9
|
-
|
10
|
-
class R10K::Synchro::Git
|
11
|
-
# Define a thingy that can synchronize git repositories.
|
12
|
-
#
|
13
|
-
# This class is built to be a general purpose mechanism for syncing and
|
14
|
-
# caching git repositories.
|
15
|
-
#
|
16
|
-
# Class instances are memoized based on the git remote path. This way if a
|
17
|
-
# single git repository is instantiated multiple times, the object cache
|
18
|
-
# will only be updated once.
|
19
|
-
|
20
|
-
class << self
|
21
|
-
attr_accessor :cache_root
|
22
|
-
|
23
|
-
# @return [Hash<R10K::Synchro::Git>] A hash of memoized class instances
|
24
|
-
def synchros
|
25
|
-
@synchros ||= {}
|
26
|
-
end
|
27
|
-
|
28
|
-
# Memoize class instances and return existing instances.
|
29
|
-
#
|
30
|
-
# This allows objects to mark themselves as cached to prevent unnecessary
|
31
|
-
# cache refreshes.
|
32
|
-
#
|
33
|
-
# @param [String] remote A git remote URL
|
34
|
-
# @return [R10K::Synchro::Git]
|
35
|
-
def new(remote)
|
36
|
-
unless synchros[remote]
|
37
|
-
obj = self.allocate
|
38
|
-
obj.send(:initialize, remote)
|
39
|
-
synchros[remote] = obj
|
40
|
-
end
|
41
|
-
synchros[remote]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
include R10K::Logging
|
46
|
-
|
47
|
-
attr_reader :remote
|
48
|
-
|
49
|
-
# Instantiates a new git synchro and optionally prepares for caching
|
50
|
-
#
|
51
|
-
# @param [String] remote A git remote URL
|
52
|
-
def initialize(remote)
|
53
|
-
@remote = remote
|
54
|
-
|
55
|
-
if self.class.cache_root
|
56
|
-
@cache_path = File.join(self.class.cache_root, @remote.gsub(/[^@\w\.-]/, '-'))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Synchronize the local git repository.
|
61
|
-
#
|
62
|
-
# @param [String] path The destination path for the files
|
63
|
-
# @param [String] ref The git ref to instantiate at the destination path
|
64
|
-
def sync(path, ref, options = {:update_cache => true})
|
65
|
-
path = File.expand_path(path)
|
66
|
-
cache if options[:update_cache]
|
67
|
-
|
68
|
-
if self.cloned?(path)
|
69
|
-
fetch(path)
|
70
|
-
else
|
71
|
-
clone(path)
|
72
|
-
end
|
73
|
-
reset(path, ref)
|
74
|
-
end
|
75
|
-
|
76
|
-
# @return [TrueClass] if the git repository is cached
|
77
|
-
def cached?
|
78
|
-
@cache_path and File.directory? @cache_path
|
79
|
-
end
|
80
|
-
|
81
|
-
# Determine if repo has been cloned into a specific dir
|
82
|
-
#
|
83
|
-
# @param [String] dirname The directory to check
|
84
|
-
#
|
85
|
-
# @return [true, false] If the repo has already been cloned
|
86
|
-
def cloned?(directory)
|
87
|
-
File.directory?(File.join(directory, '.git'))
|
88
|
-
end
|
89
|
-
|
90
|
-
# Update the git object cache repository if it hasn't been done
|
91
|
-
#
|
92
|
-
# @return [true, nil] If the cache was actually updated
|
93
|
-
def cache
|
94
|
-
unless @cached
|
95
|
-
cache!
|
96
|
-
@cached = true
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Force a cache refresh
|
101
|
-
def cache!
|
102
|
-
if cached?
|
103
|
-
logger.debug "Updating existing cache at #{@cache_path}"
|
104
|
-
git "fetch --prune", :git_dir => @cache_path
|
105
|
-
else
|
106
|
-
logger.debug "No cache for #{@remote.inspect}, forcing cache build"
|
107
|
-
cache_root = self.class.cache_root
|
108
|
-
FileUtils.mkdir_p cache_root unless File.exist? cache_root
|
109
|
-
git "clone --mirror #{@remote} #{@cache_path}"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Retrieve a list of cached branches for the git repo associated with this
|
114
|
-
# object.
|
115
|
-
#
|
116
|
-
# @return [Array<String>] A list of all cached remote branches
|
117
|
-
def branches(options = {:update_cache => false})
|
118
|
-
cache if (options[:update_cache] or not cached?)
|
119
|
-
output = git "branch", :git_dir => @cache_path
|
120
|
-
output.split("\n").map { |str| str[2..-1] }
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
|
125
|
-
# Perform a non-bare clone of a git repository.
|
126
|
-
#
|
127
|
-
# If a cachedir is available and the repo is already cached, it will be
|
128
|
-
# used as an object reference to speed up the clone.
|
129
|
-
#
|
130
|
-
# @param [String] path The directory to create the repo working directory
|
131
|
-
def clone(path)
|
132
|
-
if cached?
|
133
|
-
git "clone --reference #{@cache_path} #{@remote} #{path}"
|
134
|
-
git "remote add cache #{@cache_path}", :path => path
|
135
|
-
else
|
136
|
-
FileUtils.mkdir_p path unless File.directory? path
|
137
|
-
git "clone #{@remote} #{path}"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def fetch(path)
|
142
|
-
if cached?
|
143
|
-
git "fetch --prune cache", :path => path
|
144
|
-
else
|
145
|
-
git "fetch --prune origin", :path => path
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# Reset a git repo with a working directory to a specific ref
|
150
|
-
#
|
151
|
-
# @param [String] path The path to the working directory of the git repo
|
152
|
-
# @param [String] ref The git reference to reset to.
|
153
|
-
def reset(path, ref)
|
154
|
-
commit = resolve_commit(ref)
|
155
|
-
|
156
|
-
begin
|
157
|
-
git "reset --hard #{commit}", :path => path
|
158
|
-
rescue R10K::ExecutionFailure => e
|
159
|
-
logger.error "Unable to locate commit object #{commit} in git repo #{path}"
|
160
|
-
raise
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# Resolve a ref to a commit hash
|
165
|
-
#
|
166
|
-
# @param [String] ref
|
167
|
-
#
|
168
|
-
# @return [String] The dereferenced hash of `ref`
|
169
|
-
def resolve_commit(ref)
|
170
|
-
commit = git "rev-parse #{ref}^{commit}", :git_dir => @cache_path
|
171
|
-
commit.chomp
|
172
|
-
rescue R10K::ExecutionFailure => e
|
173
|
-
logger.error "Could not resolve ref #{ref.inspect} for git cache #{@cache_path}"
|
174
|
-
raise
|
175
|
-
end
|
176
|
-
|
177
|
-
# Wrap git commands
|
178
|
-
#
|
179
|
-
# @param [String] command_line_args The arguments for the git prompt
|
180
|
-
# @param [Hash] opts
|
181
|
-
#
|
182
|
-
# @option opts [String] :git_dir
|
183
|
-
# @option opts [String] :work_tree
|
184
|
-
# @option opts [String] :work_tree
|
185
|
-
#
|
186
|
-
# @return [String] The git command output
|
187
|
-
def git(command_line_args, opts = {})
|
188
|
-
args = %w{git}
|
189
|
-
|
190
|
-
log_event = "git #{command_line_args}"
|
191
|
-
log_event << ", args: #{opts.inspect}" unless opts.empty?
|
192
|
-
|
193
|
-
|
194
|
-
if opts[:path]
|
195
|
-
args << "--git-dir #{opts[:path]}/.git"
|
196
|
-
args << "--work-tree #{opts[:path]}"
|
197
|
-
else
|
198
|
-
if opts[:git_dir]
|
199
|
-
args << "--git-dir #{opts[:git_dir]}"
|
200
|
-
end
|
201
|
-
if opts[:work_tree]
|
202
|
-
args << "--work-tree #{opts[:work_tree]}"
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
logger.debug1 "Execute: '#{log_event}'"
|
207
|
-
|
208
|
-
args << command_line_args
|
209
|
-
cmd = args.join(' ')
|
210
|
-
|
211
|
-
status, stdout, stderr = systemu(cmd)
|
212
|
-
|
213
|
-
logger.debug2 "[#{log_event}] STDOUT: #{stdout.chomp}" unless stdout.empty?
|
214
|
-
logger.debug2 "[#{log_event}] STDERR: #{stderr.chomp}" unless stderr.empty?
|
215
|
-
|
216
|
-
unless status == 0
|
217
|
-
msg = "#{cmd.inspect} returned with non-zero exit value #{status.exitstatus}"
|
218
|
-
e = R10K::ExecutionFailure.new(msg)
|
219
|
-
e.exit_code = status
|
220
|
-
e.stdout = stdout
|
221
|
-
e.stderr = stderr
|
222
|
-
raise e
|
223
|
-
end
|
224
|
-
stdout
|
225
|
-
end
|
226
|
-
end
|