trooper 0.6.0.alpha2 → 0.6.0.beta

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.
@@ -11,27 +11,61 @@ module Trooper
11
11
  attr_reader :name, :description, :config, :block
12
12
  attr_accessor :commands
13
13
 
14
- # expects a name, description and a block
14
+ # Public: Define a new action.
15
+ #
16
+ # name - The name of the action.
17
+ # description - A description of action to be used in the cli output.
18
+ # block - A block containing the tasks to run in this action.
19
+ #
20
+ # Examples
21
+ #
15
22
  # Action.new(:my_action, 'Does great things') { run 'touch file' }
23
+ #
24
+ # Returns a new action object.
16
25
  def initialize(name, description, &block)
17
26
  @name, @description, @config = name, description, {}
18
27
  @commands, @block = [], block
19
28
  end
20
29
 
21
- # eval's the block passed on initialize and returns the command array
30
+ # Public: Eval's the block passed on initialize.
31
+ #
32
+ # configuration - The configuration object to be used for block eval.
33
+ #
34
+ # Examples
35
+ #
36
+ # @action.call(config_object) # => ['touch file']
37
+ #
38
+ # Returns an array of commands(strings).
22
39
  def call(configuration)
23
40
  @config = configuration
24
41
  eval_block(&block)
25
42
  commands
26
43
  end
27
44
  alias :execute :call
28
-
29
- # validates the action
45
+
46
+ # Public: Validates the action object. (NOT WORKING)
47
+ #
48
+ # Examples
49
+ #
50
+ # @action.ok? # => true
51
+ #
52
+ # Returns true.
30
53
  def ok?
31
54
  true
32
55
  end
33
56
 
34
57
  # run is the base run command used by the dsl
58
+
59
+ # Public: Appends command(string) to commands(array).
60
+ #
61
+ # command - A String to be added to the commands array.
62
+ #
63
+ # Examples
64
+ #
65
+ # @action.run 'touch file' # => 'touch file'
66
+ # @action.run '' # => nil
67
+ #
68
+ # Returns the command or nil.
35
69
  def run(command)
36
70
  commands << command if command != ''
37
71
  end
@@ -0,0 +1,34 @@
1
+ require 'trooper/action'
2
+
3
+ module Trooper
4
+ module Actions
5
+
6
+ class PreparePrerequisiteAction < Action
7
+
8
+ def initialize(config = {})
9
+ @name = :prepare_prerequisite
10
+ @description = "Preparing Prerequisites"
11
+ @config = config
12
+ @commands = []
13
+ end
14
+
15
+ def call(configuration)
16
+ @config = configuration
17
+ @commands = []
18
+
19
+ build_commands
20
+ commands
21
+ end
22
+
23
+ private
24
+
25
+ def build_commands
26
+ create_folders trooper_path
27
+ run "echo '#{@name}' >> #{prerequisite_list}"
28
+ run 'echo -e "Prerequisites Prepared"'
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -24,7 +24,7 @@ module Trooper
24
24
  cd application_path
25
25
  create_folder 'tmp'
26
26
  run 'touch tmp/restart.txt'
27
- run 'echo "Server restarted!"'
27
+ run 'echo -e "Server restarted!"'
28
28
  end
29
29
 
30
30
  end
@@ -0,0 +1,33 @@
1
+ require 'trooper/action'
2
+
3
+ module Trooper
4
+ module Actions
5
+
6
+ class SetupTrooperAction < Action
7
+
8
+ def initialize(config = {})
9
+ @name = :setup_trooper
10
+ @description = "Setup Trooper"
11
+ @config = config
12
+ @commands = []
13
+ end
14
+
15
+ def call(configuration)
16
+ @config = configuration
17
+ @commands = []
18
+
19
+ build_commands
20
+ commands
21
+ end
22
+
23
+ private
24
+
25
+ def build_commands
26
+ create_folders path, trooper_path
27
+ run 'echo -e "Trooper Setup on Server"'
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -3,16 +3,19 @@ require 'trooper/action'
3
3
  require 'trooper/actions/clone_repository_action'
4
4
  require 'trooper/actions/install_gems_action'
5
5
  require 'trooper/actions/migrate_database_action'
6
+ require 'trooper/actions/prepare_prerequisite_action'
6
7
  require 'trooper/actions/restart_server_action'
7
8
  require 'trooper/actions/rollback_migrate_action'
8
9
  require 'trooper/actions/setup_database_action'
10
+ require 'trooper/actions/setup_trooper_action'
9
11
  require 'trooper/actions/update_repository_action'
10
12
 
11
13
  module Trooper
12
14
  module Config
13
15
  module Action
14
16
 
15
- DEFAULT_ACTIONS = [Actions::CloneRepositoryAction, Actions::InstallGemsAction,
17
+ DEFAULT_ACTIONS = [Actions::SetupTrooperAction, Actions::PreparePrerequisiteAction,
18
+ Actions::CloneRepositoryAction, Actions::InstallGemsAction,
16
19
  Actions::MigrateDatabaseAction, Actions::RestartServerAction,
17
20
  Actions::RollbackMigrateAction, Actions::SetupDatabaseAction,
18
21
  Actions::UpdateRepositoryAction]
@@ -0,0 +1,20 @@
1
+ require 'trooper/config/action'
2
+
3
+ module Trooper
4
+ module Config
5
+ module Defaults
6
+ FILE_NAME = "Troopfile"
7
+
8
+ include Trooper::Config::Action
9
+
10
+ def load_defaults!(options = {})
11
+ config[:file_name] = options[:file_name] || FILE_NAME
12
+ config[:environment] = options[:environment] || :production
13
+ config[:ruby_bin_path] = options[:ruby_bin_path] || ""
14
+
15
+ load_default_actions!
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -28,9 +28,14 @@ module Trooper
28
28
  def path(arg)
29
29
  set :application_path => "#{arg}/application"
30
30
  set :trooper_path => "#{arg}/trooper"
31
+ set :prerequisite_list => "#{arg}/trooper/prerequisite_list"
31
32
  set :path => arg
32
33
  end
33
34
 
35
+ def ruby_bin_path(arg)
36
+ set :ruby_bin_path => arg.gsub(/[^\/]$/, '\1/') # /usr/local/bin/
37
+ end
38
+
34
39
  end
35
40
  end
36
41
  end
@@ -4,15 +4,14 @@ require 'trooper/arsenal'
4
4
 
5
5
  require 'trooper/config/environment'
6
6
  require 'trooper/config/strategy'
7
- require 'trooper/config/action'
7
+ require 'trooper/config/defaults'
8
8
 
9
9
  module Trooper
10
10
  class Configuration < Hash
11
- FILE_NAME = "Troopfile"
12
11
 
13
12
  include Trooper::Config::Environment
14
13
  include Trooper::Config::Strategy
15
- include Trooper::Config::Action
14
+ include Trooper::Config::Defaults
16
15
 
17
16
  def self.init
18
17
  gem_dir = File.dirname(__FILE__)
@@ -30,16 +29,14 @@ module Trooper
30
29
  # Configuration.new({:my_override => 'settings'})
31
30
  def initialize(options = {})
32
31
  @loaded = false
33
- @file_name = options[:file_name] || FILE_NAME
34
- self[:environment] = options[:environment] || :production
35
32
 
36
- load_default_actions!
33
+ load_defaults! options
37
34
  load_troopfile! options
38
35
  end
39
36
 
40
37
  # returns a terminal friendly version of the configuration
41
38
  def to_s
42
- self.map {|k,v| "#{k}: #{v}" }.join("\n")
39
+ config.map {|k,v| "#{k}: #{v}" }.join("\n")
43
40
  end
44
41
 
45
42
  # will find and execute the strategy name passed
@@ -51,7 +48,7 @@ module Trooper
51
48
  # a way to set variables that will be available to all actions
52
49
  # set(:my_variable => 'sdsd') # => available as method in an action
53
50
  def set(hash)
54
- self.merge! hash
51
+ config.merge! hash
55
52
  end
56
53
 
57
54
  # returns true if the troopfile was loaded
@@ -61,6 +58,10 @@ module Trooper
61
58
 
62
59
  private
63
60
 
61
+ def config
62
+ self
63
+ end
64
+
64
65
  # loads the troopfile and sets the environment up
65
66
  def load_troopfile!(options)
66
67
  if troopfile?
@@ -70,18 +71,18 @@ module Trooper
70
71
  load_environment!
71
72
  set options
72
73
  else
73
- raise Trooper::NoConfigurationFileError, "No Configuration file (#{@file_name}) can be found!"
74
+ raise Trooper::NoConfigurationFileError, "No Configuration file (#{self[:file_name]}) can be found!"
74
75
  end
75
76
  end
76
77
 
77
78
  # returns the troopfile file object
78
79
  def troopfile
79
- File.open(@file_name)
80
+ File.open(config[:file_name])
80
81
  end
81
82
 
82
83
  # returns true if the troopfile exists
83
84
  def troopfile?
84
- File.exists?(@file_name)
85
+ File.exists?(config[:file_name])
85
86
  end
86
87
 
87
88
  end
@@ -3,12 +3,12 @@ module Trooper
3
3
  module Bundler
4
4
 
5
5
  def bundle_exec(command)
6
- use_bundle = using_bundler? ? "bundle exec " : ""
6
+ use_bundle = using_bundler? ? "#{ruby_bin_path}bundle exec " : ""
7
7
  run use_bundle + command
8
8
  end
9
9
 
10
10
  def bundle_install
11
- run "bundle install --path #{trooper_path}/bundle --deployment --without development test" if using_bundler?
11
+ run "#{ruby_bin_path}bundle install --path #{trooper_path}/bundle --deployment --without development test" if using_bundler?
12
12
  end
13
13
 
14
14
  def rake(command)
@@ -20,6 +20,10 @@ module Trooper
20
20
  def using_bundler?
21
21
  File.exists? "Gemfile"
22
22
  end
23
+
24
+ def ruby_bin_path
25
+ config[:ruby_bin_path] || ""
26
+ end
23
27
 
24
28
  end
25
29
  end
@@ -3,7 +3,13 @@ module Trooper
3
3
  module Rake
4
4
 
5
5
  def rake(command)
6
- run "rake #{command}"
6
+ run "#{ruby_bin_path}rake #{command}"
7
+ end
8
+
9
+ private
10
+
11
+ def ruby_bin_path
12
+ config[:ruby_bin_path] || ""
7
13
  end
8
14
 
9
15
  end
@@ -8,28 +8,32 @@ module Trooper
8
8
  def initialize(name, description, config = {}, &block)
9
9
  @name, @description, @config = name, description, config
10
10
  @run_list = []
11
- eval_block(&block)
11
+ @block = block if block_given?
12
12
  end
13
13
 
14
14
  def execute(config = {})
15
15
  @config = config
16
+
17
+ eval_block
18
+
16
19
  Trooper.logger.debug "Configuration\n#{config}"
17
20
  Trooper.logger.strategy description
18
21
  successful = nil
19
-
22
+
20
23
  runners.each do |runner|
21
24
  begin
22
25
  Trooper.logger.info "\e[4mRunning on #{runner}\n"
23
26
 
24
- run_list.each do |item, name|
25
- self.send("#{item}_execute", runner, name)
27
+ run_list.each do |strategy, type, name|
28
+ commands = build_commands strategy, type, name
29
+ runner_execute! runner, commands if commands
26
30
  end
27
31
 
28
32
  successful = true
29
33
  Trooper.logger.success "\e[4mAll Actions Completed\n"
30
34
  rescue Exception => e
31
35
  Trooper.logger.error "#{e.class.to_s} : #{e.message}\n\n#{e.backtrace.join("\n")}"
32
-
36
+
33
37
  successful = false
34
38
  break #stop commands running on other servers
35
39
  ensure
@@ -40,47 +44,78 @@ module Trooper
40
44
  successful
41
45
  end
42
46
 
47
+ def build_run_list
48
+ eval_block
49
+ run_list
50
+ end
51
+
43
52
  def ok?
44
53
  true
45
54
  end
46
55
 
47
- def call(strategy_name)
48
- if Arsenal.strategies[strategy_name]
49
- Arsenal.strategies[strategy_name].run_list.each do |action|
50
- @run_list << action
56
+ def call(*strategy_names)
57
+ [*strategy_names].each do |strategy_name|
58
+ if Arsenal.strategies[strategy_name]
59
+ Arsenal.strategies[strategy_name].build_run_list.each do |action|
60
+ # strategy_name, type, name
61
+ @run_list << action
62
+ end
51
63
  end
52
- end
64
+ end
65
+ end
66
+
67
+ def prerequisites(*strategy_names)
68
+ unless @run_list.detect { |a| a[2] == :prepare_prerequisite }
69
+ @run_list << [@name, :action, :prepare_prerequisite]
70
+ end
71
+ [*strategy_names].each do |strategy_name|
72
+ if Arsenal.strategies[strategy_name]
73
+ Arsenal.strategies[strategy_name].build_run_list.each do |action|
74
+ # strategy_name, type, name
75
+ @run_list << [action[0], :prerequisite, action[2]]
76
+ end
77
+ end
78
+ end
53
79
  end
54
80
 
55
81
  def actions(*action_names)
56
82
  [*action_names].each do |name|
57
- @run_list << [:action, name]
83
+ # strategy_name, type, name
84
+ @run_list << [self.name, :action, name]
58
85
  end
59
86
  end
60
87
 
61
- def method_missing(method_sym, *arguments, &block)
62
- config[method_sym] || super
63
- end
88
+ def build_commands(strategy_name, type, action_name)
89
+ action = Arsenal.actions[action_name]
64
90
 
65
- private
91
+ if action
92
+ commands = action.call config
66
93
 
67
- def eval_block(&block)
68
- if block_given?
69
- if block.arity == 1
70
- block.call self
94
+ case type
95
+ when :prerequisite
96
+ commands << "echo '#{action.name}' >> #{prerequisite_list}"
97
+ commands << "echo '#{action.description}'"
98
+ commands = "touch #{prerequisite_list}; if grep -vz #{action_name} #{prerequisite_list}; then #{commands.join(' && ')}; else echo 'Already Done'; fi"
99
+ Trooper.logger.action "Prerequisite: #{action.description}"
71
100
  else
72
- instance_eval &block
101
+ Trooper.logger.action action.description
73
102
  end
103
+
104
+ commands
105
+ else
106
+ raise MissingActionError, "Cant find action: #{action_name}"
74
107
  end
75
108
  end
76
109
 
77
- def action_execute(runner, name)
78
- action = Arsenal.actions[name]
110
+ def method_missing(method_sym, *arguments, &block)
111
+ config[method_sym] || super
112
+ end
79
113
 
80
- if action
81
- commands = action.call config
82
- Trooper.logger.action action.description
83
- runner_execute!(runner, commands)
114
+ private
115
+
116
+ def eval_block
117
+ if @block
118
+ instance_eval &@block
84
119
  end
85
120
  end
86
121
 
@@ -1,29 +1,38 @@
1
+ #Basic settings
1
2
  user 'my_user'
2
3
  hosts 'stage.example.com'
4
+ path "/fullpath/to/folder"
3
5
  repository 'git@git.bar.co.uk:whatever.git'
4
- path "/path/to/data/folder"
6
+ # ruby_bin_path "/fullpath/to/ruby/bin/folder" # Define if you have issues with gems
5
7
 
6
- set :my_value => 'something'
8
+ # set :my_value => 'something' # Setting a custom value
7
9
 
8
- env :production do
9
- hosts 'production1.example.com', 'production2.example.com'
10
- set :my_value => 'something_else'
10
+ # Set environment specific settings and or actions
11
+ # env :stage do
12
+ # hosts 'stage.example.com', 'stage.example.com'
13
+ # set :my_value => 'something_else'
11
14
 
12
- action :restart do
13
- run 'touch tmp/restert.txt'
14
- end
15
- end
15
+ # action :my_action do
16
+ # #some action
17
+ # end
18
+ # end
19
+
20
+ # action :my_action do
21
+ # #some action
22
+ # end
16
23
 
17
- action :restart do
18
- run 'touch tmp/restert.txt'
24
+ strategy :setup, 'Setting up Application on the Server' do
25
+ actions :setup_trooper, :clone_repository, :setup_database
19
26
  end
20
27
 
21
28
  strategy :update, 'Update the code base on the server' do
29
+ prerequisites :setup
22
30
  actions :update_repository, :install_gems
23
31
  call :restart
24
32
  end
25
33
 
26
34
  strategy :deploy, 'Full deployment to the server' do
35
+ prerequisites :setup
27
36
  call :update
28
37
  actions :migrate_database
29
38
  call :restart
@@ -3,7 +3,7 @@ module Trooper
3
3
  MAJOR = 0
4
4
  MINOR = 6
5
5
  TINY = 0
6
- PRE = 'alpha2'
6
+ PRE = 'beta'
7
7
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
8
8
  end
9
9
  end
data/lib/trooper.rb CHANGED
@@ -11,6 +11,10 @@ module Trooper
11
11
  class MissingStrategyError < TrooperError
12
12
  end
13
13
 
14
+ # When a acton is not defined
15
+ class MissingActionError < TrooperError
16
+ end
17
+
14
18
  # When a CLI argument is missing or badly formed
15
19
  class CliArgumentError < TrooperError
16
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trooper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.alpha2
4
+ version: 0.6.0.beta
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-16 00:00:00.000000000 Z
12
+ date: 2012-07-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-ssh
@@ -168,13 +168,16 @@ files:
168
168
  - lib/trooper/actions/clone_repository_action.rb
169
169
  - lib/trooper/actions/install_gems_action.rb
170
170
  - lib/trooper/actions/migrate_database_action.rb
171
+ - lib/trooper/actions/prepare_prerequisite_action.rb
171
172
  - lib/trooper/actions/restart_server_action.rb
172
173
  - lib/trooper/actions/rollback_migrate_action.rb
173
174
  - lib/trooper/actions/setup_database_action.rb
175
+ - lib/trooper/actions/setup_trooper_action.rb
174
176
  - lib/trooper/actions/update_repository_action.rb
175
177
  - lib/trooper/arsenal.rb
176
178
  - lib/trooper/cli.rb
177
179
  - lib/trooper/config/action.rb
180
+ - lib/trooper/config/defaults.rb
178
181
  - lib/trooper/config/environment.rb
179
182
  - lib/trooper/config/strategy.rb
180
183
  - lib/trooper/configuration.rb
@@ -205,7 +208,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
208
  version: '0'
206
209
  segments:
207
210
  - 0
208
- hash: 987069315358731721
211
+ hash: -2382425093214391347
209
212
  required_rubygems_version: !ruby/object:Gem::Requirement
210
213
  none: false
211
214
  requirements: