bixby_common 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+
2
+ module Bixby
3
+ class BundleNotFound < Exception
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+
2
+ module Bixby
3
+ class CommandNotFound < Exception
4
+ end
5
+ end
@@ -0,0 +1,64 @@
1
+
2
+ require 'base64'
3
+ require 'openssl'
4
+
5
+ module Bixby
6
+ module CryptoUtil
7
+
8
+ class << self
9
+
10
+ def encrypt(data, key_pem, iv_pem)
11
+ c = new_cipher()
12
+ c.encrypt
13
+ key = c.random_key
14
+ iv = c.random_iv
15
+ encrypted = c.update(data) + c.final
16
+
17
+ out = []
18
+ out << w( key_pem.public_encrypt(key) )
19
+ out << w( iv_pem.private_encrypt(iv) )
20
+ out << e64(encrypted)
21
+
22
+ return out.join("\n")
23
+ end
24
+
25
+ def decrypt(data, key_pem, iv_pem)
26
+ data = StringIO.new(data, 'rb')
27
+ key = key_pem.private_decrypt(read_next(data))
28
+ iv = iv_pem.public_decrypt(read_next(data))
29
+
30
+ c = new_cipher()
31
+ c.decrypt
32
+ c.key = key
33
+ c.iv = iv
34
+
35
+ ret = c.update(d64(data.read)) + c.final
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def new_cipher
42
+ OpenSSL::Cipher.new("AES-256-CBC")
43
+ end
44
+
45
+ def w(s)
46
+ e64(s).gsub(/\n/, "\\n")
47
+ end
48
+
49
+ def read_next(data)
50
+ d64(data.readline.gsub(/\\n/, "\n"))
51
+ end
52
+
53
+ def e64(s)
54
+ Base64.encode64(s)
55
+ end
56
+
57
+ def d64(s)
58
+ Base64.decode64(s)
59
+ end
60
+
61
+ end
62
+
63
+ end # CryptoUtil
64
+ end # Bixby
@@ -0,0 +1,16 @@
1
+
2
+ module Bixby
3
+
4
+ # Adds to_hash method to an Object
5
+ module Hashify
6
+
7
+ # Creates a Hash representation of self
8
+ #
9
+ # @return [Hash]
10
+ def to_hash
11
+ self.instance_variables.inject({}) { |m,v| m[v[1,v.length].to_sym] = instance_variable_get(v); m }
12
+ end
13
+
14
+ end # Hashify
15
+
16
+ end # Bixby
@@ -0,0 +1,70 @@
1
+
2
+ require 'curb'
3
+ require 'multi_json'
4
+
5
+ module Bixby
6
+
7
+ # Utilities for creating HTTP Clients. Just a thin wrapper around curb and JSON
8
+ # for common cases.
9
+ module HttpClient
10
+
11
+ # Execute an HTTP GET request to the given URL
12
+ #
13
+ # @param [String] url
14
+ # @return [String] Contents of the response's body
15
+ def http_get(url)
16
+ Curl::Easy.http_get(url).body_str
17
+ end
18
+
19
+ # Execute an HTTP GET request (see #http_get) and parse the JSON response
20
+ #
21
+ # @param [String] url
22
+ # @return [Object] Result of calling JSON.parse() on the response body
23
+ def http_get_json(url)
24
+ MultiJson.load(http_get(url))
25
+ end
26
+
27
+ # Convert a Hash into a Curl::Postfield Array
28
+ #
29
+ # @param [Hash] data
30
+ def create_post_data(data)
31
+ if data.kind_of? Hash then
32
+ data = data.map{ |k,v| Curl::PostField.content(k, v) }
33
+ end
34
+ data
35
+ end
36
+
37
+ # Execute an HTTP POST request to the given URL
38
+ #
39
+ # @param [String] url
40
+ # @param [Hash] data Key/Value pairs to POST
41
+ # @return [String] Contents of the response's body
42
+ def http_post(url, data)
43
+ return Curl::Easy.http_post(url, create_post_data(data)).body_str
44
+ end
45
+
46
+ # Execute an HTTP POST request (see #http_get) and parse the JSON response
47
+ #
48
+ # @param [String] url
49
+ # @param [Hash] data Key/Value pairs to POST
50
+ # @return [Object] Result of calling JSON.parse() on the response body
51
+ def http_post_json(url, data)
52
+ MultiJson.load(http_post(url, data))
53
+ end
54
+
55
+ # Execute an HTTP post request and save the response body
56
+ #
57
+ # @param [String] url
58
+ # @param [Hash] data Key/Value pairs to POST
59
+ # @return [void]
60
+ def http_post_download(url, data, dest)
61
+ File.open(dest, "w") do |io|
62
+ c = Curl::Easy.new(url)
63
+ c.on_body { |d| io << d; d.length }
64
+ c.http_post(data)
65
+ end
66
+ end
67
+
68
+ end # HttpClient
69
+
70
+ end # Bixby
@@ -0,0 +1,27 @@
1
+
2
+ require 'multi_json'
3
+
4
+ module Bixby
5
+ module Jsonify
6
+
7
+ include Hashify
8
+
9
+ def to_json
10
+ MultiJson.dump(self.to_hash)
11
+ end
12
+
13
+ module ClassMethods
14
+ def from_json(json)
15
+ json = MultiJson.load(json) if json.kind_of? String
16
+ obj = self.allocate
17
+ json.each{ |k,v| obj.send("#{k}=".to_sym, v) }
18
+ obj
19
+ end
20
+ end
21
+
22
+ def self.included(receiver)
23
+ receiver.extend(ClassMethods)
24
+ end
25
+
26
+ end # Jsonify
27
+ end # Bixby
data/test/helper.rb ADDED
@@ -0,0 +1,74 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'minitest/unit'
11
+ require 'turn'
12
+ require 'turn/reporter'
13
+ require 'turn/reporters/outline_reporter'
14
+
15
+ Turn.config.framework = :minitest
16
+ Turn.config.format = :outline
17
+
18
+ module Turn
19
+ class OutlineReporter < Reporter
20
+ def start_test(test)
21
+ @stdout = StringIO.new
22
+ @stderr = StringIO.new
23
+
24
+ name = naturalized_name(test)
25
+
26
+ io.print " %-57s" % name
27
+
28
+ @stdout.rewind
29
+ @stderr.rewind
30
+
31
+ $stdout = @stdout
32
+ $stderr = @stderr unless $DEBUG
33
+ end
34
+ end
35
+ end
36
+
37
+ begin
38
+ require 'simplecov'
39
+ SimpleCov.start do
40
+ add_filter "/test/"
41
+ end
42
+ rescue Exception => ex
43
+ end
44
+
45
+
46
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
47
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
48
+ require 'bixby_common'
49
+
50
+ class MiniTest::Unit::TestCase
51
+
52
+ # minitest assert_throws doesn't seem to work properly
53
+ def assert_throws(clazz, msg = nil, &block)
54
+ begin
55
+ yield
56
+ rescue Exception => ex
57
+ puts "#{ex.class}: #{ex.message}"
58
+ puts ex.backtrace.join("\n")
59
+ if clazz.to_s == ex.class.name then
60
+ if msg.nil?
61
+ return
62
+ elsif msg == ex.message then
63
+ return
64
+ end
65
+ end
66
+ end
67
+ flunk("Expected #{mu_pp(clazz)} to have been thrown")
68
+ end
69
+
70
+ end
71
+
72
+ Dir.glob(File.dirname(__FILE__) + "/../lib/**/*.rb").each{ |f| require f }
73
+
74
+ MiniTest::Unit.autorun
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ cat -
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ echo hi
@@ -0,0 +1,17 @@
1
+ {
2
+ "digest": "2429629015110c29f8fae8ca97e0e494410a28b981653c0e094cfe4a7567f1b7",
3
+ "files": [
4
+ {
5
+ "file": "bin/cat",
6
+ "digest": "6d14ab63802f3ef51bdc16db1cfeb6df93167fe7a2aa09a6c737293d42c118b2"
7
+ },
8
+ {
9
+ "file": "bin/echo",
10
+ "digest": "299001868fb8c02fd431c336c6d058f5558c5dff5b5af5e6fe04b870a6a9cbba"
11
+ },
12
+ {
13
+ "file": "manifest.json",
14
+ "digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
15
+ }
16
+ ]
17
+ }
File without changes
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ module Bixby
4
+ module Test
5
+
6
+ class TestBixbyCommon < MiniTest::Unit::TestCase
7
+
8
+ def test_autoloading
9
+ assert_equal(JsonRequest, JsonRequest.new(nil, nil).class)
10
+ assert_equal(BundleNotFound, BundleNotFound.new.class)
11
+ assert_equal(CommandNotFound, CommandNotFound.new.class)
12
+ assert_equal(CommandSpec, CommandSpec.new.class)
13
+ end
14
+
15
+ end
16
+
17
+ end # Test
18
+ end # Bixby
@@ -0,0 +1,92 @@
1
+
2
+
3
+ require 'helper'
4
+
5
+ module Bixby
6
+ module Test
7
+
8
+ class TestCommandSpec < MiniTest::Unit::TestCase
9
+
10
+ def setup
11
+ BundleRepository.path = File.expand_path(File.dirname(__FILE__))
12
+ h = { :repo => "support", :bundle => "test_bundle", 'command' => "echo", :foobar => "baz" }
13
+ @c = CommandSpec.new(h)
14
+ end
15
+
16
+
17
+ def test_init_with_hash
18
+
19
+ assert(@c)
20
+ assert_equal("support", @c.repo)
21
+ assert_equal("test_bundle", @c.bundle)
22
+ assert_equal("echo", @c.command)
23
+
24
+ end
25
+
26
+ def test_to_hash
27
+
28
+ assert_equal("support", @c.to_hash[:repo])
29
+ assert_equal("test_bundle", @c.to_hash[:bundle])
30
+ assert_equal("echo", @c.to_hash[:command])
31
+
32
+ end
33
+
34
+ def test_validate
35
+ @c.validate
36
+ end
37
+
38
+ def test_validate_failures
39
+ assert_throws(BundleNotFound) do
40
+ CommandSpec.new(:repo => "support", :bundle => "foobar").validate
41
+ end
42
+ assert_throws(CommandNotFound) do
43
+ CommandSpec.new(:repo => "support", :bundle => "test_bundle", :command => "foobar").validate
44
+ end
45
+ end
46
+
47
+ def test_execute
48
+ (status, stdout, stderr) = @c.execute
49
+ assert(status.success?)
50
+ assert_equal("hi\n", stdout)
51
+ assert_equal("", stderr)
52
+ end
53
+
54
+ def test_execute_stdin
55
+ @c.command = "cat"
56
+ @c.stdin = "hi"
57
+ (status, stdout, stderr) = @c.execute
58
+ assert(status.success?)
59
+ assert_equal("hi", stdout)
60
+ assert_equal("", stderr)
61
+ end
62
+
63
+ def test_digest
64
+ assert_equal "2429629015110c29f8fae8ca97e0e494410a28b981653c0e094cfe4a7567f1b7", @c.digest
65
+ end
66
+
67
+ def test_digest_no_err
68
+ c = CommandSpec.new({ :repo => "support", :bundle => "test_bundle", 'command' => "echofoo" })
69
+ end
70
+
71
+ def test_update_digest
72
+ expected = MultiJson.load(File.read(BundleRepository.path + "/support/test_bundle/digest"))
73
+
74
+ t = "/tmp/foobar_test_repo"
75
+ d = "#{t}/support/test_bundle/digest"
76
+ `mkdir -p #{t}`
77
+ `cp -a #{BundleRepository.path}/support #{t}/`
78
+ `rm #{d}`
79
+ BundleRepository.path = t
80
+
81
+ refute File.exist? d
82
+ @c.update_digest
83
+ assert File.exist? d
84
+
85
+ assert_equal MultiJson.dump(expected), MultiJson.dump(MultiJson.load(File.read(d)))
86
+ `rm -rf #{t}`
87
+ end
88
+
89
+ end # TestCommandSpec
90
+
91
+ end # Test
92
+ end # Bixby
@@ -0,0 +1,36 @@
1
+
2
+ require 'helper'
3
+
4
+ module Bixby
5
+ module Test
6
+
7
+ class TestJsonify < MiniTest::Unit::TestCase
8
+
9
+ def test_to_json
10
+ j = JFoo.new
11
+ j.bar = "baz"
12
+ json = j.to_json
13
+ assert json
14
+ assert_equal '{"bar":"baz"}', json
15
+ end
16
+
17
+ def test_from_json
18
+ j1 = JFoo.new
19
+ j1.bar = "baz"
20
+
21
+ j2 = JFoo.from_json(j1.to_json)
22
+ assert_equal "baz", j2.bar
23
+
24
+ j3 = JFoo.from_json('{"bar":"baz"}')
25
+ assert_equal "baz", j3.bar
26
+ end
27
+
28
+ end # Jsonify
29
+
30
+ class JFoo
31
+ include Jsonify
32
+ attr_accessor :bar
33
+ end
34
+
35
+ end # Test
36
+ end # Bixby