fluent-plugin-azure-queue 0.0.6.pre → 0.0.8.pre

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: b9216faa1348ea85dd618fcc498b31efea22eac1
4
- data.tar.gz: 18989b0f648643a7f29d06f51c4b2d49b3850132
3
+ metadata.gz: 7dec8e5dd6a0f5973f5741702060efb40cc04b22
4
+ data.tar.gz: 0b1fb55a244ccc5a8a1ad390d09f1950eaf3e22c
5
5
  SHA512:
6
- metadata.gz: 9e721814bfb21da863ae2ec607743967a398c79719ba03330b7842f65cd8b27eb7e7968e685dabcd710528f5df3bcad3a2ef508507f481002aa51ebe860ed0a2
7
- data.tar.gz: 3d2ce94dcd4f395a27e76c2bc7fa1605978914def55ee44d18b113cdbd204e31e70ad17396b38742e7ee65b2f1565a236ec7739e61abee605113ca108271702f
6
+ metadata.gz: d4cf9f3f62e6213c4aeb421741bcde86fc4ecffef9a0b0b3efa0c0002390cb58e398c8187d698bab9b9f0babd01c531ea5a0273877cfbad7bbdb74cf505e4555
7
+ data.tar.gz: 6092c42d2fba01796c75085c1692e4f94696f37ba7314fdf38273d3cc309d6187fcf4562b44a46df7203f7b9f3dc865e0bb304248f0fa39d3bc9c568eb378e98
data/README.md CHANGED
@@ -76,6 +76,7 @@ public static void Run(string[] hubMessages, ICollector<string> outputQueue, Tra
76
76
  }
77
77
  }
78
78
  ```
79
+
79
80
  ## azure_event_hub_capture Input Plugin
80
81
  This plugin is designed to work with blobs stored to a container via [Azure Event Hubs Capture](https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-capture-overview)
81
82
 
@@ -121,3 +122,37 @@ The time in seconds to sleep between fetching the blob list. Default 30
121
122
  **lease_duration**
122
123
 
123
124
  The time to lease the messages for. Default 60
125
+
126
+ **queue_lease_time**
127
+
128
+ The time to lease the queue message for. Default 60
129
+
130
+ **queue_name**
131
+
132
+ If set, get the blob names from a storage queue. Good if there are many blobs because listblobs is not reliable.
133
+
134
+ ## Integration with Azure Event Hub
135
+
136
+ Use this azure function if you want to ingest event hub capture blob names from a storage queue.
137
+
138
+ ```c#
139
+ // Blob trigger binding to a CloudBlockBlob
140
+ #r "Microsoft.WindowsAzure.Storage"
141
+
142
+ using Microsoft.WindowsAzure.Storage.Blob;
143
+
144
+ public static void Run(CloudBlockBlob myBlob, out BlobIdentifier outputQueueItem, TraceWriter log)
145
+ {
146
+ log.Info($"C# Blob trigger function Processed blob Name:{myBlob.Name} URI:{myBlob.StorageUri}");
147
+ BlobIdentifier blobId = new BlobIdentifier { Name = myBlob.Name, Container = myBlob.Container.Name };
148
+ //outputQueueItem.add(blobId);
149
+ outputQueueItem = blobId;
150
+ }
151
+
152
+
153
+ public class BlobIdentifier
154
+ {
155
+ public string Container { get; set; }
156
+ public string Name { get; set; }
157
+ }
158
+ ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6.pre
1
+ 0.0.8.pre
@@ -20,6 +20,10 @@ module Fluent
20
20
  config_param :fetch_interval, :integer, default: 30
21
21
  desc 'The the lease duration on the blob in seconds'
22
22
  config_param :lease_duration, :integer, default: 60
23
+ desc 'The the lease time on the messages in seconds'
24
+ config_param :queue_lease_time, :integer, default: 60
25
+ desc 'If set, get the blob names from a queue rather than the "list blobs" operation'
26
+ config_param :queue_name, :string, default: nil
23
27
 
24
28
  def configure(conf)
25
29
  super
@@ -30,9 +34,9 @@ module Fluent
30
34
  if @lease_duration > 60 || @lease_duration < 15
31
35
  raise Fluent::ConfigError, "fluent-plugin-azure-queue: 'lease_duration' parameter must be between 15 and 60: #{@lease_duration}"
32
36
  end
33
- @blob_client = Azure::Storage::Client.create(
37
+ @azure_client = Azure::Storage::Client.create(
34
38
  :storage_account_name => @storage_account_name,
35
- :storage_access_key => @storage_access_key).blob_client
39
+ :storage_access_key => @storage_access_key)
36
40
  @running = true
37
41
  @containers = container_names.split(',').map { |c| c.strip }
38
42
 
@@ -55,19 +59,10 @@ module Fluent
55
59
  while @running
56
60
  if Time.now > @next_fetch_time
57
61
  @next_fetch_time = Time.now + @fetch_interval
58
- @containers.each do |container_name|
59
- begin
60
- blobs = @blob_client.list_blobs(container_name)
61
- blobs = blobs.select { |b| b.properties[:lease_status] == "unlocked" }
62
- log.info("Found #{blobs.count} unlocked blobs", container_name: container_name)
63
- # Blobs come back with oldest first
64
- blobs.each do |blob|
65
- ingest_blob(container_name, blob)
66
- end
67
- rescue => e
68
- log.warn(error: e)
69
- log.warn_backtrace(e.backtrace)
70
- end
62
+ if queue_name
63
+ ingest_from_queue
64
+ else
65
+ ingest_from_blob_list
71
66
  end
72
67
  else
73
68
  sleep(@next_fetch_time - Time.now)
@@ -75,25 +70,56 @@ module Fluent
75
70
  end
76
71
  end
77
72
 
78
- def ingest_blob(container_name, blob)
73
+ def ingest_from_blob_list
74
+ @containers.each do |container_name|
75
+ begin
76
+ blobs = @azure_client.blob_client.list_blobs(container_name)
77
+ blobs = blobs.select { |b| b.properties[:lease_status] == "unlocked" }
78
+ log.info("Found #{blobs.count} unlocked blobs", container_name: container_name)
79
+ # Blobs come back with oldest first
80
+ blobs.each do |blob|
81
+ ingest_blob(container_name, blob.name)
82
+ end
83
+ rescue => e
84
+ log.warn(error: e)
85
+ log.warn_backtrace(e.backtrace)
86
+ end
87
+ end
88
+ end
89
+
90
+ def ingest_from_queue
91
+ begin
92
+ blob_id_messages = @azure_client.queue_client.list_messages(@queue_name, @queue_lease_time, { number_of_messages: 32 })
93
+ blob_id_messages.each do |blob_id_message|
94
+ blob_id = JSON.parse(Base64.decode64(blob_id_message.message_text))
95
+ ingest_blob(blob_id["Container"], blob_id["Name"])
96
+ @azure_client.queue_client.delete_message(@queue_name, blob_id_message.id, blob_id_message.pop_receipt)
97
+ end
98
+ rescue => e
99
+ log.warn(error: e)
100
+ log.warn_backtrace(e.backtrace)
101
+ end
102
+ end
103
+
104
+ def ingest_blob(container_name, blob_name)
79
105
  begin
80
- lease_id = @blob_client.acquire_blob_lease(container_name, blob.name, duration: @lease_duration)
81
- log.info("Blob Leased", blob_name: blob.name)
82
- blob, blob_contents = @blob_client.get_blob(container_name, blob.name)
106
+ lease_id = @azure_client.blob_client.acquire_blob_lease(container_name, blob_name, duration: @lease_duration)
107
+ log.info("Blob Leased", blob_name: blob_name)
108
+ blob, blob_contents = @azure_client.blob_client.get_blob(container_name, blob_name)
83
109
  emit_blob_messages(blob_contents)
84
- log.trace("Done Ingest blob", blob_name: blob.name)
110
+ log.trace("Done Ingest blob", blob_name: blob_name)
85
111
  begin
86
112
  delete_blob(container_name, blob, lease_id)
87
- log.debug("Blob deleted", blob_name: blob.name)
113
+ log.debug("Blob deleted", blob_name: blob_name)
88
114
  rescue Exception => e
89
- log.warn("Records emmitted but blob not deleted", container_name: container_name, blob_name: blob.name, error: e)
115
+ log.warn("Records emmitted but blob not deleted", container_name: container_name, blob_name: blob_name, error: e)
90
116
  log.warn_backtrace(e.backtrace)
91
117
  end
92
118
  rescue Azure::Core::Http::HTTPError => e
93
119
  if e.status_code == 409
94
- log.trace("Blob already leased", blob_name: blob.name)
120
+ log.trace("Blob already leased", blob_name: blob_name)
95
121
  elsif e.status_code == 404
96
- log.trace("Blob already deleted", blob_name: blob.name)
122
+ log.trace("Blob already deleted", blob_name: blob_name)
97
123
  else
98
124
  log.warn("Error occurred while ingesting blob", error: e)
99
125
  log.warn_backtrace(e.backtrace)
@@ -127,7 +153,7 @@ module Fluent
127
153
  def delete_blob(container_name, blob, lease_id)
128
154
  # Hack because 'delete_blob' doesn't support lease_id yet
129
155
  Azure::Storage::Service::StorageService.register_request_callback { |headers| headers["x-ms-lease-id"] = lease_id }
130
- @blob_client.delete_blob(container_name, blob.name)
156
+ @azure_client.blob_client.delete_blob(container_name, blob.name)
131
157
  Azure::Storage::Service::StorageService.register_request_callback { |headers| headers }
132
158
  end
133
159
  end
@@ -11,7 +11,7 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
11
11
  end
12
12
  end
13
13
 
14
- CONFIG = %[
14
+ LIST_CONFIG = %[
15
15
  tag test_tag
16
16
  storage_account_name test_storage_account_name
17
17
  storage_access_key test_storage_access_key
@@ -19,13 +19,24 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
19
19
  fetch_interval 1
20
20
  ]
21
21
 
22
- def create_driver(conf = CONFIG)
22
+ QUEUE_CONFIG = %[
23
+ tag test_tag
24
+ storage_account_name test_storage_account_name
25
+ storage_access_key test_storage_access_key
26
+ container_names test_container_name
27
+ fetch_interval 1
28
+ queue_lease_time 30
29
+ queue_name test_queue_name
30
+ ]
31
+
32
+ def create_driver(conf = LIST_CONFIG)
23
33
  d = Fluent::Test::InputTestDriver.new(Fluent::AzureEventHubCaptureInput)
24
34
  d.configure(conf)
25
35
  d
26
36
  end
27
37
 
28
38
  Struct.new("Blob", :name, :properties)
39
+ Struct.new("QueueMessage", :id, :pop_receipt, :message_text)
29
40
 
30
41
  def test_configure
31
42
  d = create_driver
@@ -38,14 +49,15 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
38
49
 
39
50
  def setup_mocks(driver)
40
51
  blob_client = flexmock("blob_client")
41
- client = flexmock("client", :blob_client => blob_client)
52
+ queue_client = flexmock("queue_client")
53
+ client = flexmock("client", :blob_client => blob_client, :queue_client => queue_client)
42
54
  flexmock(Azure::Storage::Client, :create => client)
43
- blob_client
55
+ [blob_client, queue_client]
44
56
  end
45
57
 
46
- def test_no_blobs
58
+ def test_list_no_blobs
47
59
  d = create_driver
48
- blob_client = setup_mocks(d)
60
+ blob_client, queue_client = setup_mocks(d)
49
61
  blob_client.should_receive(:list_blobs).with(d.instance.container_names).and_return([]).once
50
62
  flexmock(d.instance).should_receive(:ingest_blob).never()
51
63
  d.run do
@@ -53,10 +65,10 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
53
65
  end
54
66
  end
55
67
 
56
- def test_two_blobs
68
+ def test_list_two_blobs
57
69
  d = create_driver
58
70
  blobs = [Struct::Blob.new("test1", lease_status: "unlocked"), Struct::Blob.new("test2", lease_status: "unlocked")]
59
- blob_client = setup_mocks(d)
71
+ blob_client, queue_client = setup_mocks(d)
60
72
  blob_client.should_receive(:list_blobs).with(d.instance.container_names).and_return(blobs).once
61
73
  plugin = flexmock(d.instance)
62
74
  plugin.should_receive(:ingest_blob).with(d.instance.container_names, blobs[0]).once()
@@ -66,10 +78,44 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
66
78
  end
67
79
  end
68
80
 
81
+ def test_queue_no_blobs
82
+ d = create_driver(QUEUE_CONFIG)
83
+ blob_client, queue_client = setup_mocks(d)
84
+ queue_client.should_receive(:list_messages).with(
85
+ d.instance.queue_name,
86
+ d.instance.queue_lease_time,
87
+ { number_of_messages: 32}).and_return([]).once
88
+ flexmock(d.instance).should_receive(:ingest_blob).never()
89
+ d.run do
90
+ sleep 1
91
+ end
92
+ end
93
+
94
+ def test_queue_two_blobs
95
+ d = create_driver(QUEUE_CONFIG)
96
+ blob_id1 = { "Name" => "test1", "Container" => "container1" }
97
+ blob_id2 = { "Name" => "test2", "Container" => "container2" }
98
+ blobs_id_messages = [ Struct::QueueMessage.new(1, 99, Base64.encode64(blob_id1.to_json)),
99
+ Struct::QueueMessage.new(2, 299, Base64.encode64(blob_id2.to_json))]
100
+ blob_client, queue_client = setup_mocks(d)
101
+ queue_client.should_receive(:list_messages).with(
102
+ d.instance.queue_name,
103
+ d.instance.queue_lease_time,
104
+ { number_of_messages: 32}).and_return(blobs_id_messages).once
105
+ plugin = flexmock(d.instance)
106
+ plugin.should_receive(:ingest_blob).with(blob_id1["Container"], blob_id1["Name"]).once()
107
+ plugin.should_receive(:ingest_blob).with(blob_id2["Container"], blob_id2["Name"]).once()
108
+ queue_client.should_receive(:delete_message).with(d.instance.queue_name, blobs_id_messages[0].id, blobs_id_messages[0].pop_receipt).once
109
+ queue_client.should_receive(:delete_message).with(d.instance.queue_name, blobs_id_messages[1].id, blobs_id_messages[1].pop_receipt).once
110
+ d.run do
111
+ sleep 1
112
+ end
113
+ end
114
+
69
115
  def test_ingest_blob
70
116
  d = create_driver
71
117
  blob = Struct::Blob.new("test1", lease_status: "unlocked")
72
- blob_client = setup_mocks(d)
118
+ blob_client, queue_client = setup_mocks(d)
73
119
  plugin = flexmock(d.instance)
74
120
  lease_id = "123"
75
121
  blob_client.should_receive(:acquire_blob_lease).with(d.instance.container_names, blob.name, duration: d.instance.lease_duration).and_return(lease_id).once
@@ -85,7 +131,7 @@ class AzureEventHubCaptureInputTest < Test::Unit::TestCase
85
131
 
86
132
  def test_emit_blob_messages
87
133
  d = create_driver
88
- setup_mocks(d)
134
+ blob_client, queue_client = setup_mocks(d)
89
135
  test_payload = flexmock("test_payload")
90
136
  buffer = flexmock("buffer")
91
137
  flexmock(StringIO).should_receive(:new).and_return(buffer)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-azure-queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6.pre
4
+ version: 0.0.8.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Bonebrake
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-20 00:00:00.000000000 Z
11
+ date: 2017-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd