constable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +63 -0
- data/bin/constable-identify +34 -0
- data/bin/constabled +107 -0
- data/lib/constable/version.rb +3 -0
- data/lib/constable.rb +1 -0
- metadata +65 -0
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
|
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: []
|