1
1
require 'diego/bbs/bbs'
2
2
require 'diego/errors'
3
3
require 'diego/routes'
4
+ require 'net/http/persistent'
5
+ require 'uri'
4
6
5
7
module Diego
6
8
class Client
7
- PROTOBUF_HEADER = { 'Content-Type' . freeze => 'application/x-protobuf' . freeze } . freeze
8
-
9
9
def initialize ( url :, ca_cert_file :, client_cert_file :, client_key_file :,
10
10
connect_timeout :, send_timeout :, receive_timeout :)
11
11
ENV [ 'PB_IGNORE_DEPRECATIONS' ] ||= 'true'
12
- @client = build_client (
13
- url ,
12
+ @bbs_url = URI ( url )
13
+ @http_client = new_http_client (
14
14
ca_cert_file ,
15
15
client_cert_file ,
16
16
client_key_file ,
@@ -20,157 +20,121 @@ def initialize(url:, ca_cert_file:, client_cert_file:, client_key_file:,
20
20
end
21
21
22
22
def ping
23
- response = with_request_error_handling do
24
- client . post ( Routes ::PING )
25
- end
23
+ req = post_request ( path : Routes ::PING )
24
+ response = request_with_error_handling ( req )
26
25
27
- validate_status! ( response : response , statuses : [ 200 ] )
26
+ validate_status! ( response )
28
27
protobuf_decode! ( response . body , Bbs ::Models ::PingResponse )
29
28
end
30
29
31
30
def upsert_domain ( domain :, ttl :)
32
- request = protobuf_encode! ( { domain : domain , ttl : ttl . to_i } , Bbs ::Models ::UpsertDomainRequest )
33
-
34
- response = with_request_error_handling do
35
- client . post ( Routes ::UPSERT_DOMAIN , request , PROTOBUF_HEADER )
36
- end
31
+ req = post_request ( body : protobuf_encode! ( { domain : domain , ttl : ttl . to_i } , Bbs ::Models ::UpsertDomainRequest ) , path : Routes ::UPSERT_DOMAIN )
32
+ response = request_with_error_handling ( req )
37
33
38
- validate_status! ( response : response , statuses : [ 200 ] )
34
+ validate_status! ( response )
39
35
protobuf_decode! ( response . body , Bbs ::Models ::UpsertDomainResponse )
40
36
end
41
37
42
38
def desire_task ( task_definition :, domain :, task_guid :)
43
- request = protobuf_encode! ( { task_definition : task_definition , domain : domain , task_guid : task_guid } , Bbs ::Models ::DesireTaskRequest )
39
+ req = post_request ( body : protobuf_encode! ( { task_definition : task_definition , domain : domain , task_guid : task_guid } , Bbs ::Models ::DesireTaskRequest ) ,
40
+ path : Routes ::DESIRE_TASK )
41
+ response = request_with_error_handling ( req )
44
42
45
- response = with_request_error_handling do
46
- client . post ( Routes ::DESIRE_TASK , request , PROTOBUF_HEADER )
47
- end
48
-
49
- validate_status! ( response : response , statuses : [ 200 ] )
43
+ validate_status! ( response )
50
44
protobuf_decode! ( response . body , Bbs ::Models ::TaskLifecycleResponse )
51
45
end
52
46
53
47
def task_by_guid ( task_guid )
54
- request = protobuf_encode! ( { task_guid : task_guid } , Bbs ::Models ::TaskByGuidRequest )
55
-
56
- response = with_request_error_handling do
57
- client . post ( Routes ::TASK_BY_GUID , request , PROTOBUF_HEADER )
58
- end
48
+ req = post_request ( body : protobuf_encode! ( { task_guid : task_guid } , Bbs ::Models ::TaskByGuidRequest ) , path : Routes ::TASK_BY_GUID )
49
+ response = request_with_error_handling ( req )
59
50
60
- validate_status! ( response : response , statuses : [ 200 ] )
51
+ validate_status! ( response )
61
52
protobuf_decode! ( response . body , Bbs ::Models ::TaskResponse )
62
53
end
63
54
64
55
def tasks ( domain : '' , cell_id : '' )
65
- request = protobuf_encode! ( { domain : domain , cell_id : cell_id } , Bbs ::Models ::TasksRequest )
56
+ req = post_request ( body : protobuf_encode! ( { domain : domain , cell_id : cell_id } , Bbs ::Models ::TasksRequest ) , path : Routes ::LIST_TASKS )
57
+ response = request_with_error_handling ( req )
66
58
67
- response = with_request_error_handling do
68
- client . post ( Routes ::LIST_TASKS , request , PROTOBUF_HEADER )
69
- end
70
-
71
- validate_status! ( response : response , statuses : [ 200 ] )
59
+ validate_status! ( response )
72
60
protobuf_decode! ( response . body , Bbs ::Models ::TasksResponse )
73
61
end
74
62
75
63
def cancel_task ( task_guid )
76
- request = protobuf_encode! ( { task_guid : task_guid } , Bbs ::Models ::TaskGuidRequest )
77
-
78
- response = with_request_error_handling do
79
- client . post ( Routes ::CANCEL_TASK , request , PROTOBUF_HEADER )
80
- end
64
+ req = post_request ( body : protobuf_encode! ( { task_guid : task_guid } , Bbs ::Models ::TaskGuidRequest ) , path : Routes ::CANCEL_TASK )
65
+ response = request_with_error_handling ( req )
81
66
82
- validate_status! ( response : response , statuses : [ 200 ] )
67
+ validate_status! ( response )
83
68
protobuf_decode! ( response . body , Bbs ::Models ::TaskLifecycleResponse )
84
69
end
85
70
86
71
def desire_lrp ( lrp )
87
- request = protobuf_encode! ( { desired_lrp : lrp } , Bbs ::Models ::DesireLRPRequest )
72
+ req = post_request ( body : protobuf_encode! ( { desired_lrp : lrp } , Bbs ::Models ::DesireLRPRequest ) , path : Routes ::DESIRE_LRP )
73
+ response = request_with_error_handling ( req )
88
74
89
- response = with_request_error_handling do
90
- client . post ( Routes ::DESIRE_LRP , request , PROTOBUF_HEADER )
91
- end
92
-
93
- validate_status! ( response : response , statuses : [ 200 ] )
75
+ validate_status! ( response )
94
76
protobuf_decode! ( response . body , Bbs ::Models ::DesiredLRPLifecycleResponse )
95
77
end
96
78
97
79
def desired_lrp_by_process_guid ( process_guid )
98
- request = protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::DesiredLRPByProcessGuidRequest )
99
-
100
- response = with_request_error_handling do
101
- client . post ( Routes ::DESIRED_LRP_BY_PROCESS_GUID , request , PROTOBUF_HEADER )
102
- end
80
+ req = post_request ( body : protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::DesiredLRPByProcessGuidRequest ) , path : Routes ::DESIRED_LRP_BY_PROCESS_GUID )
81
+ response = request_with_error_handling ( req )
103
82
104
- validate_status! ( response : response , statuses : [ 200 ] )
83
+ validate_status! ( response )
105
84
protobuf_decode! ( response . body , Bbs ::Models ::DesiredLRPResponse )
106
85
end
107
86
108
87
def update_desired_lrp ( process_guid , lrp_update )
109
- request = protobuf_encode! ( { process_guid : process_guid , update : lrp_update } , Bbs ::Models ::UpdateDesiredLRPRequest )
88
+ req = post_request ( body : protobuf_encode! ( { process_guid : process_guid , update : lrp_update } , Bbs ::Models ::UpdateDesiredLRPRequest ) , path : Routes ::UPDATE_DESIRED_LRP )
89
+ response = request_with_error_handling ( req )
110
90
111
- response = with_request_error_handling do
112
- client . post ( Routes ::UPDATE_DESIRED_LRP , request , PROTOBUF_HEADER )
113
- end
114
-
115
- validate_status! ( response : response , statuses : [ 200 ] )
91
+ validate_status! ( response )
116
92
protobuf_decode! ( response . body , Bbs ::Models ::DesiredLRPLifecycleResponse )
117
93
end
118
94
119
95
def remove_desired_lrp ( process_guid )
120
- request = protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::RemoveDesiredLRPRequest )
121
-
122
- response = with_request_error_handling do
123
- client . post ( Routes ::REMOVE_DESIRED_LRP , request , PROTOBUF_HEADER )
124
- end
96
+ req = post_request ( body : protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::RemoveDesiredLRPRequest ) , path : Routes ::REMOVE_DESIRED_LRP )
97
+ response = request_with_error_handling ( req )
125
98
126
- validate_status! ( response : response , statuses : [ 200 ] )
99
+ validate_status! ( response )
127
100
protobuf_decode! ( response . body , Bbs ::Models ::DesiredLRPLifecycleResponse )
128
101
end
129
102
130
103
def retire_actual_lrp ( actual_lrp_key )
131
- request = protobuf_encode! ( { actual_lrp_key : actual_lrp_key } , Bbs ::Models ::RetireActualLRPRequest )
104
+ req = post_request ( body : protobuf_encode! ( { actual_lrp_key : actual_lrp_key } , Bbs ::Models ::RetireActualLRPRequest ) , path : Routes ::RETIRE_ACTUAL_LRP )
105
+ response = request_with_error_handling ( req )
132
106
133
- response = with_request_error_handling do
134
- client . post ( Routes ::RETIRE_ACTUAL_LRP , request , PROTOBUF_HEADER )
135
- end
136
-
137
- validate_status! ( response : response , statuses : [ 200 ] )
107
+ validate_status! ( response )
138
108
protobuf_decode! ( response . body , Bbs ::Models ::ActualLRPLifecycleResponse )
139
109
end
140
110
141
111
def desired_lrp_scheduling_infos ( domain )
142
- request = protobuf_encode! ( { domain : domain } , Bbs ::Models ::DesiredLRPsRequest )
143
-
144
- response = with_request_error_handling do
145
- client . post ( Routes ::DESIRED_LRP_SCHEDULING_INFOS , request , PROTOBUF_HEADER )
146
- end
112
+ req = post_request ( body : protobuf_encode! ( { domain : domain } , Bbs ::Models ::DesiredLRPsRequest ) , path : Routes ::DESIRED_LRP_SCHEDULING_INFOS )
113
+ response = request_with_error_handling ( req )
147
114
148
- validate_status! ( response : response , statuses : [ 200 ] )
115
+ validate_status! ( response )
149
116
protobuf_decode! ( response . body , Bbs ::Models ::DesiredLRPSchedulingInfosResponse )
150
117
end
151
118
152
119
def actual_lrps_by_process_guid ( process_guid )
153
- request = protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::ActualLRPsRequest )
120
+ req = post_request ( body : protobuf_encode! ( { process_guid : process_guid } , Bbs ::Models ::ActualLRPsRequest ) , path : Routes ::ACTUAL_LRPS )
121
+ response = request_with_error_handling ( req )
154
122
155
- response = with_request_error_handling do
156
- client . post ( Routes ::ACTUAL_LRPS , request , PROTOBUF_HEADER )
157
- end
158
-
159
- validate_status! ( response : response , statuses : [ 200 ] )
123
+ validate_status! ( response )
160
124
protobuf_decode! ( response . body , Bbs ::Models ::ActualLRPsResponse )
161
125
end
162
126
163
- def with_request_error_handling ( & blk )
164
- tries ||= 3
165
- yield
127
+ def request_with_error_handling ( req )
128
+ attempt ||= 1
129
+ http_client . request ( bbs_url + req . path , req )
166
130
rescue => e
167
- retry unless ( tries - = 1 ) . zero?
131
+ retry unless ( attempt + = 1 ) > 3
168
132
raise RequestError . new ( e . message )
169
133
end
170
134
171
135
private
172
136
173
- attr_reader :client
137
+ attr_reader :http_client , :bbs_url
174
138
175
139
def protobuf_encode! ( hash , protobuf_message_class )
176
140
# See below link to understand proto3 message encoding
@@ -180,8 +144,15 @@ def protobuf_encode!(hash, protobuf_message_class)
180
144
raise EncodeError . new ( e . message )
181
145
end
182
146
183
- def validate_status! ( response :, statuses :)
184
- raise ResponseError . new ( "failed with status: #{ response . status } , body: #{ response . body } " ) unless statuses . include? ( response . status )
147
+ def post_request ( body : nil , path :)
148
+ req = Net ::HTTP ::Post . new ( path )
149
+ req . body = body if body
150
+ req [ 'Content-Type' . freeze ] = 'application/x-protobuf' . freeze
151
+ req
152
+ end
153
+
154
+ def validate_status! ( response )
155
+ raise ResponseError . new ( "failed with status: #{ response . code } , body: #{ response . body } " ) unless response . code == '200'
185
156
end
186
157
187
158
def protobuf_decode! ( message , protobuf_decoder )
@@ -190,14 +161,16 @@ def protobuf_decode!(message, protobuf_decoder)
190
161
raise DecodeError . new ( e . message )
191
162
end
192
163
193
- def build_client ( url , ca_cert_file , client_cert_file , client_key_file ,
194
- connect_timeout , send_timeout , receive_timeout )
195
- client = HTTPClient . new ( base_url : url )
196
- client . connect_timeout = connect_timeout
197
- client . send_timeout = send_timeout
198
- client . receive_timeout = receive_timeout
199
- client . ssl_config . set_client_cert_file ( client_cert_file , client_key_file )
200
- client . ssl_config . set_trust_ca ( ca_cert_file )
164
+ def new_http_client ( ca_cert_file , client_cert_file , client_key_file ,
165
+ connect_timeout , send_timeout , receive_timeout )
166
+ client = Net ::HTTP ::Persistent . new ( pool_size : WorkPool ::SIZE )
167
+ client . verify_mode = OpenSSL ::SSL ::VERIFY_PEER
168
+ client . private_key = OpenSSL ::PKey ::RSA . new ( File . read ( client_key_file ) )
169
+ client . certificate = OpenSSL ::X509 ::Certificate . new ( File . read ( client_cert_file ) )
170
+ client . ca_file = ca_cert_file
171
+ client . open_timeout = connect_timeout
172
+ client . read_timeout = receive_timeout
173
+ client . write_timeout = send_timeout
201
174
client
202
175
end
203
176
end
0 commit comments