dtk-node-agent 0.5.10
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.
- checksums.yaml +15 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +18 -0
- data/README.md +42 -0
- data/bin/dtk-node-agent +16 -0
- data/dtk-node-agent.gemspec +38 -0
- data/lib/config/install.config +12 -0
- data/lib/dtk-node-agent/installer.rb +142 -0
- data/lib/dtk-node-agent/version.rb +3 -0
- data/mcollective_additions/plugins/README.md +1 -0
- data/mcollective_additions/plugins/v1.2/agent/discovery.rb +39 -0
- data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.ddl +15 -0
- data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.rb +79 -0
- data/mcollective_additions/plugins/v1.2/agent/git_access.ddl +9 -0
- data/mcollective_additions/plugins/v1.2/agent/git_access.rb +79 -0
- data/mcollective_additions/plugins/v1.2/agent/netstat.ddl +9 -0
- data/mcollective_additions/plugins/v1.2/agent/netstat.rb +34 -0
- data/mcollective_additions/plugins/v1.2/agent/puppet_apply.ddl +9 -0
- data/mcollective_additions/plugins/v1.2/agent/puppet_apply.rb +630 -0
- data/mcollective_additions/plugins/v1.2/agent/rpcutil.ddl +204 -0
- data/mcollective_additions/plugins/v1.2/agent/rpcutil.rb +101 -0
- data/mcollective_additions/plugins/v1.2/facts/pbuilder_facts.rb +35 -0
- data/mcollective_additions/plugins/v2.2/agent/dev_manager.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/dev_manager.rb +69 -0
- data/mcollective_additions/plugins/v2.2/agent/discovery.rb +39 -0
- data/mcollective_additions/plugins/v2.2/agent/dtk_node_agent_git_client.rb +94 -0
- data/mcollective_additions/plugins/v2.2/agent/execute_tests.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/execute_tests.rb +64 -0
- data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.ddl +15 -0
- data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.rb +79 -0
- data/mcollective_additions/plugins/v2.2/agent/git_access.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/git_access.rb +72 -0
- data/mcollective_additions/plugins/v2.2/agent/netstat.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/netstat.rb +34 -0
- data/mcollective_additions/plugins/v2.2/agent/ps.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/ps.rb +37 -0
- data/mcollective_additions/plugins/v2.2/agent/puppet_apply.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/agent/puppet_apply.rb +633 -0
- data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.ddl +10 -0
- data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.rb +78 -0
- data/mcollective_additions/plugins/v2.2/agent/rpcutil.ddl +204 -0
- data/mcollective_additions/plugins/v2.2/agent/rpcutil.rb +101 -0
- data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.ddl +10 -0
- data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.rb +85 -0
- data/mcollective_additions/plugins/v2.2/agent/tail.ddl +11 -0
- data/mcollective_additions/plugins/v2.2/agent/tail.rb +67 -0
- data/mcollective_additions/plugins/v2.2/connector/r8stomp.rb +238 -0
- data/mcollective_additions/plugins/v2.2/connector/stomp.rb +349 -0
- data/mcollective_additions/plugins/v2.2/connector/stomp_em.rb +191 -0
- data/mcollective_additions/plugins/v2.2/facts/pbuilder_facts.rb +35 -0
- data/mcollective_additions/plugins/v2.2/security/sshkey.ddl +9 -0
- data/mcollective_additions/plugins/v2.2/security/sshkey.rb +362 -0
- data/mcollective_additions/server.cfg +22 -0
- data/puppet_additions/modules/r8/lib/puppet/type/r8_export_file.rb +53 -0
- data/puppet_additions/modules/r8/manifests/export_variable.rb +10 -0
- data/puppet_additions/puppet_lib_base/puppet/indirector/catalog/r8_storeconfig_backend.rb +48 -0
- data/puppet_additions/puppet_lib_base/puppet/indirector/r8_storeconfig_backend.rb +4 -0
- data/puppet_additions/puppet_lib_base/puppet/indirector/resource/r8_storeconfig_backend.rb +72 -0
- data/src/etc/init.d/ec2-run-user-data +95 -0
- data/src/etc/logrotate.d/mcollective +10 -0
- data/src/etc/logrotate.d/puppet +7 -0
- metadata +189 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'grit'
|
2
|
+
module DTK
|
3
|
+
module NodeAgent
|
4
|
+
class GitClient
|
5
|
+
def initialize(repo_dir,opts={})
|
6
|
+
@repo_dir = repo_dir
|
7
|
+
@grit_repo = (opts[:create] ? ::Grit::Repo.init(repo_dir) : ::Grit::Repo.new(repo_dir))
|
8
|
+
end
|
9
|
+
|
10
|
+
def clone_branch(remote_repo,branch,opts={})
|
11
|
+
git_command__remote_add(remote_repo,branch)
|
12
|
+
git_command__checkout(opts[:sha]||branch)
|
13
|
+
end
|
14
|
+
|
15
|
+
def pull_and_checkout_branch?(branch,opts={})
|
16
|
+
sha = opts[:sha]
|
17
|
+
#shortcut
|
18
|
+
return if sha and (sha == current_branch_or_head())
|
19
|
+
|
20
|
+
unless remote_branch_exists?(branch)
|
21
|
+
git_command__remote_branch_add(branch)
|
22
|
+
git_command__fetch()
|
23
|
+
end
|
24
|
+
|
25
|
+
if branch_exists?(branch)
|
26
|
+
git_command__pull(branch)
|
27
|
+
git_command__checkout(sha) if sha
|
28
|
+
else
|
29
|
+
git_command__checkout(sha||branch)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def git_command__remote_add(remote_repo,branch,remote_name=nil)
|
35
|
+
remote_name ||= default_remote()
|
36
|
+
git_command().remote(git_command_opts(),"add","-t", branch, "-f", remote_name, remote_repo)
|
37
|
+
end
|
38
|
+
|
39
|
+
def git_command__remote_branch_add(branch,remote_name=nil)
|
40
|
+
remote_name ||= default_remote()
|
41
|
+
git_command().remote(git_command_opts(),"set-branches", "--add", remote_name, branch)
|
42
|
+
end
|
43
|
+
|
44
|
+
def git_command__checkout(ref)
|
45
|
+
unless current_branch_or_head() == ref
|
46
|
+
git_command().checkout(git_command_opts(),ref)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def git_command__fetch(remote_name=nil)
|
51
|
+
remote_name ||= default_remote()
|
52
|
+
git_command().fetch(git_command_opts(),remote_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def git_command__pull(branch,remote_name=nil)
|
56
|
+
remote_name ||= default_remote()
|
57
|
+
git_command().pull(git_command_opts(),remote_name,branch)
|
58
|
+
end
|
59
|
+
|
60
|
+
def branch_exists?(branch)
|
61
|
+
@grit_repo.heads.find{|h|h.name == branch} ? true : nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def remote_branch_exists?(branch,remote_name=nil)
|
65
|
+
remote_name ||= default_remote()
|
66
|
+
remote_branch = "#{remote_name}/#{branch}"
|
67
|
+
@grit_repo.remotes.find{|h|h.name == remote_branch} ? true : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def current_branch_or_head()
|
71
|
+
#this returns sha when detached head
|
72
|
+
if @grit_repo.head
|
73
|
+
@grit_repo.head.name
|
74
|
+
elsif @grit_repo.commit('HEAD')
|
75
|
+
@grit_repo.commit('HEAD').id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_remote()
|
80
|
+
'origin'
|
81
|
+
end
|
82
|
+
|
83
|
+
def git_command_opts(opts={})
|
84
|
+
ret = {:raise => true, :timeout => 60}
|
85
|
+
ret.merge!(:chdir => @repo_dir) unless opts[:no_chdir]
|
86
|
+
end
|
87
|
+
|
88
|
+
def git_command()
|
89
|
+
@grit_repo.git
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
metadata :name => "component module tests executor",
|
2
|
+
:description => "Agent to executing component module infrastructure tests",
|
3
|
+
:author => "Reactor8",
|
4
|
+
:license => "",
|
5
|
+
:version => "",
|
6
|
+
:url => "",
|
7
|
+
:timeout => 10
|
8
|
+
action "execute_tests", :description => "execute all component module infrastructure tests" do
|
9
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module MCollective
|
2
|
+
module Agent
|
3
|
+
class Execute_tests < RPC::Agent
|
4
|
+
def initialize()
|
5
|
+
super()
|
6
|
+
@log = Log.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
action "execute_tests" do
|
10
|
+
#Get list of component modules that have spec tests
|
11
|
+
list_output=`ls /etc/puppet/modules/*/dtk/serverspec/spec/localhost/*/*_spec.rb`
|
12
|
+
regex_pattern=/modules\/(.+)\/dtk\/serverspec\/spec\/localhost\/(.+)\//
|
13
|
+
ModuleInfo = Struct.new(:module_name, :component_name)
|
14
|
+
modules_info = []
|
15
|
+
|
16
|
+
components = []
|
17
|
+
request[:components].each do |c|
|
18
|
+
if c.include? "::"
|
19
|
+
components << c.split("::").last
|
20
|
+
elsif c.include? "/"
|
21
|
+
components << c.split("/").last
|
22
|
+
else
|
23
|
+
components << c
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
list_output.each do |line|
|
28
|
+
match = line.match(regex_pattern)
|
29
|
+
components.each do |c|
|
30
|
+
if c.eql? match[2]
|
31
|
+
modules_info << ModuleInfo.new(match[1],match[2])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
all_spec_results = []
|
37
|
+
#filter out redundant module info if any
|
38
|
+
modules_info = modules_info.uniq
|
39
|
+
modules_info.each do |module_info|
|
40
|
+
component_module = module_info[:module_name]
|
41
|
+
component = module_info[:component_name]
|
42
|
+
|
43
|
+
spec_results=`/opt/puppet-omnibus/embedded/bin/rspec /etc/puppet/modules/#{component_module}/dtk/serverspec/spec/localhost/#{component}/*_spec.rb --format j`
|
44
|
+
@log.info("Executing serverspec test: /etc/puppet/modules/#{component_module}/tests/serverspec/spec/localhost/#{component}/*_spec.rb")
|
45
|
+
|
46
|
+
spec_results_json = JSON.parse(spec_results)
|
47
|
+
|
48
|
+
spec_results_json['examples'].each do |spec|
|
49
|
+
spec_result = {}
|
50
|
+
spec_result.store(:module_name, component_module)
|
51
|
+
spec_result.store(:component_name, component)
|
52
|
+
spec_result.store(:test_result, spec['full_description'])
|
53
|
+
spec_result.store(:status, spec['status'])
|
54
|
+
all_spec_results << spec_result
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
reply[:data] = all_spec_results
|
59
|
+
reply[:pbuilderid] = Facts["pbuilderid"]
|
60
|
+
reply[:status] = :ok
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
metadata :name => "get log fragment",
|
2
|
+
:description => "get log fragment",
|
3
|
+
:author => "Reactor8",
|
4
|
+
:license => "",
|
5
|
+
:version => "",
|
6
|
+
:url => "",
|
7
|
+
:timeout => 20
|
8
|
+
action "get", :description => "get log data fragment" do
|
9
|
+
display :always
|
10
|
+
%w{status error data pbuilderid}.each do |k|
|
11
|
+
output k.to_sym,
|
12
|
+
:description => k.capitalize,
|
13
|
+
:display_as => k.capitalize
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
module MCollective
|
5
|
+
#TODO: shoudl go in common area
|
6
|
+
LogFileHandles = {:task_id => Hash.new, :top_task_id => Hash.new}
|
7
|
+
|
8
|
+
module Agent
|
9
|
+
class Get_log_fragment < RPC::Agent
|
10
|
+
metadata :name => "get log fragment",
|
11
|
+
:description => "get log fragment",
|
12
|
+
:author => "Reactor8",
|
13
|
+
:license => "",
|
14
|
+
:version => "",
|
15
|
+
:url => "",
|
16
|
+
:timeout => 20
|
17
|
+
def initialize()
|
18
|
+
super()
|
19
|
+
@log = Log.instance
|
20
|
+
end
|
21
|
+
def get_action()
|
22
|
+
validate :key, String
|
23
|
+
validate :value, String
|
24
|
+
log_file_dir = "/var/log/puppet"
|
25
|
+
key = request[:key]
|
26
|
+
value = request[:value]
|
27
|
+
lines = get_log_fragment(log_file_dir,key,value)
|
28
|
+
pbuilderid = Facts["pbuilderid"]
|
29
|
+
if lines.nil?
|
30
|
+
error_msg = "Cannot find log fragment matching #{key}=#{value}"
|
31
|
+
error_response = {
|
32
|
+
:status => :failed,
|
33
|
+
:error => {
|
34
|
+
:message => error_msg
|
35
|
+
},
|
36
|
+
:pbuilderid => pbuilderid
|
37
|
+
}
|
38
|
+
@log.error(error_msg)
|
39
|
+
reply.data = error_response
|
40
|
+
else
|
41
|
+
ok_response = {
|
42
|
+
:status => :ok,
|
43
|
+
:data => lines,
|
44
|
+
:pbuilderid => pbuilderid
|
45
|
+
}
|
46
|
+
reply.data = ok_response
|
47
|
+
end
|
48
|
+
end
|
49
|
+
private
|
50
|
+
def get_log_fragment(log_file_dir,key,value)
|
51
|
+
#flush file if it is open
|
52
|
+
if file_handle = (LogFileHandles[key.to_sym]||{})[value]
|
53
|
+
file_handle.flush
|
54
|
+
end
|
55
|
+
|
56
|
+
delim = key.to_sym == :top_task_id ? "\\." : ":"
|
57
|
+
string_key = "#{key}:#{value.to_s}#{delim}"
|
58
|
+
ret = Array.new
|
59
|
+
matches = Dir["#{log_file_dir}/*.log"].grep(Regexp.new(string_key))
|
60
|
+
if matches.size == 0
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
matching_file = matches.size == 1 ?
|
64
|
+
matches.first :
|
65
|
+
#this finds teh most recent file
|
66
|
+
matches.map{|file|[file,File.mtime(file)]}.sort{|a,b|b[1]<=>a[1]}.first[0]
|
67
|
+
begin
|
68
|
+
f = File.open(matching_file)
|
69
|
+
until f.eof
|
70
|
+
ret << f.readline.chop
|
71
|
+
end
|
72
|
+
ensure
|
73
|
+
f.close
|
74
|
+
end
|
75
|
+
ret
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module MCollective
|
2
|
+
module Agent
|
3
|
+
class Git_access < RPC::Agent
|
4
|
+
action "add_rsa_info" do
|
5
|
+
ssh_folder_path = '/root/.ssh'
|
6
|
+
rsa_path = "#{ssh_folder_path}/id_rsa"
|
7
|
+
rsa_pub_path = "#{ssh_folder_path}/id_rsa.pub"
|
8
|
+
known_hosts = "#{ssh_folder_path}/known_hosts"
|
9
|
+
|
10
|
+
begin
|
11
|
+
# validate request
|
12
|
+
validate_request(request)
|
13
|
+
|
14
|
+
#create private rsa file if needed
|
15
|
+
unless donot_create_file?(:private,rsa_path,request[:agent_ssh_key_private])
|
16
|
+
File.open(rsa_path,"w",0600){|f|f.print request[:agent_ssh_key_private]}
|
17
|
+
end
|
18
|
+
|
19
|
+
#create public rsa file if needed
|
20
|
+
unless donot_create_file?(:public,rsa_pub_path,request[:agent_ssh_key_public])
|
21
|
+
File.open(rsa_pub_path,"w"){|f|f.print request[:agent_ssh_key_public]}
|
22
|
+
end
|
23
|
+
|
24
|
+
#create or append if key not there
|
25
|
+
skip = nil
|
26
|
+
fp = request[:server_ssh_rsa_fingerprint]
|
27
|
+
if File.exists?(known_hosts)
|
28
|
+
fp_key = (fp =~ Regexp.new("^[|]1[|]([^=]+)=");$1)
|
29
|
+
if fp_key
|
30
|
+
fp_key_regexp = Regexp.new("^.1.#{fp_key}")
|
31
|
+
skip = !!File.open(known_hosts){|f|f.find{|line|line =~ fp_key_regexp}}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
unless skip
|
35
|
+
File.open(known_hosts,"a"){|f|f.print request[:server_ssh_rsa_fingerprint]}
|
36
|
+
end
|
37
|
+
|
38
|
+
reply.data = { :status => :succeeded}
|
39
|
+
rescue Exception => e
|
40
|
+
reply.data = { :status => :failed, :error => {:message => e.message}}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#TODO: move to using mcollective vallidation on ddl
|
45
|
+
def validate_request(req)
|
46
|
+
required_params = [:agent_ssh_key_public, :agent_ssh_key_private, :server_ssh_rsa_fingerprint]
|
47
|
+
missing_params = []
|
48
|
+
required_params.each do |param|
|
49
|
+
missing_params << param if req[param].nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
unless missing_params.empty?
|
53
|
+
raise "Request is missing required param(s): #{missing_params.join(',')} please review your request."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def donot_create_file?(type,path,content)
|
58
|
+
# raises exception if these files already exists and content differs
|
59
|
+
if File.exists?(path)
|
60
|
+
existing = File.open(path).read
|
61
|
+
if existing == content
|
62
|
+
true
|
63
|
+
else
|
64
|
+
raise "RSA #{type} key already exists and differs from one in payload"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MCollective
|
2
|
+
module Agent
|
3
|
+
class Netstat < RPC::Agent
|
4
|
+
metadata :name => "netstat info",
|
5
|
+
:description => "Agent to get netstat info",
|
6
|
+
:author => "Reactor8",
|
7
|
+
:license => "",
|
8
|
+
:version => "",
|
9
|
+
:url => "",
|
10
|
+
:timeout => 2
|
11
|
+
action "get_tcp_udp" do
|
12
|
+
output = `netstat -nltpu`
|
13
|
+
results = output.scan(/(^[a-z0-9]+)\s+(\d)\s+(\d)\s+([0-9:.*]+)\s+([0-9:.*]+)\s+(LISTEN)?\s+([0-9a-zA-Z\/\-: ]+)/m)
|
14
|
+
|
15
|
+
netstat_result = []
|
16
|
+
results.each do |result|
|
17
|
+
netstat_packet = {}
|
18
|
+
netstat_packet.store(:protocol, result[0])
|
19
|
+
netstat_packet.store(:recv_q, result[1])
|
20
|
+
netstat_packet.store(:send_q, result[2])
|
21
|
+
netstat_packet.store(:local, result[3])
|
22
|
+
netstat_packet.store(:foreign, result[4])
|
23
|
+
netstat_packet.store(:state, result[5])
|
24
|
+
netstat_packet.store(:program, result[6].strip)
|
25
|
+
netstat_result << netstat_packet
|
26
|
+
end
|
27
|
+
|
28
|
+
reply[:data] = netstat_result
|
29
|
+
reply[:pbuilderid] = Facts["pbuilderid"]
|
30
|
+
reply[:status] = :ok
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MCollective
|
2
|
+
module Agent
|
3
|
+
class Ps < RPC::Agent
|
4
|
+
metadata :name => "ps info",
|
5
|
+
:description => "Agent to get ps info (running processes)",
|
6
|
+
:author => "Reactor8",
|
7
|
+
:license => "",
|
8
|
+
:version => "",
|
9
|
+
:url => "",
|
10
|
+
:timeout => 2
|
11
|
+
action "get_ps" do
|
12
|
+
output=`ps -ef`
|
13
|
+
output.gsub!(/^.+\]$/,'')
|
14
|
+
results = output.scan(/(\S+)[\s].*?(\S+)[\s].*?(\S+)[\s].*?(\S+)[\s].*?(\S+)[\s].*?(\S+)[\s].*?(\S+)[\s].*?(.+)/)
|
15
|
+
results.shift
|
16
|
+
ps_result = []
|
17
|
+
results.each do |result|
|
18
|
+
ps_packet = {}
|
19
|
+
ps_packet.store(:uid, result[0])
|
20
|
+
ps_packet.store(:pid, result[1])
|
21
|
+
ps_packet.store(:ppid, result[2])
|
22
|
+
ps_packet.store(:cpu, result[3])
|
23
|
+
ps_packet.store(:start_time, result[4])
|
24
|
+
ps_packet.store(:tty, result[5])
|
25
|
+
ps_packet.store(:time, result[6])
|
26
|
+
result[7] = (result[7][0...60].strip + '...') if result[7].strip.length > 60
|
27
|
+
ps_packet.store(:command, result[7])
|
28
|
+
ps_result << ps_packet
|
29
|
+
end
|
30
|
+
|
31
|
+
reply[:data] = ps_result
|
32
|
+
reply[:pbuilderid] = Facts["pbuilderid"]
|
33
|
+
reply[:status] = :ok
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|