dtk-node-agent 0.5.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|