producer-core 0.5.8 → 0.5.9

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/lib/producer/core/version.rb +1 -1
  3. metadata +21 -202
  4. data/.gitignore +0 -3
  5. data/.travis.yml +0 -14
  6. data/Gemfile +0 -5
  7. data/Guardfile +0 -14
  8. data/LICENSE +0 -30
  9. data/Rakefile +0 -19
  10. data/config/cucumber.yaml +0 -2
  11. data/features/actions/echo.feature +0 -11
  12. data/features/actions/file_append.feature +0 -15
  13. data/features/actions/file_replace_content.feature +0 -24
  14. data/features/actions/file_write.feature +0 -21
  15. data/features/actions/mkdir.feature +0 -31
  16. data/features/actions/sh.feature +0 -43
  17. data/features/actions/yaml_write.feature +0 -14
  18. data/features/cli/debug.feature +0 -19
  19. data/features/cli/dry_run.feature +0 -22
  20. data/features/cli/error_reporting.feature +0 -32
  21. data/features/cli/target.feature +0 -15
  22. data/features/cli/usage.feature +0 -13
  23. data/features/cli/verbose.feature +0 -48
  24. data/features/condition/negated_test.feature +0 -47
  25. data/features/condition/target.feature +0 -15
  26. data/features/recipe/compose_macro.feature +0 -29
  27. data/features/recipe/errors.feature +0 -9
  28. data/features/recipe/macro.feature +0 -50
  29. data/features/recipe/registry.feature +0 -82
  30. data/features/recipe/source.feature +0 -17
  31. data/features/recipe/target.feature +0 -23
  32. data/features/recipe/test_macro.feature +0 -50
  33. data/features/ssh/config.feature +0 -25
  34. data/features/steps/environment_steps.rb +0 -3
  35. data/features/support/env.rb +0 -1
  36. data/features/task/ask.feature +0 -23
  37. data/features/task/condition.feature +0 -13
  38. data/features/task/nested_tasks.feature +0 -20
  39. data/features/task/recipe_argv.feature +0 -13
  40. data/features/task/target.feature +0 -11
  41. data/features/task/template.feature +0 -49
  42. data/features/tests/dir.feature +0 -21
  43. data/features/tests/env.feature +0 -47
  44. data/features/tests/executable.feature +0 -26
  45. data/features/tests/file.feature +0 -21
  46. data/features/tests/file_contains.feature +0 -26
  47. data/features/tests/file_eq.feature +0 -26
  48. data/features/tests/file_match.feature +0 -26
  49. data/features/tests/shell_command_status.feature +0 -46
  50. data/features/tests/yaml_eq.feature +0 -26
  51. data/producer-core.gemspec +0 -28
  52. data/spec/fixtures/recipes/empty.rb +0 -1
  53. data/spec/fixtures/recipes/raise.rb +0 -1
  54. data/spec/fixtures/recipes/some_recipe.rb +0 -5
  55. data/spec/fixtures/recipes/throw.rb +0 -1
  56. data/spec/fixtures/templates/basic.erb +0 -1
  57. data/spec/fixtures/templates/basic_yaml.yaml +0 -1
  58. data/spec/fixtures/templates/variables.erb +0 -1
  59. data/spec/producer/core/action_spec.rb +0 -46
  60. data/spec/producer/core/actions/echo_spec.rb +0 -20
  61. data/spec/producer/core/actions/file_append_spec.rb +0 -49
  62. data/spec/producer/core/actions/file_replace_content_spec.rb +0 -42
  63. data/spec/producer/core/actions/file_writer_spec.rb +0 -52
  64. data/spec/producer/core/actions/mkdir_spec.rb +0 -71
  65. data/spec/producer/core/actions/shell_command_spec.rb +0 -45
  66. data/spec/producer/core/actions/yaml_writer_spec.rb +0 -25
  67. data/spec/producer/core/cli_spec.rb +0 -211
  68. data/spec/producer/core/condition_spec.rb +0 -198
  69. data/spec/producer/core/env_spec.rb +0 -196
  70. data/spec/producer/core/error_formatter_spec.rb +0 -86
  71. data/spec/producer/core/logger_formatter_spec.rb +0 -26
  72. data/spec/producer/core/prompter_spec.rb +0 -40
  73. data/spec/producer/core/recipe/file_evaluator_spec.rb +0 -22
  74. data/spec/producer/core/recipe_spec.rb +0 -126
  75. data/spec/producer/core/remote/environment_spec.rb +0 -19
  76. data/spec/producer/core/remote/fs_spec.rb +0 -144
  77. data/spec/producer/core/remote_spec.rb +0 -168
  78. data/spec/producer/core/task_spec.rb +0 -198
  79. data/spec/producer/core/template_spec.rb +0 -41
  80. data/spec/producer/core/test_spec.rb +0 -7
  81. data/spec/producer/core/testing/mock_remote_spec.rb +0 -66
  82. data/spec/producer/core/tests/condition_test_spec.rb +0 -55
  83. data/spec/producer/core/tests/file_contains_spec.rb +0 -46
  84. data/spec/producer/core/tests/file_eq_spec.rb +0 -45
  85. data/spec/producer/core/tests/file_match_spec.rb +0 -46
  86. data/spec/producer/core/tests/has_dir_spec.rb +0 -25
  87. data/spec/producer/core/tests/has_env_spec.rb +0 -75
  88. data/spec/producer/core/tests/has_executable_spec.rb +0 -29
  89. data/spec/producer/core/tests/has_file_spec.rb +0 -25
  90. data/spec/producer/core/tests/shell_command_status_spec.rb +0 -34
  91. data/spec/producer/core/tests/yaml_eq_spec.rb +0 -47
  92. data/spec/producer/core/worker_spec.rb +0 -88
  93. data/spec/spec_helper.rb +0 -13
  94. data/spec/support/exit_helpers.rb +0 -6
  95. data/spec/support/fixtures_helpers.rb +0 -7
  96. data/spec/support/net_ssh_story_helpers.rb +0 -36
  97. data/spec/support/shared_action.rb +0 -44
  98. data/spec/support/shared_test.rb +0 -82
  99. data/spec/support/test_env_helpers.rb +0 -44
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- describe Prompter do
5
- let(:input) { StringIO.new }
6
- let(:output) { StringIO.new }
7
- subject(:prompter) { described_class.new(input, output) }
8
-
9
- describe '#initialize' do
10
- it 'assigns the given input' do
11
- expect(prompter.input).to be input
12
- end
13
-
14
- it 'assigns the given output' do
15
- expect(prompter.output).to be output
16
- end
17
- end
18
-
19
- describe '#prompt' do
20
- let(:question) { 'Which letter?' }
21
- let(:choices) { [[:a, ?A], [:b, ?B]] }
22
-
23
- it 'prompts choices' do
24
- prompter.prompt question, choices
25
- expect(output.string).to eq <<-eoh.gsub /^\s+\|/, ''
26
- |#{question}
27
- |0: A
28
- |1: B
29
- |Choice:
30
- eoh
31
- end
32
-
33
- it 'returns value for entry chosen by user' do
34
- input.puts '1'
35
- input.rewind
36
- expect(prompter.prompt question, choices).to eq :b
37
- end
38
- end
39
- end
40
- end
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- class Recipe
5
- describe FileEvaluator do
6
- include FixturesHelpers
7
-
8
- describe '.evaluate' do
9
- let(:env) { Env.new }
10
- let(:file_path) { fixture_path_for 'recipes/some_recipe.rb' }
11
- subject(:recipe) { described_class.evaluate(file_path, env) }
12
-
13
- it 'returns an evaluated recipe' do
14
- expect(recipe.tasks).to match [
15
- an_object_having_attributes(name: :some_task),
16
- an_object_having_attributes(name: :another_task)
17
- ]
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,126 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- describe Recipe do
5
- include FixturesHelpers
6
-
7
- let(:env) { Env.new }
8
- subject(:recipe) { described_class.new(env) }
9
-
10
- describe '#initialize' do
11
- it 'assigns no task' do
12
- expect(recipe.tasks).to be_empty
13
- end
14
- end
15
-
16
- describe '#source' do
17
- let(:filepath) { fixture_path_for 'recipes/throw' }
18
-
19
- it 'sources the recipe given as argument' do
20
- expect { recipe.source filepath }.to throw_symbol :recipe_code
21
- end
22
- end
23
-
24
- describe '#target' do
25
- let(:host) { 'some_host.example' }
26
-
27
- context 'when env has no assigned target' do
28
- it 'registers the target host in the env' do
29
- recipe.target host
30
- expect(env.target).to eq host
31
- end
32
- end
33
-
34
- context 'when env has an assigned target' do
35
- before { env.target = 'already_assigned_host.example' }
36
-
37
- it 'does not change env target' do
38
- expect { recipe.target host }.not_to change { env.target }
39
- end
40
- end
41
-
42
- context 'when no arguments are provided' do
43
- it 'returns current target' do
44
- recipe.target host
45
- expect(recipe.target).to eq host
46
- end
47
- end
48
- end
49
-
50
- describe '#task' do
51
- it 'registers a new evaluated task' do
52
- expect { recipe.task(:some_task) { :some_task_code } }
53
- .to change { recipe.tasks.count }.by 1
54
- end
55
-
56
- it 'returns the task' do
57
- expect(recipe.task(:some_task) { }).to be_a Task
58
- end
59
- end
60
-
61
- describe '#macro' do
62
- it 'defines the new recipe keyword' do
63
- recipe.macro(:hello) { }
64
- expect(recipe).to respond_to(:hello)
65
- end
66
-
67
- it 'defines the new task keyword' do
68
- recipe.macro(:hello) { }
69
- expect { recipe.task(:some_task) { hello } }.not_to raise_error
70
- end
71
-
72
- context 'when a defined macro is called' do
73
- before { recipe.macro(:hello) { :some_macro_code } }
74
-
75
- it 'registers the new task' do
76
- expect { recipe.hello }.to change { recipe.tasks.count }.by 1
77
- end
78
- end
79
-
80
- context 'when a defined macro is called with arguments' do
81
- before { recipe.macro(:hello) { |a, b| echo a, b } }
82
-
83
- it 'evaluates task code with given arguments' do
84
- recipe.hello :foo, :bar
85
- expect(recipe.tasks.first.actions.first.arguments).to eq %i[foo bar]
86
- end
87
- end
88
- end
89
-
90
- describe '#compose_macro' do
91
- before do
92
- recipe.macro(:hello) { }
93
- recipe.compose_macro :hello_composed, :some_arg
94
- end
95
-
96
- it 'defines the new recipe keyword' do
97
- expect(recipe).to respond_to(:hello_composed)
98
- end
99
-
100
- it 'defines the new task keyword' do
101
- expect(recipe.task(:some_task) { }).to respond_to(:hello_composed)
102
- end
103
- end
104
-
105
- describe '#test_macro' do
106
- it 'defines the new test' do
107
- recipe.test_macro(:some_test) { }
108
- expect(Condition.new).to respond_to :some_test
109
- end
110
- end
111
-
112
- describe '#set' do
113
- it 'registers a key/value pair in env registry' do
114
- recipe.set :some_key, :some_value
115
- expect(env[:some_key]).to eq :some_value
116
- end
117
- end
118
-
119
- describe '#get' do
120
- it 'fetches a value from the registry at given index' do
121
- recipe.set :some_key, :some_value
122
- expect(recipe.get :some_key).to eq :some_value
123
- end
124
- end
125
- end
126
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- class Remote
5
- describe Environment do
6
- let(:string) { "FOO=bar\nBAZ=qux" }
7
- let(:argument) { variables }
8
-
9
- describe '.string_to_hash' do
10
- it 'converts key=value pairs separated by new lines to a hash' do
11
- expect(described_class.string_to_hash(string)).to eq ({
12
- 'FOO' => 'bar',
13
- 'BAZ' => 'qux'
14
- })
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,144 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- class Remote
5
- describe FS do
6
- let(:sftp_file) { double 'sftp_file' }
7
- let(:sftp) { double('sftp', file: sftp_file) }
8
- subject(:fs) { described_class.new(sftp) }
9
-
10
- describe '#initialize' do
11
- it 'assigns the sftp session' do
12
- expect(fs.sftp).to be sftp
13
- end
14
- end
15
-
16
- describe '#dir?' do
17
- let(:path) { 'some_directory_path' }
18
- let(:stat) { double 'stat' }
19
-
20
- before { allow(sftp).to receive(:stat!).with(path) { stat } }
21
-
22
- context 'when path given as argument is a directory' do
23
- before { allow(stat).to receive(:directory?) { true } }
24
-
25
- it 'returns true' do
26
- expect(fs.dir? path).to be true
27
- end
28
- end
29
-
30
- context 'when path given as argument is not a directory' do
31
- before { allow(stat).to receive(:directory?) { false } }
32
-
33
- it 'returns false' do
34
- expect(fs.dir? path).to be false
35
- end
36
- end
37
-
38
- context 'when querying the path raises a Net::SFTP::StatusException' do
39
- before do
40
- response = double 'response', code: '42', message: 'some message'
41
- ex = Net::SFTP::StatusException.new(response)
42
- allow(sftp).to receive(:stat!).with(path).and_raise(ex)
43
- end
44
-
45
- it 'returns false' do
46
- expect(fs.dir? path).to be false
47
- end
48
- end
49
- end
50
-
51
- describe '#file?' do
52
- let(:file_path) { 'some_file_path' }
53
- let(:stat) { double 'stat' }
54
-
55
- before { allow(sftp).to receive(:stat!) { stat } }
56
-
57
- context 'when path given as argument exists' do
58
- context 'when path is a file' do
59
- before { allow(stat).to receive(:file?) { true } }
60
-
61
- it 'returns true' do
62
- expect(fs.file? file_path).to be true
63
- end
64
- end
65
-
66
- context 'when path is not a file' do
67
- before { allow(stat).to receive(:file?) { false } }
68
-
69
- it 'returns false' do
70
- expect(fs.file? file_path).to be false
71
- end
72
- end
73
- end
74
-
75
- context 'when querying the path raises a Net::SFTP::StatusException' do
76
- before do
77
- response = double 'response', code: '42', message: 'some message'
78
- ex = Net::SFTP::StatusException.new(response)
79
- allow(stat).to receive(:file?).and_raise(ex)
80
- end
81
-
82
- it 'returns false' do
83
- expect(fs.file? file_path).to be false
84
- end
85
- end
86
- end
87
-
88
- describe '#mkdir' do
89
- let(:path) { 'some_directory_path' }
90
- let(:attributes) { { foo: :bar } }
91
-
92
- it 'creates the directory' do
93
- expect(sftp).to receive(:mkdir!).with(path, attributes)
94
- fs.mkdir path, attributes
95
- end
96
- end
97
-
98
- describe '#file_read' do
99
- let(:f) { double 'f' }
100
- let(:path) { 'some_file_path' }
101
- let(:content) { 'some_content' }
102
-
103
- before do
104
- allow(sftp_file).to receive(:open).and_yield(f)
105
- allow(f).to receive(:read) { content }
106
- end
107
-
108
- it 'returns the file content' do
109
- expect(fs.file_read(path)).to eq content
110
- end
111
-
112
- context 'when opening the file raises a Net::SFTP::StatusException' do
113
- before do
114
- response = double 'response', code: '42', message: 'some message'
115
- ex = Net::SFTP::StatusException.new(response)
116
- allow(sftp_file).to receive(:open).and_raise(ex)
117
- end
118
-
119
- it 'returns nil' do
120
- expect(fs.file_read(path)).to be nil
121
- end
122
- end
123
- end
124
-
125
- describe '#file_write' do
126
- let(:path) { 'some_file_path' }
127
- let(:content) { 'some_content' }
128
-
129
- it 'opens the file' do
130
- expect(sftp_file).to receive(:open).with(path, 'w')
131
- fs.file_write path, content
132
- end
133
-
134
- it 'writes the content' do
135
- expect(sftp_file).to receive(:open).with(any_args) do |&b|
136
- expect(sftp_file).to receive(:write).with(content)
137
- b.call sftp_file
138
- end
139
- fs.file_write path, content
140
- end
141
- end
142
- end
143
- end
144
- end
@@ -1,168 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Producer::Core
4
- describe Remote do
5
- let(:hostname) { 'some_host.example' }
6
- subject(:remote) { described_class.new(hostname) }
7
-
8
- describe '#initialize' do
9
- it 'assigns the given hostname' do
10
- expect(remote.hostname).to eq hostname
11
- end
12
- end
13
-
14
- describe '#session' do
15
- it 'builds a new SSH session to the remote host with #user_name' do
16
- expect(Net::SSH).to receive(:start).with(hostname, remote.user_name)
17
- remote.session
18
- end
19
-
20
- it 'returns the session' do
21
- session = double('SSH session')
22
- allow(Net::SSH).to receive(:start) { session }
23
- expect(remote.session).to eq session
24
- end
25
-
26
- it 'memoizes the session' do
27
- allow(Net::SSH).to receive(:start) { Object.new }
28
- expect(remote.session).to be remote.session
29
- end
30
-
31
- context 'when hostname is invalid' do
32
- let(:hostname) { nil }
33
-
34
- it 'raises RemoteInvalidError' do
35
- expect { remote.session }.to raise_error RemoteInvalidError
36
- end
37
- end
38
- end
39
-
40
- describe '#config' do
41
- it 'builds a config for current host name' do
42
- expect(Net::SSH::Config).to receive(:for).with(hostname)
43
- remote.config
44
- end
45
-
46
- it 'returns the config' do
47
- ssh_config = double('ssh config')
48
- allow(Net::SSH::Config).to receive(:for) { ssh_config }
49
- expect(remote.config).to be ssh_config
50
- end
51
-
52
- it 'memoizes the config' do
53
- allow(Net::SSH::Config).to receive(:for) { Object.new }
54
- expect(remote.config).to be remote.config
55
- end
56
- end
57
-
58
- describe '#user_name' do
59
- context 'ssh config has an entry for user' do
60
- let(:config_user_name) { 'my_user_name' }
61
-
62
- before do
63
- allow(Net::SSH::Config).to receive(:for) { { user: config_user_name } }
64
- end
65
-
66
- it 'returns the configured value' do
67
- expect(remote.user_name).to eq config_user_name
68
- end
69
- end
70
-
71
- context 'ssh config has no entry for user' do
72
- it 'returns the name of the user currently logged in' do
73
- expect(remote.user_name).to eq Etc.getlogin
74
- end
75
- end
76
- end
77
-
78
- describe '#fs' do
79
- let(:sftp_session) { double 'sftp session' }
80
-
81
- it 'returns an FS instance built with a new sftp session' do
82
- allow(remote)
83
- .to receive_message_chain(:session, :sftp, :connect) { sftp_session }
84
- expect(remote.fs.sftp).to be sftp_session
85
- end
86
- end
87
-
88
- describe '#execute', :ssh do
89
- let(:arguments) { 'some remote command' }
90
- let(:command) { "echo #{arguments}" }
91
- let(:output) { StringIO.new }
92
-
93
- it 'executes the given command in a new channel' do
94
- story_with_new_channel do |ch|
95
- ch.sends_exec command
96
- ch.gets_data arguments
97
- end
98
- expect_story_completed { remote.execute command }
99
- end
100
-
101
- it 'returns the command standard output output' do
102
- story_with_new_channel do |ch|
103
- ch.sends_exec command
104
- ch.gets_data arguments
105
- end
106
- expect(remote.execute command).to eq arguments
107
- end
108
-
109
- it 'writes command standard output to provided output' do
110
- story_with_new_channel do |ch|
111
- ch.sends_exec command
112
- ch.gets_data arguments
113
- end
114
- remote.execute command, output
115
- expect(output.string).to eq arguments
116
- end
117
-
118
- it 'writes command error output to provided error output' do
119
- error_output = StringIO.new
120
- story_with_new_channel do |ch|
121
- ch.sends_exec command
122
- ch.gets_extended_data arguments
123
- end
124
- remote.execute command, output, error_output
125
- expect(error_output.string).to eq arguments
126
- end
127
-
128
- context 'when command execution fails' do
129
- before do
130
- story_with_new_channel do |ch|
131
- ch.sends_exec command
132
- ch.gets_data arguments
133
- ch.gets_exit_status 1
134
- end
135
- end
136
-
137
- it 'raises an exception' do
138
- expect { remote.execute command }
139
- .to raise_error RemoteCommandExecutionError
140
- end
141
-
142
- it 'includes the command in the exception message' do
143
- expect { remote.execute command }.to raise_error /#{command}/
144
- end
145
- end
146
- end
147
-
148
- describe '#environment' do
149
- let(:command) { 'env' }
150
- let(:output) { 'FOO=bar' }
151
-
152
- before { allow(remote).to receive(:execute) { output } }
153
-
154
- it 'returns a remote environment' do
155
- expect(remote.environment['FOO']).to eq 'bar'
156
- end
157
- end
158
-
159
- describe '#cleanup' do
160
- before { remote.session = double 'session' }
161
-
162
- it 'closes the session' do
163
- expect(remote.session).to receive :close
164
- remote.cleanup
165
- end
166
- end
167
- end
168
- end