@@ -106,12 +106,38 @@ def install_plugin(self) -> bool:
106106 test_result = subprocess .run (test_cmd , capture_output = True , text = True , timeout = 10 )
107107
108108 if test_result .returncode == 0 and "dns-namecheap" in test_result .stdout :
109- print (f"Plugin { self .provider .CERTBOT_PLUGIN } is available in certbot" )
109+ print (f"✓ Plugin { self .provider .CERTBOT_PLUGIN } is available in certbot" )
110110 return True
111111 else :
112112 print (f"Warning: dns-namecheap plugin not found in certbot plugins list" )
113113 if test_result .stderr :
114114 print (f"Plugin test stderr: { test_result .stderr } " )
115+
116+ # Debug plugin registration
117+ self ._debug_plugin_registration ()
118+
119+ # Try force reinstall to fix plugin registration
120+ print ("Attempting to fix plugin registration..." )
121+ try :
122+ import sys
123+ force_cmd = [sys .executable , "-m" , "pip" , "install" , "--force-reinstall" ,
124+ "--no-deps" , self .provider .CERTBOT_PACKAGE ]
125+ print (f"Running: { ' ' .join (force_cmd )} " )
126+ force_result = subprocess .run (force_cmd , capture_output = True , text = True )
127+
128+ if force_result .returncode == 0 :
129+ # Test again after reinstall
130+ retest_result = subprocess .run (test_cmd , capture_output = True , text = True , timeout = 10 )
131+ if retest_result .returncode == 0 and "dns-namecheap" in retest_result .stdout :
132+ print (f"✓ Plugin registration fixed after reinstall" )
133+ return True
134+ else :
135+ print (f"Plugin still not registered, may work anyway" )
136+ else :
137+ print (f"Force reinstall failed: { force_result .stderr } " )
138+ except Exception as fix_error :
139+ print (f"Plugin fix attempt failed: { fix_error } " )
140+
115141 # Continue anyway - may work in Docker environments
116142 return True
117143
@@ -121,6 +147,45 @@ def install_plugin(self) -> bool:
121147
122148 return True
123149
150+ def _debug_plugin_registration (self ) -> None :
151+ """Debug why plugin is not being registered by certbot."""
152+ try :
153+ import pkg_resources
154+ print ("=== Plugin Registration Debug ===" )
155+
156+ # Check entry points
157+ try :
158+ entry_points = list (pkg_resources .iter_entry_points ('certbot.plugins' ))
159+ print (f"Found { len (entry_points )} certbot plugins:" )
160+ for ep in entry_points :
161+ print (f" - { ep .name } : { ep .module_name } " )
162+
163+ # Look specifically for dns-namecheap
164+ namecheap_eps = [ep for ep in entry_points if ep .name == 'dns-namecheap' ]
165+ if namecheap_eps :
166+ print (f"✓ Found dns-namecheap entry point: { namecheap_eps [0 ]} " )
167+ else :
168+ print (f"✗ dns-namecheap entry point not found" )
169+ except Exception as ep_error :
170+ print (f"Entry point check failed: { ep_error } " )
171+
172+ # Check if certbot can import the plugin module
173+ try :
174+ from certbot_dns_namecheap import dns_namecheap
175+ print (f"✓ Plugin module can be imported" )
176+
177+ # Check if it has the right class
178+ if hasattr (dns_namecheap , 'Authenticator' ):
179+ print (f"✓ Authenticator class found" )
180+ else :
181+ print (f"✗ Authenticator class not found" )
182+ except Exception as import_error :
183+ print (f"✗ Plugin module import failed: { import_error } " )
184+
185+ print ("=== End Debug ===" )
186+ except Exception as debug_error :
187+ print (f"Debug failed: { debug_error } " )
188+
124189 def _validate_provider_credentials (self ) -> bool :
125190 """Validate provider credentials by testing API access."""
126191 print (f"Validating { self .provider_type } API credentials..." )
@@ -204,10 +269,24 @@ def obtain_certificate(self, domain: str, email: str) -> bool:
204269 return True
205270 else :
206271 print (f"✗ Certificate obtaining failed (exit code: { result .returncode } )" )
207- if result .stderr .strip ():
208- print (f"Error details: { result .stderr .strip ()} " )
209- if result .stdout .strip ():
210- print (f"Output: { result .stdout .strip ()} " )
272+
273+ # Check for specific error patterns
274+ error_output = result .stderr .strip () if result .stderr else ""
275+ stdout_output = result .stdout .strip () if result .stdout else ""
276+
277+ if "unrecognized arguments" in error_output :
278+ print (f"Plugin arguments not recognized by certbot" )
279+ print (f"This suggests the plugin is not properly registered" )
280+ elif "DNS problem" in error_output or "DNS problem" in stdout_output :
281+ print (f"DNS validation failed - check domain configuration" )
282+ elif "Rate limited" in error_output or "Rate limited" in stdout_output :
283+ print (f"Rate limited by Let's Encrypt" )
284+
285+ if error_output :
286+ print (f"stderr: { error_output } " )
287+ if stdout_output :
288+ print (f"stdout: { stdout_output } " )
289+
211290 return False
212291
213292 except subprocess .TimeoutExpired :
@@ -233,9 +312,31 @@ def renew_certificate(self, domain: str) -> Tuple[bool, bool]:
233312 cmd = self ._build_certbot_command ("renew" , domain , "" )
234313
235314 try :
236- result = subprocess .run (cmd , capture_output = True , text = True )
237- if result .returncode != 0 :
238- print (f"Certificate renewal failed: { result .stderr } " , file = sys .stderr )
315+ result = subprocess .run (cmd , capture_output = True , text = True , timeout = 300 )
316+
317+ if result .returncode == 0 :
318+ print (f"✓ Certificate renewal completed" )
319+ return True , True
320+ else :
321+ error_output = result .stderr .strip () if result .stderr else ""
322+ stdout_output = result .stdout .strip () if result .stdout else ""
323+
324+ print (f"✗ Certificate renewal failed (exit code: { result .returncode } )" )
325+
326+ # Check for specific error patterns
327+ if "unrecognized arguments" in error_output :
328+ print (f"Plugin arguments not recognized by certbot" )
329+ elif "No renewals were attempted" in stdout_output :
330+ print (f"No certificates need renewal" )
331+ return True , False # Success but no renewal needed
332+ elif "DNS problem" in error_output or "DNS problem" in stdout_output :
333+ print (f"DNS validation failed during renewal" )
334+
335+ if error_output :
336+ print (f"stderr: { error_output } " )
337+ if stdout_output :
338+ print (f"stdout: { stdout_output } " )
339+
239340 return False , False
240341
241342 # Check if no renewals were needed
0 commit comments