capistrano-hivequeen 0.9.1 → 1.0.0

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