myer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +5 -0
- data/Rakefile +44 -0
- data/bin/myer +198 -0
- data/features/myer.feature +8 -0
- data/features/step_definitions/myer_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/lib/myer.rb +25 -0
- data/lib/myer/admin_cli_controller.rb +70 -0
- data/lib/myer/api.rb +104 -0
- data/lib/myer/cli_controller.rb +204 -0
- data/lib/myer/config.rb +86 -0
- data/lib/myer/content.rb +92 -0
- data/lib/myer/crypto.rb +40 -0
- data/lib/myer/exceptions.rb +7 -0
- data/lib/myer/plot.rb +11 -0
- data/lib/myer/proc_net_parser.rb +11 -0
- data/lib/myer/test_cli_controller.rb +52 -0
- data/lib/myer/ticket.rb +3 -0
- data/lib/myer/ticket_store.rb +61 -0
- data/lib/myer/version.rb +3 -0
- data/myer.gemspec +26 -0
- data/myer.rdoc +5 -0
- data/scripts/plot-helper.py +32 -0
- data/spec/admin_cli_controller_spec.rb +128 -0
- data/spec/api_spec.rb +136 -0
- data/spec/cli_controller_spec.rb +368 -0
- data/spec/config_spec.rb +116 -0
- data/spec/content_spec.rb +103 -0
- data/spec/crypto_spec.rb +37 -0
- data/spec/data/myer-full.config +9 -0
- data/spec/data/myer-multiple.config +14 -0
- data/spec/data/myer.config +6 -0
- data/spec/data/plot-data.csv +31 -0
- data/spec/data/secret-ticket-12345678.json +1 -0
- data/spec/data/secret-ticket-987654321.json +1 -0
- data/spec/plot_spec.rb +9 -0
- data/spec/proc_net_parser_spec.rb +15 -0
- data/spec/shared_examples_for_config.rb +47 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/test_cli_controller_spec.rb +72 -0
- data/spec/ticket_store_spec.rb +86 -0
- data/test/default_test.rb +14 -0
- data/test/test_helper.rb +9 -0
- metadata +220 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
require "spec_helper.rb"
|
2
|
+
|
3
|
+
include GivenFilesystemSpecHelpers
|
4
|
+
|
5
|
+
describe Content do
|
6
|
+
use_given_filesystem
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@content = Content.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "types" do
|
13
|
+
it "receives type tag" do
|
14
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"type","data":"sometype"}')
|
15
|
+
|
16
|
+
expect(@content.empty?).to be true
|
17
|
+
expect(@content.type).to eq "sometype"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses quoted JSON" do
|
21
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"type","data":"json"}')
|
22
|
+
@content.add('{"id":"63705782","written_at":"2014-10-24T12:53:17Z","data":"[\"2014-06-02\",\"37\"]"}')
|
23
|
+
|
24
|
+
item = @content.first
|
25
|
+
|
26
|
+
expect(item.id).to eq "63705782"
|
27
|
+
expect(item.written_at).to eq "2014-10-24T12:53:17Z"
|
28
|
+
expect(item.data).to eq ["2014-06-02", "37"]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "parses untyped data" do
|
32
|
+
@content.add('{"id":"63705782","written_at":"2014-10-24T12:53:17Z","data":"42"}')
|
33
|
+
|
34
|
+
item = @content.first
|
35
|
+
|
36
|
+
expect(item.id).to eq "63705782"
|
37
|
+
expect(item.written_at).to eq "2014-10-24T12:53:17Z"
|
38
|
+
expect(item.data).to eq "42"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "receives title" do
|
43
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"title","data":"My Title"}')
|
44
|
+
|
45
|
+
expect(@content.empty?).to be true
|
46
|
+
expect(@content.title).to eq "My Title"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "receives multiple items" do
|
50
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"type","data":"json"}')
|
51
|
+
@content.add('{"id":"92285309","written_at":"2014-10-24T12:53:38Z","data":"[\"2014-06-03\",\"37\"]"}')
|
52
|
+
@content.add('{"id":"63758143","written_at":"2014-10-24T12:53:49Z","data":"[\"2014-06-04\",\"39\"]"}')
|
53
|
+
|
54
|
+
expect(@content.length).to eq 2
|
55
|
+
expect(@content.at(0).data[1]).to eq "37"
|
56
|
+
expect(@content.at(1).data[1]).to eq "39"
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "writes data as CSV" do
|
60
|
+
it "from JSON" do
|
61
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"type","data":"json"}')
|
62
|
+
@content.add('{"data":"[\"2014-06-03\",\"37\"]"}')
|
63
|
+
@content.add('{"data":"[\"2014-06-04\",\"39\"]"}')
|
64
|
+
|
65
|
+
output_path = given_dummy_file
|
66
|
+
|
67
|
+
@content.write_as_csv(output_path)
|
68
|
+
expect(File.read(output_path)).to eq(<<EOT
|
69
|
+
2014-06-03,37
|
70
|
+
2014-06-04,39
|
71
|
+
EOT
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "from untyped data" do
|
76
|
+
@content.add('{"data":"37"}')
|
77
|
+
@content.add('{"data":"39"}')
|
78
|
+
|
79
|
+
output_path = given_dummy_file
|
80
|
+
|
81
|
+
@content.write_as_csv(output_path)
|
82
|
+
expect(File.read(output_path)).to eq(<<EOT
|
83
|
+
37
|
84
|
+
39
|
85
|
+
EOT
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "writes data as JSON" do
|
91
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"type","data":"json"}')
|
92
|
+
@content.add('{"id":"15938189","written_at":"2014-10-24T12:52:42Z","tag":"title","data":"My Title"}')
|
93
|
+
@content.add('{"data":"[\"2014-06-03\",\"37\"]"}')
|
94
|
+
@content.add('{"data":"[\"2014-06-04\",\"39\"]"}')
|
95
|
+
|
96
|
+
output_path = given_dummy_file
|
97
|
+
|
98
|
+
expected_json = "{\"title\":\"My Title\",\"data\":[{\"date\":\"2014-06-03\",\"value\":\"37\"},{\"date\":\"2014-06-04\",\"value\":\"39\"}]}"
|
99
|
+
|
100
|
+
@content.write_as_json(output_path)
|
101
|
+
expect(File.read(output_path)).to eq(expected_json)
|
102
|
+
end
|
103
|
+
end
|
data/spec/crypto_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Crypto do
|
4
|
+
before(:each) do
|
5
|
+
@crypto = Crypto.new
|
6
|
+
@crypto.passphrase = "aOfZ+F6TcorXRFTK"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "generates passphrase" do
|
10
|
+
passphrase = @crypto.generate_passphrase
|
11
|
+
|
12
|
+
expect(passphrase.length).to be > 16
|
13
|
+
expect(passphrase).to_not match /\n/
|
14
|
+
end
|
15
|
+
|
16
|
+
it "encrypts and decrypts" do
|
17
|
+
encrypted = @crypto.encrypt("some data")
|
18
|
+
|
19
|
+
expect(encrypted).to match /PGP/
|
20
|
+
|
21
|
+
decrypted = @crypto.decrypt(encrypted)
|
22
|
+
|
23
|
+
expect(decrypted).to eq "some data"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesn't decrypt with wrong passphrase" do
|
27
|
+
encrypted = @crypto.encrypt("some data")
|
28
|
+
|
29
|
+
expect(encrypted).to match /PGP/
|
30
|
+
|
31
|
+
@crypto.passphrase = "wrong"
|
32
|
+
|
33
|
+
expect {
|
34
|
+
@crypto.decrypt(encrypted)
|
35
|
+
}.to raise_error Myer::DecryptionFailed
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
default_server: example.org
|
2
|
+
servers:
|
3
|
+
example.org:
|
4
|
+
admin_id: 'one_admin_id'
|
5
|
+
admin_password: 'one_admin_password'
|
6
|
+
user_id: 'one_user_id'
|
7
|
+
user_password: 'one_user_password'
|
8
|
+
default_bucket_id: 'one_default_bucket'
|
9
|
+
localhost:
|
10
|
+
admin_id: 'two_admin_id'
|
11
|
+
admin_password: 'two_admin_password'
|
12
|
+
user_id: 'two_user_id'
|
13
|
+
user_password: 'two_user_password'
|
14
|
+
default_bucket_id: 'two_default_bucket'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
2014-06-02,37
|
2
|
+
2014-06-03,37
|
3
|
+
2014-06-04,39
|
4
|
+
2014-06-23,39
|
5
|
+
2014-06-24,37
|
6
|
+
2014-06-25,37
|
7
|
+
2014-06-26,37
|
8
|
+
2014-06-27,37
|
9
|
+
2014-07-01,39
|
10
|
+
2014-07-02,37
|
11
|
+
2014-07-03,36
|
12
|
+
2014-07-04,37
|
13
|
+
2014-07-11,37
|
14
|
+
2014-07-14,37
|
15
|
+
2014-07-15,37
|
16
|
+
2014-07-16,37
|
17
|
+
2014-07-17,37
|
18
|
+
2014-07-18,37
|
19
|
+
2014-07-23,37
|
20
|
+
2014-07-24,37
|
21
|
+
2014-07-25,37
|
22
|
+
2014-07-29,37
|
23
|
+
2014-08-05,38
|
24
|
+
2014-08-06,37
|
25
|
+
2014-08-07,6
|
26
|
+
2014-08-18,37
|
27
|
+
2014-08-19,37
|
28
|
+
2014-08-22,37
|
29
|
+
2014-08-25,37
|
30
|
+
2014-08-28,37
|
31
|
+
2014-08-29,37
|
@@ -0,0 +1 @@
|
|
1
|
+
{"server":"mycroft.example.org","name":"Test Data","bucket_id":"12345678","key":"secret key"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"server":"localhost","name":"Test Data","bucket_id":"987654321","key":"secret key"}
|
data/spec/plot_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative "spec_helper.rb"
|
2
|
+
|
3
|
+
describe ProcNetParser do
|
4
|
+
it "parses received bytes" do
|
5
|
+
input = <<EOT
|
6
|
+
Inter-| Receive | Transmit
|
7
|
+
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
8
|
+
lo: 773884 8999 0 0 0 0 0 0 773884 8999 0 0 0 0 0 0
|
9
|
+
enp0s5: 967587512 749231 0 0 0 0 0 1896 40848584 466347 0 0 0 0 0 0
|
10
|
+
EOT
|
11
|
+
parser = ProcNetParser.new
|
12
|
+
parser.parse input
|
13
|
+
expect(parser.received_bytes).to eq 967587512
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
shared_examples "config" do
|
2
|
+
describe "remembers state" do
|
3
|
+
it "writes config file" do
|
4
|
+
config_dir = File.join(given_directory, "subdir")
|
5
|
+
@controller.config_dir = config_dir
|
6
|
+
|
7
|
+
@controller.default_server = "example.com"
|
8
|
+
@controller.admin_id = "123"
|
9
|
+
@controller.admin_password = "456"
|
10
|
+
@controller.user_id = "abc"
|
11
|
+
@controller.user_password = "xyz"
|
12
|
+
@controller.default_bucket_id = "890"
|
13
|
+
|
14
|
+
@controller.write_config
|
15
|
+
|
16
|
+
expect(File.read(File.join(config_dir,"myer.config"))).to eq(<<EOT
|
17
|
+
---
|
18
|
+
default_server: example.com
|
19
|
+
servers:
|
20
|
+
example.com:
|
21
|
+
admin_id: '123'
|
22
|
+
admin_password: '456'
|
23
|
+
user_id: abc
|
24
|
+
user_password: xyz
|
25
|
+
default_bucket_id: '890'
|
26
|
+
EOT
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "reads config file" do
|
31
|
+
config_dir = given_directory do
|
32
|
+
given_file "myer.config", from: "myer-full.config"
|
33
|
+
end
|
34
|
+
@controller.config_dir = config_dir
|
35
|
+
|
36
|
+
@controller.read_config
|
37
|
+
|
38
|
+
expect(@controller.default_server).to eq "example.org"
|
39
|
+
server = @controller.server(@controller.default_server)
|
40
|
+
expect(server.admin_id).to eq "abc"
|
41
|
+
expect(server.admin_password).to eq "def"
|
42
|
+
expect(server.user_id).to eq "ddd"
|
43
|
+
expect(server.user_password).to eq "ggg"
|
44
|
+
expect(server.default_bucket_id).to eq "987654321"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "codeclimate-test-reporter"
|
2
|
+
CodeClimate::TestReporter.start
|
3
|
+
|
4
|
+
require "webmock/rspec"
|
5
|
+
require "given_filesystem/spec_helpers"
|
6
|
+
|
7
|
+
WebMock.disable_net_connect!(:allow => "codeclimate.com")
|
8
|
+
|
9
|
+
require_relative "../lib/myer"
|
10
|
+
|
11
|
+
def test_data_path(filename)
|
12
|
+
data_path = File.expand_path( "../data/", __FILE__ )
|
13
|
+
File.join(data_path, filename)
|
14
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require_relative "spec_helper.rb"
|
2
|
+
|
3
|
+
describe TestCliController do
|
4
|
+
use_given_filesystem
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@controller = TestCliController.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#full" do
|
11
|
+
it "executes" do
|
12
|
+
server = "example.org"
|
13
|
+
pin = "1234"
|
14
|
+
|
15
|
+
admin_id = "dhdhdh"
|
16
|
+
admin_password = "373737"
|
17
|
+
|
18
|
+
body = "{\"admin_id\":\"#{admin_id}\",\"password\":\"#{admin_password}\"}"
|
19
|
+
stub_request(:post, "http://#{server}:4735/admin/register/#{pin}").
|
20
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
21
|
+
to_return(:status => 200, :body => body, :headers => {})
|
22
|
+
|
23
|
+
token = "1t1t2t34uu5u5"
|
24
|
+
|
25
|
+
body = "{\"token\":\"#{token}\"}"
|
26
|
+
stub_request(:post, "http://#{admin_id}:#{admin_password}@#{server}:4735/tokens").
|
27
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
28
|
+
to_return(:status => 200, :body => body, :headers => {})
|
29
|
+
|
30
|
+
user_id = "2458383"
|
31
|
+
user_password = "sdfjksldfj"
|
32
|
+
|
33
|
+
body = "{\"user_id\":\"#{user_id}\",\"user_password\":\"#{user_password}\"}"
|
34
|
+
stub_request(:post, "http://#{server}:4735/register/#{token}").
|
35
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
36
|
+
to_return(:status => 200, :body => body, :headers => {})
|
37
|
+
|
38
|
+
bucket_id = "123455"
|
39
|
+
|
40
|
+
body = "{\"bucket_id\":\"#{bucket_id}\"}"
|
41
|
+
stub_request(:post, "http://#{user_id}:#{user_password}@#{server}:4735/data").
|
42
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
43
|
+
to_return(:status => 200, :body => body, :headers => {})
|
44
|
+
|
45
|
+
content = "octopus"
|
46
|
+
|
47
|
+
item_id = "123556"
|
48
|
+
parent_id = "49494"
|
49
|
+
|
50
|
+
body = "{\"item_id\":\"#{item_id}\",\"parent_id\":\"#{parent_id}\"}"
|
51
|
+
stub_request(:post, "http://#{user_id}:#{user_password}@#{server}:4735/data/#{bucket_id}").
|
52
|
+
with(:body => content, :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
53
|
+
to_return(:status => 200, :body => body, :headers => {})
|
54
|
+
|
55
|
+
body = <<EOT
|
56
|
+
[
|
57
|
+
{"item_id":"#{item_id}","parent_id":"","content":"#{content}"}
|
58
|
+
]
|
59
|
+
EOT
|
60
|
+
|
61
|
+
stub_request(:get, "http://#{user_id}:#{user_password}@#{server}:4735/data/#{bucket_id}").
|
62
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
63
|
+
to_return(:status => 200, :body => body, :headers => {})
|
64
|
+
|
65
|
+
@controller.out = double
|
66
|
+
|
67
|
+
expect(@controller.out).to receive(:puts).with("Full acceptance test passed")
|
68
|
+
|
69
|
+
@controller.full(server, pin)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
include GivenFilesystemSpecHelpers
|
4
|
+
|
5
|
+
describe TicketStore do
|
6
|
+
use_given_filesystem
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
end
|
10
|
+
|
11
|
+
it "loads ticket for bucket id" do
|
12
|
+
bucket_id = "12345678"
|
13
|
+
|
14
|
+
ticket_dir = given_directory do
|
15
|
+
ticket_path = given_file("secret-ticket-#{bucket_id}.json")
|
16
|
+
end
|
17
|
+
|
18
|
+
store = TicketStore.new(ticket_dir)
|
19
|
+
ticket = store.load_ticket(bucket_id)
|
20
|
+
|
21
|
+
expect(ticket.server).to eq "mycroft.example.org"
|
22
|
+
expect(ticket.bucket_id).to eq bucket_id
|
23
|
+
expect(ticket.key).to eq "secret key"
|
24
|
+
expect(ticket.name).to eq "Test Data"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "loads ticket from file" do
|
28
|
+
bucket_id = "12345678"
|
29
|
+
|
30
|
+
ticket_path = nil
|
31
|
+
ticket_dir = given_directory do
|
32
|
+
ticket_path = given_file("secret-ticket-#{bucket_id}.json")
|
33
|
+
end
|
34
|
+
|
35
|
+
store = TicketStore.new(ticket_dir)
|
36
|
+
ticket = store.load_ticket_from_file(ticket_path)
|
37
|
+
|
38
|
+
expect(ticket.bucket_id).to eq(bucket_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises exception on load of invalid ticket" do
|
42
|
+
expect {
|
43
|
+
TicketStore.new.load_ticket(given_dummy_file)
|
44
|
+
}.to raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it "loads all tickets" do
|
48
|
+
ticket_dir = given_directory do
|
49
|
+
given_file("secret-ticket-12345678.json")
|
50
|
+
given_file("secret-ticket-987654321.json")
|
51
|
+
end
|
52
|
+
|
53
|
+
store = TicketStore.new(ticket_dir)
|
54
|
+
tickets = store.tickets_per_server
|
55
|
+
|
56
|
+
expect(tickets.size).to eq 2
|
57
|
+
expect(tickets.keys).to eq ["mycroft.example.org", "localhost"]
|
58
|
+
expect(tickets["mycroft.example.org"][0].bucket_id).to eq "12345678"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "saves" do
|
62
|
+
ticket_dir = given_directory
|
63
|
+
|
64
|
+
server = "mycroft.example.org"
|
65
|
+
bucket_id = "456789012"
|
66
|
+
bucket_key = "geheim"
|
67
|
+
bucket_name = "Test Data"
|
68
|
+
|
69
|
+
store = TicketStore.new(ticket_dir)
|
70
|
+
ticket = Ticket.new
|
71
|
+
ticket.bucket_id = bucket_id
|
72
|
+
ticket.key = bucket_key
|
73
|
+
ticket.name = bucket_name
|
74
|
+
ticket.server = server
|
75
|
+
|
76
|
+
store.save_ticket(ticket)
|
77
|
+
|
78
|
+
ticket_path = File.join(ticket_dir, "secret-ticket-#{bucket_id}.json")
|
79
|
+
|
80
|
+
expect(File.read(ticket_path)).to eq(<<EOT
|
81
|
+
{"server":"mycroft.example.org","name":"Test Data","bucket_id":"456789012","key":"geheim"}
|
82
|
+
EOT
|
83
|
+
)
|
84
|
+
expect(File.stat(ticket_path).mode).to eq 0100600
|
85
|
+
end
|
86
|
+
end
|