dtk-action-agent 0.0.1 → 0.0.2

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