borg-rb 0.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.
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: