dtk-node-agent 0.6.7 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +8 -8
  2. data/dtk-node-agent.gemspec +1 -0
  3. data/lib/config/install.config +2 -0
  4. data/lib/dtk-node-agent/installer.rb +14 -1
  5. data/lib/dtk-node-agent/version.rb +1 -1
  6. data/mcollective_additions/plugins/v2.2/agent/action_agent.ddl +9 -0
  7. data/mcollective_additions/plugins/v2.2/agent/action_agent.rb +41 -0
  8. data/mcollective_additions/plugins/v2.2/agent/dev_manager.rb +12 -2
  9. data/mcollective_additions/plugins/v2.2/audit/logfile.rb +26 -0
  10. data/mcollective_additions/plugins/v2.2/data/agent_data.ddl +22 -0
  11. data/mcollective_additions/plugins/v2.2/data/agent_data.rb +17 -0
  12. data/mcollective_additions/plugins/v2.2/data/collective_data.ddl +20 -0
  13. data/mcollective_additions/plugins/v2.2/data/collective_data.rb +9 -0
  14. data/mcollective_additions/plugins/v2.2/data/fact_data.ddl +28 -0
  15. data/mcollective_additions/plugins/v2.2/data/fact_data.rb +55 -0
  16. data/mcollective_additions/plugins/v2.2/data/fstat_data.ddl +89 -0
  17. data/mcollective_additions/plugins/v2.2/data/fstat_data.rb +56 -0
  18. data/mcollective_additions/plugins/v2.2/discovery/flatfile.ddl +11 -0
  19. data/mcollective_additions/plugins/v2.2/discovery/flatfile.rb +48 -0
  20. data/mcollective_additions/plugins/v2.2/discovery/mc.ddl +11 -0
  21. data/mcollective_additions/plugins/v2.2/discovery/mc.rb +30 -0
  22. data/mcollective_additions/plugins/v2.2/discovery/stdin.ddl +11 -0
  23. data/mcollective_additions/plugins/v2.2/discovery/stdin.rb +66 -0
  24. data/mcollective_additions/plugins/v2.2/facts/yaml_facts.rb +61 -0
  25. data/mcollective_additions/plugins/v2.2/registration/agentlist.rb +10 -0
  26. data/mcollective_additions/plugins/v2.2/validator/array_validator.ddl +7 -0
  27. data/mcollective_additions/plugins/v2.2/validator/array_validator.rb +9 -0
  28. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.ddl +7 -0
  29. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.rb +16 -0
  30. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.ddl +7 -0
  31. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.rb +16 -0
  32. data/mcollective_additions/plugins/v2.2/validator/length_validator.ddl +7 -0
  33. data/mcollective_additions/plugins/v2.2/validator/length_validator.rb +11 -0
  34. data/mcollective_additions/plugins/v2.2/validator/regex_validator.ddl +7 -0
  35. data/mcollective_additions/plugins/v2.2/validator/regex_validator.rb +9 -0
  36. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.ddl +7 -0
  37. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.rb +13 -0
  38. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.ddl +7 -0
  39. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.rb +28 -0
  40. data/src/etc/init.d/logstash-forwarder.rpm.init +112 -0
  41. metadata +50 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODVhMGY3YTdhZWQwN2Q4ZTZmMmI5ODgzYzNiNTkxMTRiYzg4MjkyNg==
4
+ OGU1YzU1MGExMTNiOWE2YmY5YjI0YmY0ZjVhODZkZDM2MGI0OTM3Nw==
5
5
  data.tar.gz: !binary |-
6
- NTI5NDk3NGUyOTIyZTI5ZjNlZmNkMDNkMTg4ZGJkNDE5YmYwNDRjMg==
6
+ NTIxY2IwNmIyYzI4OTgxNGI2OGU0NzFmMmM5MjQ1MGI2OTE1ZDBjMw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZjI2MzM4M2M4NDA2OTZmNjA1ZjNlYjA2OWMwYTk0MTY2ZjYyZTA0YmZmZTMz
10
- NzY0ODUwYmMxMzQzYWVmMDYzYmJlZThjN2RkYzE3YWM3NTdlNWYyNTZlOWVh
11
- MGI3MzZhYjk2NmMzOTkzYTY0MjFlNTdhZGQwOTY2YTE3NWU2Y2M=
9
+ Y2JlZDAzNGEyMjgzZmM4ZDMwYWJlOTZlNzIxNGIxNDkwZGNiYzhjMWFhMjhm
10
+ ODA2YmM0MTIxY2U5ODViM2NiOGRkYTVhZmEwMDg3ZWNjNWRjYjM0NGM5ODA5
11
+ NjgxYWVjMGFkNjllODU5NzU4ZWJkYTlkZGYwY2NjYjI5MWYyYTQ=
12
12
  data.tar.gz: !binary |-
13
- MzYyNWRkN2NlMTU4MWJkNGY3OGVhNzhmNWQ2OTg0ZDk2M2I0ZmY2ZWIyZjcx
14
- MjIxMTFhYmI0NWNkOTNlMmMxNzBiYzBjZGU4YTUwZjA0OTJlNDM5NDViNTJj
15
- YzllNWNmMDBiMzQ3Y2U1N2Q3NjgxZjcwYmMwOTJiYmNiYjQ0MjQ=
13
+ MmUxNGYyNzNjZTkwZTJiODA4ZTM2MmJlOGU3YTg1YTM4NTE0NGI5NGNhMzgz
14
+ ODExMTQ4NzkzMGMzNTlmYWYzYjNjYzA0MGRjODRjZWY0NDMzZTFiODY4MTkz
15
+ MjUxOWVkY2ZlM2I1ZGMyOTAwZTQ2OTczN2FkOGQwMGE3Yjc5NmQ=
@@ -36,5 +36,6 @@ Gem::Specification.new do |gem|
36
36
  gem.add_dependency 'serverspec', '~> 1.1.0'
37
37
  gem.add_dependency 'specinfra', '~> 1.0.4'
38
38
  gem.add_dependency 'posix-spawn', '0.3.8'
39
+ gem.add_dependency 'dtk-action-agent'
39
40
 
40
41
  end
@@ -10,6 +10,8 @@
10
10
  :rpm_forge_el6_i686_repo => 'http://apt.sw.be/redhat/el6/en/i386/rpmforge/RPMS/rpmforge-release-0.5.3-1.el6.rf.i686.rpm',
11
11
  :puppet_omnibus_deb64 => 'http://dtk-storage.s3.amazonaws.com/puppet-omnibus_2.7.23-fpm0_amd64.deb',
12
12
  :puppet_omnibus_rpm64 => 'http://dtk-storage.s3.amazonaws.com/puppet-omnibus-2.7.23.fpm0-1.x86_64.rpm',
13
+ :logstash_forwarder_rpm64 => 'http://dtk-storage.s3.amazonaws.com/logstash-forwarder-0.3.1-1.x86_64.rpm',
14
+ :logstash_forwarder_deb64 => 'http://dtk-storage.s3.amazonaws.com/logstash-forwarder_0.3.1_amd64.deb',
13
15
  :upgrades => {
14
16
  :redhat => ['openssl', 'bash', 'emacs-nox', 'vim-enhanced'],
15
17
  :debian => ['openssl', 'bash', 'emacs23-nox', 'vim']
@@ -36,8 +36,16 @@ module DTK
36
36
  shell "wget http://apt.puppetlabs.com/puppetlabs-release-#{@distcodename}.deb"
37
37
  puts "Installing Puppet Labs repository..."
38
38
  shell "dpkg -i puppetlabs-release-#{@distcodename}.deb"
39
+ puts "Installing Puppet Labs repository..."
40
+ shell "dpkg -i puppetlabs-release-#{@distcodename}.deb"
41
+ # install logstash forwarder
42
+ logstash_forwarder_url = CONFIG[:logstash_forwarder_deb64]
43
+ logstash_forwarder_package = logstash_forwarder_url.rpartition('/').last
44
+ shell "wget #{logstash_forwarder_url}"
45
+ puts "Installing logstash-forwarder"
46
+ shell "dpkg -i #{logstash_forwarder_package}"
39
47
  shell "apt-get update"
40
- shell "rm puppetlabs-release-#{@distcodename}.deb"
48
+ shell "rm puppetlabs-release-#{@distcodename}.deb #{logstash_forwarder_package}"
41
49
  # install mcollective
42
50
  puts "Installing MCollective..."
43
51
  shell "apt-get -y install mcollective"
@@ -74,6 +82,11 @@ module DTK
74
82
  FileUtils.cp("#{base_dir}/src/etc/init.d/ec2-run-user-data", "/etc/init.d/ec2-run-user-data") unless File.exist?("/etc/init.d/ec2-run-user-data")
75
83
  set_init("ec2-run-user-data")
76
84
  end
85
+ # install logstash-forwarder
86
+ puts "Installing logstash-forwarder"
87
+ shell "rpm -ivh #{CONFIG[:logstash_forwarder_rpm64]}"
88
+ FileUtils.cp("#{base_dir}/src/etc/init.d/logstash-forwarder.rpm.init", "/etc/init.d/logstash-forwarder")
89
+ set_init("logstash-forwarder")
77
90
  else
78
91
  puts "Unsuported OS for automatic agent installation. Exiting now..."
79
92
  exit(1)
@@ -1,3 +1,3 @@
1
1
  module DtkNodeAgent
2
- VERSION="0.6.7"
2
+ VERSION="0.7.0"
3
3
  end
@@ -0,0 +1,9 @@
1
+ metadata :name => "action agent",
2
+ :description => "Action Agent allows us to run native bash commands on target system",
3
+ :author => "Reactor8",
4
+ :license => "",
5
+ :version => "",
6
+ :url => "",
7
+ :timeout => 180
8
+ action "run_command", :description => "Run provided command on system" do
9
+ end
@@ -0,0 +1,41 @@
1
+ require 'json'
2
+ require 'cgi'
3
+
4
+ module MCollective
5
+ module Agent
6
+ class Action_agent < RPC::Agent
7
+ action "run_command" do
8
+ #validate :action_agent_request, String
9
+
10
+ payload = request[:action_agent_request].to_json
11
+ Log.info "Run command has been started with params: "
12
+ Log.info payload
13
+
14
+ # we encode payload
15
+ encoded_payload = CGI.escape(payload)
16
+ result = `/opt/puppet-omnibus/embedded/bin/dtk-action-agent '#{encoded_payload}'`
17
+
18
+ json_result = JSON.parse(result)
19
+ reply[:results] = json_result['results']
20
+ reply[:errors] = json_result['errors']
21
+
22
+ Log.info reply
23
+ reply[:pbuilderid] = Facts["pbuilderid"]
24
+
25
+ if reply[:errors].empty?
26
+ Log.info "DTK Action Agent has finished successfully sending proper response"
27
+ reply[:status] = :ok
28
+ else
29
+ reply[:status] = :failed
30
+ reply[:statusmsg] = :failed
31
+ reply[:statuscode] = 1
32
+
33
+ Log.error "DTK Action Agent has errors:"
34
+ reply[:errors].each { |a| Log.error a }
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -9,7 +9,10 @@ module MCollective
9
9
  action "inject_agent" do
10
10
  begin
11
11
 
12
- ret ||= Response.new()
12
+ ret ||= Response.new()
13
+
14
+ # make sure default `service` command paths are set
15
+ ENV['PATH'] += ":/usr/sbin:/sbin"
13
16
 
14
17
  request[:agent_files].each do |k,v|
15
18
  if v == :deleted
@@ -24,7 +27,14 @@ module MCollective
24
27
  ret.set_status_succeeded!()
25
28
 
26
29
  t1 = Thread.new do
27
- system("sudo /etc/init.d/mcollective restart")
30
+ sleep(2)
31
+ Log.instance.info "Initiating mcollective restart..."
32
+ system("#{service_command} restart")
33
+ end
34
+
35
+ def self.service_command
36
+ cmd = `which service`.chomp
37
+ cmd.empty? ? "/etc/init.d/mcollective" : "#{cmd} mcollective"
28
38
  end
29
39
 
30
40
  return ret
@@ -0,0 +1,26 @@
1
+ module MCollective
2
+ module RPC
3
+ # An audit plugin that just logs to a file
4
+ #
5
+ # You can configure which file it logs to with the setting
6
+ #
7
+ # plugin.rpcaudit.logfile
8
+
9
+ class Logfile<Audit
10
+ require 'pp'
11
+
12
+ def audit_request(request, connection)
13
+ logfile = Config.instance.pluginconf["rpcaudit.logfile"] || "/var/log/mcollective-audit.log"
14
+
15
+ now = Time.now
16
+ # Already told timezone to be in UTC so we don't look it up again
17
+ # This avoids platform specific timezone representation issues
18
+ now_iso8601 = now.utc.strftime("%Y-%m-%d %H:%M:%S UTC")
19
+
20
+ File.open(logfile, "a") do |f|
21
+ f.puts("[#{now_iso8601}] reqid=#{request.uniqid}: reqtime=#{request.time} caller=#{request.caller}@#{request.sender} agent=#{request.agent} action=#{request.action} data=#{request.data.pretty_print_inspect}")
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ metadata :name => "Agent",
2
+ :description => "Meta data about installed MColletive Agents",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
8
+
9
+ dataquery :description => "Agent Meta Data" do
10
+ input :query,
11
+ :prompt => "Agent Name",
12
+ :description => "Valid agent name",
13
+ :type => :string,
14
+ :validation => /^[\w\_]+$/,
15
+ :maxlength => 20
16
+
17
+ [:license, :timeout, :description, :url, :version, :author].each do |item|
18
+ output item,
19
+ :description => "Agent #{item}",
20
+ :display_as => item.to_s.capitalize
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ module MCollective
2
+ module Data
3
+ class Agent_data<Base
4
+ query do |plugin|
5
+ raise "No agent called #{plugin} found" unless PluginManager.include?("#{plugin}_agent")
6
+
7
+ agent = PluginManager["#{plugin}_agent"]
8
+
9
+ result[:agent] = plugin
10
+
11
+ [:license, :timeout, :description, :url, :version, :author].each do |item|
12
+ result[item] = agent.meta[item]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ metadata :name => "Collective",
2
+ :description => "Collective membership",
3
+ :author => "Puppet Labs",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
8
+
9
+ dataquery :description => "Collective" do
10
+ input :query,
11
+ :prompt => 'Collective',
12
+ :description => 'Collective name to ask about, eg mcollective',
13
+ :type => :string,
14
+ :validation => /./,
15
+ :maxlength => 256
16
+
17
+ output :member,
18
+ :description => 'Node is a member of the named collective',
19
+ :display_as => 'member'
20
+ end
@@ -0,0 +1,9 @@
1
+ module MCollective
2
+ module Data
3
+ class Collective_data<Base
4
+ query do |collective|
5
+ result[:member] = Config.instance.collectives.include?(collective)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ metadata :name => "Fact",
2
+ :description => "Structured fact query",
3
+ :author => "Puppet Labs",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
8
+
9
+ dataquery :description => "Fact" do
10
+ input :query,
11
+ :prompt => 'Fact Path',
12
+ :description => 'Path to a fact, eg network.eth0.address',
13
+ :type => :string,
14
+ :validation => /./,
15
+ :maxlength => 256
16
+
17
+ output :exists,
18
+ :description => 'Fact is present',
19
+ :display_as => 'exists'
20
+
21
+ output :value,
22
+ :description => 'Fact value',
23
+ :display_as => 'value'
24
+
25
+ output :value_encoding,
26
+ :description => 'Encoding of the fact value (text/plain or application/json)',
27
+ :display_as => 'value_encoding'
28
+ end
@@ -0,0 +1,55 @@
1
+ module MCollective
2
+ module Data
3
+ class Fact_data<Base
4
+ query do |path|
5
+ parts = path.split /\./
6
+ walk_path(parts)
7
+ end
8
+
9
+ private
10
+
11
+ def walk_path(path)
12
+ # Set up results as though we didn't find the value
13
+ result[:exists] = false
14
+ result[:value] = false
15
+ result[:value_encoding] = false
16
+
17
+ facts = PluginManager['facts_plugin'].get_facts
18
+
19
+ path.each do |level|
20
+ case facts
21
+ when Array
22
+ level = Integer(level)
23
+ if level >= facts.size
24
+ # array index out would be out of bounds, so we don't have the value
25
+ return
26
+ end
27
+ when Hash
28
+ if !facts.include?(level)
29
+ # we don't have the key for the next level, so give up
30
+ return
31
+ end
32
+ else
33
+ # this isn't a container data type, so we can't walk into it
34
+ return
35
+ end
36
+
37
+ facts = facts[level]
38
+ end
39
+
40
+ result[:exists] = true
41
+ case facts
42
+ when Array, Hash
43
+ # Currently data plugins cannot return structured data, so until
44
+ # this is fixed flatten the data with json and flag that we have
45
+ # munged the data
46
+ result[:value] = facts.to_json
47
+ result[:value_encoding] = 'application/json'
48
+ else
49
+ result[:value] = facts
50
+ result[:value_encoding] = 'text/plain'
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,89 @@
1
+ metadata :name => "File Stat",
2
+ :description => "Retrieve file stat data for a given file",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
8
+
9
+ dataquery :description => "File stat information" do
10
+ input :query,
11
+ :prompt => "File Name",
12
+ :description => "Valid File Name",
13
+ :type => :string,
14
+ :validation => /.+/,
15
+ :maxlength => 120
16
+
17
+ output :name,
18
+ :description => "File name",
19
+ :display_as => "Name"
20
+
21
+ output :output,
22
+ :description => "Human readable information about the file",
23
+ :display_as => "Status"
24
+
25
+ output :present,
26
+ :description => "Indicates if the file exist using 0 or 1",
27
+ :display_as => "Present"
28
+
29
+ output :size,
30
+ :description => "File size",
31
+ :display_as => "Size"
32
+
33
+ output :mode,
34
+ :description => "File mode",
35
+ :display_as => "Mode"
36
+
37
+ output :md5,
38
+ :description => "File MD5 digest",
39
+ :display_as => "MD5"
40
+
41
+ output :mtime,
42
+ :description => "File modification time",
43
+ :display_as => "Modification time"
44
+
45
+ output :ctime,
46
+ :description => "File change time",
47
+ :display_as => "Change time"
48
+
49
+ output :atime,
50
+ :description => "File access time",
51
+ :display_as => "Access time"
52
+
53
+ output :mtime_seconds,
54
+ :description => "File modification time in seconds",
55
+ :display_as => "Modification time"
56
+
57
+ output :ctime_seconds,
58
+ :description => "File change time in seconds",
59
+ :display_as => "Change time"
60
+
61
+ output :atime_seconds,
62
+ :description => "File access time in seconds",
63
+ :display_as => "Access time"
64
+
65
+ output :mtime_age,
66
+ :description => "File modification age in seconds",
67
+ :display_as => "Modification age"
68
+
69
+ output :ctime_age,
70
+ :description => "File change age in seconds",
71
+ :display_as => "Change age"
72
+
73
+ output :atime_age,
74
+ :description => "File access age in seconds",
75
+ :display_as => "Access age"
76
+
77
+ output :uid,
78
+ :description => "File owner",
79
+ :display_as => "Owner"
80
+
81
+ output :gid,
82
+ :description => "File group",
83
+ :display_as => "Group"
84
+
85
+ output :type,
86
+ :description => "File type",
87
+ :display_as => "Type"
88
+ end
89
+
@@ -0,0 +1,56 @@
1
+ module MCollective
2
+ module Data
3
+ class Fstat_data<Base
4
+ query do |file|
5
+ result[:name] = file
6
+ result[:output] = "not present"
7
+ result[:type] = "unknown"
8
+ result[:mode] = "0000"
9
+ result[:present] = 0
10
+ result[:size] = 0
11
+ result[:mtime] = 0
12
+ result[:ctime] = 0
13
+ result[:atime] = 0
14
+ result[:mtime_seconds] = 0
15
+ result[:ctime_seconds] = 0
16
+ result[:atime_seconds] = 0
17
+ result[:md5] = 0
18
+ result[:uid] = 0
19
+ result[:gid] = 0
20
+
21
+
22
+ if File.exists?(file)
23
+ result[:output] = "present"
24
+ result[:present] = 1
25
+
26
+ if File.symlink?(file)
27
+ stat = File.lstat(file)
28
+ else
29
+ stat = File.stat(file)
30
+ end
31
+
32
+ [:size, :uid, :gid].each do |item|
33
+ result[item] = stat.send(item)
34
+ end
35
+
36
+ [:mtime, :ctime, :atime].each do |item|
37
+ result[item] = stat.send(item).strftime("%F %T")
38
+ result["#{item}_seconds".to_sym] = stat.send(item).to_i
39
+ result["#{item}_age".to_sym] = Time.now.to_i - stat.send(item).to_i
40
+ end
41
+
42
+ result[:mode] = "%o" % [stat.mode]
43
+ result[:md5] = Digest::MD5.hexdigest(File.read(file)) if stat.file?
44
+
45
+ result[:type] = "directory" if stat.directory?
46
+ result[:type] = "file" if stat.file?
47
+ result[:type] = "symlink" if stat.symlink?
48
+ result[:type] = "socket" if stat.socket?
49
+ result[:type] = "chardev" if stat.chardev?
50
+ result[:type] = "blockdev" if stat.blockdev?
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,11 @@
1
+ metadata :name => "flatfile",
2
+ :description => "Flatfile based discovery for node identities",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "ASL 2.0",
5
+ :version => "0.1",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 0
8
+
9
+ discovery do
10
+ capabilities :identity
11
+ end
@@ -0,0 +1,48 @@
1
+ # discovers against a flatfile instead of the traditional network discovery
2
+ # the flat file must have a node name per line which should match identities
3
+ # as configured
4
+ module MCollective
5
+ class Discovery
6
+ class Flatfile
7
+ def self.discover(filter, timeout, limit=0, client=nil)
8
+ unless client.options[:discovery_options].empty?
9
+ file = client.options[:discovery_options].first
10
+ else
11
+ raise "The flatfile discovery method needs a path to a text file"
12
+ end
13
+
14
+ raise "Cannot read the file %s specified as discovery source" % file unless File.readable?(file)
15
+
16
+ discovered = []
17
+ hosts = []
18
+
19
+ File.readlines(file).each do |host|
20
+ host = host.chomp.strip
21
+ if host.empty? || host.match(/^#/)
22
+ next
23
+ end
24
+ raise 'Identities can only match /^[\w\.\-]+$/' unless host.match(/^[\w\.\-]+$/)
25
+ hosts << host
26
+ end
27
+
28
+ # this plugin only supports identity filters, do regex matches etc against
29
+ # the list found in the flatfile
30
+ if !(filter["identity"].empty?)
31
+ filter["identity"].each do |identity|
32
+ identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
33
+
34
+ if identity.is_a?(Regexp)
35
+ discovered = hosts.grep(identity)
36
+ elsif hosts.include?(identity)
37
+ discovered << identity
38
+ end
39
+ end
40
+ else
41
+ discovered = hosts
42
+ end
43
+
44
+ discovered
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ metadata :name => "mc",
2
+ :description => "MCollective Broadcast based discovery",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "ASL 2.0",
5
+ :version => "0.1",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 2
8
+
9
+ discovery do
10
+ capabilities [:classes, :facts, :identity, :agents, :compound]
11
+ end
@@ -0,0 +1,30 @@
1
+ module MCollective
2
+ class Discovery
3
+ class Mc
4
+ def self.discover(filter, timeout, limit, client)
5
+ begin
6
+ hosts = []
7
+ Timeout.timeout(timeout) do
8
+ reqid = client.sendreq("ping", "discovery", filter)
9
+ Log.debug("Waiting #{timeout} seconds for discovery replies to request #{reqid}")
10
+
11
+ loop do
12
+ reply = client.receive(reqid)
13
+ Log.debug("Got discovery reply from #{reply.payload[:senderid]}")
14
+ hosts << reply.payload[:senderid]
15
+
16
+ return hosts if limit > 0 && hosts.size == limit
17
+ end
18
+ end
19
+ rescue Timeout::Error => e
20
+ rescue Exception => e
21
+ raise
22
+ ensure
23
+ client.unsubscribe("discovery", :reply)
24
+ end
25
+
26
+ hosts
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ metadata :name => "stdin",
2
+ :description => "STDIN based discovery for node identities",
3
+ :author => "Tomas Doran <bobtfish@bobtfish.net.net>",
4
+ :license => "ASL 2.0",
5
+ :version => "0.1",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 0
8
+
9
+ discovery do
10
+ capabilities :identity
11
+ end
@@ -0,0 +1,66 @@
1
+ # discovers against stdin instead of the traditional network discovery
2
+ # the input must be a flat file with a node name per line which should match identities as configured,
3
+ # or it should be a json string as output by the -j option of mco rpc
4
+ require 'mcollective/rpc/helpers'
5
+
6
+ module MCollective
7
+ class Discovery
8
+ class Stdin
9
+ def self.discover(filter, timeout, limit=0, client=nil)
10
+ unless client.options[:discovery_options].empty?
11
+ type = client.options[:discovery_options].first.downcase
12
+ else
13
+ type = 'auto'
14
+ end
15
+
16
+ discovered = []
17
+
18
+ file = STDIN.read
19
+
20
+ if file =~ /^\s*$/
21
+ raise("data piped on STDIN contained only whitespace - could not discover hosts from it.")
22
+ end
23
+
24
+ if type == 'auto'
25
+ if file =~ /^\s*\[/
26
+ type = 'json'
27
+ else
28
+ type = 'text'
29
+ end
30
+ end
31
+
32
+ if type == 'json'
33
+ hosts = MCollective::RPC::Helpers.extract_hosts_from_json(file)
34
+ elsif type == 'text'
35
+ hosts = file.split("\n")
36
+ else
37
+ raise("stdin discovery plugin only knows the types auto/text/json, not \"#{type}\"")
38
+ end
39
+
40
+ hosts.map do |host|
41
+ raise 'Identities can only match /\w\.\-/' unless host.match(/^[\w\.\-]+$/)
42
+ host
43
+ end
44
+
45
+ # this plugin only supports identity filters, do regex matches etc against
46
+ # the list found in the flatfile
47
+ unless filter["identity"].empty?
48
+ filter["identity"].each do |identity|
49
+ identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
50
+
51
+ if identity.is_a?(Regexp)
52
+ discovered = hosts.grep(identity)
53
+ elsif hosts.include?(identity)
54
+ discovered << identity
55
+ end
56
+ end
57
+ else
58
+ discovered = hosts
59
+ end
60
+
61
+ discovered
62
+ end
63
+ end
64
+ end
65
+ end
66
+
@@ -0,0 +1,61 @@
1
+ module MCollective
2
+ module Facts
3
+ require 'yaml'
4
+
5
+ # A factsource that reads a hash of facts from a YAML file
6
+ #
7
+ # Multiple files can be specified seperated with a : in the
8
+ # config file, they will be merged with later files overriding
9
+ # earlier ones in the list.
10
+ class Yaml_facts<Base
11
+ def initialize
12
+ @yaml_file_mtimes = {}
13
+
14
+ super
15
+ end
16
+
17
+ def load_facts_from_source
18
+ config = Config.instance
19
+
20
+ fact_files = config.pluginconf["yaml"].split(File::PATH_SEPARATOR)
21
+ facts = {}
22
+
23
+ fact_files.each do |file|
24
+ begin
25
+ if File.exist?(file)
26
+ facts.merge!(YAML.load_file(file))
27
+ else
28
+ raise("Can't find YAML file to load: #{file}")
29
+ end
30
+ rescue Exception => e
31
+ Log.error("Failed to load yaml facts from #{file}: #{e.class}: #{e}")
32
+ end
33
+ end
34
+
35
+ facts
36
+ end
37
+
38
+ # force fact reloads when the mtime on the yaml file change
39
+ def force_reload?
40
+ config = Config.instance
41
+
42
+ fact_files = config.pluginconf["yaml"].split(File::PATH_SEPARATOR)
43
+
44
+ fact_files.each do |file|
45
+ @yaml_file_mtimes[file] ||= File.stat(file).mtime
46
+ mtime = File.stat(file).mtime
47
+
48
+ if mtime > @yaml_file_mtimes[file]
49
+ @yaml_file_mtimes[file] = mtime
50
+
51
+ Log.debug("Forcing fact reload due to age of #{file}")
52
+
53
+ return true
54
+ end
55
+ end
56
+
57
+ false
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,10 @@
1
+ module MCollective
2
+ module Registration
3
+ # A registration plugin that simply sends in the list of agents we have
4
+ class Agentlist<Base
5
+ def body
6
+ Agents.agentlist
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "Array",
2
+ :description => "Validates that a value is included in a list",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,9 @@
1
+ module MCollective
2
+ module Validator
3
+ class ArrayValidator
4
+ def self.validate(validator, array)
5
+ raise ValidatorError, "value should be one of %s" % [ array.join(", ") ] unless array.include?(validator)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "IPv4 Address",
2
+ :description => "Validates that a value is an ipv4 address",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,16 @@
1
+ module MCollective
2
+ module Validator
3
+ class Ipv4addressValidator
4
+ require 'ipaddr'
5
+
6
+ def self.validate(validator)
7
+ begin
8
+ ip = IPAddr.new(validator)
9
+ raise ValidatorError, "value should be an ipv4 adddress" unless ip.ipv4?
10
+ rescue
11
+ raise ValidatorError, "value should be an ipv4 address"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "IPv6 Address",
2
+ :description => "Validates that a value is an ipv6 address",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,16 @@
1
+ module MCollective
2
+ module Validator
3
+ class Ipv6addressValidator
4
+ require 'ipaddr'
5
+
6
+ def self.validate(validator)
7
+ begin
8
+ ip = IPAddr.new(validator)
9
+ raise ValidatorError, "value should be an ipv6 adddress" unless ip.ipv6?
10
+ rescue
11
+ raise ValidatorError, "value should be an ipv6 address"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "Length",
2
+ :description => "Validates that the length of a string is less or equal to a specified value",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,11 @@
1
+ module MCollective
2
+ module Validator
3
+ class LengthValidator
4
+ def self.validate(validator, length)
5
+ if (validator.size > length) && (length > 0)
6
+ raise ValidatorError, "Input string is longer than #{length} character(s)"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "Regex",
2
+ :description => "Validates that a string matches a supplied regular expression",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,9 @@
1
+ module MCollective
2
+ module Validator
3
+ class RegexValidator
4
+ def self.validate(validator, regex)
5
+ raise ValidatorError, "value should match #{regex}" unless validator.match(regex)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "Shellsafe",
2
+ :description => "Validates that a string is shellsafe",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,13 @@
1
+ module MCollective
2
+ module Validator
3
+ class ShellsafeValidator
4
+ def self.validate(validator)
5
+ raise ValidatorError, "value should be a String" unless validator.is_a?(String)
6
+
7
+ ['`', '$', ';', '|', '&&', '>', '<'].each do |chr|
8
+ raise ValidatorError, "value should not have #{chr} in it" if validator.match(Regexp.escape(chr))
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ metadata :name => "Typecheck",
2
+ :description => "Validates that a value is of a certain type",
3
+ :author => "P. Loubser <pieter.loubser@puppetlabs.com>",
4
+ :license => "ASL 2.0",
5
+ :version => "1.0",
6
+ :url => "http://marionette-collective.org/",
7
+ :timeout => 1
@@ -0,0 +1,28 @@
1
+ module MCollective
2
+ module Validator
3
+ class TypecheckValidator
4
+ def self.validate(validator, validation_type)
5
+ raise ValidatorError, "value should be a #{validation_type.to_s}" unless check_type(validator, validation_type)
6
+ end
7
+
8
+ def self.check_type(validator, validation_type)
9
+ case validation_type
10
+ when Class
11
+ validator.is_a?(validation_type)
12
+ when :integer
13
+ validator.is_a?(Fixnum)
14
+ when :float
15
+ validator.is_a?(Float)
16
+ when :number
17
+ validator.is_a?(Numeric)
18
+ when :string
19
+ validator.is_a?(String)
20
+ when :boolean
21
+ [TrueClass, FalseClass].include?(validator.class)
22
+ else
23
+ false
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,112 @@
1
+ #!/bin/bash
2
+ # chkconfig: 345 80 20
3
+ # description: Logstash Forwarder
4
+ # processname: logstash-forwarder
5
+ # config: /etc/logstash-forwarder
6
+ # pidfile: /var/run/logstash-forwarder.pid
7
+
8
+ ### BEGIN INIT INFO
9
+ # Provides: logstash-forwarder
10
+ # Required-Start: $local_fs $network $remote_fs
11
+ # Required-Stop: $local_fs $network $remote_fs
12
+ # Default-Start: 2 3 4 5
13
+ # Default-Stop: 0 1 6
14
+ # Short-Description: start and stop logstash-forwarder
15
+ # Description: Logstash Forwarder
16
+ ### END INIT INFO
17
+
18
+ # Source function library.
19
+ . /etc/rc.d/init.d/functions
20
+
21
+ PATH=/sbin:/usr/sbin:/bin:/usr/bin
22
+
23
+ prog=logstash-forwarder
24
+ DAEMON=/opt/logstash-forwarder/bin/logstash-forwarder
25
+ pidfile=/var/run/$prog.pid
26
+ lockfile=/var/lock/subsys/$prog
27
+
28
+ # load defaults
29
+
30
+ [ -e /etc/default/$prog ] && . /etc/default/$prog
31
+ [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
32
+
33
+ DAEMON_ARGS="${DAEMON_ARGS:--config /etc/logstash-forwarder -spool-size 100 -log-to-syslog}"
34
+
35
+ start()
36
+ {
37
+ echo -n $"Starting $prog: "
38
+ nohup $DAEMON $DAEMON_ARGS </dev/null >/dev/null 2>&1 &
39
+ retval=$?
40
+ pid=$!
41
+ echo $pid > $pidfile
42
+ if [ rh_status_q ]; then
43
+ touch $lockfile
44
+ success
45
+ echo
46
+ fi
47
+ return $retval
48
+ }
49
+
50
+ stop()
51
+ {
52
+ echo -n $"Stopping $prog: "
53
+ killproc -p "$pidfile" $prog
54
+ retval=$?
55
+ [ -f "$pidfile" ] && rm -f $pidfile
56
+ echo
57
+ [ $retval -eq 0 ] && rm -f $lockfile
58
+ return $retval
59
+ }
60
+
61
+ restart() {
62
+ stop
63
+ start
64
+ }
65
+
66
+ reload() {
67
+ restart
68
+ }
69
+
70
+ force_reload() {
71
+ restart
72
+ }
73
+
74
+ rh_status() {
75
+ status -p $pidfile $prog
76
+ }
77
+
78
+ rh_status_q() {
79
+ rh_status >/dev/null 2>&1
80
+ }
81
+
82
+ case "$1" in
83
+ start)
84
+ rh_status_q && exit 0
85
+ $1
86
+ ;;
87
+ stop)
88
+ rh_status_q || exit 0
89
+ $1
90
+ ;;
91
+ restart)
92
+ $1
93
+ ;;
94
+ reload)
95
+ rh_status_q || exit 7
96
+ $1
97
+ ;;
98
+ force-reload)
99
+ force_reload
100
+ ;;
101
+ condrestart|try-restart)
102
+ rh_status_q || exit 0
103
+ restart
104
+ ;;
105
+ status)
106
+ rh_status
107
+ ;;
108
+ *)
109
+ echo "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
110
+ exit 2
111
+ esac
112
+ exit $?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dtk-node-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich PELAVIN
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-04 00:00:00.000000000 Z
11
+ date: 2015-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puppet
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.3.8
125
+ - !ruby/object:Gem::Dependency
126
+ name: dtk-action-agent
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: The DTK Node Agent runs on your nodes that you wish to manage using your
126
140
  DTK Server. It comes pre-installed on all nodes created/managed by hosted DTK Server
127
141
  accounts.
@@ -154,6 +168,8 @@ files:
154
168
  - mcollective_additions/plugins/v1.2/agent/rpcutil.ddl
155
169
  - mcollective_additions/plugins/v1.2/agent/rpcutil.rb
156
170
  - mcollective_additions/plugins/v1.2/facts/pbuilder_facts.rb
171
+ - mcollective_additions/plugins/v2.2/agent/action_agent.ddl
172
+ - mcollective_additions/plugins/v2.2/agent/action_agent.rb
157
173
  - mcollective_additions/plugins/v2.2/agent/dev_manager.ddl
158
174
  - mcollective_additions/plugins/v2.2/agent/dev_manager.rb
159
175
  - mcollective_additions/plugins/v2.2/agent/discovery.rb
@@ -182,13 +198,44 @@ files:
182
198
  - mcollective_additions/plugins/v2.2/agent/sync_agent_code.rb
183
199
  - mcollective_additions/plugins/v2.2/agent/tail.ddl
184
200
  - mcollective_additions/plugins/v2.2/agent/tail.rb
201
+ - mcollective_additions/plugins/v2.2/audit/logfile.rb
185
202
  - mcollective_additions/plugins/v2.2/connector/r8stomp.rb
186
203
  - mcollective_additions/plugins/v2.2/connector/stomp.rb
187
204
  - mcollective_additions/plugins/v2.2/connector/stomp_em.rb
205
+ - mcollective_additions/plugins/v2.2/data/agent_data.ddl
206
+ - mcollective_additions/plugins/v2.2/data/agent_data.rb
207
+ - mcollective_additions/plugins/v2.2/data/collective_data.ddl
208
+ - mcollective_additions/plugins/v2.2/data/collective_data.rb
209
+ - mcollective_additions/plugins/v2.2/data/fact_data.ddl
210
+ - mcollective_additions/plugins/v2.2/data/fact_data.rb
211
+ - mcollective_additions/plugins/v2.2/data/fstat_data.ddl
212
+ - mcollective_additions/plugins/v2.2/data/fstat_data.rb
213
+ - mcollective_additions/plugins/v2.2/discovery/flatfile.ddl
214
+ - mcollective_additions/plugins/v2.2/discovery/flatfile.rb
215
+ - mcollective_additions/plugins/v2.2/discovery/mc.ddl
216
+ - mcollective_additions/plugins/v2.2/discovery/mc.rb
217
+ - mcollective_additions/plugins/v2.2/discovery/stdin.ddl
218
+ - mcollective_additions/plugins/v2.2/discovery/stdin.rb
188
219
  - mcollective_additions/plugins/v2.2/facts/pbuilder_facts.rb
220
+ - mcollective_additions/plugins/v2.2/facts/yaml_facts.rb
221
+ - mcollective_additions/plugins/v2.2/registration/agentlist.rb
189
222
  - mcollective_additions/plugins/v2.2/security/sshkey.ddl
190
223
  - mcollective_additions/plugins/v2.2/security/sshkey.rb
191
224
  - mcollective_additions/plugins/v2.2/util/puppetrunner.rb
225
+ - mcollective_additions/plugins/v2.2/validator/array_validator.ddl
226
+ - mcollective_additions/plugins/v2.2/validator/array_validator.rb
227
+ - mcollective_additions/plugins/v2.2/validator/ipv4address_validator.ddl
228
+ - mcollective_additions/plugins/v2.2/validator/ipv4address_validator.rb
229
+ - mcollective_additions/plugins/v2.2/validator/ipv6address_validator.ddl
230
+ - mcollective_additions/plugins/v2.2/validator/ipv6address_validator.rb
231
+ - mcollective_additions/plugins/v2.2/validator/length_validator.ddl
232
+ - mcollective_additions/plugins/v2.2/validator/length_validator.rb
233
+ - mcollective_additions/plugins/v2.2/validator/regex_validator.ddl
234
+ - mcollective_additions/plugins/v2.2/validator/regex_validator.rb
235
+ - mcollective_additions/plugins/v2.2/validator/shellsafe_validator.ddl
236
+ - mcollective_additions/plugins/v2.2/validator/shellsafe_validator.rb
237
+ - mcollective_additions/plugins/v2.2/validator/typecheck_validator.ddl
238
+ - mcollective_additions/plugins/v2.2/validator/typecheck_validator.rb
192
239
  - mcollective_additions/redhat.mcollective.init
193
240
  - mcollective_additions/redhat.mcollective.service
194
241
  - mcollective_additions/server.cfg
@@ -199,6 +246,7 @@ files:
199
246
  - puppet_additions/puppet_lib_base/puppet/indirector/resource/r8_storeconfig_backend.rb
200
247
  - src/etc/apt/preferences.d/puppetlabs
201
248
  - src/etc/init.d/ec2-run-user-data
249
+ - src/etc/init.d/logstash-forwarder.rpm.init
202
250
  - src/etc/logrotate.d/mcollective
203
251
  - src/etc/logrotate.d/puppet
204
252
  homepage: https://github.com/rich-reactor8/dtk-node-agent