producer-core 0.1.2 → 0.1.3

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.
@@ -0,0 +1,3 @@
1
+ Given(/^a remote file named "(.*?)"$/) do |file_name|
2
+ write_file file_name, ''
3
+ end
@@ -76,6 +76,7 @@ Protocol 2
76
76
  HostKey #{File.expand_path @base_path}/#{KEY_PATH}
77
77
  PidFile /dev/null
78
78
  UsePrivilegeSeparation no
79
+ Subsystem sftp /usr/lib/openssh/sftp-server
79
80
  ForceCommand HOME=#{File.expand_path @base_path} sh -c "cd ~; $SSH_ORIGINAL_COMMAND"
80
81
  eoh
81
82
 
@@ -0,0 +1,23 @@
1
+ @sshd
2
+ Feature: `has_file' condition keyword
3
+
4
+ Background:
5
+ Given a recipe with:
6
+ """
7
+ target 'some_host.test'
8
+
9
+ task :testing_file_existence do
10
+ condition { has_file 'some_file' }
11
+
12
+ echo 'evaluated'
13
+ end
14
+ """
15
+
16
+ Scenario: succeeds when file exists
17
+ Given a remote file named "some_file"
18
+ When I successfully execute the recipe
19
+ Then the output must contain "evaluated"
20
+
21
+ Scenario: fails when file does not exist
22
+ When I successfully execute the recipe
23
+ Then the output must not contain "evaluated"
data/lib/producer/core.rb CHANGED
@@ -6,6 +6,7 @@ require 'producer/core/actions/shell_command'
6
6
  # condition tests (need to be defined before the condition DSL)
7
7
  require 'producer/core/test'
8
8
  require 'producer/core/tests/has_env'
9
+ require 'producer/core/tests/has_file'
9
10
 
10
11
  require 'producer/core/cli'
11
12
  require 'producer/core/condition'
@@ -17,6 +18,7 @@ require 'producer/core/recipe'
17
18
  require 'producer/core/recipe/dsl'
18
19
  require 'producer/core/remote'
19
20
  require 'producer/core/remote/environment'
21
+ require 'producer/core/remote/fs'
20
22
  require 'producer/core/task'
21
23
  require 'producer/core/task/dsl'
22
24
  require 'producer/core/version'
@@ -16,7 +16,8 @@ module Producer
16
16
  end
17
17
  end
18
18
 
19
- define_test :has_env, Tests::HasEnv
19
+ define_test :has_env, Tests::HasEnv
20
+ define_test :has_file, Tests::HasFile
20
21
 
21
22
  attr_accessor :tests
22
23
 
@@ -14,6 +14,10 @@ module Producer
14
14
  @session ||= Net::SSH.start(@hostname, Etc.getlogin)
15
15
  end
16
16
 
17
+ def fs
18
+ @fs ||= Remote::FS.new(self)
19
+ end
20
+
17
21
  def execute(command)
18
22
  output = ''
19
23
  session.open_channel do |channel|
@@ -0,0 +1,23 @@
1
+ module Producer
2
+ module Core
3
+ class Remote
4
+ class FS
5
+ require 'net/sftp'
6
+
7
+ def initialize(remote)
8
+ @remote = remote
9
+ end
10
+
11
+ def sftp
12
+ @sftp ||= @remote.session.sftp.connect
13
+ end
14
+
15
+ def has_file?(path)
16
+ sftp.stat!(path).file?
17
+ rescue Net::SFTP::StatusException
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module Producer
2
+ module Core
3
+ module Tests
4
+ class HasFile < Test
5
+ def success?
6
+ env.remote.fs.has_file? arguments.first
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module Producer
2
2
  module Core
3
- VERSION = '0.1.2'
3
+ VERSION = '0.1.3'
4
4
  end
5
5
  end
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
 
21
21
 
22
22
  s.add_dependency 'net-ssh'
23
+ s.add_dependency 'net-sftp'
23
24
 
24
25
  s.add_development_dependency 'rspec'
25
26
  s.add_development_dependency 'cucumber'
@@ -6,7 +6,7 @@ module Producer::Core
6
6
  let(:env) { double('env') }
7
7
  subject(:dsl) { Condition::DSL.new(env, &block) }
8
8
 
9
- %w[has_env].each do |test|
9
+ %w[has_env has_file].each do |test|
10
10
  it "has `#{test}' test defined" do
11
11
  expect(dsl).to respond_to test.to_sym
12
12
  end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Remote::FS do
5
+ let(:remote) { Remote.new('some_host.example') }
6
+ subject(:fs) { Remote::FS.new(remote) }
7
+
8
+ describe '#new' do
9
+ it 'assigns the remote given as argument' do
10
+ expect(fs.instance_eval { @remote }).to be remote
11
+ end
12
+ end
13
+
14
+ describe '#sftp', :ssh do
15
+ before { sftp_story }
16
+
17
+ it 'builds a new SFTP session' do
18
+ expect(remote.session.sftp).to receive(:connect)
19
+ fs.sftp
20
+ end
21
+
22
+ it 'returns the new SFTP session' do
23
+ session = double('session')
24
+ allow(remote.session.sftp).to receive(:connect) { session }
25
+ expect(fs.sftp).to be session
26
+ end
27
+
28
+ it 'memoizes the FS' do
29
+ allow(remote.session.sftp).to receive(:connect) { Object.new }
30
+ expect(fs.sftp).to be fs.sftp
31
+ end
32
+ end
33
+
34
+ # FIXME: We rely a lot on mocking net-sftp heavily, while we already use a
35
+ # part of net-ssh story helpers, which are more close to integration tests.
36
+ describe '#has_file?', :ssh do
37
+ let(:file_path) { "some_file_path" }
38
+ let(:stat) { double('stat') }
39
+
40
+ before do
41
+ sftp_story
42
+ allow(fs.sftp).to receive(:stat!) { stat }
43
+ end
44
+
45
+ context 'when path given as argument exists' do
46
+ context 'when path is a file' do
47
+ before do
48
+ allow(stat).to receive(:file?) { true }
49
+ end
50
+
51
+ it 'returns true' do
52
+ expect(fs.has_file?(file_path)).to be true
53
+ end
54
+ end
55
+
56
+ context 'when path is not a file' do
57
+ before do
58
+ allow(stat).to receive(:file?) { false }
59
+ end
60
+
61
+ it 'returns false' do
62
+ expect(fs.has_file?(file_path)).to be false
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'when querying the path raises a Net::SFTP::StatusException' do
68
+ before do
69
+ response = double('response', code: '42', message: '…')
70
+ ex = Net::SFTP::StatusException.new(response)
71
+ allow(stat).to receive(:file?).and_raise(ex)
72
+ end
73
+
74
+ it 'returns false' do
75
+ expect(fs.has_file?(file_path)).to be false
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -29,6 +29,24 @@ module Producer::Core
29
29
  end
30
30
  end
31
31
 
32
+ describe '#fs' do
33
+ it 'builds a new FS' do
34
+ expect(Remote::FS).to receive(:new)
35
+ remote.fs
36
+ end
37
+
38
+ it 'returns the new FS instance' do
39
+ fs = double('fs')
40
+ allow(Remote::FS).to receive(:new) { fs }
41
+ expect(remote.fs).to be fs
42
+ end
43
+
44
+ it 'memoizes the FS' do
45
+ allow(Remote::FS).to receive(:new) { Object.new }
46
+ expect(remote.fs).to be remote.fs
47
+ end
48
+ end
49
+
32
50
  describe '#execute', :ssh do
33
51
  let(:arguments) { 'some remote command' }
34
52
  let(:command) { "echo #{arguments}" }
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Tests::HasFile do
5
+ let(:env) { Env.new }
6
+ let(:filepath) { 'some_file' }
7
+ subject(:has_file) { Tests::HasFile.new(env, filepath) }
8
+
9
+ it 'is a kind of test' do
10
+ expect(has_file).to be_a Test
11
+ end
12
+
13
+ describe '#success?', :ssh do
14
+ before { sftp_story }
15
+
16
+ it 'delegates the call on remote FS' do
17
+ expect(env.remote.fs).to receive(:has_file?).with(filepath)
18
+ has_file.success?
19
+ end
20
+
21
+ it 'returns the file existence' do
22
+ existence = double('existence')
23
+ allow(env.remote.fs).to receive(:has_file?) { existence }
24
+ expect(has_file.success?).to be existence
25
+ end
26
+ end
27
+ end
28
+ end
@@ -2,6 +2,24 @@ module NetSSHStoryHelpers
2
2
  require 'net/ssh/test'
3
3
  include Net::SSH::Test
4
4
 
5
+ # FIXME: must be moved elsewhere or implemented another way/form.
6
+ class ::Net::SSH::Test::Channel
7
+ def gets_packet(type, *args)
8
+ gets_data(sftp_packet(type, *args))
9
+ end
10
+
11
+ def sends_packet(type, *args)
12
+ sends_data(sftp_packet(type, *args))
13
+ end
14
+
15
+ private
16
+
17
+ def sftp_packet(type, *args)
18
+ data = Net::SSH::Buffer.from(*args)
19
+ Net::SSH::Buffer.from(:long, data.length + 1, :byte, type, :raw, data).to_s
20
+ end
21
+ end
22
+
5
23
  def story_with_new_channel
6
24
  story do |session|
7
25
  ch = session.opens_channel
@@ -14,4 +32,20 @@ module NetSSHStoryHelpers
14
32
  def story_completed?
15
33
  socket.script.events.empty?
16
34
  end
35
+
36
+ def sftp_story
37
+ story do |session|
38
+ ch = session.opens_channel
39
+ ch.sends_subsystem('sftp')
40
+ ch.sends_packet(
41
+ Net::SFTP::Constants::PacketTypes::FXP_INIT, :long,
42
+ Net::SFTP::Session::HIGHEST_PROTOCOL_VERSION_SUPPORTED
43
+ )
44
+ ch.gets_packet(
45
+ Net::SFTP::Constants::PacketTypes::FXP_VERSION, :long,
46
+ Net::SFTP::Session::HIGHEST_PROTOCOL_VERSION_SUPPORTED
47
+ )
48
+ yield ch if block_given?
49
+ end
50
+ end
17
51
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: producer-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: net-sftp
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: rspec
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -114,12 +130,14 @@ files:
114
130
  - features/recipes/source.feature
115
131
  - features/recipes/target.feature
116
132
  - features/steps/recipe_steps.rb
133
+ - features/steps/remote_steps.rb
117
134
  - features/support/env_aruba.rb
118
135
  - features/support/env_cucumber-doc_string.rb
119
136
  - features/support/ssh.rb
120
137
  - features/tasks/condition.feature
121
138
  - features/tasks/evaluation.feature
122
139
  - features/tests/has_env.feature
140
+ - features/tests/has_file.feature
123
141
  - lib/producer/core.rb
124
142
  - lib/producer/core/action.rb
125
143
  - lib/producer/core/actions/echo.rb
@@ -134,10 +152,12 @@ files:
134
152
  - lib/producer/core/recipe/dsl.rb
135
153
  - lib/producer/core/remote.rb
136
154
  - lib/producer/core/remote/environment.rb
155
+ - lib/producer/core/remote/fs.rb
137
156
  - lib/producer/core/task.rb
138
157
  - lib/producer/core/task/dsl.rb
139
158
  - lib/producer/core/test.rb
140
159
  - lib/producer/core/tests/has_env.rb
160
+ - lib/producer/core/tests/has_file.rb
141
161
  - lib/producer/core/version.rb
142
162
  - producer-core.gemspec
143
163
  - spec/fixtures/recipes/empty.rb
@@ -153,11 +173,13 @@ files:
153
173
  - spec/producer/core/recipe/dsl_spec.rb
154
174
  - spec/producer/core/recipe_spec.rb
155
175
  - spec/producer/core/remote/environment_spec.rb
176
+ - spec/producer/core/remote/fs_spec.rb
156
177
  - spec/producer/core/remote_spec.rb
157
178
  - spec/producer/core/task/dsl_spec.rb
158
179
  - spec/producer/core/task_spec.rb
159
180
  - spec/producer/core/test_spec.rb
160
181
  - spec/producer/core/tests/has_env_spec.rb
182
+ - spec/producer/core/tests/has_file_spec.rb
161
183
  - spec/spec_helper.rb
162
184
  - spec/support/exit_helpers.rb
163
185
  - spec/support/fixtures_helpers.rb
@@ -186,7 +208,7 @@ rubyforge_project:
186
208
  rubygems_version: 1.8.23
187
209
  signing_key:
188
210
  specification_version: 3
189
- summary: producer-core-0.1.2
211
+ summary: producer-core-0.1.3
190
212
  test_files:
191
213
  - features/actions/echo.feature
192
214
  - features/actions/sh.feature
@@ -196,12 +218,14 @@ test_files:
196
218
  - features/recipes/source.feature
197
219
  - features/recipes/target.feature
198
220
  - features/steps/recipe_steps.rb
221
+ - features/steps/remote_steps.rb
199
222
  - features/support/env_aruba.rb
200
223
  - features/support/env_cucumber-doc_string.rb
201
224
  - features/support/ssh.rb
202
225
  - features/tasks/condition.feature
203
226
  - features/tasks/evaluation.feature
204
227
  - features/tests/has_env.feature
228
+ - features/tests/has_file.feature
205
229
  - spec/fixtures/recipes/empty.rb
206
230
  - spec/fixtures/recipes/throw.rb
207
231
  - spec/producer/core/action_spec.rb
@@ -215,11 +239,13 @@ test_files:
215
239
  - spec/producer/core/recipe/dsl_spec.rb
216
240
  - spec/producer/core/recipe_spec.rb
217
241
  - spec/producer/core/remote/environment_spec.rb
242
+ - spec/producer/core/remote/fs_spec.rb
218
243
  - spec/producer/core/remote_spec.rb
219
244
  - spec/producer/core/task/dsl_spec.rb
220
245
  - spec/producer/core/task_spec.rb
221
246
  - spec/producer/core/test_spec.rb
222
247
  - spec/producer/core/tests/has_env_spec.rb
248
+ - spec/producer/core/tests/has_file_spec.rb
223
249
  - spec/spec_helper.rb
224
250
  - spec/support/exit_helpers.rb
225
251
  - spec/support/fixtures_helpers.rb