dtk-action-agent 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21e7fee109731e73725a259437c2d996742eef6e
4
- data.tar.gz: ca71e73fdb44d748c8f4e14ce40bcb45b44b4984
3
+ metadata.gz: 6d0db3719b17b9856404b7b9e81a1e9f91bc1c04
4
+ data.tar.gz: 3bcd4713fb782f37a6894f38b99a9cba3b4e7a59
5
5
  SHA512:
6
- metadata.gz: 433e0f1761c0de50613a8a9f6e543b8857b7c15ec4316fb821eb02546efbf3822b3cf094d966d6f9cc82a656fef60d8e3e4807e362568d38900edbbf2d3ba569
7
- data.tar.gz: e9e1eb5dba5b37b41c33736a04a5e8383ef3ce0f15e94cae6dcecf2e8616e9255ec062c8dc5a557fa5ce1eeec406db98b0eaabeb41dbf285630eaa4908765dbc
6
+ metadata.gz: 8ccabb36b8cdd75c8a28b043255750f165ef03a9257e3f9e6d8ca72aaba4ec45f8b2ee8e2dca10fb1f42abe13e65e638d55c04b6eb119b9f0168c974a88fe0c6
7
+ data.tar.gz: 628007e0af112995cf08fd4e4bf395d38a213d3af5e44ddf57aa584b6e5c59f3b4f8715cce3795df42bec5a5c64eb8ac5c3cd065591ce7cf009059999ec9b899
data/bin/dtk-action-agent CHANGED
@@ -1,19 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require 'json'
4
+ require File.expand_path('../../lib/logger', __FILE__)
4
5
  require File.expand_path('../../lib/arbiter', __FILE__)
6
+ require File.expand_path('../../lib/positioner', __FILE__)
7
+ require File.expand_path('../../lib/commander', __FILE__)
5
8
 
6
9
  unless ARGV[0]
7
10
  error_msg = {
8
- :error => 'You need to provide JSON with argument to method call'
11
+ :errors => ['You need to provide JSON with argument to method call']
9
12
  }
10
13
  print error_msg.to_json
11
14
  else
12
15
  content = JSON.parse(ARGV[0])
13
16
  arbiter = DTK::Agent::Arbiter.new(content)
14
- arbiter.run()
17
+ results = arbiter.run()
15
18
 
16
- results = arbiter.results()
17
19
  # we print results in json so that they can be serialized in another
18
20
  print results.to_json
19
21
  end
@@ -21,5 +21,5 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency 'posix-spawn','0.3.8'
22
22
  gem.add_dependency 'awesome_print', '1.1.0'
23
23
  gem.add_dependency 'json', '1.8.2'
24
-
24
+ gem.add_dependency 'git', '1.2.9.1'
25
25
  end
data/lib/arbiter.rb CHANGED
@@ -10,43 +10,31 @@ module DTK
10
10
  def initialize(consumer_hash)
11
11
  @received_message = consumer_hash
12
12
  @process_pool = []
13
- end
13
+ @execution_list = @received_message['execution_list']||[]
14
14
 
15
- def run
16
- (@received_message['commands']||[]).each do |message|
17
- @process_pool << POSIX::Spawn::Child.new(message)
15
+ # no need to run other commands if there is no execution list
16
+ if @execution_list.empty?
17
+ Log.error "Execution list is not provided or empty, DTK Action Agent has nothing to run"
18
+ return
18
19
  end
19
20
 
20
- loop do
21
- sleep(1)
22
- @process_pool.each do |process|
23
- unless process.status.exited?
24
- next
25
- end
26
- end
27
- break
28
- end
21
+ # sets enviorment variables
22
+ Commander.set_environment_variables(@received_message['env_vars'])
23
+ @positioner = Positioner.new(@received_message['positioning'])
24
+ @commander = Commander.new(@received_message['execution_list'])
29
25
  end
30
26
 
31
- def results
32
- @process_pool.collect do |process|
33
- {
34
- :status => process.status.exitstatus,
35
- :stdout => process.out,
36
- :stderr => process.err
37
- }
38
- end
39
- end
27
+ def run
28
+ return { :results => [], :errors => Log.execution_errrors } if @execution_list.empty?
40
29
 
41
- def print_results
42
- @process_pool.each do |process|
43
- ap process.status
44
- ap "STDOUT"
45
- print process.out
46
- ap "STDERR"
47
- print process.err
48
- ap "-----------------------------------"
49
- end
30
+ # start positioning files
31
+ @positioner.run()
32
+
33
+ # start commander runnes
34
+ @commander.run()
35
+
36
+ # return results
37
+ { :results => @commander.results(), :errors => Log.execution_errrors }
50
38
  end
51
39
 
52
40
  end
data/lib/command.rb ADDED
@@ -0,0 +1,90 @@
1
+ module DTK
2
+ module Agent
3
+
4
+ ##
5
+ # This is container for command as received from Node Agent
6
+
7
+ class Command
8
+
9
+ attr_accessor :command_type, :command, :if_success, :if_fail, :process, :child_task
10
+
11
+ ##
12
+ # command - string to be run on system, e.g. ifconfig
13
+ # type - type of command e.g. syscall, ruby
14
+ # if - callback to be run if exit status is = 0
15
+ # unless - callback to be run if exit status is != 0
16
+ # child_task - if it is spawned by another main task
17
+ #
18
+ def initialize(value_hash)
19
+ @command_type = value_hash['type']
20
+ @command = value_hash['command']
21
+ @if_success = value_hash['if']
22
+ @if_fail = value_hash['unless']
23
+ @spawned = false
24
+ @child_task = value_hash['child_task'] || false
25
+
26
+ if @if_success && @if_fail
27
+ Log.warn "Unexpected case, both if/unless conditions have been set for command #{@command}(#{@command_type})"
28
+ end
29
+ end
30
+
31
+ ##
32
+ # Creates Posix Spawn of given process
33
+ #
34
+ def start_task
35
+ begin
36
+ @process = POSIX::Spawn::Child.new(@command)
37
+ Log.debug("Command started: '#{self.to_s}'")
38
+ rescue Exception => e
39
+ @error_message = e.message
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Checks if there is callaback present, callback beeing if/unless command
45
+ #
46
+ def callback_pending?
47
+ return false if @spawned
48
+ command_to_run = (self.exitstatus.to_i == 0) ? @if_success : @if_fail
49
+ !!command_to_run
50
+ end
51
+
52
+
53
+ ##
54
+ # Creates Command object for callback, first check 'if' than 'unless'. There should be no both set so priority is given
55
+ # to 'if' callback in case there are two
56
+ #
57
+ def spawn_callback_task
58
+ callback_command = (self.exitstatus.to_i == 0) ? @if_success : @if_fail
59
+ new_command = Command.new('type' => @command_type, 'command' => callback_command, 'child_task' => true)
60
+ @spawned = true
61
+ new_command
62
+ end
63
+
64
+ def exited?
65
+ return true if @error_message
66
+ self.process.status.exited?
67
+ end
68
+
69
+ def exitstatus
70
+ return 1 if @error_message
71
+ self.process.status.exitstatus
72
+ end
73
+
74
+ def out
75
+ return '' if @error_message
76
+ self.process.out
77
+ end
78
+
79
+ def err
80
+ return @error_message if @error_message
81
+ self.process.err
82
+ end
83
+
84
+ def to_s
85
+ "#{@command} (#{command_type})"
86
+ end
87
+
88
+ end
89
+ end
90
+ end
data/lib/commander.rb ADDED
@@ -0,0 +1,76 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+
4
+ module DTK
5
+ module Agent
6
+ class Commander
7
+
8
+ def initialize(execution_list)
9
+ @command_tasks = execution_list.collect { |command| Command.new(command) }
10
+ end
11
+
12
+ def run
13
+ @command_tasks.each do |command_task|
14
+ command_task.start_task
15
+ end
16
+
17
+ loop do
18
+ all_finished = true
19
+ sleep(1)
20
+
21
+ # we check status of all tasks
22
+ # (Usually is not good practice to change array/map you are iterating but this seems as cleanest solutions)
23
+ @command_tasks.each do |command_task|
24
+
25
+ # is task finished
26
+ if command_task.exited?
27
+ Log.debug("Command '#{command_task}' finished, with status #{command_task.exitstatus}")
28
+
29
+ # if there is a callback start it
30
+ if command_task.callback_pending?
31
+ new_command_task = command_task.spawn_callback_task
32
+ new_command_task.start_task
33
+ @command_tasks << new_command_task
34
+ Log.debug("Command '#{new_command_task}' spawned as callback")
35
+ # new task added we need to check again
36
+ all_finished = false
37
+ end
38
+ else
39
+ # we are not ready yet, some tasks need to finish
40
+ all_finished = false
41
+ end
42
+ end
43
+
44
+ break if all_finished
45
+ end
46
+ end
47
+
48
+ def results
49
+ @command_tasks.collect do |command_task|
50
+ process = command_task.process
51
+ {
52
+ :status => command_task.exitstatus,
53
+ :stdout => command_task.out,
54
+ :stderr => command_task.err,
55
+ :description => command_task.to_s,
56
+ :child_task => command_task.child_task
57
+ }
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ ##
64
+ # Sets environmental variables
65
+ def self.set_environment_variables(env_vars_hash)
66
+ return unless env_vars_hash
67
+ env_vars_hash.each do |k, v|
68
+ ENV[k] = v.to_s.strip
69
+ Log.debug("Environment variable set (#{k}: #{v})")
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -1,5 +1,5 @@
1
1
  module DTK
2
2
  module ActionAgent
3
- VERSION="0.0.1"
3
+ VERSION="0.0.2"
4
4
  end
5
5
  end
data/lib/logger.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'logger'
2
+ require 'singleton'
3
+
4
+ module DTK
5
+ module Agent
6
+ class Log
7
+ include Singleton
8
+
9
+ attr_accessor :logger, :error_msgs
10
+
11
+ LOG_TO_CONSOLE = false
12
+ LOG_TO_FILE = '/var/log/action-agent.log'
13
+ # LOG_TO_FILE = '/Users/haris/test.log'
14
+
15
+ def initialize
16
+ # @logger = Logger.new(File.new(LOG_TO_FILE,'w'))
17
+ @error_msgs =[]
18
+ end
19
+
20
+ def self.execution_errrors()
21
+ self.instance.error_msgs
22
+ end
23
+
24
+ def self.debug(msg)
25
+ # self.instance.logger.debug(msg)
26
+ ap "debug: #{msg}" if LOG_TO_CONSOLE
27
+ end
28
+
29
+ def self.info(msg)
30
+ # self.instance.logger.info(msg)
31
+ ap "info: #{msg}" if LOG_TO_CONSOLE
32
+ end
33
+
34
+ def self.warn(msg)
35
+ # self.instance.logger.warn(msg)
36
+ ap "warn: #{msg}" if LOG_TO_CONSOLE
37
+ self.instance.error_msgs << msg
38
+ end
39
+
40
+ def self.error(msg)
41
+ # self.instance.logger.error(msg)
42
+ ap "error: #{msg}" if LOG_TO_CONSOLE
43
+ self.instance.error_msgs << msg
44
+ end
45
+
46
+ end
47
+ end
48
+ end
data/lib/positioner.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'thread'
2
+ require 'git'
3
+ require 'fileutils'
4
+
5
+ module DTK
6
+ module Agent
7
+ class Positioner
8
+
9
+ attr_accessor :position_file_info
10
+
11
+ def initialize(*position_file_info)
12
+ @position_file_info = position_file_info.flatten.compact
13
+ end
14
+
15
+ def run()
16
+ @position_file_info.each do |pfi|
17
+ case pfi['source']['type'].to_sym
18
+ when :git
19
+ position_git(pfi)
20
+ when :in_payload
21
+ position_in_payload(pfi)
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def position_git(position_info)
29
+ folder_path = prepare_path(position_info)
30
+ git_url = position_info['source']['url']
31
+ git_branch = position_info['source']['ref']
32
+
33
+ unless File.directory?(folder_path)
34
+ begin
35
+ g_repo = Git.clone("#{git_url}", '', :path => folder_path, :branch => git_branch)
36
+ Log.info("Positioner successfully cloned git repository '#{git_url}@#{git_branch}' to location '#{folder_path}'")
37
+ rescue Exception => e
38
+ Log.error("Positioner unable to clone #{git_url}")
39
+ Log.error(e.message)
40
+ end
41
+ else
42
+ Log.warn("Positioner detected folder '#{folder_path}' skipping git clone")
43
+ end
44
+ end
45
+
46
+ def position_in_payload(position_info)
47
+ file_path = prepare_path(position_info)
48
+ file_content = position_info['source']['content']
49
+ # write to file
50
+ File.open(file_path, 'w') { |file| file.write(file_content) }
51
+ Log.info("Positioner successfully created 'IN_PAYLOAD' file '#{file_path}'")
52
+ end
53
+
54
+ def prepare_path(position_info)
55
+ path = position_info['target']['path']
56
+
57
+ # create necessery dir structure
58
+ FileUtils.mkdir_p(File.dirname(path))
59
+
60
+ path
61
+ end
62
+
63
+ end
64
+ end
65
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dtk-action-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich PELAVIN
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-12 00:00:00.000000000 Z
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: posix-spawn
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.8.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: git
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.9.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.2.9.1
55
69
  description: The DTK Action Agent is designed to run commands on remote machine.
56
70
  email:
57
71
  - rich@reactor8.com
@@ -64,7 +78,11 @@ files:
64
78
  - bin/dtk-action-agent
65
79
  - dtk-action-agent.gemspec
66
80
  - lib/arbiter.rb
81
+ - lib/command.rb
82
+ - lib/commander.rb
67
83
  - lib/dtk-action-agent/version.rb
84
+ - lib/logger.rb
85
+ - lib/positioner.rb
68
86
  homepage: ''
69
87
  licenses:
70
88
  - GPL-3.0