Showing 3 of 3 files from the diff.
@@ -166,11 +166,12 @@
Loading
166 | 166 | agent = Agent(reactor, pool=pool) |
|
167 | 167 | jws_d = JWSClient.from_directory(agent, key, alg, directory) |
|
168 | 168 | else: |
|
169 | + | assert 0, "Not supported right now, we need a directory object." |
|
169 | 170 | jws_d = defer.succeed(jws_client) |
|
170 | 171 | ||
171 | - | def set_timeout(jws_client): |
|
172 | - | jws_client.timeout = timeout |
|
173 | - | return jws_client |
|
172 | + | def set_timeout(jws_client_and_dir): |
|
173 | + | jws_client_and_dir[0].timeout = timeout |
|
174 | + | return jws_client_and_dir |
|
174 | 175 | ||
175 | 176 | return jws_d.addCallback(set_timeout) |
|
176 | 177 |
@@ -220,6 +221,7 @@
Loading
220 | 221 | self.directory = directory |
|
221 | 222 | self.key = key |
|
222 | 223 | self._kid = None |
|
224 | + | print("created client:", vars(self)) |
|
223 | 225 | ||
224 | 226 | @classmethod |
|
225 | 227 | def from_url( |
@@ -251,11 +253,12 @@
Loading
251 | 253 | with action.context(): |
|
252 | 254 | check_directory_url_type(url) |
|
253 | 255 | directory = url.asText() |
|
254 | - | jws_client = _default_client( |
|
255 | - | jws_client, reactor, key, alg, directory, timeout |
|
256 | - | ) |
|
257 | 256 | action.add_success_fields(directory=directory) |
|
258 | - | return succeed(cls(reactor, key, jws_client)) |
|
257 | + | return DeferredContext( |
|
258 | + | _default_client(jws_client, reactor, key, alg, directory, timeout) |
|
259 | + | ).addCallback( |
|
260 | + | lambda jws_client_and_dir: cls(directory=jws_client_and_dir[1], reactor=reactor, key=key, jws_client=jws_client_and_dir[0]) |
|
261 | + | ).addActionFinish() |
|
259 | 262 | ||
260 | 263 | def start(self, email=None): |
|
261 | 264 | """ |
@@ -828,20 +831,20 @@
Loading
828 | 831 | :param str directory: The URL to the ACME v2 directory. |
|
829 | 832 | ||
830 | 833 | :return: When operation is done. |
|
831 | - | :rtype: Deferred[None] |
|
834 | + | :rtype: Deferred[Tuple[JWSClient, directory]] |
|
832 | 835 | """ |
|
833 | 836 | # Provide invalid new_nonce_url & kid, but don't expose it to the |
|
834 | 837 | # caller. |
|
835 | 838 | self = cls(agent, key, alg, None, None) |
|
836 | 839 | ||
837 | - | def cb_extract_new_nonce(directory): |
|
840 | + | def cb_extract_new_nonce(messages_dir_object): |
|
841 | + | print("MSGDIR", vars(messages_dir_object)) |
|
838 | 842 | try: |
|
839 | - | self._new_nonce = directory.newNonce |
|
843 | + | self._new_nonce = messages_dir_object.newNonce |
|
840 | 844 | except AttributeError: |
|
841 | 845 | raise errors.ClientError( |
|
842 | - | 'Directory has no newNonce URL', directory) |
|
843 | - | ||
844 | - | return directory |
|
846 | + | 'Directory has no newNonce URL', messages_dir_object) |
|
847 | + | return self, messages_dir_object |
|
845 | 848 | return ( |
|
846 | 849 | self.get(directory) |
|
847 | 850 | .addCallback(json_content) |
@@ -34,11 +34,13 @@
Loading
34 | 34 | manage. |
|
35 | 35 | ||
36 | 36 | :type client: `txacme.client.Client` |
|
37 | - | :param client: A client which is already set to be used for an |
|
38 | - | environment. For example, ``Client.from_url(reactor=reactor, |
|
39 | - | url=LETSENCRYPT_STAGING_DIRECTORY, key=acme_key, alg=RS256)``. |
|
40 | - | When the service is stopped, it will automatically call the stop |
|
41 | - | method on the client. |
|
37 | + | :param client: A client, or Deferred of a client, which is already set to |
|
38 | + | be used for an environment; for example, |
|
39 | + | Client.from_url(reactor=reactor, url=LETSENCRYPT_STAGING_DIRECTORY, |
|
40 | + | key=acme_key, alg=RS256). |
|
41 | + | ||
42 | + | When the service is stopped, it will automatically call the stop method |
|
43 | + | on the client. |
|
42 | 44 | ||
43 | 45 | :param clock: ``IReactorTime`` provider; usually the reactor, when not |
|
44 | 46 | testing. |
@@ -82,6 +84,7 @@
Loading
82 | 84 | ||
83 | 85 | _waiting = attr.ib(default=attr.Factory(list), init=False) |
|
84 | 86 | _issuing = attr.ib(default=attr.Factory(dict), init=False) |
|
87 | + | _cached_client = attr.ib(default=None) |
|
85 | 88 | ready = False |
|
86 | 89 | # Service used to repeatedly call the certificate check and renewal. |
|
87 | 90 | _timer_service = None |
@@ -95,6 +98,29 @@
Loading
95 | 98 | """ |
|
96 | 99 | return clock_now(self._clock) |
|
97 | 100 | ||
101 | + | def _get_client(self): |
|
102 | + | """ |
|
103 | + | Get the client, cache it if it's ready. |
|
104 | + | """ |
|
105 | + | if self._cached_client is not None: |
|
106 | + | return defer.succeed(self._cached_client) |
|
107 | + | client_or_d = self._client |
|
108 | + | if isinstance(client_or_d, defer.Deferred): |
|
109 | + | new_d = defer.Deferred() |
|
110 | + | @client_or_d.addCallback |
|
111 | + | def got_client(final_client): |
|
112 | + | self._cached_client = final_client |
|
113 | + | new_d.callback(final_client) |
|
114 | + | return final_client |
|
115 | + | @client_or_d.addErrback |
|
116 | + | def got_client(error): |
|
117 | + | new_d.errback(error) |
|
118 | + | return error |
|
119 | + | return got_client |
|
120 | + | else: |
|
121 | + | self._cached_client = client_or_d |
|
122 | + | return defer.succeed(client_or_d) |
|
123 | + | ||
98 | 124 | def _check_certs(self): |
|
99 | 125 | """ |
|
100 | 126 | Check all of the certs in the store, and reissue any that are expired |
@@ -199,6 +225,7 @@
Loading
199 | 225 | names = [n.strip() for n in server_names.split(',')] |
|
200 | 226 | return ','.join(names) |
|
201 | 227 | ||
228 | + | @defer.inlineCallbacks |
|
202 | 229 | def _issue_cert(self, server_names): |
|
203 | 230 | """ |
|
204 | 231 | Issue a new cert for the list of server_names. |
@@ -212,40 +239,28 @@
Loading
212 | 239 | server_names=server_names) |
|
213 | 240 | key = self._generate_key() |
|
214 | 241 | objects = [ |
|
215 | - | pem.Key(key.private_bytes( |
|
216 | - | encoding=serialization.Encoding.PEM, |
|
217 | - | format=serialization.PrivateFormat.TraditionalOpenSSL, |
|
218 | - | encryption_algorithm=serialization.NoEncryption()))] |
|
219 | - | ||
220 | - | @defer.inlineCallbacks |
|
221 | - | def answer_to_order(orderr): |
|
222 | - | """ |
|
223 | - | Answer the challenges associated with the order. |
|
224 | - | """ |
|
225 | - | for authorization in orderr.authorizations: |
|
226 | - | yield answer_challenge( |
|
227 | - | authorization, |
|
228 | - | self._client, |
|
229 | - | self._responders, |
|
230 | - | clock=self._clock, |
|
231 | - | ) |
|
232 | - | certificate = yield get_certificate( |
|
233 | - | orderr, self._client, clock=self._clock) |
|
234 | - | defer.returnValue(certificate) |
|
235 | - | ||
236 | - | def got_cert(certr): |
|
237 | - | """ |
|
238 | - | Called when we got a certificate. |
|
239 | - | """ |
|
240 | - | # The certificate is returned as chain. |
|
241 | - | objects.extend(pem.parse(certr.body)) |
|
242 | - | self.cert_store.store(','.join(names), objects) |
|
243 | - | ||
244 | - | return ( |
|
245 | - | self._client.submit_order(key, names) |
|
246 | - | .addCallback(answer_to_order) |
|
247 | - | .addCallback(got_cert) |
|
242 | + | pem.Key( |
|
243 | + | key.private_bytes( |
|
244 | + | encoding=serialization.Encoding.PEM, |
|
245 | + | format=serialization.PrivateFormat.TraditionalOpenSSL, |
|
246 | + | encryption_algorithm=serialization.NoEncryption()) |
|
247 | + | ) |
|
248 | + | ] |
|
249 | + | client = yield self._get_client() |
|
250 | + | orderr = yield client.submit_order(key, names) |
|
251 | + | for authorization in orderr.authorizations: |
|
252 | + | yield answer_challenge( |
|
253 | + | authorization, |
|
254 | + | client, |
|
255 | + | self._responders, |
|
256 | + | clock=self._clock, |
|
248 | 257 | ) |
|
258 | + | certificate = yield get_certificate( |
|
259 | + | orderr, client, clock=self._clock) |
|
260 | + | # The certificate is returned as chain. |
|
261 | + | objects.extend(pem.parse(certr.body)) |
|
262 | + | self.cert_store.store(','.join(names), objects) |
|
263 | + | return certificate |
|
249 | 264 | ||
250 | 265 | def when_certs_valid(self): |
|
251 | 266 | """ |
@@ -268,6 +283,7 @@
Loading
268 | 283 | self._waiting.append(d) |
|
269 | 284 | return d |
|
270 | 285 | ||
286 | + | @defer.inlineCallbacks |
|
271 | 287 | def start(self): |
|
272 | 288 | """ |
|
273 | 289 | Like startService, but will return a deferred once the service was |
@@ -275,16 +291,13 @@
Loading
275 | 291 | """ |
|
276 | 292 | Service.startService(self) |
|
277 | 293 | ||
278 | - | def cb_start(result): |
|
279 | - | """ |
|
280 | - | Called when the client is ready for operation. |
|
281 | - | """ |
|
282 | - | self._timer_service = TimerService( |
|
283 | - | self.check_interval.total_seconds(), self._check_certs) |
|
284 | - | self._timer_service.clock = self._clock |
|
285 | - | self._timer_service.startService() |
|
286 | - | ||
287 | - | return self._client.start(email=self._email).addCallback(cb_start) |
|
294 | + | client = yield self._get_client() |
|
295 | + | result = yield client.start(email=self._email) |
|
296 | + | self._timer_service = TimerService( |
|
297 | + | self.check_interval.total_seconds(), self._check_certs |
|
298 | + | ) |
|
299 | + | self._timer_service.clock = self._clock |
|
300 | + | self._timer_service.startService() |
|
288 | 301 | ||
289 | 302 | def startService(self): |
|
290 | 303 | """ |
@@ -295,26 +308,21 @@
Loading
295 | 308 | """ |
|
296 | 309 | self.start().addErrback(self._panic, 'FAIL-TO-START') |
|
297 | 310 | ||
311 | + | @defer.inlineCallbacks |
|
298 | 312 | def stopService(self): |
|
299 | 313 | Service.stopService(self) |
|
300 | 314 | self.ready = False |
|
301 | 315 | for d in list(self._waiting): |
|
302 | 316 | d.cancel() |
|
303 | 317 | self._waiting = [] |
|
304 | - | ||
305 | - | def stop_timer(ignored): |
|
306 | - | if not self._timer_service: |
|
307 | - | return |
|
308 | - | return self._timer_service.stopService() |
|
309 | - | ||
310 | - | def cleanup(ignored): |
|
311 | - | self._timer_service = None |
|
312 | - | ||
313 | - | return ( |
|
314 | - | self._client.stop() |
|
315 | - | .addBoth(tap(stop_timer)) |
|
316 | - | .addBoth(tap(cleanup)) |
|
317 | - | ) |
|
318 | + | client = yield self._get_client() |
|
319 | + | ||
320 | + | result = yield self._client.stop() |
|
321 | + | if not self._timer_service: |
|
322 | + | return result |
|
323 | + | yield self._timer_service.stopService() |
|
324 | + | self._timer_service = None |
|
325 | + | return result |
|
318 | 326 | ||
319 | 327 | ||
320 | 328 | __all__ = ['AcmeIssuingService'] |
Files | Coverage |
---|---|
src/txacme | 70.80% |
Project Totals (27 files) | 70.80% |
lnx-3.7-py37
lnx-3.8-py38
lnx-3.9-py39
lnx-3.6-py36
lnx-pypy-3.7-pypy3
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file.
The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files.
The size and color of each slice is representing the number of statements and the coverage, respectively.