chef-monitor 0.1.0 → 0.1.2

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.
data/bin/chef-logmon CHANGED
@@ -16,7 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require "chef_monitor"
19
+ require "chef_logmon"
20
20
  require 'rubygems'
21
21
  require 'file-tail'
22
22
  require 'bunny'
@@ -24,9 +24,12 @@ require 'json'
24
24
  require 'daemons'
25
25
 
26
26
  config=nil
27
+ debug=false
28
+
27
29
  opt=0
28
30
  ARGV.each do |arg|
29
31
  config = ARGV[opt+1] if arg == "-C" || arg == "--config"
32
+ debug = true if arg == "--debug"
30
33
  opt+=1
31
34
  end
32
35
 
@@ -47,6 +50,7 @@ MQSERVER = Monitor::Config[:mq_server]
47
50
  MQQUEUE = Monitor::Config[:mq_queue]
48
51
  MON_FILE = Monitor::Config[:mon_file]
49
52
  CHEF_URL = Monitor::Config[:chef_url]
53
+ DEBUG = debug
50
54
 
51
55
  @options = {
52
56
  :log_output => true,
data/bin/chef-worker CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ #!/opt/chef/embedded/bin/ruby
2
3
  #
3
4
  # Author:: Sander Botman (<sander.botman@gmail.com>)
4
5
  # Copyright:: Copyright (c) 2014 Sander Botman.
@@ -15,17 +16,21 @@
15
16
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
17
  # See the License for the specific language governing permissions and
17
18
  # limitations under the License.
18
-
19
- require "chef_monitor"
19
+ # $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
20
+ require "chef_worker"
20
21
  require 'rubygems'
21
22
  require 'bunny'
22
23
  require 'json'
23
24
  require 'daemons'
24
25
 
25
26
  config=nil
27
+ populate=nil
28
+ debug=false
26
29
  opt=0
27
30
  ARGV.each do |arg|
28
31
  config = ARGV[opt+1] if arg == "-C" || arg == "--config"
32
+ populate = ARGV[opt+1] if arg == "-O"
33
+ debug = true if arg == "--debug"
29
34
  opt+=1
30
35
  end
31
36
 
@@ -42,10 +47,12 @@ else
42
47
  end
43
48
  end
44
49
 
45
- MQSERVER = Monitor::Config[:mq_server]
46
- MQQUEUE = Monitor::Config[:mq_queue]
47
- DOWNLOAD_PATH = Monitor::Config[:download_path]
48
- CHEF_URL = Monitor::Config[:chef_url]
50
+ ALLOWED_OBJECTS = ['users', 'cookbooks','roles','environments','clients','nodes','groups','data']
51
+ DOWNLOAD_PATH = Monitor::Config[:download_path]
52
+ MQSERVER = Monitor::Config[:mq_server]
53
+ MQQUEUE = Monitor::Config[:mq_queue]
54
+ CHEF_URL = Monitor::Config[:chef_url]
55
+ DEBUG = debug
49
56
  Chef::Config[:node_name] = Monitor::Config[:node_name]
50
57
  Chef::Config[:client_key] = Monitor::Config[:client_key]
51
58
 
@@ -56,6 +63,26 @@ Chef::Config[:client_key] = Monitor::Config[:client_key]
56
63
  :log_dir => Monitor::Config[:log_dir]
57
64
  }
58
65
 
66
+ unless populate.nil?
67
+ Chef::Config[:chef_server_url] = CHEF_URL + "/organizations/#{populate}"
68
+ ALLOWED_OBJECTS.each do |object|
69
+ data = {}
70
+ data['object'] = object
71
+ data['action'] = 'POST'
72
+ data['org'] = populate
73
+ data['time'] = Time.now
74
+ data['user'] = 'chef-worker'
75
+ data['server'] = ENV['HOSTNAME']
76
+ pop = Monitor::Item.new(data)
77
+ obj = Monitor::ItemList.new(data)
78
+ obj.each do |item|
79
+ item.download(DOWNLOAD_PATH)
80
+ end
81
+ pop.commit_nohook(DOWNLOAD_PATH)
82
+ end
83
+ exit 0
84
+ end
85
+
59
86
  Daemons.run_proc('chef-worker', @options) do
60
87
  worker = Monitor::Worker.new
61
88
  worker.run()
@@ -0,0 +1,20 @@
1
+ #
2
+ # Author:: Sander Botman (<sander.botman@gmail.com>)
3
+ # Copyright:: Copyright (c) 2014 Sander Botman.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require "chef_monitor/log"
19
+ require "chef_monitor/config"
20
+ require "chef_monitor/logmon"
@@ -43,13 +43,12 @@ class Monitor
43
43
  attr_reader :organization
44
44
 
45
45
  def download(path)
46
- case self.object
47
- when 'data', 'roles', 'clients', 'environments', 'nodes'
48
- r = download_object(path)
49
- when 'cookbooks'
46
+
47
+ if @object == "cookbooks"
50
48
  r = download_cookbook(path)
49
+ else
50
+ r = download_object(path)
51
51
  end
52
-
53
52
 
54
53
  (@version.nil? || @version.empty?) ? object = [@organization, @object, @name].join('/') : object = [@organization, @object, @name, @version].join('/')
55
54
 
@@ -71,8 +70,8 @@ class Monitor
71
70
  items << @organization
72
71
  items << @object
73
72
  if @name
74
- filename=@name + ".json" if [ "nodes", "clients", "roles", "environments" ].include?(@object)
75
-
73
+ filename=@name + ".json"
74
+
76
75
  if @object == "cookbooks"
77
76
  (@version.nil? || @version.empty?) ? filename=@name : filename=@name + "-" + @version
78
77
  end
@@ -83,37 +82,62 @@ class Monitor
83
82
 
84
83
  items << filename
85
84
  end
86
-
87
85
  file = items.join("/")
88
- unless file.nil?
89
- FileUtils.rm_rf(file)
90
- (@version.nil? || @version.empty?) ? object = [@organization, @object, @name].join('/') : object = [@organization, @object, @name, @version].join('/')
91
- Monitor::Log.new("Deleted : " + object, 'INFO')
92
- return true
86
+ delete_file(file)
87
+ end
88
+
89
+ def delete_file(file)
90
+ FileUtils.rm_rf(file)
91
+ Monitor::Log.new("Deleted : " + file, 'INFO')
92
+ true
93
+ end
94
+
95
+ def get_item_json(object)
96
+ begin
97
+ item = rest.get_rest(object)
98
+ result = JSON.pretty_generate(item)
99
+ rescue
100
+ return nil
93
101
  end
94
- return false
102
+ return result
95
103
  end
96
104
 
97
105
  def commit(path)
98
- current_dir = Dir.pwd
99
- commit_dir = File.join(path, @organization, @object)
100
- Dir.chdir(commit_dir)
101
- @version ? object = [@organization, @object, @name, @version].join('/') : object = [@organization, @object, @name].join('/')
102
- text = "User : " + @user + "\nObject : " + @object + "\nAction : " + @action + "\nLog Time : " + @time
103
- domain = %x(git config hooks.emaildomain)
104
- domain = "@" + domain unless domain[0,1] == "@"
105
- username = @name
106
- useremail = @name + domain
107
- %x(git config hooks.username #{username} )
108
- %x(git config hooks.useremail #{useremail} )
109
- %x(git add .)
110
- %x(git commit -am \"#{text}\")
111
- Dir.chdir(current_dir)
112
- return true
106
+ current_dir = Dir.pwd
107
+ commit_dir = File.join(path, @organization, @object)
108
+ Dir.chdir(commit_dir)
109
+ @version ? object = [@organization, @object, @name, @version].join('/') : object = [@organization, @object, @name].join('/')
110
+ text = "User : " + @user + "\nObject : " + object + "\nAction : " + @action + "\nLog Time : " + @time
111
+ domain = %x(git config hooks.emaildomain) || "acme.com"
112
+ domain = "@" + domain unless domain[0,1] == "@"
113
+ username = @user
114
+ useremail = @user + domain
115
+ %x(git config hooks.username #{username} )
116
+ %x(git config hooks.useremail #{useremail} )
117
+ %x(git add .)
118
+ %x(git commit -am \"#{text}\")
119
+ Dir.chdir(current_dir)
120
+ end
121
+
122
+ def commit_nohook(path)
123
+ current_dir = Dir.pwd
124
+ commit_dir = File.join(path, @organization, @object)
125
+ Dir.chdir(commit_dir)
126
+ %x(git config hooks.exclude true)
127
+ %x(git add .)
128
+ %x(git commit -am \"no hook executed on this commit\")
129
+ Dir.chdir(current_dir)
113
130
  end
114
-
131
+
115
132
  private
116
-
133
+
134
+ def rest
135
+ @rest ||= begin
136
+ require 'chef/rest'
137
+ Chef::REST.new(Chef::Config[:chef_server_url])
138
+ end
139
+ end
140
+
117
141
  def download_cookbook(path)
118
142
  begin
119
143
  args = ['cookbook', 'download', @name ]
@@ -133,26 +157,14 @@ class Monitor
133
157
  end
134
158
 
135
159
  def download_object(path)
136
- file = File.join(path, @organization, @object, @name + '.json' )
137
- begin
138
- case @object
139
- when 'roles'
140
- data = JSON.pretty_generate(Chef::Role.load(@name))
141
- when 'nodes'
142
- data = JSON.pretty_generate(Chef::Node.load(@name))
143
- when 'environments'
144
- data = JSON.pretty_generate(Chef::Environment.load(@name))
145
- when 'clients'
146
- data = JSON.pretty_generate(Chef::ApiClient.load(@name))
147
- when 'data'
148
- data = JSON.pretty_generate(Chef::DataBagItem.load(@name, @version))
149
- file = File.join(path, @organization, @object, @name, @version + '.json' )
150
- end
160
+ args = [ @object, @name ]
161
+ args.push(@version) if @version
162
+ item = args.join('/')
163
+ file = File.join(path, @organization, item + '.json' )
164
+ data = get_item_json(item)
165
+ unless data.nil?
151
166
  FileUtils.mkdir_p(File.dirname(file)) unless File.directory?(File.dirname(file))
152
167
  File.open(file, 'w') {|f| f.write(data)}
153
- self.path = File.dirname(file)
154
- rescue Exception => e
155
- return e
156
168
  end
157
169
  return true
158
170
  end
@@ -16,7 +16,6 @@
16
16
  # limitations under the License.
17
17
 
18
18
  require 'chef/client'
19
- require 'chef_monitor/log'
20
19
  require 'chef_monitor/item'
21
20
 
22
21
  class Monitor
@@ -24,152 +23,90 @@ class Monitor
24
23
 
25
24
  def initialize(data)
26
25
  @name = data['name']
27
- @time = data['time'].freeze
28
- @user = data['user'].freeze
29
- @object = data['object'].freeze
30
- @server = data['server'].freeze
31
- @action = data['action'].freeze
26
+ @time = data['time']
27
+ @user = data['user']
28
+ @object = data['object']
29
+ @server = data['server']
30
+ @action = data['action']
32
31
  @version = data['version'] unless data['version'].nil? || data['version'].empty?
33
- @organization = data['org'].freeze
32
+ @organization = data['org']
33
+ check_sub_items()
34
34
  end
35
35
 
36
- attr_reader :name
37
- attr_reader :time
38
- attr_reader :user
39
- attr_reader :object
40
- attr_reader :action
41
- attr_reader :version
42
- attr_reader :organization
43
-
44
- def get_items()
45
- name = @name
46
- object = @object
47
- version = @version
48
-
49
- list = []
50
- items = []
51
- if object.nil? || object.empty?
52
- objects = [ "roles", "nodes", "environments", "clients", "cookbooks", "data" ]
36
+ private
37
+
38
+ def check_sub_items()
39
+ if @object == "cookbooks" || @object == "data"
40
+ if @name.nil? || @name.empty?
41
+ add_sub_items(@object)
42
+ elsif @version.nil? || @version.empty?
43
+ add_sub_items(@object, @name)
44
+ else
45
+ add_item(@object, @name, @version)
46
+ end
47
+ elsif @name.nil? || @name.empty?
48
+ add_sub_items(@object)
53
49
  else
54
- objects = [ object ]
50
+ add_item(@object, @name)
55
51
  end
56
-
57
- objects.each do |object|
58
- if object == "data"
59
- if name.nil? || name.empty?
60
- names = get_names(object)
61
- names.each {|itemname| list += get_item(object, itemname)}
52
+ end
53
+
54
+ def add_sub_items(object, name=nil)
55
+ items = get_sub_items(object, name)
56
+ items.each do |item|
57
+ res = item.split('/')
58
+ add_item(res[0], res[1], res[2])
59
+ end
60
+ end
61
+
62
+ def get_sub_items(object, name=nil)
63
+ col = []
64
+ target = [ object, name ].join('/')
65
+ items = get_rest_item(target)
66
+ items.each do |item,value|
67
+ if object == "data" || object == "cookbooks"
68
+ if name.nil?
69
+ col += get_sub_items(object, item)
62
70
  else
63
- list += get_item(object, name)
71
+ col.push([object, name, item].join('/')) if object == "data"
72
+ value['versions'].each {|ver| col << sub_item_parse(ver['url'])} if object == "cookbooks"
64
73
  end
74
+ elsif object == "users"
75
+ item.each { |k| k.each {|sv| col << "users/" + sv['username'] unless sv['username'].nil? }} unless name
65
76
  else
66
- if name.nil? || name.empty?
67
- list += get_item(object)
68
- else
69
- return [ create_item(object, name) ]
70
- end
77
+ col << sub_item_parse(value) unless name
71
78
  end
72
79
  end
80
+ return col
81
+ end
73
82
 
74
- list.each do |item|
75
- url = item['url'].split('/')
76
- items << create_item(url[5], url[6], url[7])
77
- end
78
- return items
83
+ def sub_item_parse(str)
84
+ str.gsub!(Chef::Config[:chef_server_url],"")
85
+ str[1..-1] if str[0] == '/'
79
86
  end
80
-
81
- def get_names(object)
82
- names = []
83
- result = get_item(object)
84
- result.each do |item|
85
- url = item['url'].split('/')
86
- names << url[6]
87
+
88
+ def get_rest_item(target)
89
+ begin
90
+ result = rest.get_rest(target)
91
+ rescue
92
+ return []
87
93
  end
88
- return names.uniq
89
- end
94
+ return result
95
+ end
90
96
 
91
- def create_item(object, name, version=nil)
97
+ def add_item(object, name, version=nil)
92
98
  data = {}
93
99
  data['time'] = @time
94
100
  data['user'] = @user
95
101
  data['action'] = @action
96
102
  data['server'] = @server
97
103
  data['org'] = @organization
98
- data['name'] = name
99
104
  data['object'] = object
105
+ data['name'] = name
100
106
  data['version'] = version unless version.nil?
101
- Monitor::Item.new(data)
107
+ self << Monitor::Item.new(data)
102
108
  end
103
109
 
104
- def parse_data(object, data)
105
- data = JSON[data].to_hash unless data.class == Hash
106
- items = []
107
- data.each do |key,val|
108
- item = {}
109
- item['object'] = object
110
- item['url'] = val
111
- items << item
112
- end
113
- items
114
- end
115
-
116
- def get_item(object=nil, name=nil)
117
- objects = []
118
- begin
119
- case object
120
- when 'roles'
121
- json = JSON[Chef::Role.list]
122
- objects = parse_data("role", json)
123
- when 'nodes'
124
- json = JSON[Chef::Node.list]
125
- objects = parse_data("node", json)
126
- when 'environments'
127
- json = JSON[Chef::Environment.list]
128
- objects = parse_data("environment", json)
129
- when 'clients'
130
- json = JSON[Chef::ApiClient.list]
131
- objects = parse_data("client", json)
132
- when 'data'
133
- if name
134
- json = JSON[Chef::DataBag.load(name)]
135
- items = JSON[json].to_hash
136
- items.each do |key,val|
137
- item = {}
138
- item['object'] = 'data_bag'
139
- item['url'] = val
140
- objects << item
141
- end
142
- else
143
- json = JSON[Chef::DataBag.list]
144
- items = JSON[json].to_hash
145
- items.each do |key,val|
146
- objects += get_item(object, key)
147
- end
148
- end
149
- when 'cookbooks'
150
- json = JSON[rest.get_rest("/cookbooks?num_versions=all")]
151
- items = JSON[json].to_hash
152
- items.each do |key,val|
153
- val['versions'].each do |version|
154
- item = {}
155
- item['object'] = 'cookbook'
156
- item['url'] = version['url']
157
- objects << item
158
- end
159
- end
160
- end
161
- rescue Exception => e
162
- @version ? object = [@organization, @object, @name, @version].join('/') : object = [@organization, @object, @name].join('/')
163
- if e.respond_to?("message")
164
- Monitor::Log.new(e.message + ' with object: ' + object , 'ERROR')
165
- else
166
- Monitor::Log.new('Error while downloading object: ' + object , 'ERROR')
167
- end
168
- return []
169
- end
170
- return objects
171
- end
172
-
173
110
  def rest
174
111
  @rest ||= begin
175
112
  require 'chef/rest'
@@ -17,7 +17,7 @@
17
17
 
18
18
  class Monitor
19
19
  class Log
20
-
20
+
21
21
  def initialize(text, type='INFO')
22
22
  case type.downcase
23
23
  when "INFO".downcase
@@ -26,6 +26,8 @@ class Monitor
26
26
  puts "[" + Time.now.iso8601 + "] WARN: " + text
27
27
  when "ERROR".downcase
28
28
  puts "[" + Time.now.iso8601 + "] ERROR: " + text
29
+ when "DEBUG".downcase
30
+ puts "[" + Time.now.iso8601 + "] DEBUG: " + text if DEBUG
29
31
  else
30
32
  puts "[" + Time.now.iso8601 + "] UNKNOWN: " + text
31
33
  end
@@ -16,6 +16,6 @@
16
16
  # limitations under the License.
17
17
 
18
18
  class Monitor
19
- VERSION = "0.1.0"
19
+ VERSION = "0.1.2"
20
20
  MAJOR, MINOR, TINY = VERSION.split('.')
21
21
  end
@@ -15,9 +15,9 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
+
18
19
  class Monitor
19
20
  class Worker
20
-
21
21
  def run
22
22
  conn = Bunny.new(:hostname => MQSERVER)
23
23
  conn.start
@@ -30,37 +30,32 @@ class Monitor
30
30
  q.subscribe(:ack => true, :block => true) do |delivery_info, properties, body|
31
31
  if properties[:content_type] =~ /.*json/
32
32
  data = JSON.parse(body).to_hash
33
-
34
- if data['object'].nil? || data['object'].empty?
35
- log_obj = data['org']
36
- elsif data['name'].nil? || data['name'].empty?
37
- log_obj = [ data['org'], data['object'] ].join('/')
38
- elsif data['version'].nil? || data['version'].empty?
39
- log_obj = [ data['org'], data['object'], data['name'] ].join('/')
40
- else
41
- log_obj = [ data['org'], data['object'], data['name'], data['version'] ].join('/')
42
- end
43
- Monitor::Log.new("Receiving : #{log_obj} action: #{data['action']}", "INFO")
44
-
33
+ Monitor::Log.new("Receiving : #{data}", "DEBUG")
34
+ data['object'] = nil unless ALLOWED_OBJECTS.include?(data['object'])
35
+
45
36
  unless data['object'].nil? || !File.directory?((File.join(DOWNLOAD_PATH, data['org'])))
46
37
  Chef::Config[:chef_server_url] = CHEF_URL + "/organizations/#{data['org']}"
47
38
 
48
- Monitor::Item.new(data).delete(DOWNLOAD_PATH)
49
-
50
- list_obj = Monitor::ItemList.new(data)
51
- list_items = list_obj.get_items()
52
-
53
- if data['action'] == "PUT" || data['action'] == "POST" || data['action'] == "DELETE"
54
- list_items.each do |item|
55
- if item.download(DOWNLOAD_PATH)
56
- item.commit(DOWNLOAD_PATH)
57
- else
58
- Monitor::Log.new("Could not download #{log_obj}", "ERROR")
39
+ obj = Monitor::Item.new(data)
40
+ if data['action'] == "DELETE"
41
+ obj.delete(DOWNLOAD_PATH)
42
+ else
43
+ items = Monitor::ItemList.new(data)
44
+
45
+ items.each do |item|
46
+ if data['action'] == "PUT"
47
+ item.download(DOWNLOAD_PATH)
48
+ end
49
+
50
+ if data['action'] == "POST"
51
+ item.delete(DOWNLOAD_PATH)
52
+ item.download(DOWNLOAD_PATH)
59
53
  end
60
54
  end
61
55
  end
56
+ obj.commit(DOWNLOAD_PATH)
62
57
  else
63
- Monitor::Log.new("Ignoring : #{log_obj}", "INFO")
58
+ Monitor::Log.new("Ignoring : #{data}", "DEBUG")
64
59
  end
65
60
  else
66
61
  Monitor::Log.new("Unknown : #{body}", "ERROR")
@@ -16,8 +16,6 @@
16
16
  # limitations under the License.
17
17
 
18
18
  require "chef_monitor/log"
19
- require "chef_monitor/item"
20
19
  require "chef_monitor/itemlist"
21
20
  require "chef_monitor/config"
22
21
  require "chef_monitor/worker"
23
- require "chef_monitor/logmon"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  prerelease:
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: 2014-02-04 00:00:00.000000000 Z
12
+ date: 2014-02-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bunny
@@ -92,7 +92,7 @@ files:
92
92
  - bin/chef-logmon
93
93
  - bin/chef-worker
94
94
  - chef-monitor.gemspec
95
- - lib/chef_monitor.rb
95
+ - lib/chef_logmon.rb
96
96
  - lib/chef_monitor/config.rb
97
97
  - lib/chef_monitor/item.rb
98
98
  - lib/chef_monitor/itemlist.rb
@@ -100,6 +100,7 @@ files:
100
100
  - lib/chef_monitor/logmon.rb
101
101
  - lib/chef_monitor/version.rb
102
102
  - lib/chef_monitor/worker.rb
103
+ - lib/chef_worker.rb
103
104
  homepage: https://github.com/schubergphilis/chef-monitor
104
105
  licenses:
105
106
  - Apache 2.0