etoro_utility_mcollective 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YmE5OWRlYTc4MGZiZjY2ZDZiZWY0NjkyYTYwNGU0MzU5MmUxNTg1YQ==
5
+ data.tar.gz: !binary |-
6
+ YmIxM2Q4NjRmZjZlYzRkZWVlNmY5YWE1NTE1OThjMzIxZTNiOGZiZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NzU3MTc0N2QzOTg3YWVhZjRjYjU3Nzc2YTk2YjVhNjRmZDQ0ZTI2OGI0M2Rh
10
+ NzBhMzRkNmIyZWVhYWJkZDM5NGE2NTk3ZmRjMGM3OTA2N2NjNDAwNTgwYmE5
11
+ NTZiY2EwN2ZkMmFmNTIzMzE4ODBhMzIyNmU3Zjc1NDBmOWQxNzA=
12
+ data.tar.gz: !binary |-
13
+ Mjg5YTY0M2Y1OTFjNWUwMTBiZjA0NWY1YmM5ZTY4MTZiOTc5ODRhZjVmYTk5
14
+ ZGYxYjEzMzM5YmJlMmNhY2JhMTk0YWNmZmFmYjZkMmMyYTg1NzNmNDBiOGY2
15
+ NThlMjJlNjg5ZGRjMzViNjAxOTViOWVkMzE4NzlhYjRlZGVmM2E=
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in etoro_utility_mcollective.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Alon Becker
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # EtoroUtilityMcollective
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'etoro_utility_mcollective'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install etoro_utility_mcollective
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'etoro_utility_mcollective/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "etoro_utility_mcollective"
8
+ spec.version = EtoroUtilityMcollective::VERSION
9
+ spec.authors = ["Alon Becker"]
10
+ spec.email = ["alon@etoro.com"]
11
+ spec.description = %q{test}
12
+ spec.summary = %q{test}
13
+ spec.homepage = "http://www.etoro.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,77 @@
1
+ module Etoro
2
+ module Utility
3
+ module MCollective
4
+ class HAProxy < Etoro::Utility::MCollective::RPC
5
+
6
+ def validate(config)
7
+ super
8
+ unless config.has_key?(:action)
9
+ raise RuntimeError, "config[:action] must be defined"
10
+ end
11
+ unless ['enable','maintenance'].include? config[:action]
12
+ raise RuntimeError, "Haproxy service value must be either enable or maintenance"
13
+ end
14
+ end
15
+
16
+ def execute
17
+ @state = ''
18
+ case @config[:action]
19
+ when 'enable'
20
+ @state = 'UP'
21
+ when 'maintenance'
22
+ @state = 'DOWN'
23
+ end
24
+ @logger.info("HAProxy - Bringing #{@state}")
25
+ @mc.send @config[:action]
26
+ sleep @config[:wait_for_status]
27
+ self.check_run_status
28
+ end
29
+
30
+ def status
31
+ @haproxy_status = {}
32
+ @logger.info("Getting HAProxy status")
33
+ @mc.status.each do |result|
34
+ @haproxy_status[result[:sender]] = result[:data][:msg]
35
+ @logger.info("#{result[:sender]} - HAProxy #{result[:data][:msg]}")
36
+ end
37
+ end
38
+
39
+ def hosts
40
+ hosts = []
41
+ @haproxy_status.each_key do |host|
42
+ hosts.push host
43
+ end
44
+ hosts
45
+ end
46
+
47
+ def check_run_status
48
+ @logger.info("Checking HAProxy for completion")
49
+
50
+ begin
51
+ timeout(@config[:timeout]) do
52
+ until @haproxy_status == {}
53
+ @haproxy_status.each do |host, status|
54
+ run = rpcclient(self.class.name.downcase.split('::').last, :chomp => true)
55
+ run.identity_filter host
56
+ run.progress = false
57
+ results = run.status
58
+ results.each do |result|
59
+ if result[:data][:msg] == @state
60
+ @logger.info("#{host} - HAProxy: #{result[:data][:msg]}")
61
+ @haproxy_status.delete(host)
62
+ else
63
+ @logger.info("#{host} - HAProxy action not complete")
64
+ end
65
+ end
66
+ end
67
+ sleep @config[:wait_between_checks]
68
+ end
69
+ end
70
+ rescue Timeout::Error
71
+ @logger.error("HAProxy run timed out. Took more than #{@config[:timeout]} seconds")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,24 @@
1
+ module Etoro
2
+ module Utility
3
+ module MCollective
4
+ class MultiDelegator
5
+ def initialize(*targets)
6
+ @targets = targets
7
+ end
8
+
9
+ def self.delegate(*methods)
10
+ methods.each do |m|
11
+ define_method(m) do |*args|
12
+ @targets.map { |t| t.send(m, *args) }
13
+ end
14
+ end
15
+ self
16
+ end
17
+
18
+ class <<self
19
+ alias to new
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ module Etoro
2
+ module Utility
3
+ module MCollective
4
+ class Puppet < Etoro::Utility::MCollective::RPC
5
+
6
+ def status
7
+ @last_run_puppet = {}
8
+ @logger.info("Getting last puppet run information")
9
+ @mc.last_run_summary.each do |result|
10
+ @last_run_puppet[result[:sender]] = result[:data][:lastrun]
11
+ @logger.info("#{result[:sender]} - Puppet last run: #{result[:data][:lastrun]}")
12
+ end
13
+ end
14
+
15
+ def execute
16
+ @mc.runonce
17
+ sleep @config[:wait_for_status]
18
+ self.check_run_status
19
+ end
20
+
21
+ def hosts
22
+ hosts = []
23
+ @last_run_puppet.each_key do |host|
24
+ hosts.push host
25
+ end
26
+ hosts
27
+ end
28
+
29
+ def check_run_status
30
+ @logger.info("Checking for Puppet run completion")
31
+ exit_flag = false
32
+ begin
33
+ timeout(@config[:timeout]) do
34
+ until @last_run_puppet == {}
35
+ @last_run_puppet.each do |host, lastrun|
36
+ run = rpcclient('puppet', :chomp => true)
37
+ run.identity_filter host
38
+ run.progress = false
39
+ results = run.last_run_summary
40
+ results.each do |result|
41
+ @logger.info("#{host} - Puppet last run: #{result[:data][:lastrun]}")
42
+ if lastrun != result[:data][:lastrun]
43
+ @logger.info("#{host} - run completed")
44
+ @last_run_puppet.delete(host)
45
+ if result[:data][:summary]['resources']['failed'] != 0
46
+ @logger.error("#{host} - Puppet run failed.")
47
+ exit_flag = true
48
+ end
49
+ else
50
+ @logger.info("#{host} - Puppet not complete")
51
+ end
52
+ end
53
+ end
54
+ sleep @config[:wait_between_checks]
55
+ end
56
+ end
57
+ rescue Timeout::Error
58
+ @logger.error("Puppet run timed out. Took more than #{@config[:timeout]} seconds")
59
+ exit_flag = true
60
+ end
61
+
62
+ if exit_flag == true then
63
+ @logger.error("Puppet run failed")
64
+ exit 1
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,159 @@
1
+ require 'mcollective'
2
+ require 'timeout'
3
+ require 'logger'
4
+
5
+ include MCollective::RPC
6
+
7
+ module Etoro
8
+ module Utility
9
+ module MCollective
10
+ class RPC
11
+
12
+ attr :current_host
13
+ attr_reader :hosts, :execute ,:pre_execute, :post_execute
14
+
15
+ def initialize (config={})
16
+
17
+ default_config = {
18
+ timeout: 600,
19
+ log_file: 'deployment.log',
20
+ log_level: Logger::INFO,
21
+ sequential: false,
22
+ wait_for_status: 30,
23
+ wait_between_checks: 5
24
+ }
25
+ @config = default_config.merge(config)
26
+
27
+ self.validate(config)
28
+
29
+ @mc = rpcclient(self.class.name.downcase.split('::').last, :chomp => true)
30
+ @mc.progress = false
31
+
32
+ log_descriptor = ""
33
+ if (@config.has_key?(:fact_filter) && @config[:fact_filter].has_key?(:service) && @config[:fact_filter].has_key?(:application)) || (@config.has_key?(:application) && @config.has_key?(:service))
34
+ if @config.has_key?(:fact_filter)
35
+ service=@config[:fact_filter][:service]
36
+ application=@config[:fact_filter][:application]
37
+ else
38
+ service=@config[:service]
39
+ application=@config[:application]
40
+ end
41
+ log_descriptor="service=#{service}, application=#{application},"
42
+ end
43
+
44
+ self.logging(@config[:log_file],@config[:log_level],log_descriptor)
45
+ @logger.info("Setting timeout to #{@config[:timeout]}")
46
+ @logger.info("Setting log file to #{@config[:log_file]}")
47
+ @logger.info("Setting log level to #{@config[:log_level]}")
48
+
49
+ @config.each do |key,value|
50
+ case key
51
+ when :fact_filter
52
+ self.fact_filter(value)
53
+ when :identity_filter
54
+ self.identity_filter(value)
55
+ when :class_filter
56
+ self.identity_filter(value)
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ def validate(config)
63
+ unless config.detect{|k| k.to_s =~ /:(fact|identity|class)_filter/} then
64
+ raise RuntimeError, "Filters need to be provided"
65
+ end
66
+ if self.class.name == 'Etoro::MCollective::RPC'
67
+ raise RuntimeError, "Cannot instantiate this class directly - abstract"
68
+ end
69
+ end
70
+
71
+ def sequential=(value)
72
+ @config[:sequential] = value
73
+ end
74
+
75
+ def sequential?
76
+ return @config[:sequential] ? true : false
77
+ end
78
+
79
+ def pre_execute (&block)
80
+ @config[:pre_execute] = block
81
+ end
82
+
83
+ def post_execute (&block)
84
+ @config[:post_execute] = block
85
+ end
86
+
87
+ def run
88
+ # Check
89
+ status
90
+ @logger.info("#{self.class.name.split('::').last} run begin")
91
+
92
+ if self.sequential? then
93
+ hosts = self.hosts
94
+
95
+ @logger.info("Running deployment sequentially")
96
+
97
+ hosts.each do |host|
98
+ @current_host = host
99
+
100
+ instance_eval &@config[:pre_execute] if @config.has_key?(:pre_execute)
101
+ @mc.reset_filter
102
+ @mc.identity_filter @current_host
103
+ self.status
104
+ self.execute
105
+ instance_eval &@config[:post_execute] if @config.has_key?(:post_execute)
106
+ end
107
+ else
108
+ instance_eval &@config[:pre_execute] if @config.has_key?(:pre_execute)
109
+ self.execute
110
+ instance_eval &@config[:post_execute] if @config.has_key?(:post_execute)
111
+ end
112
+
113
+ @logger.info("#{self.class.name.split('::').last} run complete")
114
+
115
+ end
116
+
117
+ def fact_filter(fact_hash)
118
+ unless fact_hash.is_a?(Hash)
119
+ @logger.error('Fact filter needs to be of type hash')
120
+ end
121
+ fact_hash.each do |key,value|
122
+ @logger.info("Setting Fact #{key} to value #{value}")
123
+ @mc.fact_filter key, value
124
+ end
125
+ end
126
+
127
+ def identity_filter(identity_array)
128
+ unless identity_array.is_a?(Array)
129
+ @logger.error('Identity filter needs to be of type array')
130
+ end
131
+ identity_array.each do |value|
132
+ @logger.info("Setting Identity to host #{value}")
133
+ @mc.identity_filter value
134
+ end
135
+ end
136
+
137
+ def class_filter(class_array)
138
+ unless class_array.is_a?(Array)
139
+ @logger.error('Class filter needs to be of type array')
140
+ end
141
+ class_array.each do |value|
142
+ @logger.info("Settting class to #{value}")
143
+ @mc.class_filter value
144
+ end
145
+ end
146
+
147
+ def logging(log_file, log_level, description='')
148
+ log = File.open(log_file,'a')
149
+ @logger = Logger.new Etoro::Utility::MCollective::MultiDelegator.delegate(:write, :close).to(STDOUT, log)
150
+ @logger.datetime_format = ('%Y-%m-%d_%H:%M:%S')
151
+ @logger.formatter = proc do |severity, datetime, progname, msg|
152
+ "#{datetime},level=#{severity},type=Deployment,#{description} message=#{msg}\n"
153
+ end
154
+ @logger.level = log_level
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,82 @@
1
+ module Etoro
2
+ module Utility
3
+ module MCollective
4
+ class Service < Etoro::Utility::MCollective::RPC
5
+
6
+ def validate(config)
7
+ super
8
+ unless config.has_key?(:service_name)
9
+ raise RuntimeError, "config[:service_name] must be defined"
10
+ end
11
+ unless config.has_key?(:action)
12
+ raise RuntimeError, "config[:action] must be defined"
13
+ end
14
+ unless ['start','stop'].include? config[:action]
15
+ raise RuntimeError, "Service action must be either start or stop"
16
+ end
17
+ end
18
+
19
+ def execute
20
+ @logger.info("Sending service #{@config[:service_name]} #{@config[:action]} action")
21
+ @mc.send @config[:action], service: @config[:service_name]
22
+ sleep @config[:wait_for_status]
23
+ self.check_run_status
24
+ end
25
+
26
+ def status
27
+ @service_status = {}
28
+ @logger.info("Getting service information")
29
+ results = @mc.send 'status', service: @config[:service_name]
30
+ results.each do |result|
31
+ @service_status[result[:sender]] = result[:data][:status]
32
+ end
33
+ end
34
+
35
+ def hosts
36
+ hosts = []
37
+ @service_status.each_key do |host|
38
+ @hosts.push host
39
+ end
40
+ hosts
41
+ end
42
+
43
+ def check_run_status
44
+ @logger.info("Checking Service #{@config[:service_name]} for completion")
45
+
46
+ begin
47
+ timeout(@config[:timeout]) do
48
+ until @service_status == {}
49
+ @service_status.each do |host, status|
50
+ run = rpcclient(self.class.name.downcase.split('::').last, :chomp => true)
51
+ run.identity_filter host
52
+ run.progress = false
53
+ results = run.send 'status', service: @config[:service_name]
54
+ results.each do |result|
55
+ state = ''
56
+ case @config[:action]
57
+ when 'start'
58
+ state = 'running'
59
+ when 'stop'
60
+ state = 'stopped'
61
+ end
62
+ @logger.info("#{host} - Service: current state: #{result[:data][:status]} desired_state: #{state}")
63
+ if result[:data][:status] == state
64
+ @logger.info("#{host} - Service: #{@config[:service_name]} #{@config[:action]} action #{result[:data][:status]} - completed")
65
+ @service_status.delete(host)
66
+ else
67
+ @logger.info("#{host} - Service #{@config[:service_name]} #{@config[:action]} action not complete - #{result[:data][:status]}")
68
+ end
69
+ end
70
+ end
71
+ sleep @config[:wait_between_checks]
72
+ end
73
+ end
74
+ rescue Timeout::Error
75
+ @logger.error("Service run timed out. Took more than #{@config[:timeout]} seconds")
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,10 @@
1
+ require "etoro_utility_mcollective/version"
2
+ require "etoro/utility/mcollective/multidelegator"
3
+ require "etoro/utility/mcollective/rpc"
4
+ require "etoro/utility/mcollective/puppet"
5
+ require "etoro/utility/mcollective/service"
6
+ require "etoro/utility/mcollective/haproxy"
7
+
8
+ module EtoroUtilityMcollective
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,3 @@
1
+ module EtoroUtilityMcollective
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etoro_utility_mcollective
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alon Becker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: test
42
+ email:
43
+ - alon@etoro.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - etoro_utility_mcollective.gemspec
54
+ - lib/etoro/utility/mcollective/haproxy.rb
55
+ - lib/etoro/utility/mcollective/multidelegator.rb
56
+ - lib/etoro/utility/mcollective/puppet.rb
57
+ - lib/etoro/utility/mcollective/rpc.rb
58
+ - lib/etoro/utility/mcollective/service.rb
59
+ - lib/etoro_utility_mcollective.rb
60
+ - lib/etoro_utility_mcollective/version.rb
61
+ homepage: http://www.etoro.com
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.0.6
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: test
85
+ test_files: []
86
+ has_rdoc: