Skip to content

Commit e5671e9

Browse files
author
Shirshendu Mukherjee
committed
Add autogeneration of gd2 api methods from endpoints API
1 parent 16a0a77 commit e5671e9

File tree

3 files changed

+60
-54
lines changed

3 files changed

+60
-54
lines changed

app/controllers/clusters_controller.rb

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,54 @@
11
class ClustersController < AuthenticatedUsersController
22
get '/clusters' do
3-
clusters = Tendrl::Cluster.all
4-
JSON.generate clusters: clusters
3+
clusters = Tendrl::Cluster.all.map do |c|
4+
c.gd2.statedump.to_h
5+
end
6+
{ clusters: clusters }.to_json
57
end
68

79
before '/clusters/:cluster_id/?*?' do
810
@cluster = Tendrl::Cluster.find(params[:cluster_id])
9-
raise Tendrl::HttpResponseErrorHandler.new(
10-
StandardError.new,
11-
cause: '/clusters/id',
12-
object_id: params[:cluster_id]
13-
)
11+
unless @cluster.present?
12+
raise Tendrl::HttpResponseErrorHandler.new(
13+
StandardError.new,
14+
cause: '/clusters/id',
15+
object_id: params[:cluster_id]
16+
)
17+
end
1418
end
1519

1620
get '/clusters/:cluster_id' do
17-
state = @cluster.gd2.state
18-
state.to_json
21+
@cluster.gd2.statedump
1922
end
2023

2124
get '/clusters/:cluster_id/peers' do
22-
peers = @cluster.gd2.peers
25+
peers = @cluster.gd2.get_peers.to_a
2326
{ peers: peers }.to_json
2427
end
2528

2629
get '/clusters/:cluster_id/volumes' do
27-
volumes = @cluster.gd2.volumes
30+
volumes = @cluster.gd2.volume_list.to_a
2831
{ volumes: volumes }.to_json
2932
end
3033

31-
get '/clusters/:cluster_id/volumes/:volume_id' do
32-
volume = @cluster.gd2.volumes(params[:volume_id])
34+
get '/clusters/:cluster_id/volumes/:volname' do
35+
volume = @cluster.gd2.volume_info(params[:volname]).to_a
3336
{ volume: volume }.to_json
3437
end
3538

36-
get '/clusters/:cluster_id/volumes/:volume_id/bricks' do
37-
bricks = @cluster.gd2.bricks(params[:volume_id])
39+
get '/clusters/:cluster_id/volumes/:volname/bricks' do
40+
bricks = @cluster.gd2.volume_bricks_status(params[:volname]).to_a
3841
{ bricks: bricks }.to_json
3942
end
4043

4144
post '/import' do
4245
new_endpoint = {
4346
'gd2_url' => parsed_body['gd2_url'],
47+
'user' => parsed_body['user'],
4448
'secret' => parsed_body['secret']
4549
}
46-
gd2 = Gd2Client.new new_endpoint.symbolize_keys
47-
state = gd2.state
50+
gd2 = Gd2Client.new new_endpoint
51+
state = gd2.statedump
4852
cluster = Tendrl::Cluster.new state['cluster-id']
4953
unless cluster.endpoints.include? new_endpoint
5054
cluster.add_endpoint new_endpoint

app/models/cluster.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ def endpoints
1515
end
1616

1717
def gd2
18-
@gd2 ||= endpoints.map { |e| Gd2Client.from_endpoint e }.find(&:ping?)
18+
@gd2 ||= endpoints.map { |e| Gd2Client.new e }.find(&:ping?)
1919
end
2020

2121
def to_json(_)
22-
gd2.state.merge(endpoints: endpoints).to_json
22+
gd2.statedump.merge(endpoints: endpoints).to_json
2323
end
2424

2525
def add_endpoint(endpoint)
@@ -33,7 +33,7 @@ def add_endpoint(endpoint)
3333
class << self
3434
def find(cluster_id)
3535
cluster = new(cluster_id)
36-
return nil unless cluster.gd2.present?
36+
cluster.gd2.present? ? cluster : nil
3737
end
3838

3939
def all

lib/gd2_client.rb

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
class Gd2Client
22
include HTTParty
33

4-
def self.from_endpoint(endpoint)
5-
new(gd2_url: endpoint['gd2_url'], secret: endpoint['secret'])
4+
UNVERSIONED_APIS = %w[/version /ping /statedump /endpoints]
5+
6+
def initialize(endpoint)
7+
endpoint = endpoint.with_indifferent_access
8+
@gd2_url = endpoint[:gd2_url]
9+
@user = endpoint[:user].present? ? endpoint[:user] : 'glustercli'
10+
@secret = endpoint[:secret] || File.read(File.join('var', 'lib', 'glusterd2', 'auth'))
11+
generate_api_methods
612
end
713

8-
def initialize(gd2_url: 'http://localhost:24007', user: 'glustercli', secret: nil)
9-
@gd2_url = gd2_url
10-
@secret = secret || File.read(File.join('var', 'lib', 'glusterd2', 'auth'))
11-
@claim = {
12-
iss: user,
14+
def claim(method, path)
15+
{
16+
iss: @user,
1317
iat: DateTime.now.utc,
1418
exp: DateTime.now.utc + 10.seconds,
15-
qsh: ''
19+
qsh: Digest::SHA256.hexdigest(method.to_s.upcase + '&' + path)
1620
}
1721
end
1822

19-
def jwt_token
20-
JWT.encode(@claim, @secret, 'HS256')
23+
def jwt_token(method, path)
24+
JWT.encode(claim(method, path), @secret, 'HS256')
2125
end
2226

2327
def respond_to_missing?(method, include_private = false)
@@ -30,41 +34,39 @@ def method_missing(m, *args, &block)
3034
end
3135

3236
def http_call(method, path, opts = {})
33-
@claim[:qsh] = Digest::SHA256.hexdigest(method.to_s.upcase + '&' + path)
34-
response = HTTParty.public_send(
37+
req_data = { headers: { 'Authorization' => 'Bearer ' + jwt_token(method, path) } }
38+
req_data[:body] = args[-1].to_h if %w[put post patch].include?(method) && args[-1].respond_to(:to_h)
39+
HTTParty.public_send(
3540
method,
3641
@gd2_url + path,
37-
opts.merge(headers: { 'Authorization' => 'Bearer ' + jwt_token })
42+
opts.merge(req_data)
3843
)
39-
return JSON.parse(response.body) if response.success?
40-
raise Tendrl::HttpResponseErrorHandler.new(StandardError.new, cause: 'gd2_api_error', object_id: method.to_s.capitalize + path.to_s)
41-
end
42-
43-
def peers
44-
get('/v1/peers')
45-
end
46-
47-
def state
48-
get('/statedump')
49-
end
50-
51-
def volumes
52-
get('/v1/volumes')
5344
end
5445

55-
def volume(vol_name)
56-
get("/v1/volumes/#{vol_name}")
46+
def prefixed_path(path)
47+
UNVERSIONED_APIS.include?(path) ? path : '/v1' + path
5748
end
5849

59-
def bricks(vol_name)
60-
get("/v1/volumes/#{vol_name}/bricks")
50+
def generate_api_methods
51+
apis.each do |api|
52+
method_name = api['name'].split.join('_').underscore
53+
action = api['methods'].downcase
54+
self.class.send(:define_method, method_name) do |*args|
55+
path = api['path'].gsub(/{.*?}/).with_index { |_, i| args[i] }
56+
path = prefixed_path(path)
57+
response = http_call(action, path, args[-1].present? && args[-1].respond_to?(:to_h) ? args[-1] : {})
58+
return response if response.success?
59+
raise Tendrl::HttpResponseErrorHandler.new(response.body, cause: 'gd2_api_error', object_id: api['methods'] + path.to_s)
60+
end
61+
end
62+
self
6163
end
6264

6365
def ping?
64-
HTTParty.get(@gd2_url + "/ping").success?
66+
HTTParty.get(@gd2_url + '/ping').success?
6567
end
6668

67-
def endpoints
68-
get('/endpoints')
69+
def apis
70+
get('/endpoints').to_a
6971
end
7072
end

0 commit comments

Comments
 (0)