puppet-armature 0.2.2 → 0.3.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 +4 -4
- data/Gemfile.lock +3 -1
- data/Rakefile +12 -0
- data/lib/armature/cache.rb +53 -59
- data/lib/armature/environments.rb +3 -8
- data/lib/armature/gitrepo.rb +63 -23
- data/lib/armature/puppetfile.rb +43 -2
- data/lib/armature/run.rb +13 -2
- data/lib/armature/version.rb +1 -1
- data/puppet-armature.gemspec +1 -0
- data/test/deploy_test.rb +306 -0
- data/test/helpers.rb +130 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20b1e802ab0134205a8fac195ba528a3664fd16f
|
4
|
+
data.tar.gz: c1a48279c939c21b4ae482ced27e44243c69c4fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee52d4da30d62132d98b0e0246c4ce6aeb5c99126e7ce9538fe7de28e72c7926f6d33edc377d403bb048d9b2e917ad1f4685b61703b32bf2d2435f85f019b1dc
|
7
|
+
data.tar.gz: 0da4f27f3df184cc48c1ae5d8383d7a62a874573a15fca64a3aff0cb54323144ef65da983a7c10c85d81c3977ce7e307abf1116ea5353fd8b7b32c28ce371a19
|
data/Gemfile.lock
CHANGED
@@ -13,13 +13,15 @@ GEM
|
|
13
13
|
logging (2.0.0)
|
14
14
|
little-plugger (~> 1.1)
|
15
15
|
multi_json (~> 1.10)
|
16
|
+
minitest (5.10.1)
|
16
17
|
multi_json (1.12.1)
|
17
18
|
|
18
19
|
PLATFORMS
|
19
20
|
ruby
|
20
21
|
|
21
22
|
DEPENDENCIES
|
23
|
+
minitest (~> 5.9)
|
22
24
|
puppet-armature!
|
23
25
|
|
24
26
|
BUNDLED WITH
|
25
|
-
1.
|
27
|
+
1.14.6
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems/package_task'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
# Build packages from all .gemspec files
|
5
|
+
FileList['*.gemspec'].each do |path|
|
6
|
+
Gem::PackageTask.new(eval(File.read(path))) { |pkg| }
|
7
|
+
end
|
8
|
+
|
9
|
+
Rake::TestTask.new do |t|
|
10
|
+
t.libs << "lib" << "test"
|
11
|
+
t.test_files = FileList['test/*_test.rb']
|
12
|
+
end
|
data/lib/armature/cache.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'logging'
|
2
3
|
require 'pathname'
|
3
4
|
require 'set'
|
4
5
|
|
@@ -6,17 +7,25 @@ module Armature
|
|
6
7
|
class Cache
|
7
8
|
def initialize(path)
|
8
9
|
FileUtils.mkdir_p(path)
|
10
|
+
@lock_file = nil
|
9
11
|
@path = File.realpath(path)
|
10
12
|
@repos = {}
|
11
13
|
@process_prefix = "#{Time.now.to_i}.#{Process.pid}"
|
12
14
|
@sequence = 0
|
13
15
|
@logger = Logging.logger[self]
|
14
16
|
|
15
|
-
%w{repo mutable immutable object tmp}.each do |subdir|
|
17
|
+
%w{repo ref/mutable ref/immutable ref/identity object tmp}.each do |subdir|
|
16
18
|
FileUtils.mkdir_p("#{@path}/#{subdir}")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
22
|
+
def flush_memory!
|
23
|
+
@logger.debug("Flushing in-memory caches for all repos")
|
24
|
+
@repos.each do |name, repo|
|
25
|
+
repo.freshen!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
20
29
|
# Get GitRepo object for a local clone of a remote repo at a URL
|
21
30
|
#
|
22
31
|
# This will clone the repo if it doesn't already exist.
|
@@ -47,56 +56,38 @@ module Armature
|
|
47
56
|
end
|
48
57
|
|
49
58
|
# Check out a ref from a repo and return the path
|
50
|
-
def checkout(repo, ref, options={})
|
51
|
-
|
52
|
-
{ :name=>nil }, { :refresh=>false })
|
53
|
-
|
54
|
-
safe_ref = fs_sanitize(ref)
|
55
|
-
|
56
|
-
if options[:refresh]
|
59
|
+
def checkout(repo, ref, refresh=false, options={})
|
60
|
+
if refresh
|
57
61
|
# Don't check the cache; refresh it from source.
|
58
62
|
repo.freshen()
|
63
|
+
ref = repo.canonical_ref(ref)
|
59
64
|
else
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
65
|
+
# This will raise a RefError if the ref doesn't exist
|
66
|
+
begin
|
67
|
+
ref = repo.canonical_ref(ref)
|
68
|
+
rescue RefError
|
69
|
+
repo.freshen()
|
70
|
+
ref = repo.canonical_ref(ref)
|
66
71
|
end
|
72
|
+
end
|
67
73
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
return ref_path
|
73
|
-
end
|
74
|
+
type = repo.ref_type(ref)
|
75
|
+
safe_ref = fs_sanitize(ref)
|
76
|
+
repo_path = "#{@path}/ref/#{type}/#{repo.name}"
|
77
|
+
ref_path = "#{repo_path}/#{safe_ref}"
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
ref_path = "#{@path}/immutable/#{repo.name}/#{safe_tag}"
|
79
|
+
if ! refresh
|
80
|
+
# Check cache first
|
78
81
|
if Dir.exist? ref_path
|
79
82
|
return ref_path
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
83
|
-
|
84
|
-
begin
|
85
|
-
type, sha, real_ref = repo.ref_info(ref)
|
86
|
-
rescue
|
87
|
-
repo.freshen()
|
88
|
-
type, sha, real_ref = repo.ref_info(ref)
|
89
|
-
end
|
90
|
-
|
91
|
-
repo_dir = "#{@path}/#{type}/#{repo.name}"
|
92
|
-
if ! Dir.exist? repo_dir
|
93
|
-
Dir.mkdir(repo_dir)
|
94
|
-
end
|
86
|
+
FileUtils.mkdir_p(repo_path)
|
95
87
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
atomic_symlink(sha_path, ref_path)
|
88
|
+
identity_path = checkout_identity(repo, repo.ref_identity(ref))
|
89
|
+
if identity_path != ref_path
|
90
|
+
atomic_symlink(identity_path, ref_path)
|
100
91
|
end
|
101
92
|
|
102
93
|
ref_path
|
@@ -129,9 +120,8 @@ module Armature
|
|
129
120
|
end
|
130
121
|
|
131
122
|
def update_branches()
|
132
|
-
Dir.glob("#{@path}/mutable/*/*") do |path|
|
133
|
-
ref = File.basename(path)
|
134
|
-
### FIXME decode
|
123
|
+
Dir.glob("#{@path}/ref/mutable/*/*") do |path|
|
124
|
+
ref = fs_unsanitize(File.basename(path))
|
135
125
|
repo = get_repo_by_name(File.basename(File.dirname(path)))
|
136
126
|
@logger.info("Updating #{ref} ref from #{repo.url}")
|
137
127
|
|
@@ -198,34 +188,38 @@ module Armature
|
|
198
188
|
ref.sub(/\A\./, "\\.").gsub(/[\\|]/, '\\\0').gsub(/\//, '|')
|
199
189
|
end
|
200
190
|
|
201
|
-
|
202
|
-
|
203
|
-
|
191
|
+
def fs_unsanitize(name)
|
192
|
+
name.gsub(/\|/, '/').gsub(/\\([\\|])/, '\0').sub(/^\\\./, '.')
|
193
|
+
end
|
194
|
+
|
195
|
+
# Assumes identity exists. Use checkout() if it might not.
|
196
|
+
def checkout_identity(repo, identity)
|
197
|
+
safe_identity = fs_sanitize(identity)
|
204
198
|
|
205
|
-
repo_path = "#{@path}/
|
206
|
-
|
207
|
-
if Dir.exist?
|
208
|
-
return
|
199
|
+
repo_path = "#{@path}/identity/#{repo.name}"
|
200
|
+
identity_path = "#{repo_path}/#{safe_identity}"
|
201
|
+
if Dir.exist? identity_path
|
202
|
+
return identity_path
|
209
203
|
end
|
210
204
|
|
211
205
|
FileUtils.mkdir_p(repo_path)
|
212
206
|
|
213
|
-
Armature::Util::lock
|
207
|
+
Armature::Util::lock identity_path, File::LOCK_EX, "checkout" do
|
214
208
|
# Another process may have created the object before we got the lock
|
215
|
-
if Dir.exist?
|
216
|
-
return
|
209
|
+
if Dir.exist? identity_path
|
210
|
+
return identity_path
|
217
211
|
end
|
218
212
|
|
219
|
-
object_path = new_object_path(
|
213
|
+
object_path = new_object_path(identity)
|
220
214
|
FileUtils.mkdir_p object_path
|
221
215
|
|
222
216
|
@logger.debug(
|
223
|
-
"Checking out '#{
|
224
|
-
repo.git "reset", "--hard",
|
225
|
-
atomic_symlink(object_path,
|
217
|
+
"Checking out '#{identity}' from '#{repo.url}' into '#{object_path}'")
|
218
|
+
repo.git "reset", "--hard", identity, :work_dir=>object_path
|
219
|
+
atomic_symlink(object_path, identity_path)
|
226
220
|
end
|
227
221
|
|
228
|
-
|
222
|
+
identity_path
|
229
223
|
end
|
230
224
|
|
231
225
|
# Put a directory into a trash directory for off-line deletion
|
@@ -318,7 +312,7 @@ module Armature
|
|
318
312
|
def garbage_collect_refs(referenced_paths)
|
319
313
|
# Must be run from garbage_collect, since that handles the lock as well
|
320
314
|
# as emptying the trash
|
321
|
-
all_references = Set.new(Dir.glob("#{@path}/
|
315
|
+
all_references = Set.new(Dir.glob("#{@path}/ref/*/*/*"))
|
322
316
|
difference = all_references - referenced_paths
|
323
317
|
@logger.info(
|
324
318
|
"Deleting #{difference.size} of #{all_references.size} references")
|
@@ -348,7 +342,7 @@ module Armature
|
|
348
342
|
all_repos = Set.new(all_repos.map { |path| File.basename(path) })
|
349
343
|
used_repos = Set.new()
|
350
344
|
|
351
|
-
referenced_repos = Dir.glob("#{@path}/
|
345
|
+
referenced_repos = Dir.glob("#{@path}/ref/*/*")
|
352
346
|
referenced_repos.each do |path|
|
353
347
|
# No refs within the repo in use (for this ref type)
|
354
348
|
if Dir.glob("#{path}/*").empty?
|
@@ -39,7 +39,7 @@ module Armature
|
|
39
39
|
" environment '#{name}'"
|
40
40
|
|
41
41
|
begin
|
42
|
-
ref_path = @cache.checkout(repo, ref,
|
42
|
+
ref_path = @cache.checkout(repo, ref, true)
|
43
43
|
rescue RefError
|
44
44
|
@logger.info "Ref '#{ref}' does not exist; ensuring environment" \
|
45
45
|
" '#{name}' is gone"
|
@@ -50,9 +50,7 @@ module Armature
|
|
50
50
|
puppetfile_path = "#{ref_path}/Puppetfile"
|
51
51
|
if File.exist?(puppetfile_path)
|
52
52
|
@logger.debug "Found Puppetfile in environment '#{name}'"
|
53
|
-
|
54
|
-
puppetfile.include(puppetfile_path)
|
55
|
-
module_refs = puppetfile.results
|
53
|
+
module_refs = Armature::Puppetfile.new().include(puppetfile_path)
|
56
54
|
@logger.debug "Loaded Puppetfile in environment '#{name}' with" \
|
57
55
|
" #{module_refs.length} modules"
|
58
56
|
else
|
@@ -84,10 +82,7 @@ module Armature
|
|
84
82
|
raise "Module name may not contain /: '#{name}'"
|
85
83
|
end
|
86
84
|
|
87
|
-
ref_path = @cache.checkout(
|
88
|
-
@cache.get_repo(info[:git]),
|
89
|
-
info[:ref],
|
90
|
-
:name=>"#{name}.#{info[:ref]}")
|
85
|
+
ref_path = @cache.checkout(@cache.get_repo(info[:git]), info[:ref])
|
91
86
|
|
92
87
|
@cache.atomic_symlink(ref_path, "#{modules_path}/#{name}")
|
93
88
|
end
|
data/lib/armature/gitrepo.rb
CHANGED
@@ -19,17 +19,22 @@ module Armature
|
|
19
19
|
|
20
20
|
def freshen
|
21
21
|
if ! @fetched
|
22
|
-
|
23
|
-
Armature::Util::lock @git_dir, File::LOCK_EX, "fetch" do
|
24
|
-
git "remote", "update", "--prune"
|
25
|
-
end
|
26
|
-
@fetched = true
|
22
|
+
freshen!
|
27
23
|
true
|
28
24
|
else
|
29
25
|
false
|
30
26
|
end
|
31
27
|
end
|
32
28
|
|
29
|
+
def freshen!
|
30
|
+
@logger.info("Fetching from #{url}")
|
31
|
+
Armature::Util::lock @git_dir, File::LOCK_EX, "fetch" do
|
32
|
+
git "remote", "update", "--prune"
|
33
|
+
end
|
34
|
+
@ref_cache = {}
|
35
|
+
@fetched = true
|
36
|
+
end
|
37
|
+
|
33
38
|
def git(*arguments)
|
34
39
|
# This accepts a hash of options as the last argument
|
35
40
|
options = if arguments.last.is_a? Hash then arguments.pop else {} end
|
@@ -57,43 +62,78 @@ module Armature
|
|
57
62
|
|
58
63
|
lines.map do |line|
|
59
64
|
sha, ref = line.split(' ', 2)
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
name = ref.sub("refs/heads/", "")
|
66
|
+
@ref_cache[ref] = [:mutable, sha, ref, "branch", name]
|
67
|
+
name
|
63
68
|
end
|
64
69
|
end
|
65
70
|
|
66
|
-
|
71
|
+
def ref_type(ref)
|
72
|
+
ref_info(ref)[0]
|
73
|
+
end
|
74
|
+
|
75
|
+
def ref_identity(ref)
|
76
|
+
ref_info(ref)[1]
|
77
|
+
end
|
78
|
+
|
79
|
+
def canonical_ref(ref)
|
80
|
+
ref_info(ref)[2]
|
81
|
+
end
|
82
|
+
|
83
|
+
def ref_human_name(ref)
|
84
|
+
info = ref_info(ref)
|
85
|
+
|
86
|
+
"#{info[3]} '#{info[4]}'"
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# Get information about ref, checking the cache first
|
67
92
|
def ref_info(ref)
|
68
|
-
if
|
69
|
-
|
93
|
+
if ! @ref_cache[ref]
|
94
|
+
freshen_ref_cache(ref)
|
95
|
+
end
|
96
|
+
|
97
|
+
@ref_cache[ref]
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get information about a ref and put it in the cache
|
101
|
+
def freshen_ref_cache(ref)
|
102
|
+
if ref.start_with? "refs/heads/"
|
103
|
+
@ref_cache[ref] = [:mutable, rev_parse!(ref), ref, "branch", ref.sub("refs/heads/", "")]
|
104
|
+
elsif ref.start_with? "refs/tags/"
|
105
|
+
@ref_cache[ref] = [:immutable, rev_parse!(ref), ref, "tag", ref.sub("refs/tags/", "")]
|
106
|
+
elsif ref.start_with? "refs/"
|
107
|
+
@ref_cache[ref] = [:mutable, rev_parse!(ref), ref, "ref", ref]
|
70
108
|
elsif sha = rev_parse("refs/heads/#{ref}")
|
71
|
-
@ref_cache["refs/heads/#{ref}"] = [:mutable, sha, "refs/heads/#{ref}"]
|
109
|
+
@ref_cache["refs/heads/#{ref}"] = [:mutable, sha, "refs/heads/#{ref}", "branch", ref]
|
110
|
+
@ref_cache[ref] = @ref_cache["refs/heads/#{ref}"]
|
72
111
|
elsif sha = rev_parse("refs/tags/#{ref}")
|
73
|
-
@ref_cache["refs/tags/#{ref}"] = [:immutable, sha, "refs/tags/#{ref}"]
|
112
|
+
@ref_cache["refs/tags/#{ref}"] = [:immutable, sha, "refs/tags/#{ref}", "tag", ref]
|
113
|
+
@ref_cache[ref] = @ref_cache["refs/tags/#{ref}"]
|
74
114
|
elsif sha = rev_parse(ref)
|
75
115
|
if sha == ref
|
76
|
-
@ref_cache[ref] = [:
|
116
|
+
@ref_cache[ref] = [:identity, sha, ref, "revision", ref]
|
77
117
|
else
|
78
|
-
@ref_cache[ref] = [:mutable, sha, ref]
|
118
|
+
@ref_cache[ref] = [:mutable, sha, ref, "ref", ref]
|
79
119
|
end
|
80
120
|
else
|
81
121
|
raise RefError.new("no such ref '#{ref}' in repo '#{url}'")
|
82
122
|
end
|
83
123
|
end
|
84
124
|
|
85
|
-
private
|
86
|
-
def check_cache(ref)
|
87
|
-
@ref_cache[ref] \
|
88
|
-
|| @ref_cache["refs/heads/#{ref}"] \
|
89
|
-
|| @ref_cache["refs/tags/#{ref}"]
|
90
|
-
end
|
91
|
-
|
92
125
|
# Get the sha for a ref, or nil if it doesn't exist
|
93
126
|
def rev_parse(ref)
|
127
|
+
rev_parse!(ref)
|
128
|
+
rescue RefError
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
# Get the sha for a ref, or raise if it doesn't exist
|
133
|
+
def rev_parse!(ref)
|
94
134
|
git("rev-parse", "--verify", "#{ref}^{commit}").chomp
|
95
135
|
rescue Armature::Run::CommandFailureError
|
96
|
-
|
136
|
+
raise RefError.new("no such ref '#{ref}' in repo '#{url}'")
|
97
137
|
end
|
98
138
|
end
|
99
139
|
end
|
data/lib/armature/puppetfile.rb
CHANGED
@@ -8,6 +8,7 @@ module Armature
|
|
8
8
|
|
9
9
|
def include(path)
|
10
10
|
instance_eval(IO.read(path), path)
|
11
|
+
@results
|
11
12
|
end
|
12
13
|
|
13
14
|
def mod(name, options={})
|
@@ -21,10 +22,50 @@ module Armature
|
|
21
22
|
raise "Module #{name} declared twice"
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
options = Armature::Util.process_options(options, {
|
26
|
+
:commit => nil,
|
27
|
+
:tag => nil,
|
28
|
+
:branch => nil,
|
29
|
+
:ref => nil,
|
30
|
+
}, {
|
25
31
|
:git => nil,
|
26
|
-
:ref => "master",
|
27
32
|
})
|
33
|
+
|
34
|
+
ref = nil
|
35
|
+
|
36
|
+
if options[:commit]
|
37
|
+
if ref
|
38
|
+
raise "Module #{name} has more than one of :commit, :tag, :branch, or :ref"
|
39
|
+
end
|
40
|
+
ref = options[:commit]
|
41
|
+
end
|
42
|
+
|
43
|
+
if options[:tag]
|
44
|
+
if ref
|
45
|
+
raise "Module #{name} has more than one of :commit, :tag, :branch, or :ref"
|
46
|
+
end
|
47
|
+
ref = "refs/tags/#{options[:tag]}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if options[:branch]
|
51
|
+
if ref
|
52
|
+
raise "Module #{name} has more than one of :commit, :tag, :branch, or :ref"
|
53
|
+
end
|
54
|
+
ref = "refs/heads/#{options[:branch]}"
|
55
|
+
end
|
56
|
+
|
57
|
+
if options[:ref]
|
58
|
+
if ref
|
59
|
+
raise "Module #{name} has more than one of :commit, :tag, :branch, or :ref"
|
60
|
+
end
|
61
|
+
ref = options[:ref]
|
62
|
+
end
|
63
|
+
|
64
|
+
if ! ref
|
65
|
+
ref = "refs/heads/master"
|
66
|
+
end
|
67
|
+
|
68
|
+
@results[name] = { :name => name, :ref => ref, :git => options[:git] }
|
28
69
|
end
|
29
70
|
|
30
71
|
def forge(*arguments)
|
data/lib/armature/run.rb
CHANGED
@@ -26,11 +26,11 @@ module Armature::Run
|
|
26
26
|
command.shelljoin
|
27
27
|
end
|
28
28
|
|
29
|
-
def command(*command)
|
29
|
+
def command(environment={}, *command)
|
30
30
|
logger = Logging.logger[self]
|
31
31
|
|
32
32
|
logger.debug(command_to_string(*command))
|
33
|
-
out, status = Open3.capture2e(*command)
|
33
|
+
out, status = Open3.capture2e(environment, *command)
|
34
34
|
logger.debug(command_to_string(command.first) + ": #{status}")
|
35
35
|
|
36
36
|
if ! status.success?
|
@@ -39,4 +39,15 @@ module Armature::Run
|
|
39
39
|
|
40
40
|
out
|
41
41
|
end
|
42
|
+
|
43
|
+
def clean_git(*command)
|
44
|
+
# Disable general configuration files
|
45
|
+
environment = {
|
46
|
+
"HOME" => "",
|
47
|
+
"XDG_CONFIG_HOME" => "",
|
48
|
+
"GIT_CONFIG_NOSYSTEM" => "1",
|
49
|
+
}
|
50
|
+
|
51
|
+
command(environment, "git", *command)
|
52
|
+
end
|
42
53
|
end
|
data/lib/armature/version.rb
CHANGED
data/puppet-armature.gemspec
CHANGED
data/test/deploy_test.rb
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'helpers'
|
3
|
+
|
4
|
+
class DeployTest < Minitest::Test
|
5
|
+
include ArmatureTestHelpers
|
6
|
+
|
7
|
+
def test_deploy_just_master_branch
|
8
|
+
with_context do
|
9
|
+
repo = @cache.get_repo(repo_path("control"))
|
10
|
+
branches = Set.new(repo.get_branches())
|
11
|
+
|
12
|
+
assert_equal(Set.new(['master']), branches,
|
13
|
+
"Branches before test incorrect")
|
14
|
+
assert_equal([], @environments.names(),
|
15
|
+
"Environments before test incorrect")
|
16
|
+
|
17
|
+
@environments.checkout_ref(repo, "master")
|
18
|
+
|
19
|
+
assert_equal(["master"], @environments.names(),
|
20
|
+
"Environments after test incorrect")
|
21
|
+
assert_equal([".", "..", "master"], Dir.entries(@environments.path),
|
22
|
+
"Environments directory after test incorrect")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
### FIXME: should this generate an error?
|
27
|
+
def test_deploy_nonexistant_branch
|
28
|
+
with_context do
|
29
|
+
repo = @cache.get_repo(repo_path("control"))
|
30
|
+
branches = Set.new(repo.get_branches())
|
31
|
+
|
32
|
+
assert_equal(Set.new(['master']), branches,
|
33
|
+
"Branches before test incorrect")
|
34
|
+
|
35
|
+
@environments.checkout_ref(repo, "foo")
|
36
|
+
|
37
|
+
assert_equal([], @environments.names(),
|
38
|
+
"Environments after test incorrect")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_deploy_all_branches
|
43
|
+
with_context do
|
44
|
+
repo = @cache.get_repo(repo_path("control"))
|
45
|
+
branches = Set.new(repo.get_branches())
|
46
|
+
|
47
|
+
Dir.mkdir(@context_path + "/foo")
|
48
|
+
File.symlink(@context_path + "/foo", @environments.path + "/foo")
|
49
|
+
|
50
|
+
assert_equal(["foo"], @environments.names(),
|
51
|
+
"Environments before test incorrect")
|
52
|
+
|
53
|
+
(Set.new(@environments.names()) - branches).each do |name|
|
54
|
+
@environments.remove(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
branches.each do |branch|
|
58
|
+
@environments.checkout_ref(repo, branch)
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_equal(["master"], @environments.names(),
|
62
|
+
"Environments after test incorrect")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_deploy_one_module
|
67
|
+
with_context do
|
68
|
+
repo = @cache.get_repo(repo_path("control"))
|
69
|
+
@environments.checkout_ref(repo, "master")
|
70
|
+
|
71
|
+
assert_equal(
|
72
|
+
[".", "..", "module1"],
|
73
|
+
Dir.entries(@environments.path + "/master/modules"),
|
74
|
+
"Modules installed after test incorrect")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_adding_module_and_redeploying
|
79
|
+
with_context do
|
80
|
+
repo = @cache.get_repo(repo_path("control"))
|
81
|
+
@environments.checkout_ref(repo, "master")
|
82
|
+
|
83
|
+
repo_init("module-2")
|
84
|
+
repo_commit("control", "Add module-2") do
|
85
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
86
|
+
forge "https://forge.puppet.com"
|
87
|
+
|
88
|
+
mod "module1", :git=>"#{repo_path('module-1')}"
|
89
|
+
mod "module2", :git=>"#{repo_path('module-2')}"
|
90
|
+
PUPPETFILE
|
91
|
+
end
|
92
|
+
|
93
|
+
@cache.flush_memory!
|
94
|
+
@environments.checkout_ref(repo, "master")
|
95
|
+
assert_equal(
|
96
|
+
[".", "..", "module1", "module2"],
|
97
|
+
Dir.entries(@environments.path + "/master/modules"),
|
98
|
+
"Modules installed after test incorrect")
|
99
|
+
assert_environment_file_contains(
|
100
|
+
"master/modules/module1/README.md",
|
101
|
+
"# Armature test repo: module-1")
|
102
|
+
assert_environment_file_contains(
|
103
|
+
"master/modules/module2/README.md",
|
104
|
+
"# Armature test repo: module-2")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_removing_module_and_redeploying
|
109
|
+
with_context do
|
110
|
+
repo = @cache.get_repo(repo_path("control"))
|
111
|
+
@environments.checkout_ref(repo, "master")
|
112
|
+
|
113
|
+
repo_commit("control", "Remove module-1") do
|
114
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
115
|
+
forge "https://forge.puppet.com"
|
116
|
+
PUPPETFILE
|
117
|
+
end
|
118
|
+
|
119
|
+
@cache.flush_memory!
|
120
|
+
@environments.checkout_ref(repo, "master")
|
121
|
+
assert_equal(
|
122
|
+
[".", ".."],
|
123
|
+
Dir.entries(@environments.path + "/master/modules"),
|
124
|
+
"Modules installed after test incorrect")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_module_with_bad_ref
|
129
|
+
with_context do
|
130
|
+
repo = @cache.get_repo(repo_path("control"))
|
131
|
+
repo_commit("control", "Set module-1 to bad ref") do
|
132
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
133
|
+
forge "https://forge.puppet.com"
|
134
|
+
|
135
|
+
mod "module1", :git=>"#{repo_path('module-1')}", :ref=>"bad"
|
136
|
+
PUPPETFILE
|
137
|
+
end
|
138
|
+
|
139
|
+
assert_raises(Armature::RefError) do
|
140
|
+
@environments.checkout_ref(repo, "master")
|
141
|
+
end
|
142
|
+
|
143
|
+
### FIXME state of repo after an error is undefined, but this behavior
|
144
|
+
### seems reasonable.
|
145
|
+
assert_equal(
|
146
|
+
[".", ".."],
|
147
|
+
Dir.entries(@environments.path),
|
148
|
+
"Modules installed after test incorrect")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_redeploying_module_with_bad_ref
|
153
|
+
with_context do
|
154
|
+
repo = @cache.get_repo(repo_path("control"))
|
155
|
+
@environments.checkout_ref(repo, "master")
|
156
|
+
|
157
|
+
repo_commit("control", "Set module-1 to bad ref") do
|
158
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
159
|
+
forge "https://forge.puppet.com"
|
160
|
+
|
161
|
+
mod "module1", :git=>"#{repo_path('module-1')}", :ref=>"bad"
|
162
|
+
PUPPETFILE
|
163
|
+
end
|
164
|
+
|
165
|
+
@cache.flush_memory!
|
166
|
+
assert_raises(Armature::RefError) do
|
167
|
+
@environments.checkout_ref(repo, "master")
|
168
|
+
end
|
169
|
+
|
170
|
+
### FIXME state of repo after an error is undefined
|
171
|
+
### What happens if other modules already exist?
|
172
|
+
skip("state of repo after an error is undefined")
|
173
|
+
assert_equal(
|
174
|
+
[".", "..", "module1"],
|
175
|
+
Dir.entries(@environments.path + "/master/modules"),
|
176
|
+
"Modules installed after test incorrect")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_redeploying_module_with_ref_tag
|
181
|
+
with_context do
|
182
|
+
set_up_interesting_module("interesting")
|
183
|
+
redeploy_module_with_ref_of_type("ref", "tag_one") do
|
184
|
+
assert_module_manifests("interesting", ["one.pp"],
|
185
|
+
"Incorrect module version after redeploy")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_redeploying_module_with_ref_branch
|
191
|
+
with_context do
|
192
|
+
set_up_interesting_module("interesting")
|
193
|
+
redeploy_module_with_ref_of_type("ref", "branch_two") do
|
194
|
+
assert_module_manifests("interesting", ["one.pp", "two.pp", "two_a.pp"],
|
195
|
+
"Incorrect module version after redeploy")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_redeploying_module_with_ref_commit
|
201
|
+
with_context do
|
202
|
+
set_up_interesting_module("interesting")
|
203
|
+
sha = repo_git("interesting", "rev-parse", "branch_two^").chomp
|
204
|
+
redeploy_module_with_ref_of_type("ref", sha) do
|
205
|
+
assert_module_manifests("interesting", ["one.pp", "two.pp"],
|
206
|
+
"Incorrect module version after redeploy")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_redeploying_module_with_tag
|
212
|
+
with_context do
|
213
|
+
set_up_interesting_module("interesting")
|
214
|
+
redeploy_module_with_ref_of_type("tag", "tag_one") do
|
215
|
+
assert_module_manifests("interesting", ["one.pp"],
|
216
|
+
"Incorrect module version after redeploy")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_redeploying_module_with_branch
|
222
|
+
with_context do
|
223
|
+
set_up_interesting_module("interesting")
|
224
|
+
redeploy_module_with_ref_of_type("branch", "branch_two") do
|
225
|
+
assert_module_manifests("interesting", ["one.pp", "two.pp", "two_a.pp"],
|
226
|
+
"Incorrect module version after redeploy")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_redeploying_module_with_commit
|
232
|
+
with_context do
|
233
|
+
set_up_interesting_module("interesting")
|
234
|
+
sha = repo_git("interesting", "rev-parse", "branch_two^").chomp
|
235
|
+
redeploy_module_with_ref_of_type("commit", sha) do
|
236
|
+
assert_module_manifests("interesting", ["one.pp", "two.pp"],
|
237
|
+
"Incorrect module version after redeploy")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_redeploying_module_with_updated_branch
|
243
|
+
with_context do
|
244
|
+
set_up_interesting_module("interesting")
|
245
|
+
redeploy_module_with_ref_of_type("ref", "branch_two") do
|
246
|
+
repo_git("interesting", "checkout", "branch_two")
|
247
|
+
add_module_class("interesting", "two_b")
|
248
|
+
|
249
|
+
@cache.flush_memory!
|
250
|
+
@environments.checkout_ref(@cache.get_repo(repo_path("control")), "master")
|
251
|
+
|
252
|
+
skip("checkout_ref doesn't update branches at the moment")
|
253
|
+
assert_module_manifests("interesting",
|
254
|
+
["one.pp", "two.pp", "two_a.pp", "two_b.pp"],
|
255
|
+
"Incorrect module version after redeploy")
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_updating_branches_on_module_with_updated_branch
|
261
|
+
with_context do
|
262
|
+
set_up_interesting_module("interesting")
|
263
|
+
redeploy_module_with_ref_of_type("ref", "branch_two") do
|
264
|
+
repo_git("interesting", "checkout", "branch_two")
|
265
|
+
add_module_class("interesting", "two_b")
|
266
|
+
|
267
|
+
@cache.flush_memory!
|
268
|
+
@cache.update_branches()
|
269
|
+
|
270
|
+
assert_module_manifests("interesting",
|
271
|
+
["one.pp", "two.pp", "two_a.pp", "two_b.pp"],
|
272
|
+
"Incorrect module version after redeploy")
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
# The "interesting" repo must be created first so it can be queried for shas
|
280
|
+
def redeploy_module_with_ref_of_type(ref_type, ref)
|
281
|
+
repo = @cache.get_repo(repo_path("control"))
|
282
|
+
|
283
|
+
repo_puppetfile_update("control", <<-MODULES)
|
284
|
+
mod "interesting", :git=>"#{repo_path('interesting')}"
|
285
|
+
MODULES
|
286
|
+
|
287
|
+
@environments.checkout_ref(repo, "master")
|
288
|
+
|
289
|
+
assert_module_manifests("interesting", ["one.pp", "two.pp", "three.pp"],
|
290
|
+
"Incorrect module version after initial deploy")
|
291
|
+
|
292
|
+
repo_commit("control", "Add interesting module") do
|
293
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
294
|
+
forge "https://forge.puppet.com"
|
295
|
+
|
296
|
+
mod "interesting", :git=>"#{repo_path('interesting')}",
|
297
|
+
:#{ref_type}=>"#{ref}"
|
298
|
+
PUPPETFILE
|
299
|
+
end
|
300
|
+
|
301
|
+
@cache.flush_memory!
|
302
|
+
@environments.checkout_ref(repo, "master")
|
303
|
+
|
304
|
+
yield
|
305
|
+
end
|
306
|
+
end
|
data/test/helpers.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'armature'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
module ArmatureTestHelpers
|
6
|
+
def repo_path(name)
|
7
|
+
@context_path + "/repos/" + name
|
8
|
+
end
|
9
|
+
|
10
|
+
def repo_init(name)
|
11
|
+
Armature::Run.clean_git("init", repo_path(name))
|
12
|
+
repo_commit(name, "Initial revision of #{name}") do
|
13
|
+
File.write("README.md", <<-README)
|
14
|
+
# Armature test repo: #{name}
|
15
|
+
|
16
|
+
Located at #{repo_path(name)}
|
17
|
+
README
|
18
|
+
|
19
|
+
Dir.mkdir("manifests")
|
20
|
+
File.write("manifests/.keep", "")
|
21
|
+
|
22
|
+
if block_given?
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def repo_commit(name, message)
|
29
|
+
Dir.chdir(repo_path(name)) do
|
30
|
+
yield
|
31
|
+
Armature::Run.clean_git("add", ".")
|
32
|
+
Armature::Run.clean_git("commit", "-m", message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def repo_git(name, *command)
|
37
|
+
Dir.chdir(repo_path(name)) do
|
38
|
+
Armature::Run.clean_git(*command)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def repo_puppetfile_update(name, modules)
|
43
|
+
repo_commit(name, "Update Puppetfile") do
|
44
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
45
|
+
forge "https://forge.puppet.com"
|
46
|
+
|
47
|
+
#{modules}
|
48
|
+
PUPPETFILE
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_module_class(module_name, class_name)
|
53
|
+
repo_commit(module_name, "Add #{class_name}.pp") do
|
54
|
+
File.write("manifests/#{class_name}.pp", <<-MANIFEST)
|
55
|
+
class module1::#{class_name} {
|
56
|
+
notify { "in #{module_name}::#{class_name}": }
|
57
|
+
}
|
58
|
+
MANIFEST
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_up_interesting_module(module_name)
|
63
|
+
repo_init(module_name)
|
64
|
+
|
65
|
+
add_module_class(module_name, "one")
|
66
|
+
repo_git(module_name, "tag", "tag_one")
|
67
|
+
add_module_class(module_name, "two")
|
68
|
+
repo_git(module_name, "checkout", "-b", "branch_two")
|
69
|
+
add_module_class(module_name, "two_a")
|
70
|
+
repo_git(module_name, "checkout", "master")
|
71
|
+
add_module_class(module_name, "three")
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_up_context
|
75
|
+
@context_path = Dir.mktmpdir("armature.test_context.")
|
76
|
+
@cache = Armature::Cache.new(@context_path + "/cache")
|
77
|
+
|
78
|
+
Dir.mkdir(@context_path + "/environments")
|
79
|
+
@environments = Armature::Environments.new(@context_path + "/environments", @cache)
|
80
|
+
|
81
|
+
repo_init("module-1")
|
82
|
+
|
83
|
+
repo_init("control") do
|
84
|
+
File.write("Puppetfile", <<-PUPPETFILE)
|
85
|
+
forge "https://forge.puppet.com"
|
86
|
+
|
87
|
+
mod "module1", :git=>"#{repo_path('module-1')}"
|
88
|
+
PUPPETFILE
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def tear_down_context
|
93
|
+
FileUtils.rm_rf(@context_path)
|
94
|
+
|
95
|
+
# Ensure that code trying to use these after this point fails in a
|
96
|
+
# predictable way.
|
97
|
+
@context_path = nil
|
98
|
+
@cache = nil
|
99
|
+
@environments = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_context
|
103
|
+
set_up_context
|
104
|
+
yield
|
105
|
+
tear_down_context
|
106
|
+
end
|
107
|
+
|
108
|
+
def environment_file_contains?(path, search)
|
109
|
+
File.foreach(@environments.path + "/" + path).any? do
|
110
|
+
|line| line.include? search
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def assert_environment_file_contains(path, search, message=nil)
|
115
|
+
if ! message
|
116
|
+
message = "#{path} does not contain '#{search}'"
|
117
|
+
end
|
118
|
+
|
119
|
+
assert(environment_file_contains?(path, search), message)
|
120
|
+
end
|
121
|
+
|
122
|
+
def assert_module_manifests(module_name, manifest_names=["init.pp"],
|
123
|
+
message="Incorrect manifests in module '#{module_name}'",
|
124
|
+
environment="master")
|
125
|
+
assert_equal(
|
126
|
+
([".", "..", ".keep"] + manifest_names).sort(),
|
127
|
+
Dir.entries(@environments.path + "/#{environment}/modules/#{module_name}/manifests"),
|
128
|
+
message)
|
129
|
+
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet-armature
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Parks
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.9'
|
41
55
|
description: Armature sets up Puppet environments for each branch in your control
|
42
56
|
repo and installs modules as specified by the Puppetfile for each environment. It
|
43
57
|
is designed as a replacement for r10k.
|
@@ -51,6 +65,7 @@ files:
|
|
51
65
|
- Gemfile.lock
|
52
66
|
- LICENSE
|
53
67
|
- README.md
|
68
|
+
- Rakefile
|
54
69
|
- TODO.md
|
55
70
|
- bin/armature
|
56
71
|
- docs/puppetfile-syntax.md
|
@@ -63,6 +78,8 @@ files:
|
|
63
78
|
- lib/armature/util.rb
|
64
79
|
- lib/armature/version.rb
|
65
80
|
- puppet-armature.gemspec
|
81
|
+
- test/deploy_test.rb
|
82
|
+
- test/helpers.rb
|
66
83
|
homepage: https://github.com/danielparks/armature
|
67
84
|
licenses:
|
68
85
|
- BSD-2-Clause
|
@@ -89,4 +106,3 @@ signing_key:
|
|
89
106
|
specification_version: 4
|
90
107
|
summary: Deploy Puppet environments and manage modules
|
91
108
|
test_files: []
|
92
|
-
has_rdoc: false
|