borg-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YmUyMjY1NWY1ZGQxY2IzMWI0NWY5OGJiZDA4ZWY1NzczM2ZhYzBkZA==
5
+ data.tar.gz: !binary |-
6
+ NjQ2ZjUwN2I1MzU0ZGM3NmViNzFkY2QzNjZjNTMyMGNlMWRkNzQ5MA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MTMxMDRmYTQ1ZWY2ZDk2NTEwMWM5NjhmNzExYjVlOWU0MGEyNmMzZDRhZWU5
10
+ ZWQ4YTgyMGY3ZTAyZTUwY2Q0ZGJiN2I5N2ZiMGQ5YjE2NWQ2N2U5NTk4N2Fk
11
+ ODJmZTNlZjhhYTAxMzFmOWI3NmVlMmQ3ZGU0ZjU4MWFjNWE4YzQ=
12
+ data.tar.gz: !binary |-
13
+ YzBkOTZjZmIyM2NiNGM5NDE2NDA2OGJlMDdiZjc3MmE5NmQyMmQ4Yjk3ODVh
14
+ NTJmMjQ5ODYxNWI1ZWQzODRjOGJlYTBlNmVjYTA4MDZhMGM3Y2ZhYTgxNjlj
15
+ MmIwMjA4NDQ5ZjY4MTQ2Yzk5YWIyYmNkNzhhYzk5NGFlNWEwZDg=
data/.gitignore ADDED
@@ -0,0 +1,41 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ Gemfile.lock
6
+ InstalledFiles
7
+ coverage
8
+ lib/bundler/man
9
+ pkg
10
+ rdoc
11
+ spec/reports
12
+ test/tmp
13
+ test/version_tmp
14
+ tmp
15
+
16
+ # Local Ruby Dev Configs
17
+ .rvmrc
18
+
19
+ # YARD artifacts
20
+ .yardoc
21
+ _yardoc
22
+ doc/
23
+
24
+ # JetBrains IDE files
25
+ *.iml
26
+ *.ipr
27
+ *.iws
28
+ .idea/
29
+
30
+ # OS X
31
+ .DS_Store
32
+ .AppleDouble
33
+ .LSOverride
34
+ Icon
35
+
36
+ # Thumbnails
37
+ ._*
38
+
39
+ # Files that might appear on external disk
40
+ .Spotlight-V100
41
+ .Trashes
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode # JRuby in 1.9 mode
5
+ - rbx-19mode
6
+ script: bundle exec rspec spec
data/Capfile ADDED
@@ -0,0 +1 @@
1
+ load 'lib/borg'
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # Borg
2
+ This is a project inspired by Caphub. It expands on the concept and makes it into a framework for multi application
3
+ deployment.
4
+
5
+ [![Build Status](https://travis-ci.org/B0RG/borg.png?branch=master)](https://travis-ci.org/B0RG/borg)
6
+ [![Dependency Status](https://gemnasium.com/B0RG/borg.png)](https://gemnasium.com/B0RG/borg)
7
+ [![Code Climate](https://codeclimate.com/github/B0RG/borg.png)](https://codeclimate.com/github/B0RG/borg)
8
+
9
+ # Setup
10
+ ## Deployer Package
11
+
12
+ `borgify` Sets up the following structure
13
+
14
+ ```
15
+ my-deployer-package
16
+ ├── cap
17
+ | ├── applications
18
+ | | ├── application1.rb
19
+ │ | └── application2.rb
20
+ | ├── initilizers
21
+ | | ├── initilizer1.rb
22
+ │ | └── initilizer2.rb
23
+ | └── recipies
24
+ | ├── recipie1.rb
25
+ │ └── recipie2.rb
26
+ ├── Capfile
27
+ ├── Gemfile
28
+ └── Gemfile.lock
29
+ ```
30
+
31
+ ### Default Capfile contents
32
+ ```
33
+ # provides a performance report at the end of execution
34
+ # set :borg_performance_reports, true
35
+
36
+ # runs on :exit events when ctrl-c is hit
37
+ # set :borg_sigint_triggers_exit, true
38
+
39
+ load 'borg'
40
+ # load any other borg gems here.
41
+ # NOTE: require ends up causing the initializers to be called every time a config is loaded.
42
+
43
+ ```
44
+
45
+ ## Services Package
46
+ `borgify plugin` Sets up the following structure
47
+
48
+ ```
49
+ my-service-package
50
+ ├── cap
51
+ | ├── initilizers
52
+ | | ├── initilizer1.rb
53
+ │ | └── initilizer2.rb
54
+ | └── recipies
55
+ | ├── recipie1.rb
56
+ │ └── recipie2.rb
57
+ ├── my-service-package.gemspec
58
+ ├── Gemfile
59
+ └── Gemfile.lock
60
+ ```
61
+
62
+ ### Guidelines
63
+ * While working on this there was a realization that the if you write a "on :exit" event then make sure it is executable
64
+ even if it is called when ctrl-c is hit.
65
+
66
+ ## Borg Application Config
67
+ Borg provides a application and stage config setup.
68
+ One can define applications with the format.
69
+ ``` ruby
70
+ application :app_name do
71
+ do things needed to setup the application environment.
72
+ end
73
+
74
+ stage :app_name, :stage_name do
75
+ do things for specific stage for the applications.
76
+ end
77
+ ```
78
+
79
+ By default borg looks for application confi files in cap/applications and loads all those files.
80
+ If multiple application and stage blocks with the same parameters are defined
81
+ then all the blocks will be run for that application/stage.
82
+
83
+ The CLI enforces that all configs be specified at the start. Consider the command `borg app1:stage1 app2 deploy`
84
+ will result in config app1:stage1, all configs for app2 (1 config for each stage, if there is no stage it assumes the app is the only stage)
85
+ to be load and the deploy task be run against all of them.
data/bin/borg ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'capistrano/cli'
4
+ require 'borg/cli/applications'
5
+ require 'borg/configuration/applications'
6
+ require 'borg/configuration/stages'
7
+ require 'borg/configuration/assimilator'
8
+ require 'erb'
9
+
10
+ require 'borg/errors'
11
+ require 'borg/server/base'
12
+ require 'borg/servers/base'
13
+
14
+ # Ensure ruby 1.9.X
15
+ raise "Ruby 1.9.X required" unless RUBY_VERSION =~ /^1\.9\.\d$/
16
+
17
+ Capistrano::CLI.execute
data/bin/borgify ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+ plugin = (ARGV.count == 1 and ARGV[0] == "plugin")
4
+
5
+ if ARGV.empty? or plugin
6
+ skeleton_dir = File.expand_path('../../skeleton', __FILE__)
7
+ gem_name = File.basename(Dir.pwd)
8
+
9
+ puts "Copying Skeleton"
10
+ FileUtils.cp_r("#{skeleton_dir}/.", ".")
11
+
12
+ puts "Creating lib/#{gem_name}.rb"
13
+ File.open("lib/#{gem_name}.rb", 'w') { |file| file.write("assimilate '#{gem_name}'") }
14
+
15
+ puts "Removing unnecessary files and folders"
16
+ if plugin
17
+ FileUtils.rm_r "cap/applications"
18
+ FileUtils.rm_r "Capfile"
19
+ FileUtils.rm_r "Gemfile"
20
+ puts "Setting up gemspec file"
21
+ FileUtils.mv "mygem.gemspec.skeleton", "#{gem_name}.gemspec"
22
+ else
23
+ FileUtils.rm_r "mygem.gemspec.skeleton"
24
+ end
25
+
26
+ else
27
+ # display help if parameters input
28
+ puts <<-HELP
29
+ borgify only supports to ways of calling it.
30
+ borgify # to setup deployment project
31
+ borgify plugin # to setup a pluging for borg
32
+ HELP
33
+ end
data/borg.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'borg/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "borg-rb"
8
+ s.version = Borg::VERSION
9
+ s.authors = ["Identified"]
10
+ s.email = ["phil@identified.com", "tejas@identified.com"]
11
+ s.description = %q{Ruby-based software provisioning and deployment framework}
12
+ s.summary = %q{Ruby-based software provisioning and deployment framework}
13
+ s.homepage = "https://github.com/B0RG/borg"
14
+ s.license = "MIT"
15
+
16
+ s.files = `git ls-files`.split($/)
17
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "capistrano"
22
+ s.add_dependency "capistrano_colors"
23
+ s.add_dependency "colored"
24
+ s.add_dependency "term-ansicolor"
25
+
26
+ s.add_development_dependency "rspec"
27
+ end
@@ -0,0 +1,15 @@
1
+ application :app1 do
2
+ puts "application = app1"
3
+ end
4
+
5
+ stage :app1, :prd do
6
+ puts "stage = prd"
7
+ end
8
+
9
+ stage :app1, :stg do
10
+ puts "stage = stg"
11
+ end
12
+
13
+ stage :app1, :alf do
14
+ puts "stage = alf"
15
+ end
@@ -0,0 +1,4 @@
1
+ # Colors
2
+ require 'colored'
3
+ require 'term/ansicolor'
4
+ require 'capistrano_colors'
@@ -0,0 +1,42 @@
1
+ _cset :borg_performance_reports, true
2
+ if borg_performance_reports
3
+ # source: https://github.com/PagerDuty/pd-cap-recipes/blob/master/lib/pd-cap-recipes/tasks/performance.rb
4
+ start_times = {}
5
+ end_times = {}
6
+ order = []
7
+
8
+ on :before do
9
+ order << [:start, current_task]
10
+ start_times[current_task] = Time.now
11
+ end
12
+
13
+ on :after do
14
+ order << [:end, current_task]
15
+ end_times[current_task] = Time.now
16
+ end
17
+
18
+ on :exit do
19
+ print_report(start_times, end_times, order) if order.count > 0
20
+ end
21
+
22
+ def print_report(start_times, end_times, order)
23
+ def l(s)
24
+ logger.info s
25
+ end
26
+
27
+ l " Performance Report"
28
+ l "=========================================================="
29
+ indent = 0
30
+ (order + [nil]).each_cons(2) do |payload1, payload2|
31
+ action, task = payload1
32
+ if action == :start
33
+ l "#{".." * indent}#{task.fully_qualified_name}" unless task == payload2.last
34
+ indent += 1
35
+ else
36
+ indent -= 1
37
+ l "#{".." * indent}#{task.fully_qualified_name} #{(end_times[task] - start_times[task]).to_i}s"
38
+ end
39
+ end
40
+ l "=========================================================="
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ # Added for convenience allowing dynamic
2
+
3
+ module ::Capistrano
4
+ class Role
5
+ def reset!
6
+ @dynamic_servers.each(&:reset!)
7
+ end
8
+ end
9
+ end
10
+
11
+ desc "Resets all dynamic capistrano roles."
12
+ task(:reset_roles) { roles.each {|k,v| v.reset!} }
@@ -0,0 +1,9 @@
1
+ _cset :borg_sigint_triggers_exit, true
2
+
3
+ if borg_sigint_triggers_exit
4
+ __cap = Capistrano::Configuration.instance
5
+ ::Signal.trap "SIGINT" do
6
+ __cap.trigger :exit
7
+ exit 1
8
+ end
9
+ end
@@ -0,0 +1,66 @@
1
+ module Borg
2
+ module CLI
3
+ module Applications
4
+ def self.included(base) #:nodoc:
5
+ base.send :alias_method, :execute_requested_actions_without_applications, :execute_requested_actions
6
+ base.send :alias_method, :execute_requested_actions, :execute_requested_actions_with_applications
7
+ end
8
+
9
+ def execute_requested_actions_with_applications(config)
10
+
11
+ load_applications config
12
+
13
+ separate_actions_and_applications config
14
+
15
+ if options[:applications].empty? or Thread.current[:borg_application]
16
+ Thread.current[:borg_application].load_into config if Thread.current[:borg_application]
17
+ execute_requested_actions_without_applications(config)
18
+ else
19
+ options[:applications].each do |app|
20
+ puts "Executing commands in context of #{app.name}"
21
+ Thread.current[:borg_application] = app
22
+ execute!
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def load_applications config
30
+ # load applications
31
+ unless @apps_loaded
32
+ Dir["./cap/applications/**/*.rb"].each do |file|
33
+ config.load file
34
+ end
35
+ @apps_loaded = true
36
+ end
37
+ end
38
+
39
+ def separate_actions_and_applications config
40
+ options[:applications] = []
41
+ found_non_application = false
42
+ options[:actions] = Array(options[:actions]).keep_if do |action|
43
+ app, stg = action.split(":").map(&:to_sym)
44
+ ret = if config.applications[app] and config.applications[app].stages[stg]
45
+ options[:applications] << config.applications[app].stages[stg]
46
+ false
47
+ elsif config.applications[app] and stg.nil?
48
+ if config.applications[app].stages.empty?
49
+ options[:applications] << config.applications[app]
50
+ else
51
+ config.applications[app].stages.each{|name, stg| options[:applications] << stg}
52
+ end
53
+ false
54
+ else
55
+ found_non_application = true
56
+ true
57
+ end
58
+ raise ArgumentError, "Can not have non application configs between application configs" if !ret and found_non_application
59
+ ret
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ Capistrano::CLI.send :include, Borg::CLI::Applications
@@ -0,0 +1,49 @@
1
+ module Borg
2
+ module Configuration
3
+ module Applications
4
+
5
+ def self.included(base) #:nodoc:
6
+ base.send :alias_method, :initialize_without_applications, :initialize
7
+ base.send :alias_method, :initialize, :initialize_with_applications
8
+ end
9
+ attr_reader :applications
10
+
11
+ def initialize_with_applications(*args) #:nodoc:
12
+ initialize_without_applications(*args)
13
+ @applications = {}
14
+ end
15
+ private :initialize_with_applications
16
+
17
+ def application (name, &block)
18
+ name = name.to_sym
19
+ namespace name do
20
+ desc "Load Application #{name} (All Stages if any)"
21
+ task :default do
22
+ @applications[name].execute
23
+ end
24
+ end
25
+ @applications[name] ||= Application.new(name, @namespaces[name])
26
+ @applications[name].execution_blocks << block if block_given?
27
+ end
28
+
29
+ class Application
30
+ attr_accessor :execution_blocks
31
+ attr_accessor :stages
32
+ attr_reader :name
33
+
34
+ def initialize name, namespace
35
+ @execution_blocks = []
36
+ @name = name
37
+ @namespace = namespace
38
+ @stages = {}
39
+ end
40
+
41
+ def load_into config
42
+ @execution_blocks.each {|blk| config.load &blk}
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ Capistrano::Configuration.send :include, Borg::Configuration::Applications
@@ -0,0 +1,14 @@
1
+ module Borg
2
+ module Configuration
3
+ module Assimilator
4
+ def assimilate gem_name
5
+ gem_home = Gem::Specification.find_by_name(gem_name).gem_dir
6
+ Dir["#{gem_home}/cap/initializers/**/*.rb"].each do |file|
7
+ load file
8
+ end
9
+ @load_paths << "#{gem_home}/cap"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ Capistrano::Configuration.send :include, Borg::Configuration::Assimilator
@@ -0,0 +1,42 @@
1
+ module Borg
2
+ module Configuration
3
+ module Stages
4
+
5
+ def stage (app, name, &block)
6
+ app = app.to_sym
7
+ name = name.to_sym
8
+ application app unless @applications[app]
9
+
10
+ namespace app do
11
+ desc "Load Application #{app} and Stage #{name}"
12
+ task name do
13
+ @applications[app].stages[name].execute
14
+ end
15
+ end
16
+ @applications[app].stages[name] ||= Stage.new(name, @applications[app])
17
+ @applications[app].stages[name].execution_blocks << block
18
+ end
19
+
20
+ class Stage
21
+ attr_accessor :execution_blocks
22
+ attr_accessor :parent
23
+ def name
24
+ "#{parent.name}:#{@name}"
25
+ end
26
+
27
+ def initialize name, parent
28
+ @execution_blocks = []
29
+ @name = name
30
+ @parent = parent
31
+ end
32
+
33
+ def load_into config
34
+ parent.load_into config
35
+ @execution_blocks.each {|blk| config.load &blk}
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Capistrano::Configuration.send :include, Borg::Configuration::Stages
@@ -0,0 +1,4 @@
1
+ module Borg
2
+ class BaseError < StandardError; end
3
+ class UnimplementedError < BaseError; end
4
+ end
@@ -0,0 +1,29 @@
1
+ module Borg
2
+ module Server
3
+ class Base < ::Capistrano::ServerDefinition
4
+
5
+ def self.create opts
6
+ unimplemented "Use a subclass of Borg::Server::Base that implements the create functionality."
7
+ end
8
+
9
+ def start
10
+ unimplemented "Use a subclass of Borg::Server::Base that implements the start functionality."
11
+ end
12
+
13
+ def stop
14
+ unimplemented "Use a subclass of Borg::Server::Base that implements the stop functionality."
15
+ end
16
+
17
+ def destroy
18
+ unimplemented "Use a subclass of Borg::Server::Base that implements the destroy functionality."
19
+ end
20
+
21
+ private
22
+
23
+ def unimplemented msg
24
+ raise Borg::UnimplementedError.new msg
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ module Borg
2
+ module Servers
3
+ class Base
4
+ class << self
5
+ def all
6
+ unimplemented "Use a subclass of Borg::Servers::Base that implements the all functionality."
7
+ end
8
+
9
+ def [] name
10
+ all.select{|s| s.name == name}.first
11
+ end
12
+
13
+ private
14
+
15
+ def unimplemented msg
16
+ raise Borg::UnimplementedError.new msg
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Borg
2
+ VERSION = "0.0.1"
3
+ end
data/lib/borg.rb ADDED
@@ -0,0 +1,8 @@
1
+ # source capistrano/deploy.rb
2
+ def _cset(name, *args, &block)
3
+ unless exists?(name)
4
+ set(name, *args, &block)
5
+ end
6
+ end
7
+
8
+ assimilate "borg-rb"
data/skeleton/Capfile ADDED
@@ -0,0 +1,9 @@
1
+ # provides a performance report at the end of execution
2
+ # set :borg_performance_reports, true
3
+
4
+ # runs on :exit events when ctrl-c is hit
5
+ # set :borg_sigint_triggers_exit, true
6
+
7
+ load 'borg.rb'
8
+ # load any other borg gems here.
9
+ # NOTE: require ends up causing the initializers to be called every time a config is loaded.
data/skeleton/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'borg-rb'
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = raise "fill gem name here"
5
+ s.version = raise "fill gem version here"
6
+ s.date = Time.now.strftime('%Y-%m-%d')
7
+ s.summary = raise "fill gem summary here"
8
+ s.homepage = raise "fill gem homepage here"
9
+ s.email = raise "fill gem contact emails here"
10
+ s.authors = raise "fill gem author names here"
11
+ s.has_rdoc = false
12
+
13
+ s.files = %w( README.md Rakefile LICENSE )
14
+ s.files += Dir.glob("lib/**/*")
15
+ s.files += Dir.glob("cap/**/*")
16
+
17
+ s.description = raise "fill gem description here"
18
+
19
+ s.add_dependency "borg-rb"
20
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'borg/cli/applications'
3
+
4
+ describe Borg::CLI::Applications do
5
+ before :each do
6
+ @config = double("config1")
7
+ @files = %w{cap/applications/app1.rb cap/applications/app1/stg1.rb cap/applications/app1/stg2.rb}
8
+ Dir.stub("[]").and_return(@files)
9
+ @cli = Capistrano::CLI.new([])
10
+ end
11
+
12
+ context "#load_applications when called" do
13
+ before do
14
+ @files.each { |f| @config.should_receive(:load).with(f) }
15
+ end
16
+
17
+ it "should load all files in ./cap/applications/**/*.rb" do
18
+ @cli.send :load_applications, @config
19
+ end
20
+
21
+ context "with a second call" do
22
+ before do
23
+ @cli.send :load_applications, @config
24
+ @config2 = double("config2")
25
+ @files.each { |f| @config2.should_not_receive(:load).with(f) }
26
+ end
27
+
28
+ it "should not load all files in ./cap/applications/**/*.rb for further calls" do
29
+ @cli.send :load_applications, @config2
30
+ end
31
+ end
32
+ end
33
+
34
+ context "#separate_actions_and_applications when called" do
35
+ before do
36
+ @cli.instance_eval do
37
+ @options = {}
38
+ @options[:actions] = %w{app1 app2:stg1 app2:stg3 test test2}
39
+ end
40
+ @config.stub(:applications).and_return({
41
+ app1: double("app1"),
42
+ app2: double("app2")
43
+ })
44
+ @config.applications[:app1].stub(:stages).and_return({})
45
+ @config.applications[:app2].stub(:stages).and_return({
46
+ stg1: double("stg1"),
47
+ stg2: double("stg2")
48
+ })
49
+ end
50
+ it "should remove all applications from actions" do
51
+ @cli.send :separate_actions_and_applications, @config
52
+ @cli.options[:actions].should == %w{app2:stg3 test test2}
53
+ @cli.options[:applications].should == [
54
+ @config.applications[:app1],
55
+ @config.applications[:app2].stages[:stg1]
56
+ ]
57
+ end
58
+
59
+ it "should queue both stages if app2" do
60
+ @cli.instance_eval do
61
+ @options[:actions] = %w{app1 app2 test test2}
62
+ end
63
+
64
+ @cli.send :separate_actions_and_applications, @config
65
+
66
+ @cli.options[:actions].should == %w{test test2}
67
+ @cli.options[:applications].should == [
68
+ @config.applications[:app1],
69
+ @config.applications[:app2].stages[:stg1],
70
+ @config.applications[:app2].stages[:stg2]
71
+ ]
72
+ end
73
+
74
+ it "should raise exception if configs are not isolated to start of the actions list" do
75
+ @cli.instance_eval do
76
+ @options[:actions] << "app2:stg2"
77
+ end
78
+ expect{ @cli.send(:separate_actions_and_applications, @config)}.to raise_error(ArgumentError, "Can not have non application configs between application configs")
79
+ end
80
+
81
+ end
82
+
83
+ context "#execute_requested_actions_with_applications when called" do
84
+ before do
85
+
86
+ @cli.instance_eval do
87
+ @apps_loaded = true
88
+ @options = {}
89
+ @options[:actions] = %w{app1 app2:stg1 app2:stg3 test test2}
90
+ @options[:applications] = []
91
+ end
92
+ @config.stub(:applications).and_return({})
93
+
94
+ @cli.stub(:execute_requested_actions_without_applications)
95
+
96
+ end
97
+
98
+ it "should load applications" do
99
+ @cli.should_receive(:load_applications).with(@config)
100
+ @cli.execute_requested_actions_with_applications @config
101
+ end
102
+
103
+ it "should separate actions and applications" do
104
+ @cli.should_receive(:separate_actions_and_applications).with(@config)
105
+ @cli.execute_requested_actions_with_applications @config
106
+ end
107
+
108
+ it "should call #execute_requested_actions_without_applications when there is an empty applications list" do
109
+ @cli.should_receive(:execute_requested_actions_without_applications).with(@config)
110
+ @cli.execute_requested_actions_with_applications @config
111
+ end
112
+
113
+ context "when applications exist" do
114
+ before do
115
+ apps = [double(:app1), double(:app2)]
116
+ apps[0].stub(:name).and_return(:app1)
117
+ apps[1].stub(:name).and_return(:app2)
118
+ @cli.instance_eval do
119
+ @options[:applications] = apps
120
+ end
121
+ @cli.stub(:puts)
122
+ end
123
+
124
+ after do
125
+ Thread.current[:borg_application] = nil
126
+ end
127
+
128
+ it "should call call execute! for each application" do
129
+ @cli.stub(:load_applications)
130
+ @cli.stub(:separate_actions_and_applications)
131
+ @cli.should_receive(:execute!).with().twice
132
+ @cli.execute_requested_actions_with_applications @config
133
+ end
134
+
135
+ it "should set Thread's borg_application" do
136
+ @cli.stub(:load_applications)
137
+ @cli.stub(:separate_actions_and_applications)
138
+ @cli.stub(:execute!) do
139
+ @cli.options[:applications].should include Thread.current[:borg_application]
140
+ end
141
+ @cli.execute_requested_actions_with_applications @config
142
+ end
143
+
144
+ it "should call #execute_requested_actions_without_applications when Thread's borg_application is set" do
145
+ Thread.current[:borg_application] = @cli.options[:applications][0]
146
+ @cli.stub(:load_applications)
147
+ @cli.stub(:separate_actions_and_applications)
148
+ @cli.should_receive(:execute_requested_actions_without_applications).with(@config)
149
+ @cli.options[:applications][0].stub(:load_into)
150
+ @cli.execute_requested_actions_with_applications @config
151
+ end
152
+
153
+ it "should load the application's config when Thread's borg_application is set" do
154
+ Thread.current[:borg_application] = @cli.options[:applications][0]
155
+ @cli.stub(:load_applications)
156
+ @cli.stub(:separate_actions_and_applications)
157
+ @cli.stub(:execute_requested_actions_without_applications)
158
+ @cli.options[:applications][0].should_receive(:load_into)
159
+ @cli.execute_requested_actions_with_applications @config
160
+ end
161
+
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'borg/configuration/applications'
3
+
4
+ describe Borg::Configuration::Applications do
5
+ it "should be included into Capistrano::Configuration" do
6
+ Capistrano::Configuration.ancestors.should include Borg::Configuration::Applications
7
+ end
8
+
9
+ context "when a new Capistrano::Configuration is initialized" do
10
+ subject { Capistrano::Configuration.new }
11
+ it "should initialize the applications hash" do
12
+ expect(subject.applications).to eq({})
13
+ end
14
+ end
15
+
16
+ context "when an applications is defined" do
17
+ before do
18
+ @config = Capistrano::Configuration.new
19
+ @config.load do
20
+ application "app1" do
21
+ test_notice "You have called app1"
22
+ end
23
+ end
24
+ end
25
+ subject { @config }
26
+
27
+ it "should symobolize the name" do
28
+ expect(subject.applications[:app1].name).to eq :app1
29
+ end
30
+
31
+ it "should create a namespace app1 with task default and a description" do
32
+ expect(subject.namespaces[:app1]).to be_true
33
+ expect(subject.namespaces[:app1].tasks[:default]).to be_true
34
+ expect(subject.namespaces[:app1].tasks[:default].desc).to be_true
35
+ end
36
+
37
+ it "should add it to applications hash and have a block" do
38
+ expect(subject.applications[:app1].class).to eq Borg::Configuration::Applications::Application
39
+ expect(subject.applications[:app1].execution_blocks.count).to eq 1
40
+ end
41
+ end
42
+ end
43
+
44
+ describe Borg::Configuration::Applications::Application do
45
+ it "should be initialize all variables" do
46
+ app1 = Borg::Configuration::Applications::Application.new(:app1, double("namespace app1"))
47
+ expect(app1.stages).to eq({})
48
+ expect(app1.name).to eq(:app1)
49
+ expect(app1.execution_blocks).to eq([])
50
+ end
51
+
52
+ context "an applications with 2 blocks" do
53
+ before do
54
+ @app1 = Borg::Configuration::Applications::Application.new(:app1, double("namespace app1"))
55
+ @app1.execution_blocks << -> {
56
+ raise "block 1 called"
57
+ }
58
+ @app1.execution_blocks << -> {
59
+ raise "block 2 called"
60
+ }
61
+ end
62
+ context "when #load_into is called" do
63
+ it "should all blocks into the provided config" do
64
+ config = double("test config")
65
+ config.should_receive(:load).twice
66
+ @app1.load_into config
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'borg/configuration/assimilator'
3
+
4
+ describe Borg::Configuration::Assimilator do
5
+ it "should be included into Capistrano::Configuration" do
6
+ Capistrano::Configuration.new.should respond_to :assimilate
7
+ end
8
+
9
+ context "when assimilate('borg') is called" do
10
+ subject { Capistrano::Configuration.new }
11
+ it "should loads all the initializers" do
12
+ Dir["cap/initializers/**/*.rb"].each do |file|
13
+ subject.should_receive(:load).with(File.expand_path(file))
14
+ end
15
+ subject.assimilate ('borg-rb')
16
+ end
17
+
18
+ it "should add the cap directory to teh load path" do
19
+ Dir.stub("[]").and_return([])
20
+ lambda { subject.assimilate ('borg-rb') }.should change(subject.load_paths, :count).by 1
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'borg/configuration/applications'
3
+ require 'borg/configuration/stages'
4
+
5
+ describe Borg::Configuration::Stages do
6
+ it "should be included into Capistrano::Configuration" do
7
+ Capistrano::Configuration.ancestors.should include Borg::Configuration::Stages
8
+ end
9
+
10
+ context "when an applications is defined" do
11
+ before do
12
+ @config = Capistrano::Configuration.new
13
+ @config.load do
14
+ stage "app1", "stg1" do
15
+ test_notice "You have called app1 stg1"
16
+ end
17
+ end
18
+ end
19
+ subject { @config }
20
+
21
+ it "should create application since it does not exist" do
22
+ expect(subject.applications[:app1]).to be_true
23
+ end
24
+
25
+ it "should symobolize the name" do
26
+ expect(subject.applications[:app1].stages.keys.first).to eq :stg1
27
+ end
28
+
29
+ it "should create a namespace app1 with task stg1 and a description" do
30
+ expect(subject.namespaces[:app1]).to be_true
31
+ expect(subject.namespaces[:app1].tasks[:stg1]).to be_true
32
+ expect(subject.namespaces[:app1].tasks[:stg1].desc).to be_true
33
+ end
34
+
35
+ it "should add it to applications hash and have a block" do
36
+ expect(subject.applications[:app1].stages[:stg1].class).to eq Borg::Configuration::Stages::Stage
37
+ expect(subject.applications[:app1].stages[:stg1].execution_blocks.count).to eq 1
38
+ end
39
+ end
40
+ end
41
+
42
+ describe Borg::Configuration::Stages::Stage do
43
+ it "should be initialize all variables" do
44
+ parent = double "app1"
45
+ parent.stub(:name).and_return :app1
46
+ stg1 = Borg::Configuration::Stages::Stage.new(:stg1, parent)
47
+ expect(stg1.name).to eq("app1:stg1")
48
+ expect(stg1.parent).to eq(parent)
49
+ expect(stg1.execution_blocks).to eq([])
50
+ end
51
+
52
+ context "a stage with 2 blocks" do
53
+ before do
54
+ @stg1 = Borg::Configuration::Stages::Stage.new(:stg1, double("app1"))
55
+ @stg1.execution_blocks << -> {
56
+ raise "block 1 called"
57
+ }
58
+ @stg1.execution_blocks << -> {
59
+ raise "block 2 called"
60
+ }
61
+ end
62
+ context "when #load_into is called" do
63
+ it "should all blocks into the provided config" do
64
+ config = double("test config")
65
+ @stg1.parent.should_receive(:load_into).with(config)
66
+ config.should_receive(:load).twice
67
+ @stg1.load_into config
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ require 'capistrano/cli'
2
+
3
+ require 'yaml'
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: borg-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Identified
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: capistrano_colors
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colored
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: term-ansicolor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Ruby-based software provisioning and deployment framework
84
+ email:
85
+ - phil@identified.com
86
+ - tejas@identified.com
87
+ executables:
88
+ - borg
89
+ - borgify
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - .gitignore
94
+ - .travis.yml
95
+ - Capfile
96
+ - Gemfile
97
+ - README.md
98
+ - bin/borg
99
+ - bin/borgify
100
+ - borg.gemspec
101
+ - cap/applications/app1.rb
102
+ - cap/initializers/output.rb
103
+ - cap/initializers/performance.rb
104
+ - cap/initializers/role_reset.rb
105
+ - cap/initializers/sigint.rb
106
+ - lib/borg.rb
107
+ - lib/borg/cli/applications.rb
108
+ - lib/borg/configuration/applications.rb
109
+ - lib/borg/configuration/assimilator.rb
110
+ - lib/borg/configuration/stages.rb
111
+ - lib/borg/errors.rb
112
+ - lib/borg/server/base.rb
113
+ - lib/borg/servers/base.rb
114
+ - lib/borg/version.rb
115
+ - skeleton/Capfile
116
+ - skeleton/Gemfile
117
+ - skeleton/cap/applications/.gitkeep
118
+ - skeleton/cap/initializers/.gitkeep
119
+ - skeleton/cap/recipies/.gitkeep
120
+ - skeleton/lib/.gitkeep
121
+ - skeleton/mygem.gemspec.skeleton
122
+ - spec/lib/borg/cli/applications_spec.rb
123
+ - spec/lib/borg/configuration/applications_spec.rb
124
+ - spec/lib/borg/configuration/assimilator_spec.rb
125
+ - spec/lib/borg/configuration/stages_spec.rb
126
+ - spec/spec_helper.rb
127
+ homepage: https://github.com/B0RG/borg
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.0.3
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Ruby-based software provisioning and deployment framework
151
+ test_files:
152
+ - spec/lib/borg/cli/applications_spec.rb
153
+ - spec/lib/borg/configuration/applications_spec.rb
154
+ - spec/lib/borg/configuration/assimilator_spec.rb
155
+ - spec/lib/borg/configuration/stages_spec.rb
156
+ - spec/spec_helper.rb
157
+ has_rdoc: