dtk-node-agent 0.6.7 → 0.7.0

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.
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