producer-core 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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