screwcap 0.1

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