@@ -81,226 +81,135 @@ def install_plugin(self) -> bool:
8181
8282 print (f"Successfully installed { self .provider .CERTBOT_PACKAGE } " )
8383
84- # Add diagnostic information
84+ # Diagnostic information for troubleshooting
8585 try :
86- print ("=== Diagnostic Information ===" )
87- # Check which Python executable is being used
8886 import sys
89- print (f"Python executable: { sys .executable } " )
90- print (f"Python version: { sys .version } " )
91-
92- # Check where the package was installed
9387 import pkg_resources
88+ print (f"Installed to Python: { sys .executable } " )
89+
9490 try :
9591 dist = pkg_resources .get_distribution ("certbot-dns-namecheap" )
96- print (f"Package location: { dist .location } " )
97- print (f"Package version: { dist .version } " )
92+ print (f"Package version: { dist .version } at { dist .location } " )
9893 except pkg_resources .DistributionNotFound :
99- print ("Package not found in current environment" )
100-
101- # Check sys.path
102- print (f"Python path: { sys .path [:3 ]} ..." )
103- print ("=== End Diagnostic Information ===" )
94+ print ("Warning: Package not found in current environment" )
10495 except Exception as diag_error :
10596 print (f"Diagnostic error: { diag_error } " )
10697
107- # For Docker environments, we need to check if the plugin is actually usable
108- # Try a direct test of the plugin functionality
98+ # Verify plugin installation
10999 try :
110100 if self .provider .CERTBOT_PLUGIN == "dns-namecheap" :
111101 import certbot_dns_namecheap .dns_namecheap
112102 print (f"Plugin { self .provider .CERTBOT_PLUGIN } successfully imported" )
113103
114- # Try to create a simple test to see if the plugin works
115- print (f"Testing if plugin { self .provider .CERTBOT_PLUGIN } is available..." )
104+ # Test if plugin is recognized by certbot
116105 test_cmd = ["certbot" , "plugins" ]
117106 test_result = subprocess .run (test_cmd , capture_output = True , text = True , timeout = 10 )
118107
119- print (f"Certbot plugins command returned: { test_result .returncode } " )
120- if test_result .stdout :
121- print (f"Available plugins:" )
122- print (test_result .stdout )
123-
124- if test_result .stderr :
125- print (f"Plugin test stderr: { test_result .stderr } " )
126-
127108 if test_result .returncode == 0 and "dns-namecheap" in test_result .stdout :
128- print (f"Plugin { self .provider .CERTBOT_PLUGIN } is available and working correctly " )
109+ print (f"Plugin { self .provider .CERTBOT_PLUGIN } is available in certbot " )
129110 return True
130111 else :
131- print (f"Plugin { self .provider .CERTBOT_PLUGIN } may not be properly installed" )
132- if "dns-namecheap" not in test_result .stdout :
133- print (f"Warning: dns-namecheap plugin not found in certbot plugins list" )
134-
135- # Try some additional fixes
136- print ("Attempting additional fixes..." )
137-
138- # Try to reload Python modules
139- try :
140- import importlib
141- import certbot_dns_namecheap
142- importlib .reload (certbot_dns_namecheap )
143- print ("Reloaded certbot_dns_namecheap module" )
144- except Exception as reload_error :
145- print (f"Module reload failed: { reload_error } " )
146-
147- # Try installing with --force-reinstall
148- try :
149- print ("Trying force reinstall..." )
150- import sys
151- force_cmd = [sys .executable , "-m" , "pip" , "install" , "--force-reinstall" , self .provider .CERTBOT_PACKAGE ]
152- print (f"Force reinstall command: { ' ' .join (force_cmd )} " )
153- force_result = subprocess .run (force_cmd , capture_output = True , text = True )
154- if force_result .returncode == 0 :
155- print ("Force reinstall succeeded" )
156- else :
157- print (f"Force reinstall failed: { force_result .stderr } " )
158- except Exception as force_error :
159- print (f"Force reinstall error: { force_error } " )
160-
161- # Test plugins again after fixes
162- print ("Testing plugins again after fixes..." )
163- retest_cmd = ["certbot" , "plugins" ]
164- retest_result = subprocess .run (retest_cmd , capture_output = True , text = True , timeout = 10 )
165- if retest_result .returncode == 0 and "dns-namecheap" in retest_result .stdout :
166- print (f"Plugin { self .provider .CERTBOT_PLUGIN } is now available after fixes!" )
167- return True
168-
169- # In Docker environments, this might still work in practice
170- print ("Continuing anyway - plugin may work in actual certbot execution" )
112+ print (f"Warning: dns-namecheap plugin not found in certbot plugins list" )
113+ if test_result .stderr :
114+ print (f"Plugin test stderr: { test_result .stderr } " )
115+ # Continue anyway - may work in Docker environments
171116 return True
172117
173118 except Exception as e :
174- print (f"Plugin test warning: { e } " )
175- # Continue anyway - the plugin may still work
119+ print (f"Plugin verification warning: { e } " )
176120 return True
177121
178122 return True
179123
124+ def _validate_provider_credentials (self ) -> bool :
125+ """Validate provider credentials by testing API access."""
126+ print (f"Validating { self .provider_type } API credentials..." )
127+
128+ try :
129+ # For Namecheap, test API access
130+ if hasattr (self .provider , '_make_request' ):
131+ test_result = self .provider ._make_request ("namecheap.users.getBalances" )
132+ if test_result .get ("success" , False ):
133+ print (f"✓ { self .provider_type } API credentials are valid" )
134+ return True
135+ else :
136+ print (f"✗ { self .provider_type } API validation failed: { test_result .get ('errors' , ['Unknown error' ])} " )
137+ return False
138+ else :
139+ print (f"No API validation available for { self .provider_type } , skipping" )
140+ return True
141+ except Exception as e :
142+ print (f"Error validating { self .provider_type } credentials: { e } " )
143+ return False
144+
180145 def setup_credentials (self ) -> bool :
181146 """Setup credentials file for certbot using provider implementation."""
182- print (f"Setting up credentials for { self .provider_type } provider" )
183147 result = self .provider .setup_certbot_credentials ()
184- if result :
185- print (f"Credentials setup successful for { self .provider_type } " )
186- else :
187- print (f"Credentials setup failed for { self .provider_type } " )
148+ if not result :
149+ print (f"Failed to setup credentials file for { self .provider_type } " )
188150 return result
189151
190152 def _build_certbot_command (self , action : str , domain : str , email : str ) -> List [str ]:
191153 """Build certbot command using provider configuration."""
192- print (f"Building certbot command for action: { action } , domain: { domain } " )
193-
194154 plugin = self .provider .CERTBOT_PLUGIN
195- print (f"Using plugin: { plugin } " )
196-
197155 if not plugin :
198156 raise ValueError (f"No certbot plugin configured for { self .provider_type } " )
199157
200- propagation_seconds = self .provider .CERTBOT_PROPAGATION_SECONDS
201- print (f"Propagation seconds configured: { propagation_seconds } " )
202-
203- base_cmd = ["certbot" , action ]
158+ base_cmd = ["certbot" , action , "-a" , plugin , "--non-interactive" , "-v" ]
204159
205- # Add DNS plugin configuration
206- base_cmd .extend (
207- [
208- "-a" , plugin ,
209- "--non-interactive" ,
210- "-v" , # Add verbose flag for detailed output
211- ]
212- )
213- print (f"Added plugin and non-interactive flags" )
214-
215- # Add credentials file if provider has one configured
160+ # Add credentials file if configured
216161 if self .provider .CERTBOT_CREDENTIALS_FILE :
217- credentials_file = os .path .expanduser (
218- self .provider .CERTBOT_CREDENTIALS_FILE
219- )
220- print (f"Credentials file path (expanded): { credentials_file } " )
221-
162+ credentials_file = os .path .expanduser (self .provider .CERTBOT_CREDENTIALS_FILE )
222163 if os .path .exists (credentials_file ):
223- credentials_arg = f"--{ plugin } -credentials={ credentials_file } "
224- base_cmd .extend ([credentials_arg ])
225- print (f"Added credentials argument: { credentials_arg } " )
164+ base_cmd .extend ([f"--{ plugin } -credentials={ credentials_file } " ])
226165 else :
227- print (f"Warning: Credentials file does not exist: { credentials_file } " )
228- else :
229- print (f"No credentials file configured for provider" )
166+ raise ValueError (f"Credentials file does not exist: { credentials_file } " )
230167
231168 if action == "certonly" :
232- base_cmd .extend (
233- ["--agree-tos" , "--no-eff-email" , "--email" , email , "-d" , domain ]
234- )
235- print (f"Added certonly-specific arguments" )
169+ base_cmd .extend (["--agree-tos" , "--no-eff-email" , "--email" , email , "-d" , domain ])
236170
237- # Print the final command with masked email
238- masked_cmd = []
239- for i , arg in enumerate (base_cmd ):
240- if i > 0 and base_cmd [i - 1 ] == "--email" :
241- masked_cmd .append ("<email>" )
242- else :
243- masked_cmd .append (arg )
244- print (f"Final certbot command: { ' ' .join (masked_cmd )} " )
171+ # Log command with masked email for debugging
172+ masked_cmd = [arg if not (i > 0 and base_cmd [i - 1 ] == "--email" ) else "<email>"
173+ for i , arg in enumerate (base_cmd )]
174+ print (f"Executing: { ' ' .join (masked_cmd )} " )
245175
246176 return base_cmd
247177
248178 def obtain_certificate (self , domain : str , email : str ) -> bool :
249179 """Obtain a new certificate for the domain."""
250- print (f"Starting certificate obtaining process for { domain } using { self .provider_type } " )
180+ print (f"Obtaining certificate for { domain } using { self .provider_type } " )
251181
252182 # Ensure plugin is installed
253- print (f"Checking plugin installation..." )
254183 if not self .install_plugin ():
255184 print (f"Failed to install plugin for { self .provider_type } " , file = sys .stderr )
256185 return False
257- print (f"Plugin installation completed" )
258186
259- # Check if credentials are set up
260- print (f"Checking credentials setup..." )
187+ # Validate credentials before proceeding
188+ if not self ._validate_provider_credentials ():
189+ print (f"Failed to validate credentials for { self .provider_type } " , file = sys .stderr )
190+ return False
191+
192+ # Setup credentials file
261193 if not self .setup_credentials ():
262194 print (f"Failed to setup credentials for { self .provider_type } " , file = sys .stderr )
263195 return False
264- print (f"Credentials setup completed" )
265196
266- # Check certbot version for debugging
267- try :
268- version_cmd = ["certbot" , "--version" ]
269- version_result = subprocess .run (version_cmd , capture_output = True , text = True , timeout = 10 )
270- if version_result .returncode == 0 :
271- print (f"Certbot version: { version_result .stdout .strip ()} " )
272- else :
273- print (f"Could not determine certbot version" )
274- except Exception as e :
275- print (f"Error checking certbot version: { e } " )
276-
277197 cmd = self ._build_certbot_command ("certonly" , domain , email )
278- print (f"Executing certbot command..." )
279198
280199 try :
281200 result = subprocess .run (cmd , capture_output = True , text = True , timeout = 300 )
282201
283- print (f"Certbot command completed with return code: { result .returncode } " )
284-
285- # Always print stdout if available
286- if result .stdout .strip ():
287- print (f"=== Certbot stdout ===" )
288- print (result .stdout )
289- print (f"=== End stdout ===" )
290-
291- # Always print stderr if available
292- if result .stderr .strip ():
293- print (f"=== Certbot stderr ===" , file = sys .stderr )
294- print (result .stderr , file = sys .stderr )
295- print (f"=== End stderr ===" , file = sys .stderr )
296-
297- if result .returncode != 0 :
298- print (f"Certificate obtaining failed with return code { result .returncode } " )
202+ if result .returncode == 0 :
203+ print (f"✓ Certificate obtained successfully for { domain } " )
204+ return True
205+ else :
206+ 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 ()} " )
299211 return False
300212
301- print (f"Certificate obtained successfully for { domain } " )
302- return True
303-
304213 except subprocess .TimeoutExpired :
305214 print (f"Certbot command timed out after 300 seconds" , file = sys .stderr )
306215 return False
@@ -316,12 +225,10 @@ def renew_certificate(self, domain: str) -> Tuple[bool, bool]:
316225 """
317226 print (f"Renewing certificate using { self .provider_type } " )
318227
319- # Ensure plugin is installed for renewal too
320- print (f"Checking plugin installation for renewal..." )
228+ # Ensure plugin is installed
321229 if not self .install_plugin ():
322- print (f"Failed to install plugin for renewal for { self . provider_type } " , file = sys .stderr )
230+ print (f"Failed to install plugin for renewal" , file = sys .stderr )
323231 return False , False
324- print (f"Plugin installation completed for renewal" )
325232
326233 cmd = self ._build_certbot_command ("renew" , domain , "" )
327234
0 commit comments