influxdb-client 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +157 -0
  3. data/.circleci/setup-rubygems.sh +3 -0
  4. data/.codecov.yml +3 -0
  5. data/.github/PULL_REQUEST_TEMPLATE +8 -0
  6. data/.gitignore +16 -0
  7. data/.rubocop.yml +38 -0
  8. data/CHANGELOG.md +37 -0
  9. data/Gemfile +24 -0
  10. data/LICENSE +21 -0
  11. data/README.md +268 -0
  12. data/Rakefile +37 -0
  13. data/bin/generate-sources.sh +23 -0
  14. data/bin/influxdb-onboarding.sh +39 -0
  15. data/bin/influxdb-restart.sh +60 -0
  16. data/bin/pom.xml +34 -0
  17. data/bin/swagger.yml +9867 -0
  18. data/examples/influxdb_18_example.rb +35 -0
  19. data/influxdb-client.gemspec +53 -0
  20. data/lib/influxdb2/client.rb +30 -0
  21. data/lib/influxdb2/client/client.rb +96 -0
  22. data/lib/influxdb2/client/default_api.rb +95 -0
  23. data/lib/influxdb2/client/delete_api.rb +80 -0
  24. data/lib/influxdb2/client/flux_csv_parser.rb +251 -0
  25. data/lib/influxdb2/client/flux_table.rb +99 -0
  26. data/lib/influxdb2/client/health_api.rb +49 -0
  27. data/lib/influxdb2/client/influx_error.rb +31 -0
  28. data/lib/influxdb2/client/models/delete_predicate_request.rb +215 -0
  29. data/lib/influxdb2/client/models/dialect.rb +317 -0
  30. data/lib/influxdb2/client/models/health_check.rb +256 -0
  31. data/lib/influxdb2/client/models/query.rb +284 -0
  32. data/lib/influxdb2/client/point.rb +215 -0
  33. data/lib/influxdb2/client/query_api.rb +93 -0
  34. data/lib/influxdb2/client/version.rb +23 -0
  35. data/lib/influxdb2/client/worker.rb +115 -0
  36. data/lib/influxdb2/client/write_api.rb +243 -0
  37. data/test/influxdb/client_test.rb +92 -0
  38. data/test/influxdb/delete_api_integration_test.rb +100 -0
  39. data/test/influxdb/delete_api_test.rb +121 -0
  40. data/test/influxdb/flux_csv_parser_test.rb +401 -0
  41. data/test/influxdb/point_test.rb +221 -0
  42. data/test/influxdb/query_api_integration_test.rb +58 -0
  43. data/test/influxdb/query_api_stream_test.rb +98 -0
  44. data/test/influxdb/query_api_test.rb +96 -0
  45. data/test/influxdb/write_api_batching_test.rb +292 -0
  46. data/test/influxdb/write_api_integration_test.rb +76 -0
  47. data/test/influxdb/write_api_test.rb +275 -0
  48. data/test/test_helper.rb +39 -0
  49. metadata +217 -0
@@ -0,0 +1,292 @@
1
+ # The MIT License
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'test_helper'
22
+
23
+ class WriteApiBatchingTest < MiniTest::Test
24
+ def setup
25
+ WebMock.disable_net_connect!
26
+
27
+ @write_options = InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING,
28
+ batch_size: 2, flush_interval: 5_000, retry_interval: 2_000)
29
+ @client = InfluxDB2::Client.new('http://localhost:9999',
30
+ 'my-token',
31
+ bucket: 'my-bucket',
32
+ org: 'my-org',
33
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
34
+ use_ssl: false)
35
+
36
+ @write_client = @client.create_write_api(write_options: @write_options)
37
+ end
38
+
39
+ def teardown
40
+ @client.close!
41
+
42
+ assert_equal true, @write_client.closed
43
+
44
+ WebMock.reset!
45
+ end
46
+
47
+ def test_batch_configuration
48
+ error = assert_raises ArgumentError do
49
+ InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING, batch_size: 0)
50
+ end
51
+ assert_equal "The 'batch_size' should be positive or zero, but is: 0", error.message
52
+
53
+ error = assert_raises ArgumentError do
54
+ InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING, flush_interval: -10)
55
+ end
56
+ assert_equal "The 'flush_interval' should be positive or zero, but is: -10", error.message
57
+
58
+ error = assert_raises ArgumentError do
59
+ InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING, retry_interval: 0)
60
+ end
61
+ assert_equal "The 'retry_interval' should be positive or zero, but is: 0", error.message
62
+
63
+ InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING, jitter_interval: 0)
64
+ error = assert_raises ArgumentError do
65
+ InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING, jitter_interval: -10)
66
+ end
67
+ assert_equal "The 'jitter_interval' should be positive number, but is: -10", error.message
68
+ end
69
+
70
+ def test_batch_size
71
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
72
+ .to_return(status: 204)
73
+
74
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=1.0 1')
75
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2')
76
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3')
77
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=4.0 4')
78
+
79
+ sleep(1)
80
+
81
+ request1 = "h2o_feet,location=coyote_creek level\\ water_level=1.0 1\n" \
82
+ 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2'
83
+ request2 = "h2o_feet,location=coyote_creek level\\ water_level=3.0 3\n" \
84
+ 'h2o_feet,location=coyote_creek level\\ water_level=4.0 4'
85
+
86
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
87
+ times: 1, body: request1)
88
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
89
+ times: 1, body: request2)
90
+ end
91
+
92
+ def test_batch_size_group_by
93
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
94
+ .to_return(status: 204)
95
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=s')
96
+ .to_return(status: 204)
97
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org-a&precision=ns')
98
+ .to_return(status: 204)
99
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket2&org=my-org-a&precision=ns')
100
+ .to_return(status: 204)
101
+
102
+ bucket = 'my-bucket'
103
+ bucket2 = 'my-bucket2'
104
+ org_a = 'my-org-a'
105
+
106
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=1.0 1', bucket: bucket, org: 'my-org')
107
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2', bucket: bucket, org: 'my-org',
108
+ precision: InfluxDB2::WritePrecision::SECOND)
109
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3', bucket: bucket, org: org_a)
110
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=4.0 4', bucket: bucket, org: org_a)
111
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=5.0 5', bucket: bucket2, org: org_a)
112
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=6.0 6', bucket: bucket, org: org_a)
113
+
114
+ sleep(1)
115
+
116
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
117
+ times: 1, body: 'h2o_feet,location=coyote_creek level\\ water_level=1.0 1')
118
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=s',
119
+ times: 1, body: 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2')
120
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org-a&precision=ns',
121
+ times: 1, body: "h2o_feet,location=coyote_creek level\\ water_level=3.0 3\n" \
122
+ 'h2o_feet,location=coyote_creek level\\ water_level=4.0 4')
123
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket2&org=my-org-a&precision=ns',
124
+ times: 1, body: 'h2o_feet,location=coyote_creek level\\ water_level=5.0 5')
125
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org-a&precision=ns',
126
+ times: 1, body: 'h2o_feet,location=coyote_creek level\\ water_level=6.0 6')
127
+ end
128
+
129
+ def test_flush_interval
130
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
131
+ .to_return(status: 204)
132
+
133
+ request1 = "h2o_feet,location=coyote_creek level\\ water_level=1.0 1\n" \
134
+ 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2'
135
+ request2 = 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3'
136
+
137
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=1.0 1')
138
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2')
139
+
140
+ sleep(1)
141
+
142
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
143
+ times: 1, body: request1)
144
+
145
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3')
146
+
147
+ sleep(2)
148
+
149
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
150
+ times: 0, body: request2)
151
+
152
+ sleep(3)
153
+
154
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
155
+ times: 1, body: request2)
156
+ end
157
+
158
+ def test_flush_all_by_close_client
159
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
160
+ .to_return(status: 204)
161
+
162
+ @client.close!
163
+
164
+ @write_options = InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING,
165
+ batch_size: 10, flush_interval: 5_000)
166
+ @client = InfluxDB2::Client.new('http://localhost:9999',
167
+ 'my-token',
168
+ bucket: 'my-bucket',
169
+ org: 'my-org',
170
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
171
+ use_ssl: false)
172
+
173
+ @write_client = @client.create_write_api(write_options: @write_options)
174
+
175
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=1.0 1')
176
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=2.0 2')
177
+ @write_client.write(data: 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3')
178
+
179
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
180
+ times: 0, body: 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3')
181
+
182
+ @client.close!
183
+
184
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
185
+ times: 1, body: "h2o_feet,location=coyote_creek level\\ water_level=1.0 1\n" \
186
+ "h2o_feet,location=coyote_creek level\\ water_level=2.0 2\n" \
187
+ 'h2o_feet,location=coyote_creek level\\ water_level=3.0 3')
188
+ end
189
+
190
+ def test_retry_interval_by_config
191
+ error_body = '{"code":"temporarily unavailable","message":"Token is temporarily over quota. '\
192
+ 'The Retry-After header describes when to try the write again."}'
193
+
194
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
195
+ .to_return(status: 429, headers: { 'X-Platform-Error-Code' => 'temporarily unavailable' }, body: error_body).then
196
+ .to_return(status: 204)
197
+
198
+ request = "h2o_feet,location=coyote_creek water_level=1.0 1\n" \
199
+ 'h2o_feet,location=coyote_creek water_level=2.0 2'
200
+
201
+ @write_client.write(data: ['h2o_feet,location=coyote_creek water_level=1.0 1',
202
+ 'h2o_feet,location=coyote_creek water_level=2.0 2'])
203
+
204
+ sleep(0.5)
205
+
206
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
207
+ times: 1, body: request)
208
+
209
+ sleep(1)
210
+
211
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
212
+ times: 1, body: request)
213
+
214
+ sleep(1)
215
+
216
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
217
+ times: 2, body: request)
218
+ end
219
+
220
+ def test_retry_interval_by_header
221
+ error_body = '{"code":"temporarily unavailable","message":"Server is temporarily unavailable to accept writes. '\
222
+ 'The Retry-After header describes when to try the write again."}'
223
+
224
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
225
+ .to_return(status: 503, headers: { 'X-Platform-Error-Code' => 'temporarily unavailable', 'Retry-After' => '3' },
226
+ body: error_body).then
227
+ .to_return(status: 204)
228
+
229
+ request = "h2o_feet,location=coyote_creek water_level=1.0 1\n" \
230
+ 'h2o_feet,location=coyote_creek water_level=2.0 2'
231
+
232
+ @write_client.write(data: ['h2o_feet,location=coyote_creek water_level=1.0 1',
233
+ InfluxDB2::Point.new(name: 'h2o_feet')
234
+ .add_tag('location', 'coyote_creek')
235
+ .add_field('water_level', 2.0)
236
+ .time(2, InfluxDB2::WritePrecision::NANOSECOND)])
237
+
238
+ sleep(0.5)
239
+
240
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
241
+ times: 1, body: request)
242
+
243
+ sleep(1)
244
+
245
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
246
+ times: 1, body: request)
247
+
248
+ sleep(1)
249
+
250
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
251
+ times: 1, body: request)
252
+
253
+ sleep(1)
254
+
255
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
256
+ times: 2, body: request)
257
+ end
258
+
259
+ def test_jitter_interval
260
+ @client.close!
261
+
262
+ @client = InfluxDB2::Client.new('http://localhost:9999',
263
+ 'my-token',
264
+ bucket: 'my-bucket',
265
+ org: 'my-org',
266
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
267
+ use_ssl: false)
268
+
269
+ @write_options = InfluxDB2::WriteOptions.new(write_type: InfluxDB2::WriteType::BATCHING,
270
+ batch_size: 2, flush_interval: 5_000, jitter_interval: 2_000)
271
+ @write_client = @client.create_write_api(write_options: @write_options)
272
+
273
+ stub_request(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
274
+ .to_return(status: 204)
275
+
276
+ request = "h2o_feet,location=coyote_creek water_level=1.0 1\n" \
277
+ 'h2o_feet,location=coyote_creek water_level=2.0 2'
278
+
279
+ @write_client.write(data: ['h2o_feet,location=coyote_creek water_level=1.0 1',
280
+ 'h2o_feet,location=coyote_creek water_level=2.0 2'])
281
+
282
+ sleep(0.05)
283
+
284
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
285
+ times: 0, body: request)
286
+
287
+ sleep(2)
288
+
289
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
290
+ times: 1, body: request)
291
+ end
292
+ end
@@ -0,0 +1,76 @@
1
+ # The MIT License
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'test_helper'
22
+ require 'csv'
23
+
24
+ class WriteApiIntegrationTest < MiniTest::Test
25
+ def setup
26
+ WebMock.allow_net_connect!
27
+ end
28
+
29
+ def test_write_into_influx_db
30
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
31
+ bucket: 'my-bucket',
32
+ org: 'my-org',
33
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
34
+ use_ssl: false)
35
+
36
+ now = Time.now.utc
37
+
38
+ measurement = 'h2o_' + now.to_i.to_s + now.nsec.to_s
39
+ point = InfluxDB2::Point.new(name: measurement)
40
+ .add_tag('location', 'europe')
41
+ .add_field('level', 2)
42
+ .time(now, InfluxDB2::WritePrecision::NANOSECOND)
43
+
44
+ client.create_write_api.write(data: point)
45
+
46
+ csv = _query(measurement)
47
+
48
+ refute_nil csv
49
+ assert_equal measurement, csv[0]['_measurement']
50
+ assert_equal 'europe', csv[0]['location']
51
+ assert_equal '2', csv[0]['_value']
52
+ assert_equal 'level', csv[0]['_field']
53
+ end
54
+
55
+ private
56
+
57
+ def _query(measurement)
58
+ query = { 'query': 'from(bucket: "my-bucket") |> range(start: -15m, stop: now()) '\
59
+ "|> filter(fn: (r) => r._measurement == \"#{measurement}\")", 'type': 'flux' }
60
+
61
+ uri = URI.parse('http://localhost:9999/api/v2/query?org=my-org')
62
+ request = Net::HTTP::Post.new(uri.request_uri)
63
+ request['Authorization'] = 'Token my-token'
64
+ request[InfluxDB2::DefaultApi::HEADER_CONTENT_TYPE] = 'application/json'
65
+ request.body = query.to_json
66
+
67
+ http = Net::HTTP.new(uri.host, uri.port)
68
+ begin
69
+ response = http.request(request)
70
+
71
+ CSV.parse(response.body, headers: true)
72
+ ensure
73
+ http.finish if http.started?
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,275 @@
1
+ # The MIT License
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'test_helper'
22
+
23
+ class WriteApiTest < MiniTest::Test
24
+ def setup
25
+ WebMock.disable_net_connect!
26
+ end
27
+
28
+ def test_required_arguments
29
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token')
30
+ write_api = client.create_write_api
31
+
32
+ # precision
33
+ assert_raises ArgumentError do
34
+ write_api.write(data: {}, bucket: 'my-bucket', org: 'my-org')
35
+ end
36
+ # bucket
37
+ assert_raises ArgumentError do
38
+ write_api.write(data: {}, org: 'my-org', precision: InfluxDB2::WritePrecision::NANOSECOND)
39
+ end
40
+ # org
41
+ assert_raises ArgumentError do
42
+ write_api.write(data: {}, bucket: 'my-bucket', precision: InfluxDB2::WritePrecision::NANOSECOND)
43
+ end
44
+ end
45
+
46
+ def test_default_arguments_
47
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
48
+ bucket: 'my-bucket',
49
+ org: 'my-org',
50
+ precision: InfluxDB2::WritePrecision::NANOSECOND)
51
+ write_api = client.create_write_api
52
+
53
+ # without argument errors
54
+ write_api.write(data: {})
55
+ end
56
+
57
+ def test_write_line_protocol
58
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
59
+ .to_return(status: 204)
60
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
61
+ bucket: 'my-bucket',
62
+ org: 'my-org',
63
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
64
+ use_ssl: false)
65
+
66
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
67
+
68
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
69
+ times: 1, body: 'h2o,location=west value=33i 15')
70
+ end
71
+
72
+ def test_write_point
73
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
74
+ .to_return(status: 204)
75
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
76
+ bucket: 'my-bucket',
77
+ org: 'my-org',
78
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
79
+ use_ssl: false)
80
+
81
+ client.create_write_api.write(data: InfluxDB2::Point.new(name: 'h2o')
82
+ .add_tag('location', 'europe')
83
+ .add_field('level', 2))
84
+
85
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
86
+ times: 1, body: 'h2o,location=europe level=2i')
87
+ end
88
+
89
+ def test_write_hash
90
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
91
+ .to_return(status: 204)
92
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
93
+ bucket: 'my-bucket',
94
+ org: 'my-org',
95
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
96
+ use_ssl: false)
97
+
98
+ client.create_write_api.write(data: { name: 'h2o',
99
+ tags: { host: 'aws', region: 'us' },
100
+ fields: { level: 5, saturation: '99%' }, time: 123 })
101
+
102
+ expected = 'h2o,host=aws,region=us level=5i,saturation="99%" 123'
103
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
104
+ times: 1, body: expected)
105
+ end
106
+
107
+ def test_write_collection
108
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
109
+ .to_return(status: 204)
110
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
111
+ bucket: 'my-bucket',
112
+ org: 'my-org',
113
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
114
+ use_ssl: false)
115
+
116
+ point = InfluxDB2::Point.new(name: 'h2o')
117
+ .add_tag('location', 'europe')
118
+ .add_field('level', 2)
119
+
120
+ hash = { name: 'h2o',
121
+ tags: { host: 'aws', region: 'us' },
122
+ fields: { level: 5, saturation: '99%' }, time: 123 }
123
+
124
+ client.create_write_api.write(data: ['h2o,location=west value=33i 15', nil, '', point, hash])
125
+
126
+ expected = "h2o,location=west value=33i 15\nh2o,location=europe level=2i"\
127
+ "\nh2o,host=aws,region=us level=5i,saturation=\"99%\" 123"
128
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
129
+ times: 1, body: expected)
130
+ end
131
+
132
+ def test_array_of_array
133
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
134
+ .to_return(status: 204)
135
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
136
+ bucket: 'my-bucket',
137
+ org: 'my-org',
138
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
139
+ use_ssl: false)
140
+
141
+ client.create_write_api.write(data: ['h2o,location=west value=33i 15', ['h2o,location=west value=34i 16',
142
+ 'h2o,location=west value=35i 17']])
143
+
144
+ expected = "h2o,location=west value=33i 15\nh2o,location=west value=34i 16"\
145
+ "\nh2o,location=west value=35i 17"
146
+
147
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
148
+ times: 1, body: expected)
149
+ end
150
+
151
+ def test_authorization_header
152
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
153
+ .to_return(status: 204)
154
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
155
+ bucket: 'my-bucket',
156
+ org: 'my-org',
157
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
158
+ use_ssl: false)
159
+
160
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
161
+
162
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
163
+ times: 1, headers: { 'Authorization' => 'Token my-token' })
164
+ end
165
+
166
+ def test_without_data
167
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
168
+ .to_return(status: 204)
169
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
170
+ bucket: 'my-bucket',
171
+ org: 'my-org',
172
+ precision: InfluxDB2::WritePrecision::NANOSECOND)
173
+
174
+ client.create_write_api.write(data: '')
175
+
176
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns', times: 0)
177
+ end
178
+
179
+ def test_influx_exception
180
+ error_body = '{"code":"invalid","message":"unable to parse '\
181
+ '\'h2o_feet, location=coyote_creek water_level=1.0 1\': missing tag key"}'
182
+
183
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
184
+ .to_return(status: 400, headers: { 'X-Platform-Error-Code' => 'invalid' }, body: error_body)
185
+
186
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
187
+ bucket: 'my-bucket',
188
+ org: 'my-org',
189
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
190
+ use_ssl: false)
191
+
192
+ error = assert_raises InfluxDB2::InfluxError do
193
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
194
+ end
195
+
196
+ assert_equal '400', error.code
197
+ assert_equal 'invalid', error.reference
198
+ assert_equal "unable to parse 'h2o_feet, location=coyote_creek water_level=1.0 1': missing tag key", error.message
199
+ end
200
+
201
+ def test_follow_redirect
202
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
203
+ .to_return(status: 307, headers:
204
+ { 'location' => 'http://localhost:9090/api/v2/write?bucket=my-bucket&org=my-org&precision=ns' })
205
+ .then.to_return(status: 204)
206
+ stub_request(:any, 'http://localhost:9090/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
207
+ .to_return(status: 204)
208
+
209
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
210
+ bucket: 'my-bucket',
211
+ org: 'my-org',
212
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
213
+ use_ssl: false)
214
+
215
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
216
+
217
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
218
+ times: 1, body: 'h2o,location=west value=33i 15')
219
+ assert_requested(:post, 'http://localhost:9090/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
220
+ times: 1, body: 'h2o,location=west value=33i 15')
221
+ end
222
+
223
+ def test_follow_redirect_max
224
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
225
+ .to_return(status: 307, headers:
226
+ { 'location' => 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns' })
227
+
228
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
229
+ bucket: 'my-bucket',
230
+ org: 'my-org',
231
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
232
+ max_redirect_count: 5,
233
+ use_ssl: false)
234
+
235
+ error = assert_raises InfluxDB2::InfluxError do
236
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
237
+ end
238
+
239
+ assert_equal 'Too many HTTP redirects. Exceeded limit: 5', error.message
240
+ end
241
+
242
+ def test_write_precision_constant
243
+ assert_equal InfluxDB2::WritePrecision::SECOND, InfluxDB2::WritePrecision.new.get_from_value('s')
244
+ assert_equal InfluxDB2::WritePrecision::MILLISECOND, InfluxDB2::WritePrecision.new.get_from_value('ms')
245
+ assert_equal InfluxDB2::WritePrecision::MICROSECOND, InfluxDB2::WritePrecision.new.get_from_value('us')
246
+ assert_equal InfluxDB2::WritePrecision::NANOSECOND, InfluxDB2::WritePrecision.new.get_from_value('ns')
247
+
248
+ error = assert_raises RuntimeError do
249
+ InfluxDB2::WritePrecision.new.get_from_value('not_supported')
250
+ end
251
+
252
+ assert_equal 'The time precision not_supported is not supported.', error.message
253
+ end
254
+
255
+ def test_headers
256
+ stub_request(:any, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns')
257
+ .to_return(status: 204)
258
+
259
+ client = InfluxDB2::Client.new('http://localhost:9999', 'my-token',
260
+ bucket: 'my-bucket',
261
+ org: 'my-org',
262
+ precision: InfluxDB2::WritePrecision::NANOSECOND,
263
+ use_ssl: false)
264
+
265
+ client.create_write_api.write(data: 'h2o,location=west value=33i 15')
266
+
267
+ headers = {
268
+ 'Authorization' => 'Token my-token',
269
+ 'User-Agent' => "influxdb-client-ruby/#{InfluxDB2::VERSION}",
270
+ 'Content-Type' => 'text/plain'
271
+ }
272
+ assert_requested(:post, 'http://localhost:9999/api/v2/write?bucket=my-bucket&org=my-org&precision=ns',
273
+ times: 1, body: 'h2o,location=west value=33i 15', headers: headers)
274
+ end
275
+ end