capistrano-hivequeen 0.9.1 → 1.0.0

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.
@@ -1,3 +1,5 @@
1
+ require File.expand_path('./lib/capistrano/hivequeen/version.rb')
2
+
1
3
  Gem::Specification.new do |s|
2
4
  s.specification_version = 2 if s.respond_to? :specification_version=
3
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
@@ -6,7 +8,7 @@ Gem::Specification.new do |s|
6
8
  ## If your rubyforge_project name is different, then edit it and comment out
7
9
  ## the sub! line in the Rakefile
8
10
  s.name = 'capistrano-hivequeen'
9
- s.version = '0.9.1'
11
+ s.version = HiveQueen::Version.to_s
10
12
  s.date = Time.now.strftime("%Y-%m-%d")
11
13
 
12
14
  ## Make sure your summary is short. The description may be as long
@@ -35,8 +37,8 @@ Gem::Specification.new do |s|
35
37
 
36
38
  ## List your runtime dependencies here. Runtime dependencies are those
37
39
  ## that are needed for an end user to actually USE your code.
38
- s.add_dependency('capistrano-ext')
39
- s.add_dependency('capistrano')
40
+ s.add_dependency('capistrano-ext', '= 1.2.1')
41
+ s.add_dependency('capistrano', '~> 2.11.2')
40
42
  s.add_dependency('json')
41
43
  s.add_dependency('excon', '>= 0.6.0') # Perhaps we can support older. Haven't checked.
42
44
 
@@ -1,80 +1,123 @@
1
- # Load environment configuration from HiveQueen
2
- require "capistrano/hivequeen/server"
3
-
4
- Capistrano::Configuration.instance(:must_exist).load do
5
- HiveQueen.endpoint = hivequeen_endpoint
6
- HiveQueen.project = application
7
- HiveQueen.logger = logger
8
- HiveQueen.get_credentials!
9
-
10
- # Redefine stage tasks from multistage extension
11
- # Set the list of available stages
12
- set :stages, HiveQueen.environment_names
13
-
14
- # Default to using the current branch as the stage name
15
- # NB: current branch may not be set
16
- current_branch = `git symbolic-ref HEAD`.chomp.sub('refs/heads/', '')
17
- unless current_branch.empty?
18
- env_name = HiveQueen.environment_for_branch(current_branch)
19
- set(:default_stage, env_name) if env_name
20
- end
1
+ # HTTP Client for Hive Queen environment configuration
2
+ require 'json'
3
+ require 'fileutils'
4
+ require 'excon'
5
+ require 'base64'
6
+ require 'capistrano/hivequeen/version'
21
7
 
22
- set :repository, HiveQueen.repository
23
- set :scm, :git
24
- ssh_options[:forward_agent] = true
25
-
26
- # By default, don't override deployments if there's another deployment in progress.
27
- # From the command line, use -s override=true to force a deployment
28
- set :override, false
29
-
30
- # Time to wait for Background jobs processes to start/stop
31
- set :bg_wait_time, 30
32
-
33
- # Option to skip background tasks
34
- set :skip_bg, false
35
-
36
- # Load capistrano multi-stage extension
37
- require 'fileutils' # required until https://github.com/capistrano/capistrano-ext/commit/930ca840a0b4adad0ec53546790b3f5ffe726538 is released
38
- require 'capistrano/ext/multistage'
39
- require 'capistrano/hivequeen/setup'
40
- require 'capistrano/hivequeen/deploy'
41
-
42
- # Redefine stage tasks from multistage extension
43
- HiveQueen.environments.each do |env|
44
- name = env['name']
45
- hive_queen_id = env['id']
46
-
47
- desc "Use environment #{name}"
48
- task name do
49
- environment = HiveQueen.roles(hive_queen_id)
50
- # Check if environment is ready
51
- unless environment['state'] == 'running'
52
- abort "Environment #{name} is not ready. State: #{environment['state']}"
53
- end
8
+ # Special cases:
9
+ # - environment not found
10
+ # - environment not ready: fail
11
+ class HiveQueen
12
+ class DeploymentError < Exception; end
13
+ class InsecureCredentials < Exception; end
54
14
 
55
- set :stage, name.to_sym
56
- set :rails_env, name
57
- set :environment_id, hive_queen_id
58
- unless exists?(:branch)
59
- set :branch, environment['branch']
60
- end
15
+ class << self
16
+ attr_accessor :endpoint, :logger, :project, :username, :password
17
+
18
+ def project_data
19
+ @project_data ||= get("/projects/#{project}.json")
20
+ end
21
+
22
+ def environments
23
+ project_data['environments']
24
+ end
25
+
26
+ def environment_names
27
+ environments.map{|e| e['name'].to_sym }
28
+ end
29
+
30
+ def environment_for_branch(branch)
31
+ env = environments.detect{|e| e['branch'] == branch }
32
+ env['name'] if env
33
+ end
34
+
35
+ def repository
36
+ project_data['repo']
37
+ end
38
+
39
+ def roles(env_id)
40
+ env_id = env_id.to_sym
41
+ @roles ||= {}
42
+ @roles[env_id] ||= get("/environments/#{env_id}.json")
43
+ end
61
44
 
62
- # Set servers for each role
63
- environment['roles'].each do |role_name, role_config|
64
- role(role_name.to_sym) { role_config['servers'] }
45
+ def start_deployment(environment_id, params)
46
+ required_params = [:task, :commit]
47
+ required_params.each do |key|
48
+ raise ArgumentError.new("#{key} is a required param") unless params.key?(key)
65
49
  end
50
+ put_or_post('POST', "/environments/#{environment_id}/deployments.json", :deployment => params)
51
+ end
52
+
53
+ def finish_deployment(environment_id, deployment_id)
54
+ state = $! ? 'failed' : 'succeeded'
55
+ puts "Finishing deployment in Hivequeen. State: #{state}"
56
+ params = {:deployment => {:state => state}}
57
+ put_or_post('PUT', "/environments/#{environment_id}/deployments/#{deployment_id}.json", params)
58
+ end
59
+
60
+ # Load credentials from ~/.hivequeen
61
+ def get_credentials!
62
+ @username, @password = File.read(credential_path).chomp.split(':')
63
+ raise unless username && password
64
+ # Check that credentials are not accessible to world or group
65
+ mode = File.stat(credential_path).mode
66
+ raise InsecureCredentials unless (mode % 64 == 0)
67
+ rescue InsecureCredentials
68
+ puts "#{credential_path} is insecure. Please change you password and run"
69
+ puts "chmod 600 #{credential_path}"
70
+ exit 1
71
+ rescue Errno::ENOENT, RuntimeError
72
+ puts "Could not read HiveQueen credentials from #{credential_path}."
73
+ puts "#{credential_path} should contain your username and password seperated by a colon"
74
+ puts "Run this command with your credentials:"
75
+ puts " $ echo username:password > #{credential_path}; chmod 600 #{credential_path}"
76
+ exit 1
77
+ end
78
+
79
+ protected
80
+ def credential_path
81
+ File.join(ENV['HOME'], '.hivequeen')
82
+ end
66
83
 
67
- # Ensure some server designated as db server
68
- unless roles.key?(:db)
69
- # Prefer the bg server
70
- db_server = roles[:bg].servers.first if roles.key?(:bg)
84
+ def connection
85
+ Excon.new(endpoint)
86
+ end
71
87
 
72
- # Otherwise, use any server
73
- db_server ||= roles.values.map{|x| x.servers}.flatten.compact.first
74
- logger.trace "Using #{db_server} as primary db server"
75
- role :db, db_server.to_s, :primary => true
88
+ def auth_header
89
+ value = Base64.encode64([username, password] * ':').chomp
90
+ { 'Authorization' => "Basic #{value}" }
91
+ end
92
+
93
+ def get(path)
94
+ url = "#{endpoint}#{path}"
95
+ logger.trace "Fetching #{url}"
96
+ response = connection.request(:method => 'GET', :path => path, :headers => auth_header)
97
+ unless (200..299).include?(response.status)
98
+ raise "Request to #{url} returned #{response.status} status"
76
99
  end
100
+ JSON.parse(response.body)
101
+ end
77
102
 
103
+ def put_or_post(method, path, data)
104
+ headers = auth_header.merge("Content-type"=>"application/json", "Accept"=>"application/json")
105
+ response = connection.request(:path => path, :method => method, :headers => headers, :body => data.to_json)
106
+ case response.status
107
+ when 204
108
+ # Do nothing
109
+ when (200..299)
110
+ JSON.parse(response.body)
111
+ when (400..499)
112
+ errors = JSON.parse(response.body)
113
+ raise DeploymentError.new(errors.inspect)
114
+ else
115
+ raise "Request to #{path} returned #{response.status} status"
116
+ end
78
117
  end
118
+
79
119
  end
80
120
  end
121
+
122
+ require "capistrano/hivequeen/capistrano_configuration"
123
+
@@ -0,0 +1,77 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+ HiveQueen.endpoint = hivequeen_endpoint
3
+ HiveQueen.project = application
4
+ HiveQueen.logger = logger
5
+ HiveQueen.get_credentials!
6
+
7
+ # Redefine stage tasks from multistage extension
8
+ # Set the list of available stages
9
+ set :stages, HiveQueen.environment_names
10
+
11
+ # Default to using the current branch as the stage name
12
+ # NB: current branch may not be set
13
+ current_branch = `git symbolic-ref HEAD`.chomp.sub('refs/heads/', '')
14
+ unless current_branch.empty?
15
+ env_name = HiveQueen.environment_for_branch(current_branch)
16
+ set(:default_stage, env_name) if env_name
17
+ end
18
+
19
+ set :repository, HiveQueen.repository
20
+ set :scm, :git
21
+ ssh_options[:forward_agent] = true
22
+
23
+ # By default, don't override deployments if there's another deployment in progress.
24
+ # From the command line, use -s override=true to force a deployment
25
+ set :override, false
26
+
27
+ # Time to wait for Background jobs processes to start/stop
28
+ set :bg_wait_time, 30
29
+
30
+ # Option to skip background tasks
31
+ set :skip_bg, false
32
+
33
+ # Load capistrano multi-stage extension
34
+ require 'fileutils' # required until https://github.com/capistrano/capistrano-ext/commit/930ca840a0b4adad0ec53546790b3f5ffe726538 is released
35
+ require 'capistrano/ext/multistage'
36
+ require 'capistrano/hivequeen/setup'
37
+ require 'capistrano/hivequeen/deploy'
38
+
39
+ # Redefine stage tasks from multistage extension
40
+ HiveQueen.environments.each do |env|
41
+ name = env['name']
42
+ hive_queen_id = env['id']
43
+
44
+ desc "Use environment #{name}"
45
+ task name do
46
+ environment = HiveQueen.roles(hive_queen_id)
47
+ # Check if environment is ready
48
+ unless environment['state'] == 'running'
49
+ abort "Environment #{name} is not ready. State: #{environment['state']}"
50
+ end
51
+
52
+ set :stage, name.to_sym
53
+ set :rails_env, name
54
+ set :environment_id, hive_queen_id
55
+ unless exists?(:branch)
56
+ set :branch, environment['branch']
57
+ end
58
+
59
+ # Set servers for each role
60
+ environment['roles'].each do |role_name, role_config|
61
+ role(role_name.to_sym) { role_config['servers'] }
62
+ end
63
+
64
+ # Ensure some server designated as db server
65
+ unless roles.key?(:db)
66
+ # Prefer the bg server
67
+ db_server = roles[:bg].servers.first if roles.key?(:bg)
68
+
69
+ # Otherwise, use any server
70
+ db_server ||= roles.values.map{|x| x.servers}.flatten.compact.first
71
+ logger.trace "Using #{db_server} as primary db server"
72
+ role :db, db_server.to_s, :primary => true
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,10 @@
1
+ class HiveQueen
2
+ class Version
3
+ @@version = '1.0.0'
4
+
5
+ def self.to_s
6
+ @@version
7
+ end
8
+
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-hivequeen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,33 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-21 00:00:00.000000000 Z
12
+ date: 2012-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano-ext
16
- requirement: &70238578596280 !ruby/object:Gem::Requirement
16
+ requirement: &70240114614400 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - =
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 1.2.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70238578596280
24
+ version_requirements: *70240114614400
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: capistrano
27
- requirement: &70238578595320 !ruby/object:Gem::Requirement
27
+ requirement: &70240114612720 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
- - - ! '>='
30
+ - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 2.11.2
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70238578595320
35
+ version_requirements: *70240114612720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: json
38
- requirement: &70238578594620 !ruby/object:Gem::Requirement
38
+ requirement: &70240114611740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70238578594620
46
+ version_requirements: *70240114611740
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: excon
49
- requirement: &70238578593960 !ruby/object:Gem::Requirement
49
+ requirement: &70240114610620 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: 0.6.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70238578593960
57
+ version_requirements: *70240114610620
58
58
  description: Capistrano extensions for interacting with HiveQueen
59
59
  email: aaron@kickstarter.com
60
60
  executables: []
@@ -66,9 +66,10 @@ files:
66
66
  - README.rdoc
67
67
  - capistrano-hivequeen.gemspec
68
68
  - lib/capistrano/hivequeen.rb
69
+ - lib/capistrano/hivequeen/capistrano_configuration.rb
69
70
  - lib/capistrano/hivequeen/deploy.rb
70
- - lib/capistrano/hivequeen/server.rb
71
71
  - lib/capistrano/hivequeen/setup.rb
72
+ - lib/capistrano/hivequeen/version.rb
72
73
  homepage: http://github.com/kickstarter/capistrano-hivequeen
73
74
  licenses: []
74
75
  post_install_message:
@@ -1,117 +0,0 @@
1
- # HTTP Client for Hive Queen environment configuration
2
- require 'json'
3
- require 'fileutils'
4
- require 'excon'
5
- require 'base64'
6
-
7
- # Special cases:
8
- # - environment not found
9
- # - environment not ready: fail
10
- class HiveQueen
11
- class DeploymentError < Exception; end
12
- class InsecureCredentials < Exception; end
13
-
14
- class << self
15
- attr_accessor :endpoint, :logger, :project, :username, :password
16
-
17
- def project_data
18
- @project_data ||= get("/projects/#{project}.json")
19
- end
20
-
21
- def environments
22
- project_data['environments']
23
- end
24
-
25
- def environment_names
26
- environments.map{|e| e['name'].to_sym }
27
- end
28
-
29
- def environment_for_branch(branch)
30
- env = environments.detect{|e| e['branch'] == branch }
31
- env['name'] if env
32
- end
33
-
34
- def repository
35
- project_data['repo']
36
- end
37
-
38
- def roles(env_id)
39
- env_id = env_id.to_sym
40
- @roles ||= {}
41
- @roles[env_id] ||= get("/environments/#{env_id}.json")
42
- end
43
-
44
- def start_deployment(environment_id, params)
45
- required_params = [:task, :commit]
46
- required_params.each do |key|
47
- raise ArgumentError.new("#{key} is a required param") unless params.key?(key)
48
- end
49
- put_or_post('POST', "/environments/#{environment_id}/deployments.json", :deployment => params)
50
- end
51
-
52
- def finish_deployment(environment_id, deployment_id)
53
- state = $! ? 'failed' : 'succeeded'
54
- puts "Finishing deployment in Hivequeen. State: #{state}"
55
- params = {:deployment => {:state => state}}
56
- put_or_post('PUT', "/environments/#{environment_id}/deployments/#{deployment_id}.json", params)
57
- end
58
-
59
- # Load credentials from ~/.hivequeen
60
- def get_credentials!
61
- @username, @password = File.read(credential_path).chomp.split(':')
62
- raise unless username && password
63
- # Check that credentials are not accessible to world or group
64
- mode = File.stat(credential_path).mode
65
- raise InsecureCredentials unless (mode % 64 == 0)
66
- rescue InsecureCredentials
67
- puts "#{credential_path} is insecure. Please change you password and run"
68
- puts "chmod 600 #{credential_path}"
69
- exit 1
70
- rescue Errno::ENOENT, RuntimeError
71
- puts "Could not read HiveQueen credentials from #{credential_path}."
72
- puts "#{credential_path} should contain your username and password seperated by a colon"
73
- puts "Run this command with your credentials:"
74
- puts " $ echo username:password > #{credential_path}; chmod 600 #{credential_path}"
75
- exit 1
76
- end
77
-
78
- protected
79
- def credential_path
80
- File.join(ENV['HOME'], '.hivequeen')
81
- end
82
-
83
- def connection
84
- Excon.new(endpoint)
85
- end
86
-
87
- def auth_header
88
- value = Base64.encode64([username, password] * ':').chomp
89
- { 'Authorization' => "Basic #{value}" }
90
- end
91
-
92
- def get(path)
93
- url = "#{endpoint}#{path}"
94
- logger.trace "Fetching #{url}"
95
- response = connection.request(:method => 'GET', :path => path, :headers => auth_header)
96
- unless (200..299).include?(response.status)
97
- raise "Request to #{url} returned #{response.status} status"
98
- end
99
- JSON.parse(response.body)
100
- end
101
-
102
- def put_or_post(method, path, data)
103
- headers = auth_header.merge("Content-type"=>"application/json", "Accept"=>"application/json")
104
- response = connection.request(:path => path, :method => method, :headers => headers, :body => data.to_json)
105
- case response.status
106
- when (200..299)
107
- JSON.parse(response.body)
108
- when (400..499)
109
- errors = JSON.parse(response.body)
110
- raise DeploymentError.new(errors.inspect)
111
- else
112
- raise "Request to #{path} returned #{response.status} status"
113
- end
114
- end
115
-
116
- end
117
- end