threatinator 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d9b3ddb0e013a94d6675ff6f56a67f6fe5a30c3b
4
- data.tar.gz: 0f502d65e4235795d0d4cf1a8874a31d9321e49e
3
+ metadata.gz: 9094ef4d662acb87c6f8425a90700527449fa7e6
4
+ data.tar.gz: ed120159fc6800df5902e105634c006844707f31
5
5
  SHA512:
6
- metadata.gz: 9772c07ba057684f6814f984a8fd397a52266e78642b9faf1e2ffdb63e365b1f6ff6d6a80c9fac7253ab812a55656a66da46aee50d3ab9c7b4ac1556049d9ecf
7
- data.tar.gz: 91aa0d43d7150bc5b36d45922b560a7486c2690c82825146beeeed5980730a92d3bc17b059743aaadfc305727e225a74ecb56dfc01ba758856b1b28b23af8c49
6
+ metadata.gz: c98dc47be2f5aabc58a776af93401cd1b01ef380216992fd9310794f08c21e63a03b212081ce1cd64e50b25022c7d8ea61a87fb693b76b8795200745b5a92c3c
7
+ data.tar.gz: a8a459c5103636ba1c45c500bafb650162145ef01897148a5c54e6e4e9db4f7960de94868159e91964cccd5042607b3b554096f4c1c35e74cf4fa59b534b9b7d
@@ -3,6 +3,11 @@ Next
3
3
 
4
4
  * Your contribution here.
5
5
 
6
+ 0.1.6
7
+ ====
8
+
9
+ * Add JSON support: 'threatinator list --list.format=json' - [@justfalter](https://github.com/justfalter)
10
+
6
11
  0.1.5
7
12
  ====
8
13
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.1.6
@@ -1,6 +1,7 @@
1
1
  require 'threatinator/action'
2
2
  require 'threatinator/exceptions'
3
3
  require 'csv'
4
+ require 'multi_json'
4
5
 
5
6
  module Threatinator
6
7
  module Actions
@@ -11,8 +12,7 @@ module Threatinator
11
12
  @config = config
12
13
  end
13
14
 
14
- def exec
15
- io_out = $stdout
15
+ def output_table(io_out)
16
16
  feed_info = [['provider', 'name', 'type', 'link/path']]
17
17
  registry.each do |feed|
18
18
  info = [ feed.provider, feed.name ]
@@ -47,6 +47,40 @@ module Threatinator
47
47
  io_out.printf(fmt, *sep)
48
48
  io_out.puts("Total: #{feed_info.count}")
49
49
  end
50
+
51
+ def output_json(io_out)
52
+ feeds = []
53
+ registry.each do |feed|
54
+ info = {
55
+ provider: feed.provider,
56
+ name: feed.name,
57
+ type: 'unknown',
58
+ link: 'unknown'
59
+ }
60
+ fetcher = feed.fetcher_builder.call()
61
+ case fetcher
62
+ when Threatinator::Fetchers::Http
63
+ info[:type] = "http"
64
+ info[:link] = fetcher.url
65
+ end
66
+
67
+ feeds << info
68
+ end
69
+ feeds.sort! { |a,b| [a[:provider], a[:name]] <=> [b[:provider], b[:name]] }
70
+
71
+ io_out.write(MultiJson.dump(feeds))
72
+ end
73
+
74
+ def exec
75
+ case @config.format
76
+ when 'table'
77
+ output_table($stdout)
78
+ when 'json'
79
+ output_json($stdout)
80
+ else
81
+ raise ArgumentError, "Invalid argument for 'format' = '#{@config.format}'"
82
+ end
83
+ end
50
84
  end
51
85
  end
52
86
  end
@@ -4,6 +4,8 @@ module Threatinator
4
4
  module Actions
5
5
  module List
6
6
  class Config < Threatinator::Config::Base
7
+ attribute :format, String, default: lambda { |c,a| 'table' },
8
+ description: "The format in which to generate output: 'table' (default), 'json'"
7
9
  end
8
10
  end
9
11
  end
@@ -1,93 +1,146 @@
1
1
  require 'spec_helper'
2
2
  require 'threatinator/actions/list/action'
3
3
  require 'threatinator/actions/list/config'
4
+ require 'multi_json'
4
5
 
5
6
  describe Threatinator::Actions::List::Action do
6
7
  let(:feed_registry) { build(:feed_registry) }
7
8
  let(:config) { Threatinator::Actions::List::Config.new }
8
9
  let(:action) { described_class.new(feed_registry, config) }
9
10
 
10
- describe "the header row, header separator, and footer separator" do
11
- it "should vary the width of 'provider' based on the longest provider name" do
12
- feed_registry.register(build(:feed, :mini, provider: 'A' * 10))
13
- feed_registry.register(build(:feed, :mini, provider: 'A' * 20))
14
- feed_registry.register(build(:feed, :mini, provider: 'A' * 30))
11
+ shared_examples_for 'table output' do
12
+ describe "the header row, header separator, and footer separator" do
13
+ it "should vary the width of 'provider' based on the longest provider name" do
14
+ 1.upto(3) do |i|
15
+ feed_registry.register(build(:feed, :http, url: "http://#{i}", name:i.to_s, provider: ('A' * (10 * i))))
16
+ end
15
17
 
16
- output = temp_stdout do
17
- action.exec
18
+ output = temp_stdout do
19
+ action.exec
20
+ end
21
+ lines = output.lines.to_a
22
+ expect(lines[0]).to eq("provider name type link/path\n")
23
+ expect(lines[1]).to eq("------------------------------ ---- ---- ---------\n")
24
+ expect(lines[-2]).to eq("------------------------------ ---- ---- ---------\n")
25
+ end
26
+
27
+ it "should vary the width of 'name' based on the longest feed name" do
28
+ 1.upto(3) do |i|
29
+ feed_registry.register(build(:feed, :http, url: "http://#{i}", provider:i.to_s, name: ('A' * (10 * i))))
30
+ end
31
+
32
+ output = temp_stdout do
33
+ action.exec
34
+ end
35
+ lines = output.lines.to_a
36
+ expect(lines[0]).to eq("provider name type link/path\n")
37
+ expect(lines[1]).to eq("-------- ------------------------------ ---- ---------\n")
38
+ expect(lines[-2]).to eq("-------- ------------------------------ ---- ---------\n")
18
39
  end
19
- lines = output.lines.to_a
20
- expect(lines[0]).to eq("provider name type link/path\n")
21
- expect(lines[1]).to eq("------------------------------ ---- ---- ---------\n")
22
- expect(lines[-2]).to eq("------------------------------ ---- ---- ---------\n")
23
- end
24
40
 
25
- it "should vary the width of 'name' based on the longest feed name" do
26
- feed_registry.register(build(:feed, :mini, name: 'A' * 10))
27
- feed_registry.register(build(:feed, :mini, name: 'A' * 20))
28
- feed_registry.register(build(:feed, :mini, name: 'A' * 30))
41
+ it "should vary the width of 'link/path' based on the longest link name" do
42
+ 1.upto(3) do |i|
43
+ feed_registry.register(build(:feed, :http, url: 'http://' + ('A' * (i * 10)), provider:i.to_s,name:i.to_s))
44
+ end
29
45
 
30
- output = temp_stdout do
31
- action.exec
46
+ output = temp_stdout do
47
+ action.exec
48
+ end
49
+ lines = output.lines.to_a
50
+ expect(lines[0]).to eq("provider name type link/path \n")
51
+ expect(lines[1]).to eq("-------- ---- ---- -------------------------------------\n")
52
+ expect(lines[-2]).to eq("-------- ---- ---- -------------------------------------\n")
32
53
  end
33
- lines = output.lines.to_a
34
- expect(lines[0]).to eq("provider name type link/path\n")
35
- expect(lines[1]).to eq("-------- ------------------------------ ---- ---------\n")
36
- expect(lines[-2]).to eq("-------- ------------------------------ ---- ---------\n")
37
54
  end
38
55
 
39
- it "should vary the width of 'link/path' based on the longest link name" do
40
- feed_registry.register(build(:feed, :mini, url: 'http://' + ('A' * 10)))
41
- feed_registry.register(build(:feed, :mini, url: 'http://' + ('A' * 20)))
42
- feed_registry.register(build(:feed, :mini, url: 'http://' + ('A' * 30)))
56
+ describe "the list of feeds" do
57
+ it "should be sorted by provider name and then feed name" do
58
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_c' ))
59
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_d' ))
60
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_a' ))
61
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_d' ))
62
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_c' ))
63
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_a' ))
64
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_b' ))
65
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_b' ))
43
66
 
44
- output = temp_stdout do
45
- action.exec
67
+ output = temp_stdout do
68
+ action.exec
69
+ end
70
+ lines = output.lines.to_a
71
+ expect(lines[2]).to match(/^provider_a feed_a .*$/)
72
+ expect(lines[3]).to match(/^provider_a feed_b .*$/)
73
+ expect(lines[4]).to match(/^provider_a feed_c .*$/)
74
+ expect(lines[5]).to match(/^provider_a feed_d .*$/)
75
+ expect(lines[6]).to match(/^provider_b feed_a .*$/)
76
+ expect(lines[7]).to match(/^provider_b feed_b .*$/)
77
+ expect(lines[8]).to match(/^provider_b feed_c .*$/)
78
+ expect(lines[9]).to match(/^provider_b feed_d .*$/)
46
79
  end
47
- lines = output.lines.to_a
48
- expect(lines[0]).to eq("provider name type link/path \n")
49
- expect(lines[1]).to eq("-------- ---- ---- -------------------------------------\n")
50
- expect(lines[-2]).to eq("-------- ---- ---- -------------------------------------\n")
51
80
  end
52
- end
53
81
 
54
- describe "the list of feeds" do
55
- it "should be sorted by provider name and then feed name" do
56
- feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_c' ))
57
- feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_d' ))
58
- feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_a' ))
59
- feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_d' ))
60
- feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_c' ))
61
- feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_a' ))
62
- feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_b' ))
63
- feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_b' ))
64
-
65
- output = temp_stdout do
66
- action.exec
82
+ describe "the footer" do
83
+ it "should indicate the number of feeds" do
84
+ 20.times do |i|
85
+ feed_registry.register(build(:feed))
86
+ end
87
+ output = temp_stdout do
88
+ action.exec
89
+ end
90
+ lines = output.lines.to_a
91
+ expect(lines[-1]).to eq("Total: 20\n")
67
92
  end
68
- lines = output.lines.to_a
69
- expect(lines[2]).to match(/^provider_a feed_a .*$/)
70
- expect(lines[3]).to match(/^provider_a feed_b .*$/)
71
- expect(lines[4]).to match(/^provider_a feed_c .*$/)
72
- expect(lines[5]).to match(/^provider_a feed_d .*$/)
73
- expect(lines[6]).to match(/^provider_b feed_a .*$/)
74
- expect(lines[7]).to match(/^provider_b feed_b .*$/)
75
- expect(lines[8]).to match(/^provider_b feed_c .*$/)
76
- expect(lines[9]).to match(/^provider_b feed_d .*$/)
77
93
  end
78
94
  end
79
95
 
80
- describe "the footer" do
81
- it "should indicate the number of feeds" do
82
- 20.times do |i|
83
- feed_registry.register(build(:feed))
84
- end
85
- output = temp_stdout do
86
- action.exec
96
+ shared_examples_for 'json output' do
97
+ describe "the output" do
98
+ it "should be sorted by provider name and then feed name" do
99
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_c' ))
100
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_d' ))
101
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_a' ))
102
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_d' ))
103
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_c' ))
104
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_a' ))
105
+ feed_registry.register(build(:feed, provider: 'provider_b', name: 'feed_b' ))
106
+ feed_registry.register(build(:feed, provider: 'provider_a', name: 'feed_b' ))
107
+
108
+ output = temp_stdout do
109
+ action.exec
110
+ end
111
+
112
+ data = MultiJson.load(output)
113
+ expect(data).to match(
114
+ [
115
+ {'provider' => 'provider_a', 'name' => 'feed_a', 'type' => kind_of(String), 'link' => kind_of(String)},
116
+ {'provider' => 'provider_a', 'name' => 'feed_b', 'type' => kind_of(String), 'link' => kind_of(String)},
117
+ {'provider' => 'provider_a', 'name' => 'feed_c', 'type' => kind_of(String), 'link' => kind_of(String)},
118
+ {'provider' => 'provider_a', 'name' => 'feed_d', 'type' => kind_of(String), 'link' => kind_of(String)},
119
+ {'provider' => 'provider_b', 'name' => 'feed_a', 'type' => kind_of(String), 'link' => kind_of(String)},
120
+ {'provider' => 'provider_b', 'name' => 'feed_b', 'type' => kind_of(String), 'link' => kind_of(String)},
121
+ {'provider' => 'provider_b', 'name' => 'feed_c', 'type' => kind_of(String), 'link' => kind_of(String)},
122
+ {'provider' => 'provider_b', 'name' => 'feed_d', 'type' => kind_of(String), 'link' => kind_of(String)}
123
+ ]
124
+ )
87
125
  end
88
- lines = output.lines.to_a
89
- expect(lines[-1]).to eq("Total: 20\n")
90
126
  end
91
127
  end
92
128
 
129
+ context "when list.format is not set" do
130
+ it_behaves_like 'table output'
131
+ end
132
+ context "when list.format == 'table'" do
133
+ before :each do
134
+ config.format = 'table'
135
+ end
136
+ it_behaves_like 'table output'
137
+ end
138
+
139
+ context "when list.format == 'json'" do
140
+ before :each do
141
+ config.format = 'json'
142
+ end
143
+ it_behaves_like 'json output'
144
+ end
145
+
93
146
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: threatinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Ryan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-02 00:00:00.000000000 Z
12
+ date: 2014-12-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: typhoeus