bigpanda 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ require 'bigpanda/bp-api'
@@ -0,0 +1,134 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'net/https'
4
+
5
+ module BigPanda
6
+
7
+ VERSION = '0.1.0'
8
+
9
+ DEFAULT_CONFIG_FILES = [ "/etc/bigpanda.yaml", "/etc/bigpanda.yml" ]
10
+ DEFAULT_CONFIGURATION = { # overridable via the configuration file
11
+ :access_token => nil,
12
+ :target_url => 'https://api.bigpanda.io',
13
+ :deployment_start_path => '/data/events/deployments/start',
14
+ :deployment_end_path => '/data/events/deployments/end'
15
+ }
16
+
17
+ #
18
+ # Main BigPanda API Class
19
+ #
20
+ # The client needs to be initialized with the access_token of the organization.
21
+ # Possible options:
22
+ # 1. Pass the access_token as a :access_token parameter
23
+ # 2. Place a bigpanda.yaml file in /etc/ and add to the file - 'access_token': YOUR_TOKEN
24
+ # 3. Pass a location of a yaml file using the :file parameter
25
+ #
26
+ #
27
+ class Client
28
+ attr_reader :config, :ssl
29
+
30
+ def initialize(options = {})
31
+
32
+ unless options.fetch(:access_token, nil)
33
+ file = options.delete(:file)
34
+ file_config, config_files = read_config_from_file(file)
35
+ options.merge!(file_config) if file_config
36
+ end
37
+
38
+ @config = DEFAULT_CONFIGURATION.merge(options)
39
+ @ssl = options.delete(:ssl) || {}
40
+
41
+ unless @config.fetch(:access_token, nil)
42
+ raise "No BigPanda config token received, and no configuration file found. Searched: #{config_files.join ','}."
43
+ end
44
+ end
45
+
46
+ def deployment_start(options = {})
47
+ return deployment_notification config[:deployment_start_path], options
48
+ end
49
+
50
+ def deployment_end(options = {})
51
+ return deployment_notification config[:deployment_end_path], options
52
+ end
53
+
54
+ private
55
+
56
+ class Error < RuntimeError; end
57
+ class Unauthorized < RuntimeError; end
58
+
59
+ # Prepare the call to BigPanda API and send a HTTP Request
60
+ #
61
+ def deployment_notification(path, options)
62
+ place_default_values(options)
63
+
64
+ return request path, JSON.generate(options)
65
+ end
66
+
67
+ # Perform the actual request to BigPanda API
68
+ #
69
+ def request(path, body, target_url = config[:target_url])
70
+ headers = { 'Accept' => 'application/json',
71
+ 'Content-Type' => 'application/json',
72
+ 'Authorization' => "Bearer #{config[:access_token]}" }
73
+
74
+ uri = URI.parse(target_url)
75
+ h = Net::HTTP.new uri.host, uri.port
76
+ h.set_debug_output $stderr if $DEBUG
77
+ h.use_ssl = (uri.scheme.downcase == 'https')
78
+
79
+ set_ssl_overrides(h)
80
+
81
+ h.start do |http|
82
+ response = http.request_post path, body, headers
83
+ raise Unauthorized if response.code.to_i == 401
84
+ raise Error, "server error: #{response.body}" if response.code.to_i >= 500
85
+
86
+ answer = JSON.load(response.body)['response']
87
+ raise Error, answer['errors'].join(", ") if response.code.to_i >= 400
88
+
89
+ return answer
90
+ end
91
+ end
92
+
93
+ def place_default_values(options)
94
+ options[:timestamp] = options.fetch(:timestamp, Time.now.utc.to_i) # unix time
95
+
96
+ if options.has_key?(:hosts)
97
+ options[:hosts] = options[:hosts].kind_of?(Array) ? options[:hosts] : [options[:hosts]]
98
+ end
99
+ end
100
+
101
+ # Read configuration from the default list of configuration files and the received file.
102
+ #
103
+ # Returns the the found configuration and the list of files which were used.
104
+ #
105
+ def read_config_from_file(file)
106
+
107
+ config_files = ([file] + DEFAULT_CONFIG_FILES).compact
108
+ config = nil
109
+
110
+ config_files.each do |config_file|
111
+ if File.exists? config_file
112
+ config = YAML.load_file(config_file)
113
+
114
+ # Convert string keys to symbols
115
+ config.keys.each do |key|
116
+ config[(key.to_sym rescue key) || key] = config.delete(key)
117
+ end
118
+ end
119
+ end
120
+
121
+ return config, config_files
122
+ end
123
+
124
+ def set_ssl_overrides(http)
125
+ http.certificate = ssl[:client_cert] if ssl[:client_cert]
126
+ http.private_key = ssl[:client_key] if ssl[:client_key]
127
+ http.ca_file = ssl[:ca_file] if ssl[:ca_file]
128
+ http.ssl_version = ssl[:version] if ssl[:version]
129
+ http.verify_mode = ssl[:verify_mode] if ssl[:verify_mode]
130
+ end
131
+
132
+ end
133
+ end
134
+
@@ -0,0 +1,81 @@
1
+ require 'bigpanda'
2
+
3
+ Capistrano::Configuration.instance(:must_exist).load do |config|
4
+
5
+ namespace :bigpanda do
6
+
7
+ desc '[Internal] Notifies BigPanda that a deployment has started'
8
+ task :notify_deploy_started do
9
+ transaction do
10
+ on_rollback do
11
+ notify_deploy_failed
12
+ end
13
+
14
+ send_deployment_start
15
+ end
16
+ end
17
+
18
+ desc '[Internal] Notifies BigPanda that a deployment has finished successfuly'
19
+ task :notify_deploy_finished do
20
+ send_deployment_end('success')
21
+ end
22
+
23
+ desc '[Internal] Notifies BigPanda that a deployment has finished with an error'
24
+ task :notify_deploy_failed do
25
+ send_deployment_end('failure', errorMessage: 'failed to deploy')
26
+ end
27
+
28
+ end
29
+
30
+ # Map capistrano execution variables to BigPanda Fields for deployment start
31
+ #
32
+ # == Parameters:
33
+ # optional Hash which can contain all propriatery fields
34
+ #
35
+ def send_deployment_start(properties = {})
36
+ panda = create_bigpanda_client
37
+
38
+ panda.deployment_start({:component => application,
39
+ :version => "#{fetch(:branch, '')} #{release_name}",
40
+ :hosts => find_servers_for_task(current_task),
41
+ :env => rails_env,
42
+ :owner => fetch(:bp_owner, nil),
43
+ :properties => properties
44
+ })
45
+ rescue Exception => e
46
+ logger.important "err :: while sending BigPanda start, Skipping to next command. #{e.message}"
47
+ end
48
+
49
+ # Map capistrano execution variables to BigPanda Fields for deployment end
50
+ #
51
+ # == Parameters:
52
+ # optional Hash which can contain all propriatery fields
53
+ #
54
+ def send_deployment_end(status, properties = {})
55
+ panda = create_bigpanda_client
56
+
57
+ errorMessage = properties.delete(:errorMessage)
58
+
59
+ panda.deployment_end({ :component => application,
60
+ :version => "#{fetch(:branch, '')} #{release_name}",
61
+ :hosts => find_servers_for_task(current_task),
62
+ :status => status,
63
+ :env => rails_env,
64
+ :errorMessage => errorMessage,
65
+ :properties => properties})
66
+ rescue Exception => e
67
+ logger.important "err :: while sending BigPanda start, Skipping to next command. #{e.message}"
68
+ end
69
+
70
+
71
+ def create_bigpanda_client
72
+ BigPanda::Client.new(:access_token => fetch(:bigpanda_access_token, nil))
73
+ end
74
+
75
+
76
+ # Hooks:
77
+ # Wrap deploy execution
78
+
79
+ before "deploy:update_code", "bigpanda:notify_deploy_started"
80
+ after "deploy", "bigpanda:notify_deploy_finished"
81
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bigpanda
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - BigPanda
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: A Ruby client (and additional integrations) for BigPanda's API
31
+ email: support@bigpanda.io
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/bigpanda.rb
37
+ - lib/bigpanda/capistrano.rb
38
+ - lib/bigpanda/bp-api.rb
39
+ homepage: https://github.com/bigpandaio/bigpanda-rb
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.24
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: A Ruby client (and additional integrations) for BigPanda's API
63
+ test_files: []