influxdb 0.0.9 → 0.0.10

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