threatinator 0.1.5 → 0.1.6

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