bixby_common 0.2.0

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.
@@ -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