influxdb 0.0.9 → 0.0.10

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: dec07342cd8e538c3ebba57d893117c5dc3d0e35
4
- data.tar.gz: a0c35f492f8fabc6b3df66da2725c35a5f67e06f
3
+ metadata.gz: a15d18aa85145172f0abb3333ef7ffb9641b4ada
4
+ data.tar.gz: 6146be97a07658dffb26b044d15ddca5adc8e8ac
5
5
  SHA512:
6
- metadata.gz: 44e86d093b33b08031324467c78b518b49516a6374f9e6a5b0740f86b9d397f0e7ebf013f78aa6284aeee652924cce8576e5176c8f4c22c3212c0c1e9b2a90b1
7
- data.tar.gz: 13493de5cfd094646fbf68baf1b15a1fa87ba434ef2d8c988edb21bca9dd5597ab83125582df63f16fa654563610cdea87fb174a0662a2bef6cea51b29c53842
6
+ metadata.gz: 191c102bd7ad4f5e136763b16ba0efce9b2f6f1002bcea5e317cad36ad20918484c714e277a329890598bd1172469bf117013ed93e2db5ed7742aebbfaa7c8bc
7
+ data.tar.gz: 7cdbe3eefee7b679dae5c46d1a825cc36195d1bdb05326cf57dd005c1ce3663d57bd34414edaa289424281a726d9df6d25702fea527b4d8711bb6edac9d02151
data/.travis.yml CHANGED
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.8.7
4
+ - ree
4
5
  - 1.9.3
5
6
  - 2.0.0
6
- - rbx-19mode
7
- - rbx-20mode
8
- - jruby
9
7
  - ruby-head
8
+ - jruby
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
+ gem "webmock", :git => "https://github.com/influxdb/webmock.git"
data/README.md CHANGED
@@ -97,6 +97,16 @@ database = 'site_development'
97
97
  influxdb.delete_database(database)
98
98
  ```
99
99
 
100
+ Delete a database user:
101
+
102
+ ``` ruby
103
+ require 'influxdb'
104
+
105
+ influxdb = InfluxDB::Client.new
106
+
107
+ influxdb.delete_database_user(database, username)
108
+ ```
109
+
100
110
  Querying:
101
111
 
102
112
  ``` ruby
data/lib/influxdb.rb CHANGED
@@ -1,2 +1,6 @@
1
1
  require "influxdb/version"
2
+ require "influxdb/logger"
3
+
4
+ require "influxdb/max_queue"
5
+ require "influxdb/worker"
2
6
  require "influxdb/client"
@@ -2,10 +2,13 @@ require 'uri'
2
2
  require 'net/http'
3
3
  require 'json'
4
4
 
5
-
6
5
  module InfluxDB
7
6
  class Client
8
7
  attr_accessor :host, :port, :username, :password, :database
8
+ attr_accessor :queue
9
+
10
+ include InfluxDB::Logger
11
+ include InfluxDB::Worker
9
12
 
10
13
  # Initializes a new Influxdb client
11
14
  #
@@ -34,54 +37,95 @@ module InfluxDB
34
37
  @username = opts[:username] || "root"
35
38
  @password = opts[:password] || "root"
36
39
  @database = args.first
40
+ @http = Net::HTTP.new(@host, @port)
41
+ @queue = InfluxDB::MaxQueue.new
42
+ spawn_threads!
37
43
  end
38
44
 
39
45
  def create_database(name)
40
- http = Net::HTTP.new(@host, @port)
41
- url = "/db?u=#{@username}&p=#{@password}"
46
+ url = full_url("db")
42
47
  data = JSON.generate({:name => name})
43
48
 
44
- response = http.request(Net::HTTP::Post.new(url), data)
49
+ headers = {"Content-Type" => "application/json"}
50
+ response = @http.request(Net::HTTP::Post.new(url, headers), data)
45
51
  end
46
52
 
47
53
  def delete_database(name)
48
- http = Net::HTTP.new(@host, @port)
49
- url = "/db/#{name}?u=#{@username}&p=#{@password}"
54
+ url = full_url("db/#{name}")
50
55
 
51
- response = http.request(Net::HTTP::Delete.new(url))
56
+ response = @http.request(Net::HTTP::Delete.new(url))
52
57
  end
53
58
 
54
59
  def get_database_list
55
- http = Net::HTTP.new(@host, @port)
56
- url = "/dbs?u=#{@username}&p=#{@password}"
60
+ url = full_url("dbs")
57
61
 
58
- response = http.request(Net::HTTP::Get.new(url))
62
+ response = @http.request(Net::HTTP::Get.new(url))
59
63
  JSON.parse(response.body)
60
64
  end
61
65
 
66
+ def create_cluster_admin(username, password)
67
+ url = full_url("cluster_admins")
68
+ data = JSON.generate({:name => username, :password => password})
69
+
70
+ headers = {"Content-Type" => "application/json"}
71
+ response = @http.request(Net::HTTP::Post.new(url, headers), data)
72
+ end
73
+
74
+ def update_cluster_admin(username, password)
75
+ url = full_url("cluster_admins/#{username}")
76
+ data = JSON.generate({:password => password})
77
+
78
+ headers = {"Content-Type" => "application/json"}
79
+ response = @http.request(Net::HTTP::Post.new(url, headers), data)
80
+ end
81
+
82
+ def delete_cluster_admin(username)
83
+ url = full_url("cluster_admins/#{username}")
84
+
85
+ response = @http.request(Net::HTTP::Delete.new(url))
86
+ end
87
+
62
88
  def create_database_user(database, username, password)
63
- http = Net::HTTP.new(@host, @port)
64
- url = "/db/#{database}/users?u=#{@username}&p=#{@password}"
65
- data = JSON.generate({:username => username, :password => password})
66
- response = http.request(Net::HTTP::Post.new(url), data)
89
+ url = full_url("db/#{database}/users")
90
+ data = JSON.generate({:name => username, :password => password})
91
+
92
+ headers = {"Content-Type" => "application/json"}
93
+ response = @http.request(Net::HTTP::Post.new(url, headers), data)
94
+ end
95
+
96
+ def update_database_user(database, username, options = {})
97
+ url = full_url("db/#{database}/users/#{username}")
98
+ data = JSON.generate(options)
99
+
100
+ headers = {"Content-Type" => "application/json"}
101
+ @http.request(Net::HTTP::Post.new(url, headers), data)
102
+ end
103
+
104
+ def delete_database_user(database, username)
105
+ url = full_url("db/#{database}/users/#{username}")
106
+
107
+ @http.request(Net::HTTP::Delete.new(url))
67
108
  end
68
109
 
69
110
  def get_database_user_list(database)
70
- http = Net::HTTP.new(@host, @port)
71
- url = "/db/#{database}/users?u=#{@username}&p=#{@password}"
111
+ url = full_url("db/#{database}/users")
72
112
 
73
- response = http.request(Net::HTTP::Get.new(url))
113
+ response = @http.request(Net::HTTP::Get.new(url))
74
114
  JSON.parse(response.body)
75
115
  end
76
116
 
77
- def write_point(name, data)
78
- http = Net::HTTP.new(@host, @port)
79
- url = "/db/#{@database}/series?u=#{@username}&p=#{@password}"
80
- payload = {:name => name, :points => [], :columns => []}
117
+ def alter_database_privilege(database, username, admin=true)
118
+ url = full_url("db/#{database}/users/#{username}")
119
+ data = JSON.generate({:admin => admin})
120
+
121
+ headers = {"Content-Type" => "application/json"}
122
+ @http.request(Net::HTTP::Post.new(url, headers), data)
123
+ end
81
124
 
125
+ def write_point(name, data, async=false)
82
126
  data = data.is_a?(Array) ? data : [data]
83
- columns = data.reduce(:merge).keys
84
- payload[:columns] = columns
127
+ columns = data.reduce(:merge).keys.sort {|a,b| a.to_s <=> b.to_s}
128
+ payload = {:name => name, :points => [], :columns => columns}
85
129
 
86
130
  data.each do |p|
87
131
  point = []
@@ -89,15 +133,21 @@ module InfluxDB
89
133
  payload[:points].push point
90
134
  end
91
135
 
92
- data = JSON.generate([payload])
93
- response = http.request(Net::HTTP::Post.new(url), data)
136
+ async ? @queue.push(payload) : _write([payload])
137
+ end
138
+
139
+ def _write(payload)
140
+ url = full_url("db/#{@database}/series")
141
+ data = JSON.generate(payload)
142
+
143
+ headers = {"Content-Type" => "application/json"}
144
+ response = @http.request(Net::HTTP::Post.new(url, headers), data)
94
145
  end
95
146
 
96
- def query query
97
- http = Net::HTTP.new(@host, @port)
98
- url = "/db/#{@database}/series?u=#{@username}&p=#{@password}&q=#{query}"
147
+ def query(query)
148
+ url = full_url("db/#{@database}/series", "q=#{query}")
99
149
  url = URI.encode url
100
- response = http.request(Net::HTTP::Get.new(url))
150
+ response = @http.request(Net::HTTP::Get.new(url))
101
151
  series = JSON.parse(response.body)
102
152
 
103
153
  if block_given?
@@ -113,6 +163,12 @@ module InfluxDB
113
163
  end
114
164
 
115
165
  private
166
+ def full_url(path, params=nil)
167
+ "".tap do |url|
168
+ url << "/#{path}?u=#{@username}&p=#{@password}"
169
+ url << "&#{params}" unless params.nil?
170
+ end
171
+ end
116
172
 
117
173
  def denormalize_series series
118
174
  columns = series['columns']
@@ -0,0 +1,44 @@
1
+ require 'json'
2
+
3
+ module InfluxDB
4
+ class Config
5
+ attr_accessor :path, :config
6
+
7
+ # +:path+:: path to the config file
8
+ # +:config+:: hash representing InfluxDB configuration
9
+ def initialize(*args)
10
+ opts = args.last.is_a?(Hash) ? args.last : {}
11
+ @path = opts[:path] || '/opt/influxdb/shared/config.json'
12
+ @config = opts[:config] || default_config
13
+ end
14
+
15
+ def render
16
+ return JSON.pretty_generate(@config)
17
+ end
18
+
19
+ def valid?(path=@path)
20
+ begin
21
+ JSON.parse(File.read(path))
22
+ return true
23
+ rescue JSON::ParserError
24
+ return false
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def default_config
31
+ return {
32
+ 'AdminHttpPort' => 8083,
33
+ 'AdminAssetsDir' => '/opt/influxdb/current/admin',
34
+ 'ApiHttpPort' => 8086,
35
+ 'RaftServerPort' => 8090,
36
+ 'SeedServers' => [],
37
+ 'DataDir' => '/opt/influxdb/shared/data/db',
38
+ 'RaftDir' => '/opt/influxdb/shared/data/raft'
39
+ }
40
+ end
41
+
42
+ end
43
+ end
44
+
@@ -0,0 +1,10 @@
1
+ module InfluxDB
2
+ module Logger
3
+ PREFIX = "[InfluxDB] "
4
+
5
+ private
6
+ def log(level, message)
7
+ STDERR.puts(PREFIX + "(#{level}) #{message}") unless level == :debug
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ require "thread"
2
+
3
+ module InfluxDB
4
+ class MaxQueue < Queue
5
+ attr_reader :max
6
+
7
+ def initialize(max = 10_000)
8
+ raise ArgumentError, "queue size must be positive" unless max > 0
9
+ @max = max
10
+ super()
11
+ end
12
+
13
+ def push(obj)
14
+ super if length < @max
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module InfluxDB
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
@@ -0,0 +1,59 @@
1
+ require 'thread'
2
+ require "net/http"
3
+ require "uri"
4
+
5
+ module InfluxDB
6
+ module Worker
7
+ attr_accessor :queue
8
+
9
+ include InfluxDB::Logger
10
+
11
+ MAX_POST_POINTS = 200
12
+ NUM_WORKER_THREADS = 3
13
+ SLEEP_INTERVAL = 500
14
+
15
+ def current_threads
16
+ Thread.list.select {|t| t[:influxdb] == self.object_id}
17
+ end
18
+
19
+ def current_thread_count
20
+ Thread.list.count {|t| t[:influxdb] == self.object_id}
21
+ end
22
+
23
+ def spawn_threads!
24
+ NUM_WORKER_THREADS.times do |thread_num|
25
+ log :debug, "Spawning background worker thread #{thread_num}."
26
+
27
+ Thread.new do
28
+ Thread.current[:influxdb] = self.object_id
29
+
30
+ at_exit do
31
+ log :debug, "Thread exiting, flushing queue."
32
+ check_background_queue(thread_num) until @queue.empty?
33
+ end
34
+
35
+ while true
36
+ sleep SLEEP_INTERVAL
37
+ self.check_background_queue(thread_num)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def check_background_queue(thread_num = 0)
44
+ log :debug, "Checking background queue on thread #{thread_num} (#{self.current_thread_count} active)"
45
+
46
+ begin
47
+ data = []
48
+
49
+ while data.size < MAX_POST_POINTS && !@queue.empty?
50
+ p = @queue.pop(true) rescue next;
51
+ log :debug, "Found data in the queue! (#{p[:n]})"
52
+ data.push p
53
+ end
54
+
55
+ _write(data)
56
+ end while @queue.length > MAX_POST_POINTS
57
+ end
58
+ end
59
+ end
@@ -34,7 +34,7 @@ describe InfluxDB::Client do
34
34
  it "should POST to create a new database" do
35
35
  stub_request(:post, "http://influxdb.test:9999/db").with(
36
36
  :query => {:u => "username", :p => "password"},
37
- :body => JSON.generate({:name => "foo"})
37
+ :body => {:name => "foo"}
38
38
  )
39
39
 
40
40
  @influxdb.create_database("foo").should be_a(Net::HTTPOK)
@@ -56,23 +56,87 @@ describe InfluxDB::Client do
56
56
  database_list = [{"name" => "foobar"}]
57
57
  stub_request(:get, "http://influxdb.test:9999/dbs").with(
58
58
  :query => {:u => "username", :p => "password"}
59
- ).to_return(:body => JSON.generate(database_list, :status => 200))
59
+ ).to_return(:body => JSON.generate(database_list), :status => 200)
60
60
 
61
61
  @influxdb.get_database_list.should == database_list
62
62
  end
63
63
  end
64
64
 
65
+ describe "#create_cluster_admin" do
66
+ it "should POST to create a new cluster admin" do
67
+ stub_request(:post, "http://influxdb.test:9999/cluster_admins").with(
68
+ :query => {:u => "username", :p => "password"},
69
+ :body => {:name => "adminadmin", :password => "passpass"}
70
+ )
71
+
72
+ @influxdb.create_cluster_admin("adminadmin", "passpass").should be_a(Net::HTTPOK)
73
+ end
74
+ end
75
+
76
+ describe "#update_cluster_admin" do
77
+ it "should POST to update a cluster admin" do
78
+ stub_request(:post, "http://influxdb.test:9999/cluster_admins/adminadmin").with(
79
+ :query => {:u => "username", :p => "password"},
80
+ :body => {:password => "passpass"}
81
+ )
82
+
83
+ @influxdb.update_cluster_admin("adminadmin", "passpass").should be_a(Net::HTTPOK)
84
+ end
85
+ end
86
+
87
+ describe "#delete_cluster_admin" do
88
+ it "should DELETE a cluster admin" do
89
+ stub_request(:delete, "http://influxdb.test:9999/cluster_admins/adminadmin").with(
90
+ :query => {:u => "username", :p => "password"}
91
+ )
92
+
93
+ @influxdb.delete_cluster_admin("adminadmin").should be_a(Net::HTTPOK)
94
+ end
95
+ end
96
+
65
97
  describe "#create_database_user" do
66
98
  it "should POST to create a new database user" do
67
99
  stub_request(:post, "http://influxdb.test:9999/db/foo/users").with(
68
100
  :query => {:u => "username", :p => "password"},
69
- :body => JSON.generate({:username => "useruser", :password => "passpass"})
101
+ :body => {:name => "useruser", :password => "passpass"}
70
102
  )
71
103
 
72
104
  @influxdb.create_database_user("foo", "useruser", "passpass").should be_a(Net::HTTPOK)
73
105
  end
74
106
  end
75
107
 
108
+ describe "#update_database_user" do
109
+ it "should POST to update a database user" do
110
+ stub_request(:post, "http://influxdb.test:9999/db/foo/users/useruser").with(
111
+ :query => {:u => "username", :p => "password"},
112
+ :body => {:password => "passpass"}
113
+ )
114
+
115
+ @influxdb.update_database_user("foo", "useruser", :password => "passpass").should be_a(Net::HTTPOK)
116
+ end
117
+ end
118
+
119
+ describe "#alter_database_privilege" do
120
+ it "should POST to alter privileges for a user on a database" do
121
+ stub_request(:post, "http://influxdb.test:9999/db/foo/users/useruser").with(
122
+ :query => {:u => "username", :p => "password"}
123
+ )
124
+
125
+ @influxdb.alter_database_privilege("foo", "useruser", admin=true).should be_a(Net::HTTPOK)
126
+ @influxdb.alter_database_privilege("foo", "useruser", admin=false).should be_a(Net::HTTPOK)
127
+ end
128
+ end
129
+
130
+ describe "#delete_database_user" do
131
+ it "should DELETE a database user" do
132
+ stub_request(:delete, "http://influxdb.test:9999/db/foo/users/bar").with(
133
+ :query => {:u => "username", :p => "password"}
134
+ )
135
+
136
+ @influxdb.delete_database_user("foo", "bar").should be_a(Net::HTTPOK)
137
+ end
138
+ end
139
+
76
140
  describe "#get_database_user_list" do
77
141
  it "should GET a list of database users" do
78
142
  user_list = [{"username"=>"user1"}, {"username"=>"user2"}]
@@ -87,17 +151,16 @@ describe InfluxDB::Client do
87
151
  describe "#write_point" do
88
152
  it "should POST to add points" do
89
153
  body = [{
90
- :name => "seriez",
91
- :points => [["juan", 87]],
92
- :columns => ["name", "age"]
154
+ "name" => "seriez",
155
+ "points" => [[87, "juan"]],
156
+ "columns" => ["age", "name"]
93
157
  }]
94
158
 
95
159
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
96
160
  :query => {:u => "username", :p => "password"},
97
- :body => JSON.generate(body)
161
+ :body => body
98
162
  )
99
163
 
100
- # data = [{:name => "juan", :age => 87}, {:name => "pablo", :age => 64}]
101
164
  data = {:name => "juan", :age => 87}
102
165
 
103
166
  @influxdb.write_point("seriez", data).should be_a(Net::HTTPOK)
@@ -105,14 +168,14 @@ describe InfluxDB::Client do
105
168
 
106
169
  it "should POST multiple points" do
107
170
  body = [{
108
- :name => "seriez",
109
- :points => [["juan", 87], ["shahid", 99]],
110
- :columns => ["name", "age"]
171
+ "name" => "seriez",
172
+ "points" => [[87, "juan"], [99, "shahid"]],
173
+ "columns" => ["age", "name"]
111
174
  }]
112
175
 
113
176
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
114
177
  :query => {:u => "username", :p => "password"},
115
- :body => JSON.generate(body)
178
+ :body => body
116
179
  )
117
180
 
118
181
  data = [{:name => "juan", :age => 87}, { :name => "shahid", :age => 99}]
@@ -122,14 +185,14 @@ describe InfluxDB::Client do
122
185
 
123
186
  it "should POST multiple points with missing columns" do
124
187
  body = [{
125
- :name => "seriez",
126
- :points => [["juan", 87], ["shahid", nil]],
127
- :columns => ["name", "age"]
188
+ "name" => "seriez",
189
+ "points" => [[87, "juan"], [nil, "shahid"]],
190
+ "columns" => ["age", "name"]
128
191
  }]
129
192
 
130
193
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
131
194
  :query => {:u => "username", :p => "password"},
132
- :body => JSON.generate(body)
195
+ :body => body
133
196
  )
134
197
 
135
198
  data = [{:name => "juan", :age => 87}, { :name => "shahid"}]
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe InfluxDB::MaxQueue do
4
+ it "should inherit from Queue" do
5
+ InfluxDB::MaxQueue.new.should be_a(Queue)
6
+ end
7
+
8
+ context "#new" do
9
+ it "should allow max_depth to be set" do
10
+ queue = InfluxDB::MaxQueue.new(500)
11
+ queue.max.should == 500
12
+ end
13
+ end
14
+
15
+ context "#push" do
16
+ it "should allow an item to be added if the queue is not full" do
17
+ queue = InfluxDB::MaxQueue.new(5)
18
+ queue.size.should be_zero
19
+ queue.push(1)
20
+ queue.size.should == 1
21
+ end
22
+
23
+ it "should not allow items to be added if the queue is full" do
24
+ queue = InfluxDB::MaxQueue.new(5)
25
+ queue.size.should be_zero
26
+ 5.times { |n| queue.push(n) }
27
+ queue.size.should == 5
28
+ queue.push(6)
29
+ queue.size.should == 5
30
+ end
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influxdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Persen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-18 00:00:00.000000000 Z
11
+ date: 2013-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -96,9 +96,14 @@ files:
96
96
  - influxdb.gemspec
97
97
  - lib/influxdb.rb
98
98
  - lib/influxdb/client.rb
99
+ - lib/influxdb/config.rb
100
+ - lib/influxdb/logger.rb
101
+ - lib/influxdb/max_queue.rb
99
102
  - lib/influxdb/version.rb
103
+ - lib/influxdb/worker.rb
100
104
  - spec/influxdb/client_spec.rb
101
105
  - spec/influxdb_spec.rb
106
+ - spec/max_queue_spec.rb
102
107
  - spec/spec_helper.rb
103
108
  homepage: http://influxdb.org
104
109
  licenses:
@@ -127,4 +132,5 @@ summary: Ruby library for InfluxDB.
127
132
  test_files:
128
133
  - spec/influxdb/client_spec.rb
129
134
  - spec/influxdb_spec.rb
135
+ - spec/max_queue_spec.rb
130
136
  - spec/spec_helper.rb