screwcap 0.1

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/screwcap.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'bundler/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "screwcap"
9
+ s.version = "0.1"
10
+ s.platform = Gem::Platform::RUBY
11
+ s.author = "Grant Ammons"
12
+ s.email = ["grant@pipelinedealsco.com"]
13
+ s.homepage = "http://github.com/gammons/screwcap"
14
+ s.summary = "Screwcap is a wrapper of Net::SSH and allows for easy configuration, organization, and management of running tasks on remote servers."
15
+
16
+ s.add_dependency(['net-ssh','>=2.0.23'])
17
+ s.add_dependency(['net-ssh-gateway','>=1.0.1'])
18
+ s.rubyforge_project = 'screwcap'
19
+
20
+ s.files = Dir.glob("{bin,lib}/**/*") + %w(README.rdoc screwcap.gemspec)
21
+ s.require_path = 'lib'
22
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Command sets" do
4
+ before(:all) do
5
+ @stdout = []
6
+ Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg}
7
+ @deployer = Deployer.new(:recipe_file => "./test/config/command_sets.rb", :silent => false)
8
+ end
9
+
10
+ it "should be able to define a generic list of commands" do
11
+ task = @deployer.__tasks.find {|t| t.__name == :really_simple_task }
12
+ task.should have(3).__commands
13
+ task.__commands.map{|c| c[:command]}.should == %w(1 2 3)
14
+ end
15
+
16
+ it "should be able to use deployment variables" do
17
+ task = @deployer.__tasks.find {|t| t.__name == :use_command_set_no_override }
18
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
19
+ task.__commands.map {|c| c[:command]}.should == ["tester","run with tester","bongo"]
20
+ end
21
+
22
+ it "should be able to use task variables" do
23
+ task = @deployer.__tasks.find {|t| t.__name == :task_set_var }
24
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
25
+ task.__commands.map {|c| c[:command]}.should == ["bojangles"]
26
+ end
27
+
28
+ it "should favor variables that were overridden by a task" do
29
+ task = @deployer.__tasks.find {|t| t.__name == :use_command_set_with_override }
30
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
31
+ task.__commands.map {|c| c[:command]}.should == ["shasta","run with shasta","bongo"]
32
+ end
33
+
34
+ it "should favor variables defined in the command set definition" do
35
+ task = @deployer.__tasks.find {|t| t.__name == :command_set_override }
36
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
37
+ task.__commands.map {|c| c[:command]}.should == ["dingle"]
38
+ end
39
+
40
+ it "should accept nested command sets" do
41
+ task = @deployer.__tasks.find {|t| t.__name == :nested_command_set }
42
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
43
+ task.__commands.map {|c| c[:command]}.should == %w(1 2 3 4)
44
+ end
45
+
46
+ it "nested command sets have their own variable scope" do
47
+ task = @deployer.__tasks.find {|t| t.__name == :nested_scoping }
48
+ task.__command_sets.first.instance_eval(&task.__command_sets.first.__block)
49
+ task.__commands.map {|c| c[:command]}.should == %w(birdo nested birdo task)
50
+ end
51
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Deployers" do
4
+ before(:all) do
5
+ Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
6
+ end
7
+
8
+ it "should complain if no server was defined" do
9
+ lambda { Deployer.new(:recipe_file => "./test/config/no_server.rb", :silent => true)}.should raise_error(Screwcap::ConfigurationError)
10
+ end
11
+
12
+ it "should complain if there is an undefined item in a task" do
13
+ lambda { Deployer.new(:recipe_file => "./test/config/undefined_item.rb", :silent => true)}.should raise_error(NoMethodError)
14
+ end
15
+
16
+ it "should complain if screwcap cannot find the task to run" do
17
+ lambda { Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true).run! :task }.should raise_error(Screwcap::TaskNotFound)
18
+ end
19
+
20
+ it "should complain if a gateway has more than one address" do
21
+ end
22
+
23
+ it "should be able to define tasks and servers" do
24
+ deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
25
+
26
+ deployer.should have(6).__tasks
27
+ deployer.should have(2).__servers
28
+ end
29
+
30
+ it "should be able to define variables with set" do
31
+ deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
32
+ deployer.should respond_to(:deploy_var)
33
+ deployer.should respond_to(:deploy_var_2)
34
+ deployer.should respond_to(:deploy_var_3)
35
+
36
+ deployer.deploy_var.should == "tester"
37
+ deployer.deploy_var_2.should == "bongo"
38
+ deployer.deploy_var_3.should == ["one","two"]
39
+ end
40
+
41
+ it "should be able to define command sets" do
42
+ deployer = Deployer.new(:recipe_file => "./test/config/command_sets.rb", :silent => true)
43
+ deployer.should have(8).__command_sets
44
+ end
45
+
46
+ it "should be able to define gateways" do
47
+ deployer = Deployer.new(:recipe_file => "./test/config/gateway.rb", :silent => true)
48
+ deployer.should have(3).__servers
49
+ deployer.__servers.select {|s| s.__options[:is_gateway] == true }.size.should == 1
50
+ end
51
+
52
+ it "should be able to define sequences" do
53
+ deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
54
+ deployer.should have (1).__sequences
55
+ end
56
+
57
+ it "should be able to run a single task" do
58
+ deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
59
+ lambda { deployer.run! :task1 }.should_not raise_error
60
+ end
61
+
62
+ it "should be able to run multiple tasks" do
63
+ deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
64
+ lambda { deployer.run! :task1, :task2 }.should_not raise_error
65
+ end
66
+
67
+ it "should be able to include other task files with the use keyword" do
68
+ deployer = Deployer.new(:recipe_file => "./test/config/use.rb", :silent => true)
69
+ deployer.should have(6).__tasks
70
+ deployer.deploy_var.should == "tester"
71
+ end
72
+
73
+ it "should complain if we attempt to use an unknown file" do
74
+ lambda {Deployer.new(:recipe_file => "./test/config/unknown_use.rb", :silent => true) }.should raise_error(Screwcap::IncludeFileNotFound)
75
+ end
76
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Sequences" do
4
+ before(:all) do
5
+ Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
6
+ end
7
+ before(:each) do
8
+ @stdout = []
9
+ Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg}
10
+ @deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
11
+ end
12
+
13
+ it "should contain a list of tasks to be called" do
14
+ sequence = @deployer.__sequences.find {|s| s.__name == :deploy}
15
+ sequence.__task_names.should == [:seq1, :seq2]
16
+ end
17
+
18
+ it "should be callable via Deployer.run!" do
19
+ lambda { @deployer.run! :deploy }.should_not raise_error
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Servers" do
4
+ before(:each) do
5
+ @stdout = []
6
+ @stderr = []
7
+ Task.any_instance.stubs(:log).with() { |msg| @stdout << msg }
8
+ Task.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
9
+ Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg }
10
+ Deployer.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
11
+
12
+ Net::SSH::Gateway.stubs(:new).returns(SSHObject.new)
13
+ end
14
+
15
+ before(:all) do
16
+ Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
17
+ end
18
+
19
+ it "should complain if you do not provide an address" do
20
+ lambda { Server.new(:name => :test) }.should raise_error(Screwcap::InvalidServer)
21
+ end
22
+
23
+ it "should complain if you do not provide a username" do
24
+ lambda { Server.new(:name => :test, :address => "abc.com") }.should raise_error(Screwcap::InvalidServer)
25
+ end
26
+
27
+ it "should complain if a gateway contains more than one address" do
28
+ lambda { Server.new(:name => :test, :addresses => ["abc.com", "def.com"], :user => "root", :is_gateway => true) }.should raise_error(Screwcap::InvalidServer)
29
+ end
30
+
31
+ it "should provide a connection to the server" do
32
+ server = Server.new(:name => :test, :user => :root, :address => "abc.com")
33
+ server.should respond_to(:__with_connection_for)
34
+ end
35
+
36
+ it "should provide a connection to the server with a gateway" do
37
+ @deployer = Deployer.new(:recipe_file => "./test/config/gateway.rb", :silent => false)
38
+ server = @deployer.__servers.find {|s| s.__name == :test}
39
+ gateway = @deployer.__servers.find {|s| s.__name == :gateway1}
40
+
41
+ output = []
42
+ lambda { server.__with_connection {} }.should_not raise_error
43
+ end
44
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,25 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/screwcap'
4
+
5
+ require 'rubygems'
6
+ require 'mocha'
7
+ require 'ruby-debug' rescue nil
8
+ require 'net/ssh'
9
+
10
+ class SSHObject
11
+ attr_accessor :options
12
+
13
+ def initialize(options = {})
14
+ @options = {:return_stream => :stdout}
15
+ @options = options
16
+ end
17
+
18
+ def exec!(cmd, &block)
19
+ yield nil, @options[:return_stream], @options[:return_data]
20
+ end
21
+
22
+ def ssh(address, user, options = {}, &block)
23
+ yield nil
24
+ end
25
+ end
data/spec/task_spec.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Tasks" do
4
+ before(:each) do
5
+ @stdout = []
6
+ @stderr = []
7
+ Task.any_instance.stubs(:log).with() { |msg| @stdout << msg }
8
+ Task.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
9
+ Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg }
10
+ Deployer.any_instance.stubs(:errorlog).with() { |msg| @stderr << msg }
11
+ @deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => false)
12
+ end
13
+
14
+ before(:all) do
15
+ Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
16
+ Net::SCP.stubs(:upload!).returns(nil)
17
+ end
18
+
19
+ #it "should be able to create variables" do
20
+ # task = @deployer.__tasks.find {|t| t.name == :task1 }
21
+ # task.bango.should == "bongo"
22
+ #end
23
+
24
+ #it "should compile run statements" do
25
+ # task = @deployer.__tasks.find {|t| t.name == :task1 }
26
+ # task.should have(6).__commands
27
+ #end
28
+
29
+ #it "should be able to execute statements on a remote server" do
30
+ # task = @deployer.__tasks.find {|t| t.name == :task1 }
31
+ # task.execute!
32
+ # @stderr.should == []
33
+ # @stdout.size.should == 29
34
+ #end
35
+
36
+ it "should be able to use variables in the run statement" do
37
+ task = @deployer.__tasks.find {|t| t.name == :task1 }
38
+ command = task.__commands.map{|c| c[:command] }.find {|c| c.index "deploy dir" }
39
+ command.should == "deploy dir = tester"
40
+ end
41
+
42
+ #it "should be able to override a globally set variable" do
43
+ # @deployer.deploy_var_2.should == "bongo"
44
+ # @deployer.deploy_var_3.should == %w(one two)
45
+
46
+ # task = @deployer.__tasks.find {|t| t.name == :task1 }
47
+ # task.deploy_var_2.should == "shasta"
48
+
49
+ # task = @deployer.__tasks.find {|t| t.name == :task2 }
50
+ # task.deploy_var_2.should == "purple"
51
+ # task.deploy_var_3.should == "mountain dew"
52
+ #end
53
+
54
+ #it "should complain if you do not pass the task a server argument" do
55
+ # lambda { Deployer.new(:recipe_file => "./test/config/no_server.rb", :silent => false)}.should raise_error(Screwcap::ConfigurationError)
56
+ #end
57
+
58
+ #it "should complain if you pass a server that is not defined" do
59
+ # lambda { Deployer.new(:recipe_file => "./test/config/undefined_server.rb", :silent => false)}.should raise_error(Screwcap::ConfigurationError)
60
+ #end
61
+
62
+ #it "should be able to disable parallel running" do
63
+ # # this is hard to test. with threads and stuff
64
+ # lambda { @deployer.run! :non_parallel }.should_not raise_error
65
+ #end
66
+
67
+ it "should be able to run local commands" do
68
+ lambda { @deployer.run! :task3 }.should_not raise_error
69
+ end
70
+
71
+ it "should be able to upload files using the scp command" do
72
+ deployer = Deployer.new(:recipe_file => "./test/config/upload.rb", :silent => true)
73
+ deployer.run! :upload
74
+ end
75
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
@@ -0,0 +1,87 @@
1
+ set :deploy_var, "tester"
2
+ set :deploy_var_2, "bongo"
3
+ set :deploy_var_3, ["one","two"]
4
+ server :test, :addresses => ["slashdot.org","google.com"], :user => "root", :key => "id_rsa"
5
+
6
+ command_set :push_to_thang do
7
+ run :deploy_var
8
+ run "run with #{deploy_var}"
9
+ run :deploy_var_2
10
+ end
11
+
12
+ command_set :task_only_var do
13
+ run :task_var
14
+ end
15
+
16
+ command_set :set_var do
17
+ set :deploy_var, "dingle"
18
+ run :deploy_var
19
+ end
20
+
21
+ command_set :nested do
22
+ run "3"
23
+ run "4"
24
+ end
25
+
26
+ command_set :simple1 do
27
+ run "1"
28
+ run "2"
29
+ nested
30
+ end
31
+
32
+ command_set :really_simple do
33
+ run "1"
34
+ run "2"
35
+ run "3"
36
+ end
37
+
38
+ command_set :nested_inside_with_var do
39
+ set :nested_var, "nested"
40
+ run :nested_var
41
+ end
42
+
43
+ command_set :nested_outside_with_var do
44
+ set :nested_var, "birdo"
45
+ run :nested_var
46
+ nested_inside_with_var
47
+ run :nested_var
48
+ end
49
+
50
+
51
+ task_for :use_command_set_no_override, :server => :test do
52
+ push_to_thang
53
+ end
54
+
55
+ task_for :use_command_set_with_override, :server => :test do
56
+ set :deploy_var, "shasta"
57
+ push_to_thang
58
+ end
59
+
60
+ task_for :use_command_set_complex_override, :server => :test do
61
+ set :deploy_var, "bango"
62
+ set_var
63
+ end
64
+
65
+ task_for :nested_command_set, :server => :test do
66
+ simple1
67
+ end
68
+
69
+ task_for :really_simple_task, :server => :test do
70
+ really_simple
71
+ end
72
+
73
+ task_for :task_set_var, :server => :test do
74
+ set :task_var, "bojangles"
75
+ task_only_var
76
+ end
77
+
78
+ task_for :command_set_override, :server => :test do
79
+ set :deploy_var, "bubbles"
80
+ set_var
81
+ end
82
+
83
+ task_for :nested_scoping, :server => :test do
84
+ set :nested_var, "task"
85
+ nested_outside_with_var
86
+ run :nested_var
87
+ end
@@ -0,0 +1,23 @@
1
+ server :test, :address => "abc.com", :user => "root"
2
+ set :variable, 1
3
+
4
+ command_set :revert do
5
+ run "revert"
6
+ end
7
+
8
+ task_for :logic, :server => :test do
9
+ case variable
10
+ when 1
11
+ run "1"
12
+ when 2
13
+ run "2"
14
+ else
15
+ run "none"
16
+ end
17
+ end
18
+
19
+ task_for :expect, :server => :test do
20
+ run "ls"
21
+ expect "somecommand", "true", :fail => :revert
22
+ end
23
+