huginn_ruby_agent 0.2 → 0.3
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 +4 -4
- data/lib/agents/ruby_agent.rb +142 -0
- data/lib/huginn_ruby_agent/agent.rb +85 -0
- data/lib/huginn_ruby_agent/sdk.rb +70 -0
- data/lib/huginn_ruby_agent.rb +4 -2
- data/spec/agent_spec.rb +135 -0
- data/spec/sdk_spec.rb +22 -0
- metadata +9 -5
- data/lib/huginn_ruby_agent/ruby_agent.rb +0 -238
- data/spec/ruby_agent_spec.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dcca4b6d669c71c00b5797822e4dfe24c09a0b8344dcd6ad49b9076b7cfe050
|
4
|
+
data.tar.gz: e2580eb01f896a539e98096856a8b79c2416ca04abfa53433f65659cda454cdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4ad3b1d8bf620b5184cdcc9d84d312bf2fdbb5949f5e9b4311d5ae757855ae329b86745da593ace0c8d8d18434a62bb303abb85756246344944748db9a0b79d
|
7
|
+
data.tar.gz: 0512e8b2944b8e2e542e2529673ed1473062d45e8f8b409f852f31dd78b8d963c215c84dc92366593c77a4b60a14292958daa7ad653dc0da5edabe3fecc64197
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'huginn_ruby_agent'
|
3
|
+
require 'huginn_ruby_agent/agent'
|
4
|
+
|
5
|
+
module Agents
|
6
|
+
class RubyAgent < Agent
|
7
|
+
include FormConfigurable
|
8
|
+
|
9
|
+
can_dry_run!
|
10
|
+
|
11
|
+
default_schedule "never"
|
12
|
+
|
13
|
+
# TODO: remove redundant
|
14
|
+
gem_dependency_check { defined?(MiniRacer) }
|
15
|
+
|
16
|
+
description <<-MD
|
17
|
+
The Ruby Agent allows you to write code in Ruby that can create and receive events. If other Agents aren't meeting your needs, try this one!
|
18
|
+
|
19
|
+
You should put code in the `code` option.
|
20
|
+
|
21
|
+
You can implement `Agent.check` and `Agent.receive` as you see fit. The following methods will be available on Agent:
|
22
|
+
|
23
|
+
* `@api.create_event(payload)`
|
24
|
+
* `@api.incoming_vents()` (the returned event objects will each have a `payload` property) # TODO
|
25
|
+
* `@api.memory()` # TODO
|
26
|
+
* `@api.memory(key)` # TODO
|
27
|
+
* `@api.memory(keyToSet, valueToSet)` # TODO
|
28
|
+
* `@api.set_memory(object)` (replaces the Agent's memory with the provided object) # TODO
|
29
|
+
* `@api.delete_key(key)` (deletes a key from memory and returns the value) # TODO
|
30
|
+
* `@api.credential(name)`
|
31
|
+
* `@api.set_credential(name, valueToSet)`
|
32
|
+
* `@api.options()` # TODO
|
33
|
+
* `@api.options(key)` # TODO
|
34
|
+
* `@api.log(message)`
|
35
|
+
* `@api.error(message)`
|
36
|
+
MD
|
37
|
+
|
38
|
+
form_configurable :code, type: :text, ace: true
|
39
|
+
form_configurable :expected_receive_period_in_days
|
40
|
+
form_configurable :expected_update_period_in_days
|
41
|
+
|
42
|
+
def validate_options
|
43
|
+
errors.add(:base, "The 'code' option is required") unless options['code'].present?
|
44
|
+
end
|
45
|
+
|
46
|
+
def working?
|
47
|
+
return false if recent_error_logs?
|
48
|
+
|
49
|
+
if interpolated['expected_update_period_in_days'].present?
|
50
|
+
return false unless event_created_within?(interpolated['expected_update_period_in_days'])
|
51
|
+
end
|
52
|
+
|
53
|
+
if interpolated['expected_receive_period_in_days'].present?
|
54
|
+
return false unless last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago
|
55
|
+
end
|
56
|
+
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def check
|
62
|
+
running_agent do |agent|
|
63
|
+
agent.check
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def receive(events)
|
68
|
+
running_agent do |agent|
|
69
|
+
agent.receive events
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_options
|
74
|
+
code = <<~CODE
|
75
|
+
|
76
|
+
require "bundler/inline"
|
77
|
+
|
78
|
+
gemfile do
|
79
|
+
source "https://rubygems.org"
|
80
|
+
|
81
|
+
# gem "mechanize"
|
82
|
+
end
|
83
|
+
|
84
|
+
class Agent
|
85
|
+
def initialize(api)
|
86
|
+
@api = api
|
87
|
+
end
|
88
|
+
|
89
|
+
def check
|
90
|
+
@api.create_event({ message: 'I made an event!' })
|
91
|
+
end
|
92
|
+
|
93
|
+
def receive(incoming_events)
|
94
|
+
incoming_events.each do |event|
|
95
|
+
@api.create_event({ message: 'new event', event_was: event[:payload] })
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
CODE
|
100
|
+
|
101
|
+
{
|
102
|
+
'code' => code,
|
103
|
+
'expected_receive_period_in_days' => '2',
|
104
|
+
'expected_update_period_in_days' => '2'
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def running_agent
|
111
|
+
agent = HuginnRubyAgent::Agent.new(code:, credentials: credentials_hash)
|
112
|
+
yield agent
|
113
|
+
|
114
|
+
agent.events.each do |event|
|
115
|
+
create_event(payload: event)
|
116
|
+
end
|
117
|
+
agent.logs.each do |message|
|
118
|
+
log message
|
119
|
+
end
|
120
|
+
agent.errors.each do |message|
|
121
|
+
error message
|
122
|
+
end
|
123
|
+
agent.changed_credentials.each do |name, value|
|
124
|
+
set_credential(name, value)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def code
|
129
|
+
interpolated['code']
|
130
|
+
end
|
131
|
+
|
132
|
+
def credentials_hash
|
133
|
+
Hash[user.user_credentials.map { |c| [c.credential_name, c.credential_value] }]
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_credential(name, value)
|
137
|
+
c = user.user_credentials.find_or_initialize_by(credential_name: name)
|
138
|
+
c.credential_value = value
|
139
|
+
c.save!
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'json'
|
3
|
+
require 'huginn_ruby_agent/sdk'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module HuginnRubyAgent
|
7
|
+
class Agent
|
8
|
+
attr_reader :events, :errors, :logs, :changed_credentials
|
9
|
+
|
10
|
+
def initialize(code:, credentials: {})
|
11
|
+
@code = code
|
12
|
+
@events = []
|
13
|
+
@logs = []
|
14
|
+
@errors = []
|
15
|
+
@credentials = credentials
|
16
|
+
@changed_credentials = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def check
|
20
|
+
execute ".check"
|
21
|
+
end
|
22
|
+
|
23
|
+
def receive(events)
|
24
|
+
execute ".receive(api.deserialize('#{sdk.serialize(events)}'))"
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_event(payload)
|
28
|
+
@events << payload
|
29
|
+
end
|
30
|
+
|
31
|
+
def log(message)
|
32
|
+
@logs << message
|
33
|
+
end
|
34
|
+
|
35
|
+
def error(message)
|
36
|
+
@errors << message
|
37
|
+
end
|
38
|
+
|
39
|
+
def sdk
|
40
|
+
@sdk ||= SDK.new
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# https://stackoverflow.com/questions/23884526/is-there-a-safe-way-to-eval-in-ruby-or-a-better-way-to-do-this
|
46
|
+
def execute(command=".check")
|
47
|
+
Bundler.with_original_env do
|
48
|
+
Open3.popen3("ruby", chdir: '/') do |input, output, err, thread|
|
49
|
+
input.write sdk.code
|
50
|
+
input.write @code
|
51
|
+
input.write <<~CODE
|
52
|
+
|
53
|
+
api = Huginn::API.new(serialized_credentials: '#{sdk.serialize(@credentials)}')
|
54
|
+
Agent.new(api)#{command}
|
55
|
+
|
56
|
+
CODE
|
57
|
+
input.close
|
58
|
+
|
59
|
+
output.readlines.map { |line| sdk.deserialize(line) }.each do |data|
|
60
|
+
case data[:action]
|
61
|
+
when 'create_event'
|
62
|
+
create_event(data[:payload])
|
63
|
+
when 'log'
|
64
|
+
log data[:payload]
|
65
|
+
when 'error'
|
66
|
+
error data[:payload]
|
67
|
+
when 'set_credential'
|
68
|
+
@changed_credentials[data[:payload][:name].to_sym] = data[:payload][:value]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
log_errors(err)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
rescue StandardError => e
|
76
|
+
error "Runtime error: #{e.message}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def log_errors(err)
|
80
|
+
err.read.lines.each do |line|
|
81
|
+
error line.strip
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module HuginnRubyAgent
|
5
|
+
class SDK
|
6
|
+
def serialize(payload)
|
7
|
+
Base64.urlsafe_encode64(payload.to_json)
|
8
|
+
end
|
9
|
+
|
10
|
+
def deserialize(serialized_payload)
|
11
|
+
JSON.parse Base64.urlsafe_decode64(serialized_payload.strip), symbolize_names: true
|
12
|
+
end
|
13
|
+
|
14
|
+
def code
|
15
|
+
<<~CODE
|
16
|
+
require 'json'
|
17
|
+
require 'base64'
|
18
|
+
|
19
|
+
module Huginn
|
20
|
+
class API
|
21
|
+
attr_reader :changed_credentials
|
22
|
+
|
23
|
+
def initialize(serialized_credentials: nil)
|
24
|
+
@serialized_credentials = serialized_credentials
|
25
|
+
@changed_credentials = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def credentials
|
29
|
+
@credentials ||=
|
30
|
+
begin
|
31
|
+
@serialized_credentials.nil? ? {} : deserialize(@serialized_credentials)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def serialize(payload)
|
36
|
+
Base64.urlsafe_encode64(payload.to_json)
|
37
|
+
end
|
38
|
+
|
39
|
+
def deserialize(serialized_payload)
|
40
|
+
JSON.parse Base64.urlsafe_decode64(serialized_payload.strip), symbolize_names: true
|
41
|
+
end
|
42
|
+
|
43
|
+
def credential(name)
|
44
|
+
credentials[name.to_sym]
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_credential(name, value)
|
48
|
+
credentials[name.to_sym] = value
|
49
|
+
changed_credentials[name.to_sym] = value
|
50
|
+
|
51
|
+
puts serialize({ action: :set_credential, payload: { name: name, value: value } })
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_event(payload)
|
55
|
+
puts serialize({ action: :create_event, payload: payload })
|
56
|
+
end
|
57
|
+
|
58
|
+
def log(message)
|
59
|
+
puts serialize({ action: :log, payload: message })
|
60
|
+
end
|
61
|
+
|
62
|
+
def error(message)
|
63
|
+
puts serialize({ action: :error, payload: message })
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
CODE
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/huginn_ruby_agent.rb
CHANGED
data/spec/agent_spec.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'huginn_ruby_agent'
|
2
|
+
require 'huginn_ruby_agent/agent'
|
3
|
+
|
4
|
+
module HuginnRubyAgent
|
5
|
+
describe Agent do
|
6
|
+
describe '#check' do
|
7
|
+
example 'it produces event' do
|
8
|
+
code = <<~CODE
|
9
|
+
class Agent
|
10
|
+
def initialize(api)
|
11
|
+
@api = api
|
12
|
+
end
|
13
|
+
|
14
|
+
def check
|
15
|
+
@api.create_event({ message: 'hello' })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
CODE
|
19
|
+
|
20
|
+
agent = described_class.new(code: code)
|
21
|
+
agent.check
|
22
|
+
|
23
|
+
expect(agent.events.size).to eq 1
|
24
|
+
expect(agent.events[0]).to eq(message: 'hello')
|
25
|
+
end
|
26
|
+
|
27
|
+
example "it captures error" do
|
28
|
+
code = <<~CODE
|
29
|
+
class Agent
|
30
|
+
def initialize(api)
|
31
|
+
@api = api
|
32
|
+
end
|
33
|
+
|
34
|
+
def check
|
35
|
+
some error here
|
36
|
+
end
|
37
|
+
end
|
38
|
+
CODE
|
39
|
+
|
40
|
+
agent = described_class.new(code: code)
|
41
|
+
agent.check
|
42
|
+
|
43
|
+
expect(agent.events).to be_empty
|
44
|
+
expect(agent.errors).not_to be_empty
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#receive' do
|
49
|
+
example 'it produces event' do
|
50
|
+
code = <<~CODE
|
51
|
+
class Agent
|
52
|
+
def initialize(api)
|
53
|
+
@api = api
|
54
|
+
end
|
55
|
+
|
56
|
+
def receive(events)
|
57
|
+
events.each do |event|
|
58
|
+
@api.create_event({ number: event[:number] + 1 })
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
CODE
|
63
|
+
|
64
|
+
agent = described_class.new(code: code)
|
65
|
+
agent.receive([{ number: 1 }])
|
66
|
+
|
67
|
+
expect(agent.events.size).to eq 1
|
68
|
+
expect(agent.events[0]).to eq(number: 2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#logs' do
|
73
|
+
example 'it produces log' do
|
74
|
+
code = <<~CODE
|
75
|
+
class Agent
|
76
|
+
def initialize(api)
|
77
|
+
@api = api
|
78
|
+
end
|
79
|
+
|
80
|
+
def check
|
81
|
+
@api.log "hello"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
CODE
|
85
|
+
|
86
|
+
agent = described_class.new(code: code)
|
87
|
+
agent.check
|
88
|
+
|
89
|
+
expect(agent.logs.size).to eq 1
|
90
|
+
expect(agent.logs[0]).to eq "hello"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#credentials' do
|
95
|
+
example 'it gives access to creds' do
|
96
|
+
code = <<~CODE
|
97
|
+
class Agent
|
98
|
+
def initialize(api)
|
99
|
+
@api = api
|
100
|
+
end
|
101
|
+
|
102
|
+
def check
|
103
|
+
@api.create_event token_from_credential: @api.credential(:token)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
CODE
|
107
|
+
|
108
|
+
agent = described_class.new(code: code, credentials: { token: 'abc123' })
|
109
|
+
agent.check
|
110
|
+
|
111
|
+
expect(agent.events[0]).to eq({ token_from_credential: 'abc123' })
|
112
|
+
end
|
113
|
+
|
114
|
+
example 'it updates creds' do
|
115
|
+
code = <<~CODE
|
116
|
+
class Agent
|
117
|
+
def initialize(api)
|
118
|
+
@api = api
|
119
|
+
end
|
120
|
+
|
121
|
+
def check
|
122
|
+
@api.set_credential(:token, 'new_val')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
CODE
|
126
|
+
|
127
|
+
agent = described_class.new(code: code, credentials: { token: 'abc123' })
|
128
|
+
|
129
|
+
expect(agent.changed_credentials).to be_empty
|
130
|
+
agent.check
|
131
|
+
expect(agent.changed_credentials).to eq({ token: 'new_val' })
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/spec/sdk_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'huginn_ruby_agent'
|
2
|
+
require 'huginn_ruby_agent/sdk'
|
3
|
+
|
4
|
+
module HuginnRubyAgent
|
5
|
+
describe SDK do
|
6
|
+
subject(:sdk) { described_class.new }
|
7
|
+
|
8
|
+
def transfered(data)
|
9
|
+
sdk.deserialize(sdk.serialize(data))
|
10
|
+
end
|
11
|
+
|
12
|
+
def expect_to_transfer_safe(data)
|
13
|
+
expect(transfered(data)).to eq data
|
14
|
+
end
|
15
|
+
|
16
|
+
it { expect_to_transfer_safe(1) }
|
17
|
+
it { expect_to_transfer_safe({}) }
|
18
|
+
it { expect_to_transfer_safe({ payload: 1 }) }
|
19
|
+
it { expect_to_transfer_safe({ action: 'create_event', payload: { number: 1 } }) }
|
20
|
+
it { expect_to_transfer_safe({ action: 'create_event', payload: { message: "hello" }}) }
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: huginn_ruby_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergei O. Udalov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,9 +87,12 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
+
- lib/agents/ruby_agent.rb
|
90
91
|
- lib/huginn_ruby_agent.rb
|
91
|
-
- lib/huginn_ruby_agent/
|
92
|
-
-
|
92
|
+
- lib/huginn_ruby_agent/agent.rb
|
93
|
+
- lib/huginn_ruby_agent/sdk.rb
|
94
|
+
- spec/agent_spec.rb
|
95
|
+
- spec/sdk_spec.rb
|
93
96
|
homepage: https://github.com/sergio-fry/huginn_ruby_agent
|
94
97
|
licenses: []
|
95
98
|
metadata: {}
|
@@ -113,4 +116,5 @@ signing_key:
|
|
113
116
|
specification_version: 4
|
114
117
|
summary: Ruby Agent for Huginn automation platform
|
115
118
|
test_files:
|
116
|
-
- spec/
|
119
|
+
- spec/sdk_spec.rb
|
120
|
+
- spec/agent_spec.rb
|
@@ -1,238 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'date'
|
4
|
-
require 'cgi'
|
5
|
-
require 'tempfile'
|
6
|
-
require 'base64'
|
7
|
-
|
8
|
-
# https://stackoverflow.com/questions/23884526/is-there-a-safe-way-to-eval-in-ruby-or-a-better-way-to-do-this
|
9
|
-
module Agents
|
10
|
-
class RubyAgent < Agent
|
11
|
-
include FormConfigurable
|
12
|
-
|
13
|
-
can_dry_run!
|
14
|
-
|
15
|
-
default_schedule "never"
|
16
|
-
|
17
|
-
gem_dependency_check { defined?(MiniRacer) }
|
18
|
-
|
19
|
-
description <<-MD
|
20
|
-
The Ruby Agent allows you to write code in Ruby that can create and receive events. If other Agents aren't meeting your needs, try this one!
|
21
|
-
|
22
|
-
You should put code in the `code` option.
|
23
|
-
|
24
|
-
You can implement `Agent.check` and `Agent.receive` as you see fit. The following methods will be available on Agent:
|
25
|
-
|
26
|
-
* `createEvent(payload)`
|
27
|
-
* `incomingEvents()` (the returned event objects will each have a `payload` property)
|
28
|
-
* `memory()`
|
29
|
-
* `memory(key)`
|
30
|
-
* `memory(keyToSet, valueToSet)`
|
31
|
-
* `setMemory(object)` (replaces the Agent's memory with the provided object)
|
32
|
-
* `deleteKey(key)` (deletes a key from memory and returns the value)
|
33
|
-
* `credential(name)`
|
34
|
-
* `credential(name, valueToSet)`
|
35
|
-
* `options()`
|
36
|
-
* `options(key)`
|
37
|
-
* `log(message)`
|
38
|
-
* `error(message)`
|
39
|
-
MD
|
40
|
-
|
41
|
-
form_configurable :code, type: :text, ace: true
|
42
|
-
form_configurable :expected_receive_period_in_days
|
43
|
-
form_configurable :expected_update_period_in_days
|
44
|
-
|
45
|
-
def validate_options
|
46
|
-
errors.add(:base, "The 'code' option is required") unless options['code'].present?
|
47
|
-
end
|
48
|
-
|
49
|
-
def working?
|
50
|
-
return false if recent_error_logs?
|
51
|
-
|
52
|
-
if interpolated['expected_update_period_in_days'].present?
|
53
|
-
return false unless event_created_within?(interpolated['expected_update_period_in_days'])
|
54
|
-
end
|
55
|
-
|
56
|
-
if interpolated['expected_receive_period_in_days'].present?
|
57
|
-
return false unless last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago
|
58
|
-
end
|
59
|
-
|
60
|
-
true
|
61
|
-
end
|
62
|
-
|
63
|
-
def check
|
64
|
-
log_errors do
|
65
|
-
execute_check
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def receive(events)
|
70
|
-
log_errors do
|
71
|
-
execute_receive(events)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def default_options
|
76
|
-
code = <<~CODE
|
77
|
-
|
78
|
-
require "bundler/inline"
|
79
|
-
|
80
|
-
gemfile do
|
81
|
-
source "https://rubygems.org"
|
82
|
-
|
83
|
-
# gem "mechanize"
|
84
|
-
end
|
85
|
-
|
86
|
-
class Agent
|
87
|
-
def initialize(api)
|
88
|
-
@api = api
|
89
|
-
end
|
90
|
-
|
91
|
-
def check
|
92
|
-
@api.create_event({ message: 'I made an event!' })
|
93
|
-
end
|
94
|
-
|
95
|
-
def receive(incoming_events)
|
96
|
-
incoming_events.each do |event|
|
97
|
-
@api.create_event({ message: 'new event', event_was: event[:payload] })
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
CODE
|
102
|
-
|
103
|
-
{
|
104
|
-
'code' => code,
|
105
|
-
'expected_receive_period_in_days' => '2',
|
106
|
-
'expected_update_period_in_days' => '2'
|
107
|
-
}
|
108
|
-
end
|
109
|
-
|
110
|
-
private
|
111
|
-
|
112
|
-
def execute_check
|
113
|
-
Bundler.with_original_env do
|
114
|
-
Open3.popen3("ruby", chdir: '/') do |input, output, err, thread|
|
115
|
-
input.write sdk_code
|
116
|
-
input.write code
|
117
|
-
input.write <<~CODE
|
118
|
-
|
119
|
-
Agent.new(Huginn::API.new).check
|
120
|
-
|
121
|
-
CODE
|
122
|
-
input.close
|
123
|
-
|
124
|
-
|
125
|
-
output.readlines.map { |line| JSON.parse(line, symbolize_names: true) }.each do |data|
|
126
|
-
case data[:action]
|
127
|
-
when 'create_event'
|
128
|
-
create_event(payload: data[:payload])
|
129
|
-
when 'log'
|
130
|
-
log data[:payload]
|
131
|
-
when 'error'
|
132
|
-
error data[:payload]
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
errors = err.read
|
137
|
-
|
138
|
-
error err.read
|
139
|
-
log "thread #{thread.value}"
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def execute_receive(events)
|
145
|
-
Bundler.with_original_env do
|
146
|
-
Open3.popen3("ruby", chdir: '/') do |input, output, err, thread|
|
147
|
-
input.write sdk_code
|
148
|
-
input.write code
|
149
|
-
input.write <<~CODE
|
150
|
-
|
151
|
-
api = Huginn::API.new
|
152
|
-
begin
|
153
|
-
Agent.new(api).receive(
|
154
|
-
JSON.parse(
|
155
|
-
Base64.decode64(
|
156
|
-
"#{Base64.encode64(events.to_json)}"
|
157
|
-
),
|
158
|
-
symbolize_names: true
|
159
|
-
)
|
160
|
-
)
|
161
|
-
rescue StandardError => ex
|
162
|
-
api.error ex
|
163
|
-
end
|
164
|
-
|
165
|
-
CODE
|
166
|
-
input.close
|
167
|
-
|
168
|
-
|
169
|
-
output.readlines.map { |line| JSON.parse(line, symbolize_names: true) }.each do |data|
|
170
|
-
case data[:action]
|
171
|
-
when 'create_event'
|
172
|
-
create_event(payload: data[:payload])
|
173
|
-
when 'log'
|
174
|
-
log data[:payload]
|
175
|
-
when 'error'
|
176
|
-
error data[:payload]
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
errors = err.read
|
181
|
-
|
182
|
-
error err.read
|
183
|
-
log "thread #{thread.value}"
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def code
|
189
|
-
interpolated['code']
|
190
|
-
end
|
191
|
-
|
192
|
-
def sdk_code
|
193
|
-
<<~CODE
|
194
|
-
require 'json'
|
195
|
-
require 'base64'
|
196
|
-
|
197
|
-
module Huginn
|
198
|
-
class API
|
199
|
-
def create_event(payload)
|
200
|
-
puts(
|
201
|
-
{
|
202
|
-
action: :create_event,
|
203
|
-
payload: payload
|
204
|
-
}.to_json
|
205
|
-
)
|
206
|
-
end
|
207
|
-
|
208
|
-
def log(message)
|
209
|
-
puts(
|
210
|
-
{
|
211
|
-
action: :log,
|
212
|
-
payload: message
|
213
|
-
}.to_json
|
214
|
-
)
|
215
|
-
end
|
216
|
-
|
217
|
-
def error(message)
|
218
|
-
puts(
|
219
|
-
{
|
220
|
-
action: :error,
|
221
|
-
payload: message
|
222
|
-
}.to_json
|
223
|
-
)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
CODE
|
228
|
-
end
|
229
|
-
|
230
|
-
def log_errors
|
231
|
-
begin
|
232
|
-
yield
|
233
|
-
rescue StandardError => e
|
234
|
-
error "Runtime error: #{e.message}"
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
data/spec/ruby_agent_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_helper'
|
4
|
-
require 'huginn_agent/spec_helper'
|
5
|
-
|
6
|
-
describe Agents::RubyAgent do
|
7
|
-
before(:each) do
|
8
|
-
@valid_options = Agents::RubyAgent.new.default_options
|
9
|
-
@checker = Agents::RubyAgent.new(name: 'RubyAgent', options: @valid_options)
|
10
|
-
@checker.user = users(:bob)
|
11
|
-
@checker.save!
|
12
|
-
end
|
13
|
-
|
14
|
-
pending 'add specs here'
|
15
|
-
end
|