88using System . Text ;
99using System . Text . Json ;
1010using System . Threading . Tasks ;
11+ using Microsoft . Extensions . Logging ;
1112
1213public class InfobloxDnsProvider : IDnsProvider
1314{
@@ -17,13 +18,15 @@ public class InfobloxDnsProvider : IDnsProvider
1718 private readonly string _wapiVersion ;
1819 private readonly HttpClient _httpClient ;
1920 private readonly JsonSerializerOptions _jsonOptions ;
21+ private readonly ILogger _logger ;
2022
21- public InfobloxDnsProvider ( string host , string username , string password , string wapiVersion = "2.12" , bool ignoreSslErrors = false )
23+ public InfobloxDnsProvider ( string host , string username , string password , string wapiVersion = "2.12" , bool ignoreSslErrors = false , ILogger logger = null )
2224 {
2325 _host = host ? . TrimEnd ( '/' ) ?? throw new ArgumentNullException ( nameof ( host ) ) ;
2426 _username = username ?? throw new ArgumentNullException ( nameof ( username ) ) ;
2527 _password = password ?? throw new ArgumentNullException ( nameof ( password ) ) ;
2628 _wapiVersion = wapiVersion ?? "2.12" ;
29+ _logger = logger ;
2730
2831 var handler = new HttpClientHandler ( ) ;
2932 if ( ignoreSslErrors )
@@ -53,13 +56,15 @@ public async Task<bool> CreateRecordAsync(string recordName, string txtValue)
5356
5457 // Extract the zone from the record name
5558 var zoneName = ExtractZoneFromRecord ( cleanName ) ;
56- Console . WriteLine ( $ "[Infoblox] Extracted zone: { zoneName } from record: { cleanName } " ) ;
59+ _logger ? . LogDebug ( "[Infoblox] Extracted zone: {ZoneName } from record: {RecordName}" , zoneName , cleanName ) ;
5760
5861 // Verify zone exists first
5962 var zoneExists = await VerifyZoneExistsAsync ( zoneName ) ;
6063 if ( ! zoneExists )
6164 {
62- Console . WriteLine ( $ "[Infoblox] WARNING: Zone { zoneName } may not exist or is not accessible") ;
65+ var errorMsg = $ "Infoblox zone '{ zoneName } ' not found or not accessible. Cannot create DNS record '{ cleanName } '. Please verify the zone exists in Infoblox and is configured as an authoritative zone.";
66+ _logger ? . LogError ( "[Infoblox] {ErrorMessage}" , errorMsg ) ;
67+ throw new InvalidOperationException ( errorMsg ) ;
6368 }
6469
6570 // Delete any existing records with the same name first to ensure only one record exists
@@ -78,7 +83,7 @@ public async Task<bool> CreateRecordAsync(string recordName, string txtValue)
7883 if ( ! string . IsNullOrEmpty ( recordRef ) )
7984 {
8085 var deleteResponse = await _httpClient . DeleteAsync ( recordRef ) ;
81- Console . WriteLine ( $ "[Infoblox] Deleted existing TXT record { recordRef } : { deleteResponse . StatusCode } ") ;
86+ _logger ? . LogDebug ( "[Infoblox] Deleted existing TXT record {RecordRef }: {StatusCode}" , recordRef , deleteResponse . StatusCode ) ;
8287 }
8388 }
8489 }
@@ -94,40 +99,51 @@ public async Task<bool> CreateRecordAsync(string recordName, string txtValue)
9499 } ;
95100
96101 var json = JsonSerializer . Serialize ( payload ) ;
97- Console . WriteLine ( $ "[Infoblox] Creating new TXT record. Payload: { json } " ) ;
102+ _logger ? . LogDebug ( "[Infoblox] Creating new TXT record. Payload: {Payload}" , json ) ;
98103
99104 var request = new HttpRequestMessage ( HttpMethod . Post , "./record:txt" ) ;
100105 request . Content = new StringContent ( json , Encoding . UTF8 , "application/json" ) ;
101106
102- Console . WriteLine ( $ "[Infoblox] Request URI: { request . RequestUri } ") ;
107+ _logger ? . LogTrace ( "[Infoblox] Request URI: {RequestUri}" , request . RequestUri ) ;
103108
104109 var response = await _httpClient . SendAsync ( request ) ;
105110 var result = await response . Content . ReadAsStringAsync ( ) ;
106111
107- Console . WriteLine ( $ "[Infoblox] Status: { response . StatusCode } ") ;
108- Console . WriteLine ( $ "[Infoblox] Response: { result } " ) ;
112+ _logger ? . LogDebug ( "[Infoblox] Status: {StatusCode}" , response . StatusCode ) ;
113+ _logger ? . LogTrace ( "[Infoblox] Response: {Response}" , result ) ;
109114
110- if ( response . IsSuccessStatusCode )
115+ if ( ! response . IsSuccessStatusCode )
111116 {
112- // Verify the record was created by searching for it
113- await Task . Delay ( 1000 ) ; // Brief delay to ensure record is committed
114- var verifySuccess = await VerifyRecordExists ( cleanName , txtValue ) ;
115- if ( verifySuccess )
116- {
117- Console . WriteLine ( $ "[Infoblox] ✓ Verified TXT record exists: { cleanName } ") ;
118- }
119- else
120- {
121- Console . WriteLine ( $ "[Infoblox] ⚠ WARNING: Record creation returned success, but verification failed for { cleanName } ") ;
122- }
117+ // Include detailed error information in the exception
118+ var errorDetails = $ "Infoblox API returned { response . StatusCode } . Zone: { zoneName } , Record: { cleanName } , Response: { result } ";
119+ throw new InvalidOperationException ( errorDetails ) ;
123120 }
124121
125- return response . IsSuccessStatusCode ;
122+ // Verify the record was created by searching for it
123+ await Task . Delay ( 1000 ) ; // Brief delay to ensure record is committed
124+ var verifySuccess = await VerifyRecordExists ( cleanName , txtValue ) ;
125+ if ( verifySuccess )
126+ {
127+ _logger ? . LogDebug ( "[Infoblox] Verified TXT record exists: {RecordName}" , cleanName ) ;
128+ }
129+ else
130+ {
131+ _logger ? . LogWarning ( "[Infoblox] Record creation returned success, but verification failed for {RecordName}" , cleanName ) ;
132+ throw new InvalidOperationException ( $ "Infoblox record verification failed for { cleanName } . Record was created but could not be found when querying back.") ;
133+ }
134+
135+ return true ;
136+ }
137+ catch ( InvalidOperationException )
138+ {
139+ // Re-throw our specific exceptions with detailed error messages
140+ throw ;
126141 }
127142 catch ( Exception ex )
128143 {
129- Console . WriteLine ( $ "[Infoblox] ERROR: { ex . Message } ") ;
130- return false ;
144+ // Wrap unexpected exceptions with context
145+ _logger ? . LogError ( ex , "[Infoblox] DNS provider error" ) ;
146+ throw new InvalidOperationException ( $ "Infoblox DNS provider error: { ex . Message } ", ex ) ;
131147 }
132148 }
133149
@@ -141,7 +157,7 @@ public async Task<bool> DeleteRecordAsync(string recordName)
141157 var searchResponse = await _httpClient . GetAsync ( searchUrl ) ;
142158 if ( ! searchResponse . IsSuccessStatusCode )
143159 {
144- Console . WriteLine ( $ "[Infoblox] Failed to search for record: { searchResponse . StatusCode } ") ;
160+ _logger ? . LogDebug ( "[Infoblox] Failed to search for record: {StatusCode}" , searchResponse . StatusCode ) ;
145161 return false ;
146162 }
147163
@@ -150,26 +166,26 @@ public async Task<bool> DeleteRecordAsync(string recordName)
150166
151167 if ( records . GetArrayLength ( ) == 0 )
152168 {
153- Console . WriteLine ( $ "[Infoblox] No TXT records found for { cleanName } " ) ;
169+ _logger ? . LogDebug ( "[Infoblox] No TXT records found for {RecordName}" , cleanName ) ;
154170 return false ;
155171 }
156172
157173 var recordRef = records [ 0 ] . GetProperty ( "_ref" ) . GetString ( ) ;
158174 if ( string . IsNullOrEmpty ( recordRef ) )
159175 {
160- Console . WriteLine ( $ "[Infoblox] Record reference is null or empty") ;
176+ _logger ? . LogDebug ( "[Infoblox] Record reference is null or empty" ) ;
161177 return false ;
162178 }
163179
164180 var deleteResponse = await _httpClient . DeleteAsync ( recordRef ) ;
165181 var result = await deleteResponse . Content . ReadAsStringAsync ( ) ;
166182
167- Console . WriteLine ( $ "[Infoblox] Delete TXT: { deleteResponse . StatusCode } - { result } " ) ;
183+ _logger ? . LogDebug ( "[Infoblox] Delete TXT: {StatusCode} - {Result}" , deleteResponse . StatusCode , result ) ;
168184 return deleteResponse . IsSuccessStatusCode ;
169185 }
170186 catch ( Exception ex )
171187 {
172- Console . WriteLine ( $ "[Infoblox] Error deleting TXT record: { ex . Message } ") ;
188+ _logger ? . LogError ( ex , "[Infoblox] Error deleting TXT record" ) ;
173189 return false ;
174190 }
175191 }
@@ -196,20 +212,20 @@ private async Task<bool> VerifyZoneExistsAsync(string zoneName)
196212
197213 if ( ! response . IsSuccessStatusCode )
198214 {
199- Console . WriteLine ( $ "[Infoblox] Zone lookup failed: { response . StatusCode } ") ;
215+ _logger ? . LogDebug ( "[Infoblox] Zone lookup failed: {StatusCode}" , response . StatusCode ) ;
200216 return false ;
201217 }
202218
203219 var json = await response . Content . ReadAsStringAsync ( ) ;
204220 var zones = JsonDocument . Parse ( json ) . RootElement ;
205221 var zoneExists = zones . GetArrayLength ( ) > 0 ;
206222
207- Console . WriteLine ( $ "[Infoblox] Zone { zoneName } exists: { zoneExists } " ) ;
223+ _logger ? . LogDebug ( "[Infoblox] Zone {ZoneName } exists: {ZoneExists}" , zoneName , zoneExists ) ;
208224 return zoneExists ;
209225 }
210226 catch ( Exception ex )
211227 {
212- Console . WriteLine ( $ "[Infoblox] Error verifying zone: { ex . Message } ") ;
228+ _logger ? . LogError ( ex , "[Infoblox] Error verifying zone" ) ;
213229 return false ;
214230 }
215231 }
@@ -242,7 +258,7 @@ private async Task<bool> VerifyRecordExists(string recordName, string expectedVa
242258 }
243259 catch ( Exception ex )
244260 {
245- Console . WriteLine ( $ "[Infoblox] Error verifying record: { ex . Message } ") ;
261+ _logger ? . LogError ( ex , "[Infoblox] Error verifying record" ) ;
246262 return false ;
247263 }
248264 }
0 commit comments