puppet-armature 0.3.0 → 0.4.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.
data/lib/armature/run.rb CHANGED
@@ -4,7 +4,7 @@ require 'shellwords'
4
4
  module Armature::Run
5
5
  extend self
6
6
 
7
- class CommandFailureError < StandardError
7
+ class CommandFailureError < Armature::Error
8
8
  attr_reader :status
9
9
  attr_reader :command
10
10
  attr_reader :output
@@ -17,30 +17,57 @@ module Armature::Run
17
17
  end
18
18
 
19
19
  def to_s
20
- command_str = Armature::Run.command_to_string(*@command)
20
+ command_str = Armature::Run.command_to_string(@command)
21
21
  "Command failed: #{command_str}\nReturn: #{@status}\nOutput:\n#{@output}\n"
22
22
  end
23
23
  end
24
24
 
25
- def command_to_string(*command)
26
- command.shelljoin
25
+ def command_to_string(cmd)
26
+ escaped_words = cmd.map do |word|
27
+ escaped = Shellwords.escape(word)
28
+ if escaped == word || word.include?("'") || word.include?("\\")
29
+ escaped
30
+ else
31
+ # The word needs to be quoted, but doesn't contain ' or \. It can just
32
+ # singled-quoted.
33
+ "'#{word}'"
34
+ end
35
+ end
36
+
37
+ escaped_words.join(" ")
38
+ end
39
+
40
+ def command(environment={}, *cmd)
41
+ pipe_command("", environment, *cmd)
27
42
  end
28
43
 
29
- def command(environment={}, *command)
30
- logger = Logging.logger[self]
44
+ def pipe_command(input, environment={}, *cmd)
45
+ if input == ""
46
+ logger.debug("Run: " + command_to_string(cmd))
47
+ else
48
+ logger.debug("Run with input: " + command_to_string(cmd))
49
+ end
31
50
 
32
- logger.debug(command_to_string(*command))
33
- out, status = Open3.capture2e(environment, *command)
34
- logger.debug(command_to_string(command.first) + ": #{status}")
51
+ start_time = Time.now
52
+ output, status = nil, nil
53
+ Open3.popen2e(environment, *cmd) do |pipe_in, pipe_out, promise|
54
+ pipe_in.write(input)
55
+ pipe_in.close()
56
+ output = pipe_out.read()
57
+ pipe_out.close()
58
+ status = promise.value
59
+ end
60
+ seconds = Time.now - start_time
61
+ logger.debug("Finished " + command_to_string([cmd.first]) + " in #{seconds}: #{status}")
35
62
 
36
63
  if ! status.success?
37
- raise CommandFailureError.new(status, command, out)
64
+ raise CommandFailureError.new(status, cmd, output)
38
65
  end
39
66
 
40
- out
67
+ output
41
68
  end
42
69
 
43
- def clean_git(*command)
70
+ def clean_git(*cmd)
44
71
  # Disable general configuration files
45
72
  environment = {
46
73
  "HOME" => "",
@@ -48,6 +75,10 @@ module Armature::Run
48
75
  "GIT_CONFIG_NOSYSTEM" => "1",
49
76
  }
50
77
 
51
- command(environment, "git", *command)
78
+ command(environment, "git", *cmd)
79
+ end
80
+
81
+ def logger
82
+ Logging.logger[self]
52
83
  end
53
84
  end
data/lib/armature/util.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'json'
1
+ require "json"
2
+ require "net/http"
3
+ require "uri"
2
4
 
3
5
  module Armature::Util
4
6
  extend self
@@ -46,7 +48,6 @@ module Armature::Util
46
48
  # operations to block.
47
49
  File.open(path, File::RDWR|File::CREAT, 0600) do |lock|
48
50
  if not lock.flock(mode | File::LOCK_NB)
49
- logger = Logging.logger[self]
50
51
  logger.info("Waiting for lock on #{path}")
51
52
 
52
53
  start_time = Time.now
@@ -71,4 +72,52 @@ module Armature::Util
71
72
  yield lock
72
73
  end
73
74
  end
75
+
76
+ def http_get_json(url, request_headers={})
77
+ accept = { "Accept" => "application/json" }
78
+ body = http_get(url, request_headers.merge(accept))
79
+ JSON.parse(body)
80
+ end
81
+
82
+ def http_get_request(url, request_headers={})
83
+ uri = URI.parse(url)
84
+ http = Net::HTTP.new(uri.host, uri.port)
85
+ http.use_ssl = (uri.scheme == "https")
86
+
87
+ request = Net::HTTP::Get.new(uri)
88
+ request["User-Agent"] = "armature #{Armature::VERSION} #{Armature::HOMEPAGE}"
89
+ request_headers.each do |key, value|
90
+ request[key] = value
91
+ end
92
+
93
+ http.request(request)
94
+ end
95
+
96
+ def http_get(url, request_headers={})
97
+ start_time = Time.now
98
+
99
+ current_url = url
100
+ body = nil
101
+
102
+ while body == nil do
103
+ response = http_get_request(current_url, request_headers)
104
+ if response.kind_of? Net::HTTPRedirection
105
+ logger.debug("HTTP redirection: #{current_url} to #{response["Location"].inspect}")
106
+ current_url = response["Location"]
107
+ next
108
+ end
109
+
110
+ response.value() # Raise error if we don't get 2xx response
111
+ body = response.body()
112
+ end
113
+
114
+ seconds = Time.now - start_time
115
+ logger.debug("Downloaded #{body.length()} bytes from #{current_url} in #{seconds}")
116
+
117
+ body
118
+ end
119
+
120
+ def logger
121
+ Logging.logger[self]
122
+ end
74
123
  end
@@ -1,3 +1,4 @@
1
1
  module Armature
2
- VERSION = '0.3.0'
2
+ VERSION = "0.4.0"
3
+ HOMEPAGE = "https://github.com/danielparks/armature"
3
4
  end
@@ -5,7 +5,7 @@ spec = Gem::Specification.new do |s|
5
5
  s.version = Armature::VERSION
6
6
  s.author = 'Daniel Parks'
7
7
  s.email = 'dp-os-armature@oxidized.org'
8
- s.homepage = 'https://github.com/danielparks/armature'
8
+ s.homepage = Armature::HOMEPAGE
9
9
  s.license = 'BSD-2-Clause'
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.summary = 'Deploy Puppet environments and manage modules'
data/test/deploy_test.rb CHANGED
@@ -6,7 +6,7 @@ class DeployTest < Minitest::Test
6
6
 
7
7
  def test_deploy_just_master_branch
8
8
  with_context do
9
- repo = @cache.get_repo(repo_path("control"))
9
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
10
10
  branches = Set.new(repo.get_branches())
11
11
 
12
12
  assert_equal(Set.new(['master']), branches,
@@ -14,11 +14,13 @@ class DeployTest < Minitest::Test
14
14
  assert_equal([], @environments.names(),
15
15
  "Environments before test incorrect")
16
16
 
17
- @environments.checkout_ref(repo, "master")
17
+ @environments.check_out_ref(repo, "master")
18
18
 
19
19
  assert_equal(["master"], @environments.names(),
20
20
  "Environments after test incorrect")
21
- assert_equal([".", "..", "master"], Dir.entries(@environments.path),
21
+ assert_equal(
22
+ [".", "..", "master"].sort(),
23
+ Dir.entries(@environments.path).sort(),
22
24
  "Environments directory after test incorrect")
23
25
  end
24
26
  end
@@ -26,13 +28,13 @@ class DeployTest < Minitest::Test
26
28
  ### FIXME: should this generate an error?
27
29
  def test_deploy_nonexistant_branch
28
30
  with_context do
29
- repo = @cache.get_repo(repo_path("control"))
31
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
30
32
  branches = Set.new(repo.get_branches())
31
33
 
32
34
  assert_equal(Set.new(['master']), branches,
33
35
  "Branches before test incorrect")
34
36
 
35
- @environments.checkout_ref(repo, "foo")
37
+ @environments.check_out_ref(repo, "foo")
36
38
 
37
39
  assert_equal([], @environments.names(),
38
40
  "Environments after test incorrect")
@@ -41,11 +43,11 @@ class DeployTest < Minitest::Test
41
43
 
42
44
  def test_deploy_all_branches
43
45
  with_context do
44
- repo = @cache.get_repo(repo_path("control"))
46
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
45
47
  branches = Set.new(repo.get_branches())
46
48
 
47
- Dir.mkdir(@context_path + "/foo")
48
- File.symlink(@context_path + "/foo", @environments.path + "/foo")
49
+ Dir.mkdir("foo")
50
+ File.symlink("foo", @environments.path + "/foo")
49
51
 
50
52
  assert_equal(["foo"], @environments.names(),
51
53
  "Environments before test incorrect")
@@ -55,7 +57,7 @@ class DeployTest < Minitest::Test
55
57
  end
56
58
 
57
59
  branches.each do |branch|
58
- @environments.checkout_ref(repo, branch)
60
+ @environments.check_out_ref(repo, branch)
59
61
  end
60
62
 
61
63
  assert_equal(["master"], @environments.names(),
@@ -65,20 +67,20 @@ class DeployTest < Minitest::Test
65
67
 
66
68
  def test_deploy_one_module
67
69
  with_context do
68
- repo = @cache.get_repo(repo_path("control"))
69
- @environments.checkout_ref(repo, "master")
70
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
71
+ @environments.check_out_ref(repo, "master")
70
72
 
71
73
  assert_equal(
72
- [".", "..", "module1"],
73
- Dir.entries(@environments.path + "/master/modules"),
74
+ [".", "..", "module1"].sort(),
75
+ Dir.entries(@environments.path + "/master/modules").sort(),
74
76
  "Modules installed after test incorrect")
75
77
  end
76
78
  end
77
79
 
78
80
  def test_adding_module_and_redeploying
79
81
  with_context do
80
- repo = @cache.get_repo(repo_path("control"))
81
- @environments.checkout_ref(repo, "master")
82
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
83
+ @environments.check_out_ref(repo, "master")
82
84
 
83
85
  repo_init("module-2")
84
86
  repo_commit("control", "Add module-2") do
@@ -91,10 +93,10 @@ class DeployTest < Minitest::Test
91
93
  end
92
94
 
93
95
  @cache.flush_memory!
94
- @environments.checkout_ref(repo, "master")
96
+ @environments.check_out_ref(repo, "master")
95
97
  assert_equal(
96
- [".", "..", "module1", "module2"],
97
- Dir.entries(@environments.path + "/master/modules"),
98
+ [".", "..", "module1", "module2"].sort(),
99
+ Dir.entries(@environments.path + "/master/modules").sort(),
98
100
  "Modules installed after test incorrect")
99
101
  assert_environment_file_contains(
100
102
  "master/modules/module1/README.md",
@@ -107,8 +109,8 @@ class DeployTest < Minitest::Test
107
109
 
108
110
  def test_removing_module_and_redeploying
109
111
  with_context do
110
- repo = @cache.get_repo(repo_path("control"))
111
- @environments.checkout_ref(repo, "master")
112
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
113
+ @environments.check_out_ref(repo, "master")
112
114
 
113
115
  repo_commit("control", "Remove module-1") do
114
116
  File.write("Puppetfile", <<-PUPPETFILE)
@@ -117,17 +119,16 @@ class DeployTest < Minitest::Test
117
119
  end
118
120
 
119
121
  @cache.flush_memory!
120
- @environments.checkout_ref(repo, "master")
122
+ @environments.check_out_ref(repo, "master")
121
123
  assert_equal(
122
- [".", ".."],
123
- Dir.entries(@environments.path + "/master/modules"),
124
+ [".", ".."].sort(),
125
+ Dir.entries(@environments.path + "/master/modules").sort(),
124
126
  "Modules installed after test incorrect")
125
127
  end
126
128
  end
127
129
 
128
130
  def test_module_with_bad_ref
129
131
  with_context do
130
- repo = @cache.get_repo(repo_path("control"))
131
132
  repo_commit("control", "Set module-1 to bad ref") do
132
133
  File.write("Puppetfile", <<-PUPPETFILE)
133
134
  forge "https://forge.puppet.com"
@@ -136,23 +137,24 @@ class DeployTest < Minitest::Test
136
137
  PUPPETFILE
137
138
  end
138
139
 
140
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
139
141
  assert_raises(Armature::RefError) do
140
- @environments.checkout_ref(repo, "master")
142
+ @environments.check_out_ref(repo, "master")
141
143
  end
142
144
 
143
145
  ### FIXME state of repo after an error is undefined, but this behavior
144
146
  ### seems reasonable.
145
147
  assert_equal(
146
- [".", ".."],
147
- Dir.entries(@environments.path),
148
+ [".", ".."].sort(),
149
+ Dir.entries(@environments.path).sort(),
148
150
  "Modules installed after test incorrect")
149
151
  end
150
152
  end
151
153
 
152
154
  def test_redeploying_module_with_bad_ref
153
155
  with_context do
154
- repo = @cache.get_repo(repo_path("control"))
155
- @environments.checkout_ref(repo, "master")
156
+ repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
157
+ @environments.check_out_ref(repo, "master")
156
158
 
157
159
  repo_commit("control", "Set module-1 to bad ref") do
158
160
  File.write("Puppetfile", <<-PUPPETFILE)
@@ -164,15 +166,15 @@ class DeployTest < Minitest::Test
164
166
 
165
167
  @cache.flush_memory!
166
168
  assert_raises(Armature::RefError) do
167
- @environments.checkout_ref(repo, "master")
169
+ @environments.check_out_ref(repo, "master")
168
170
  end
169
171
 
170
172
  ### FIXME state of repo after an error is undefined
171
173
  ### What happens if other modules already exist?
172
174
  skip("state of repo after an error is undefined")
173
175
  assert_equal(
174
- [".", "..", "module1"],
175
- Dir.entries(@environments.path + "/master/modules"),
176
+ [".", "..", "module1"].sort(),
177
+ Dir.entries(@environments.path + "/master/modules").sort(),
176
178
  "Modules installed after test incorrect")
177
179
  end
178
180
  end
@@ -247,9 +249,8 @@ class DeployTest < Minitest::Test
247
249
  add_module_class("interesting", "two_b")
248
250
 
249
251
  @cache.flush_memory!
250
- @environments.checkout_ref(@cache.get_repo(repo_path("control")), "master")
252
+ @environments.check_out_ref(Armature::Repo::Git::from_url(@cache, repo_path("control")), "master")
251
253
 
252
- skip("checkout_ref doesn't update branches at the moment")
253
254
  assert_module_manifests("interesting",
254
255
  ["one.pp", "two.pp", "two_a.pp", "two_b.pp"],
255
256
  "Incorrect module version after redeploy")
@@ -265,7 +266,7 @@ class DeployTest < Minitest::Test
265
266
  add_module_class("interesting", "two_b")
266
267
 
267
268
  @cache.flush_memory!
268
- @cache.update_branches()
269
+ @cache.update_mutable_refs()
269
270
 
270
271
  assert_module_manifests("interesting",
271
272
  ["one.pp", "two.pp", "two_a.pp", "two_b.pp"],
@@ -278,13 +279,12 @@ private
278
279
 
279
280
  # The "interesting" repo must be created first so it can be queried for shas
280
281
  def redeploy_module_with_ref_of_type(ref_type, ref)
281
- repo = @cache.get_repo(repo_path("control"))
282
-
283
282
  repo_puppetfile_update("control", <<-MODULES)
284
283
  mod "interesting", :git=>"#{repo_path('interesting')}"
285
284
  MODULES
286
285
 
287
- @environments.checkout_ref(repo, "master")
286
+ control_repo = Armature::Repo::Git::from_url(@cache, repo_path("control"))
287
+ @environments.check_out_ref(control_repo, "master")
288
288
 
289
289
  assert_module_manifests("interesting", ["one.pp", "two.pp", "three.pp"],
290
290
  "Incorrect module version after initial deploy")
@@ -299,7 +299,7 @@ private
299
299
  end
300
300
 
301
301
  @cache.flush_memory!
302
- @environments.checkout_ref(repo, "master")
302
+ @environments.check_out_ref(control_repo, "master")
303
303
 
304
304
  yield
305
305
  end
data/test/helpers.rb CHANGED
@@ -3,8 +3,17 @@ require 'fileutils'
3
3
  require 'tmpdir'
4
4
 
5
5
  module ArmatureTestHelpers
6
+ def with_temp_dir(name="test")
7
+ work_path = Dir.mktmpdir("armature.#{name}.")
8
+ Dir.chdir(work_path) do
9
+ yield
10
+ end
11
+ ensure
12
+ FileUtils.rm_rf(work_path)
13
+ end
14
+
6
15
  def repo_path(name)
7
- @context_path + "/repos/" + name
16
+ "repos/" + name
8
17
  end
9
18
 
10
19
  def repo_init(name)
@@ -71,40 +80,32 @@ module ArmatureTestHelpers
71
80
  add_module_class(module_name, "three")
72
81
  end
73
82
 
74
- def set_up_context
75
- @context_path = Dir.mktmpdir("armature.test_context.")
76
- @cache = Armature::Cache.new(@context_path + "/cache")
83
+ def with_context
84
+ with_temp_dir("context") do
85
+ @cache = Armature::Cache.new("cache")
77
86
 
78
- Dir.mkdir(@context_path + "/environments")
79
- @environments = Armature::Environments.new(@context_path + "/environments", @cache)
87
+ Dir.mkdir("environments")
88
+ @environments = Armature::Environments.new("environments", @cache)
80
89
 
81
- repo_init("module-1")
90
+ repo_init("module-1")
82
91
 
83
- repo_init("control") do
84
- File.write("Puppetfile", <<-PUPPETFILE)
85
- forge "https://forge.puppet.com"
92
+ repo_init("control") do
93
+ File.write("Puppetfile", <<-PUPPETFILE)
94
+ forge "https://forge.puppet.com"
86
95
 
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)
96
+ mod "module1", :git=>"#{repo_path('module-1')}"
97
+ PUPPETFILE
98
+ end
94
99
 
100
+ yield
101
+ end
102
+ ensure
95
103
  # Ensure that code trying to use these after this point fails in a
96
104
  # predictable way.
97
- @context_path = nil
98
105
  @cache = nil
99
106
  @environments = nil
100
107
  end
101
108
 
102
- def with_context
103
- set_up_context
104
- yield
105
- tear_down_context
106
- end
107
-
108
109
  def environment_file_contains?(path, search)
109
110
  File.foreach(@environments.path + "/" + path).any? do
110
111
  |line| line.include? search
@@ -122,9 +123,10 @@ module ArmatureTestHelpers
122
123
  def assert_module_manifests(module_name, manifest_names=["init.pp"],
123
124
  message="Incorrect manifests in module '#{module_name}'",
124
125
  environment="master")
126
+ module_path = "#{@environments.path}/#{environment}/modules/#{module_name}"
125
127
  assert_equal(
126
128
  ([".", "..", ".keep"] + manifest_names).sort(),
127
- Dir.entries(@environments.path + "/#{environment}/modules/#{module_name}/manifests"),
129
+ Dir.entries("#{module_path}/manifests").sort(),
128
130
  message)
129
131
  end
130
132
  end