constable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ Constable
2
+ =========
3
+
4
+ Seascape Study with Rain Cloud was painted by John Constable around 1824.
5
+
6
+ Constable the Gem is a way of providing ImageMagick as a service. I doubt
7
+ anything quite as powerful will be generated using the service, but if you do
8
+ make something nice please let me know!
9
+
10
+
11
+ Installing
12
+ ----------
13
+
14
+ The server needs ImageMagick installed. Mostly I do this using `apt-get`:
15
+
16
+ apt-get isntall imagemagick
17
+
18
+ You'll need a broker that talks Stomp somewhere on your network. I use Apache
19
+ Apollo, and I'm not totally sure if the code uses anything that's specific to
20
+ that. I'd love it to be broker-agnostic though, so if you have patches that'll
21
+ bring this closer to reality please send them to me!
22
+
23
+
24
+ Usage
25
+ -----
26
+
27
+ ImageMagick provides a huge nubmer of commands and options. Supporting them
28
+ all is a big task, so I'm implementing just the few that I use. If you need
29
+ something else supported, please do fork and patch the project. Let me know
30
+ and I'll pull your changes.
31
+
32
+ Run the server, somewhere that has ImageMagick installed:
33
+
34
+ constabled --broker stomp://mq.yourdomain.com:61613
35
+
36
+ Use the services on the command line. You don't need ot have ImageMagick
37
+ installed on your client machines, just constable.
38
+
39
+ Command names are based on ImageMagick command names, prefixed with
40
+ `constable-`, eg `constable-identify`. All commands will respond to --help
41
+ and will give you a decent explanation of what they do and their options if
42
+ you ask for it.
43
+
44
+ The commands are designed to take their input on standard input and return
45
+ results on standard output. It's up to you what you do with the input and
46
+ output; write it to a file, pipe it to another process, that's not handled by
47
+ Constable (and I have no plans to handle it).
48
+
49
+ A brief example of what interacting with Constable looks like, here
50
+ identifying some image file I had lying around on disk:
51
+
52
+ $ cat input_file | constable-identify --broker stomp://mq.yourdomain.com:61613
53
+ constabled-164829495-102948483-1939485.jpg JPEG 640x480 DirectClass 87kb 0.050u 0:01
54
+
55
+ I explicitly state the broker in the above commands but if you leave out that
56
+ option it'll default to stomp://localhost:61613 ie it expects a broker running
57
+ on your local machine if you don't tell it otherwise.
58
+
59
+
60
+ Authors
61
+ -------
62
+
63
+ Craig R Webster <http://barkingiguana.com/>
@@ -0,0 +1,34 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ image = STDIN.read
4
+ if image.to_s == ''
5
+ puts "Give me some input!"
6
+ exit 1
7
+ end
8
+
9
+ require 'base64'
10
+ encoded_input = Base64.encode64 image
11
+
12
+ require 'stomp'
13
+ require 'json'
14
+
15
+ results = '/queue/constable.results-' + Process.pid.to_s + '-' + Time.now.to_i.to_s
16
+ client = Stomp::Client.new ARGV[0]
17
+ client.subscribe results, 'auto-delete' => true do |message|
18
+ results = JSON.parse message.body
19
+ if results['exit_code'] == 0
20
+ print results['stdout']
21
+ else
22
+ print results['stderr']
23
+ end
24
+ client.close
25
+ end
26
+
27
+ command = {
28
+ command: 'identify',
29
+ input: encoded_input
30
+ }
31
+ command_json = JSON.generate command
32
+
33
+ client.publish '/queue/constable', command_json, 'reply-to' => results
34
+ client.join
data/bin/constabled ADDED
@@ -0,0 +1,107 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'stomp'
4
+ require 'digest/sha1'
5
+ require 'json'
6
+ require 'tempfile'
7
+ require 'open3'
8
+ require 'base64'
9
+
10
+ class Job
11
+ module WorkingEnvironment
12
+ def with_temp_file
13
+ temp_file = Tempfile.new serial
14
+ yield temp_file
15
+ ensure
16
+ temp_file.close!
17
+ end
18
+
19
+ def serial
20
+ @job_id ||= [
21
+ File.basename($0), Time.now.to_i, rand(1_000_000)
22
+ ].join '-'
23
+ end
24
+
25
+ def using_file_with_content encoded_content, &block
26
+ decoded_content = Base64.decode64 encoded_content
27
+ with_temp_file do |file|
28
+ file.print decoded_content
29
+ file.flush
30
+ yield file
31
+ end
32
+ end
33
+
34
+ def run_command command
35
+ puts "Running #{command}"
36
+ stdin, stdout, stderr, command = Open3.popen3 command
37
+ {
38
+ stdout: stdout.readlines.join,
39
+ stderr: stderr.readlines.join,
40
+ exit_code: command.value.exitstatus,
41
+ pid: command.value.pid
42
+ }
43
+ end
44
+ end
45
+
46
+ class IdentifyCommand
47
+ include WorkingEnvironment
48
+
49
+ attr_accessor :options
50
+ private :options, :options=
51
+
52
+ def initialize options
53
+ self.options = options
54
+ end
55
+
56
+ def execute
57
+ using_file_with_content options['input'] do |file|
58
+ run_command "identify #{file.path}"
59
+ end
60
+ end
61
+ end
62
+
63
+ attr_accessor :options
64
+ private :options, :options=
65
+
66
+ def initialize options
67
+ self.options = options
68
+ end
69
+
70
+ def execute
71
+ handler.execute
72
+ end
73
+
74
+ def handler
75
+ handler_class.new options
76
+ end
77
+
78
+ def handler_class
79
+ Job.const_get handler_name
80
+ end
81
+
82
+ def handler_name
83
+ name = command_name
84
+ name.gsub!(/\/(.?)/) { "::#{$1.upcase}" }
85
+ name.gsub!(/(?:^|_)(.)/) { $1.upcase }
86
+ name + 'Command'
87
+ end
88
+
89
+ def command_name
90
+ options["command"]
91
+ end
92
+ end
93
+
94
+ client = Stomp::Client.new ARGV[0]
95
+ client.subscribe '/queue/constable' do |message|
96
+ puts "Received #{message.headers['message-id']}"
97
+
98
+ options = JSON.parse message.body
99
+ results = Job.new(options).execute
100
+
101
+ result_json = JSON.generate results
102
+ destination = message.headers['reply-to']
103
+ client.publish destination, result_json
104
+ end
105
+
106
+ puts "Waiting for clients..."
107
+ client.join
@@ -0,0 +1,3 @@
1
+ module Constable
2
+ VERSION = '0.0.1'
3
+ end
data/lib/constable.rb ADDED
@@ -0,0 +1 @@
1
+ require 'constable/version'
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: constable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Craig R Webster
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: stomp
16
+ requirement: &70138922339840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70138922339840
25
+ description: Installing ImageMagick and RMagick everywhere sucks, right? So install
26
+ it in one place and have everything else use that one install.
27
+ email:
28
+ - craig@barkingiguana.com
29
+ executables:
30
+ - constabled
31
+ - constable-identify
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - lib/constable/version.rb
36
+ - lib/constable.rb
37
+ - bin/constable-identify
38
+ - bin/constabled
39
+ - README.md
40
+ homepage:
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements:
59
+ - A broker capable of talking Stomp
60
+ rubyforge_project:
61
+ rubygems_version: 1.8.10
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: ImageMagick as a service
65
+ test_files: []