rubysdk 0.0.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b68c1b1d1dd1f48ea982f1f78a1a2f9faf9bf4757cdd8b6e0abba92b1b408ca4
4
+ data.tar.gz: 24c597c5ce8ccc0e2c4fc8993e2644f0e730e1bc64559bb36dbb9c4f704bec71
5
+ SHA512:
6
+ metadata.gz: 3d06348ec15a34af4294e5697a26980a42aaa2bd5a939d7a9f3286bfa7e3b44bed6172cdf7bb445082ea41aa4e11d08e936f05c782045113d066d8519ec841de
7
+ data.tar.gz: 06750cacb7b562dc4b03195442928a8bde0b365bb43e8f733b4ad8a158d0e7782e433c6eafcb527bee14c7af6f56687a50ef6936ea19a7a250f37ff919363ed5
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Interface
4
+ class Job
5
+ attr_accessor :handler, :title, :desc, :dependson, :args, :interaction
6
+
7
+ def initialize(handler=nil, title="", desc="", dependson=[], args=[], interaction=nil)
8
+ @handler = handler
9
+ @title = title
10
+ @desc = desc
11
+ @dependson = dependson
12
+ @args = args
13
+ @interaction = interaction
14
+ end
15
+ end
16
+
17
+ class Argument
18
+ attr_accessor :desc, :type, :key, :value
19
+
20
+ def initialize(desc="", type=nil, key="", value="")
21
+ @desc = desc
22
+ @type = type
23
+ @key = key
24
+ @value = value
25
+ end
26
+ end
27
+
28
+ class ManualInteraction
29
+ attr_accessor :desc, :type, :value
30
+
31
+ def initialize(desc="", type=nil, value="")
32
+ @desc = desc
33
+ @type = type
34
+ @value = value
35
+ end
36
+ end
37
+
38
+ class JobsWrapper
39
+ attr_accessor :handler, :job
40
+
41
+ def initialize(handler=nil, job=nil)
42
+ @handler = handler
43
+ @job = job
44
+ end
45
+ end
46
+
47
+ class ErrorExitPipeline < StandardError
48
+ end
49
+ end
50
+
@@ -0,0 +1,42 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: plugin.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "proto.Job" do
8
+ optional :unique_id, :uint32, 1
9
+ optional :title, :string, 2
10
+ optional :description, :string, 3
11
+ repeated :dependson, :uint32, 4
12
+ repeated :args, :message, 5, "proto.Argument"
13
+ optional :interaction, :message, 6, "proto.ManualInteraction"
14
+ end
15
+ add_message "proto.Argument" do
16
+ optional :description, :string, 1
17
+ optional :type, :string, 2
18
+ optional :key, :string, 3
19
+ optional :value, :string, 4
20
+ end
21
+ add_message "proto.ManualInteraction" do
22
+ optional :description, :string, 1
23
+ optional :type, :string, 2
24
+ optional :value, :string, 3
25
+ end
26
+ add_message "proto.JobResult" do
27
+ optional :unique_id, :uint32, 1
28
+ optional :failed, :bool, 2
29
+ optional :exit_pipeline, :bool, 3
30
+ optional :message, :string, 4
31
+ end
32
+ add_message "proto.Empty" do
33
+ end
34
+ end
35
+
36
+ module Proto
37
+ Job = Google::Protobuf::DescriptorPool.generated_pool.lookup("proto.Job").msgclass
38
+ Argument = Google::Protobuf::DescriptorPool.generated_pool.lookup("proto.Argument").msgclass
39
+ ManualInteraction = Google::Protobuf::DescriptorPool.generated_pool.lookup("proto.ManualInteraction").msgclass
40
+ JobResult = Google::Protobuf::DescriptorPool.generated_pool.lookup("proto.JobResult").msgclass
41
+ Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("proto.Empty").msgclass
42
+ end
@@ -0,0 +1,33 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: plugin.proto for package 'proto'
3
+ # Original file comments:
4
+ # plugin.proto
5
+ # Defines the gRPC interface between gaia and the user defined
6
+ # pipelines (plugins). All rpc Methods are called from Gaia and
7
+ # executed in the plugin.
8
+ #
9
+
10
+ require 'grpc'
11
+ require 'plugin_pb'
12
+
13
+ module Proto
14
+ module Plugin
15
+ class Service
16
+
17
+ include GRPC::GenericService
18
+
19
+ self.marshal_class_method = :encode
20
+ self.unmarshal_class_method = :decode
21
+ self.service_name = 'proto.Plugin'
22
+
23
+ # GetJobs returns a stream of Job objects.
24
+ # Used to expose jobs to gaia.
25
+ rpc :GetJobs, Empty, stream(Job)
26
+ # ExecuteJob signals the plugin to execute the given job.
27
+ # Used to execute one job from a pipeline.
28
+ rpc :ExecuteJob, Job, JobResult
29
+ end
30
+
31
+ Stub = Service.rpc_stub_class
32
+ end
33
+ end
data/lib/rubysdk.rb ADDED
@@ -0,0 +1,169 @@
1
+ this_dir = File.expand_path(File.dirname(__FILE__))
2
+ proto_dir = File.join(this_dir, 'proto')
3
+ interface_dir = File.join(this_dir, 'interface')
4
+ $LOAD_PATH.unshift(proto_dir) unless $LOAD_PATH.include?(proto_dir)
5
+ $LOAD_PATH.unshift(interface_dir) unless $LOAD_PATH.include?(interface_dir)
6
+
7
+ require 'grpc'
8
+ require 'fnv'
9
+ require 'plugin_services_pb'
10
+ require 'interface'
11
+
12
+ module RubySDK
13
+ # GRPCServer provides an implementation of the Plugin service.
14
+ class GRPCServer < Proto::Plugin::Service
15
+ def initialize(cached_jobs)
16
+ @cached_jobs = cached_jobs
17
+ end
18
+
19
+ # GetJobs returns all registered jobs.
20
+ def GetJobs(empty)
21
+ @cached_jobs.each { |job| yield job.job }
22
+ end
23
+
24
+ # ExecuteJob executes the given job and returns a result.
25
+ def ExecuteJob(job)
26
+ cjob = nil
27
+ @cached_jobs.each do |cached_job|
28
+ cjob = cached_job unless cached_job.unique_id == job.unique_id
29
+ end
30
+ if cjob == nil
31
+ JobResult.new(failed: true,
32
+ exit_pipeline: true,
33
+ message: "job not found in plugin " + job.title)
34
+ return
35
+ end
36
+
37
+ # Transform arguments
38
+ args = []
39
+ job.args.each do |arg|
40
+ new_arg = Proto::Argument.new(key: arg.key,
41
+ value: arg.value)
42
+ args.push new_arg
43
+ end
44
+
45
+ # Execute job
46
+ job_result = JobResult.new
47
+ begin
48
+ job.handler.call(args)
49
+ rescue => e
50
+ # Check if job wants to force exit pipeline.
51
+ # We will exit the pipeline but not mark it as 'failed'.
52
+ job_result.failed = true unless e == ErrorExitPipeline
53
+
54
+ # Set log message and job id
55
+ job_result.exit_pipeline = true
56
+ job_result.message = e.message
57
+ job_result.unique_id = job.job.unique_id
58
+ end
59
+ end
60
+ end
61
+
62
+ # Serve caches the given jobs and starts the gRPC server.
63
+ # This function should be last called in the plugin main function.
64
+ def Serve(jobs)
65
+ include Interface
66
+
67
+ # Cache the jobs for later processing.
68
+ # We have to transform given jobs into suitable proto models.
69
+ cached_jobs = []
70
+ jobs.each do |job|
71
+ # Transform manual interaction
72
+ manual_interaction = nil
73
+ if job.interaction != nil
74
+ manual_interaction = ManualInteraction.new(description: job.interaction.desc,
75
+ type: job.interaction.type,
76
+ value: job.interaction.value)
77
+ end
78
+
79
+ # Transform arguments
80
+ args = []
81
+ if job.args != nil
82
+ job.args.each do |arg|
83
+ trans_arg = Proto::Argument.new(description: arg.desc,
84
+ type: arg.type,
85
+ key: arg.key,
86
+ value: arg.value)
87
+
88
+ args.push trans_arg
89
+ end
90
+ end
91
+
92
+ # Create proto job object
93
+ proto_job = Proto::Job.new(unique_id: FNV.new.fnv1a_32(job.title),
94
+ title: job.title,
95
+ description: job.title,
96
+ args: args,
97
+ interaction: manual_interaction)
98
+
99
+ # Resolve job dependencies
100
+ if job.dependson != nil
101
+ proto_job.dependson = Google::Protobuf::RepeatedField.new(:uint32, [])
102
+ job.dependson.each do |dep_job|
103
+ dep_found = false
104
+ jobs.each do |curr_job|
105
+ if curr_job.title.casecmp(dep_job) == 0
106
+ proto_job.dependson += FNV.new.fnv1a_32(curr_job.title)
107
+ dep_found = true
108
+ break
109
+ end
110
+ end
111
+
112
+ raise "job #{job.title} has dependency #{dep_job} which is not declared" unless dep_found == true
113
+ end
114
+ end
115
+
116
+ # Create wrapper object
117
+ wrapper_job = JobsWrapper.new(handler: job.handler,
118
+ job: proto_job)
119
+ cached_jobs.push wrapper_job
120
+ end
121
+
122
+ # Check if two jobs have the same title which is restricted.
123
+ #dup_map = {}
124
+ cached_jobs.each do |job|
125
+ #dup_map[job.job.unique_id] = (map[job.job.unique_id] || 0) + 1
126
+
127
+ #if dup_map[job.job.unique_id] > 1
128
+ # raise "duplicate job with the title #{job.title} found which is not allowed"
129
+ #end
130
+ end
131
+
132
+ # Get certificates path from env variables.
133
+ cert_path = ENV["GAIA_PLUGIN_CERT"]
134
+ key_path = ENV["GAIA_PLUGIN_KEY"]
135
+ root_ca_path = ENV["GAIA_PLUGIN_CA_CERT"]
136
+
137
+ # Check if all certs are available.
138
+ raise "cannot find path to certificate" unless File.file?(cert_path)
139
+ raise "cannot find path to key" unless File.file?(key_path)
140
+ raise "cannot find path to root CA certificate" unless File.file?(root_ca_path)
141
+
142
+ # Implement health service.
143
+ #health_svc = GRPC::Health::Checker.new
144
+ #health_svc.add_status("plugin", GRPC::Core::StatusCodes::SERVING)
145
+
146
+ # Load certificates and create credentials.
147
+ credentials = GRPC::Core::ServerCredentials.new(
148
+ File.read(root_ca_path),
149
+ [{
150
+ private_key: File.read(key_path),
151
+ cert_chain: File.read(cert_path)
152
+ }],
153
+ true # force client authentication.
154
+ )
155
+
156
+ # Register gRPC server and handle.
157
+ host = 'localhost'
158
+ s = GRPC::RpcServer.new
159
+ port = s.add_http2_port(host+':0', credentials)
160
+ s.handle(GRPCServer.new(cached_jobs))
161
+
162
+ # Output the address and service name to stdout.
163
+ # hashicorp go-plugin will use that to establish a connection.
164
+ puts "1|2|tcp|#{host}:#{port}|grpc"
165
+ STDOUT.sync = true
166
+
167
+ s.run_till_terminated
168
+ end
169
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubysdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre1
5
+ platform: ruby
6
+ authors:
7
+ - Michel Vocks
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: grpc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fnv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grpc-tools
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.17'
55
+ description:
56
+ email: michelvocks@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/interface/interface.rb
62
+ - lib/proto/plugin_pb.rb
63
+ - lib/proto/plugin_services_pb.rb
64
+ - lib/rubysdk.rb
65
+ homepage: https://gaia-pipeline.io
66
+ licenses:
67
+ - Apache-2.0
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.3.1
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.7.6
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Ruby SDK for Gaia pipelines (https://gaia-pipeline.io).
89
+ test_files: []