@@ -24,63 +24,127 @@ const (
24
24
DefaultTimeout = 10 * time .Second
25
25
)
26
26
27
- // SetClientConfiguration initializes and configures the HTTP client based on the provided configuration file path and logger.
28
- // It loads configuration values from environment variables and, if necessary, from the provided file path.
29
- // Default values are set for any missing configuration options, and a final check is performed to ensure completeness.
30
- // If any essential configuration values are still missing after setting defaults, it returns an error.
31
- func SetClientConfiguration (configFilePath string ) (* ClientConfig , error ) {
32
- config := & ClientConfig {}
33
-
34
- // Load config values from environment variables
35
- loadConfigFromEnv (config )
36
-
37
- // Load config values from file if necessary
38
- if validateConfigCompletion (config ) && configFilePath != "" {
39
- log .Printf ("Configuration values are incomplete from environment variables, attempting to load from config file: %s" , configFilePath )
40
- if err := config .loadConfigFromFile (configFilePath ); err != nil {
41
- log .Printf ("Failed to load configuration from file: %s, error: %v" , configFilePath , err )
42
- return nil , err
27
+ // loadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
28
+ // It opens the specified configuration file, reads its content, and unmarshals the JSON data
29
+ // into the ClientConfig struct. This function is crucial for initializing the client configuration
30
+ // with values that may not be provided through environment variables or default values.
31
+ // It uses Go's standard log package for logging, as the zap logger is not yet initialized when
32
+ // this function is called.
33
+ func (config * ClientConfig ) LoadConfigFromFile (filePath string ) error {
34
+ // Open the configuration file
35
+ file , err := os .Open (filePath )
36
+ if err != nil {
37
+ log .Printf ("Failed to open the configuration file: %s, error: %v" , filePath , err )
38
+ return err
39
+ }
40
+ defer file .Close ()
41
+
42
+ reader := bufio .NewReader (file )
43
+ var builder strings.Builder
44
+
45
+ // Read the file content
46
+ for {
47
+ part , _ , err := reader .ReadLine ()
48
+ if err == io .EOF {
49
+ break
43
50
}
51
+ if err != nil {
52
+ log .Printf ("Failed to read the configuration file: %s, error: %v" , filePath , err )
53
+ return err
54
+ }
55
+ builder .Write (part )
44
56
}
45
57
58
+ // Unmarshal JSON content into the ClientConfig struct
59
+ err = json .Unmarshal ([]byte (builder .String ()), config )
60
+ if err != nil {
61
+ log .Printf ("Failed to unmarshal the configuration file: %s, error: %v" , filePath , err )
62
+ return err
63
+ }
64
+
65
+ log .Printf ("Configuration successfully loaded from file: %s" , filePath )
66
+
46
67
// Set default values if necessary
47
68
setLoggerDefaultValues (config )
48
69
setClientDefaultValues (config )
49
70
50
- // Recheck if config values are still incomplete after setting defaults
51
- if validateConfigCompletion (config ) {
52
- return nil , fmt .Errorf ("incomplete configuration values even after setting defaults" )
71
+ // validate configuration
72
+ if err := validateMandatoryConfiguration (config ); err != nil {
73
+ return fmt .Errorf ("configuration validation failed: %w" , err )
53
74
}
54
75
55
- return config , nil
76
+ return nil
56
77
}
57
78
58
- // loadConfigFromEnv populates the ClientConfig structure with values from environment variables.
79
+ // LoadConfigFromEnv populates the ClientConfig structure with values from environment variables.
59
80
// It updates the configuration for authentication, environment specifics, and client options
60
81
// based on the presence of environment variables. For each configuration option, if an environment
61
82
// variable is set, its value is used; otherwise, the existing value in the ClientConfig structure
62
- // is retained.
63
- func loadConfigFromEnv (config * ClientConfig ) {
83
+ // is retained. It also sets default values if necessary and validates the final configuration,
84
+ // returning an error if the configuration is incomplete.
85
+ func LoadConfigFromEnv (config * ClientConfig ) (* ClientConfig , error ) {
86
+ if config == nil {
87
+ config = & ClientConfig {} // Initialize config if nil
88
+ }
89
+
64
90
// AuthConfig
65
91
config .Auth .ClientID = getEnvOrDefault ("CLIENT_ID" , config .Auth .ClientID )
92
+ log .Printf ("ClientID env value found and set to: %s" , config .Auth .ClientID )
93
+
66
94
config .Auth .ClientSecret = getEnvOrDefault ("CLIENT_SECRET" , config .Auth .ClientSecret )
95
+ log .Printf ("ClientSecret env value found and set" )
67
96
68
97
// EnvironmentConfig
69
98
config .Environment .InstanceName = getEnvOrDefault ("INSTANCE_NAME" , config .Environment .InstanceName )
99
+ log .Printf ("InstanceName env value found and set to: %s" , config .Environment .InstanceName )
100
+
70
101
config .Environment .OverrideBaseDomain = getEnvOrDefault ("OVERRIDE_BASE_DOMAIN" , config .Environment .OverrideBaseDomain )
102
+ log .Printf ("OverrideBaseDomain env value found and set to: %s" , config .Environment .OverrideBaseDomain )
103
+
71
104
config .Environment .APIType = getEnvOrDefault ("API_TYPE" , config .Environment .APIType )
105
+ log .Printf ("APIType env value found and set to: %s" , config .Environment .APIType )
72
106
73
107
// ClientOptions
74
108
config .ClientOptions .LogLevel = getEnvOrDefault ("LOG_LEVEL" , config .ClientOptions .LogLevel )
109
+ log .Printf ("LogLevel env value found and set to: %s" , config .ClientOptions .LogLevel )
110
+
75
111
config .ClientOptions .LogOutputFormat = getEnvOrDefault ("LOG_OUTPUT_FORMAT" , config .ClientOptions .LogOutputFormat )
112
+ log .Printf ("LogOutputFormat env value found and set to: %s" , config .ClientOptions .LogOutputFormat )
113
+
76
114
config .ClientOptions .LogConsoleSeparator = getEnvOrDefault ("LOG_CONSOLE_SEPARATOR" , config .ClientOptions .LogConsoleSeparator )
115
+ log .Printf ("LogConsoleSeparator env value found and set to: %s" , config .ClientOptions .LogConsoleSeparator )
116
+
77
117
config .ClientOptions .HideSensitiveData = parseBool (getEnvOrDefault ("HIDE_SENSITIVE_DATA" , strconv .FormatBool (config .ClientOptions .HideSensitiveData )))
118
+ log .Printf ("HideSensitiveData env value found and set to: %t" , config .ClientOptions .HideSensitiveData )
119
+
78
120
config .ClientOptions .MaxRetryAttempts = parseInt (getEnvOrDefault ("MAX_RETRY_ATTEMPTS" , strconv .Itoa (config .ClientOptions .MaxRetryAttempts )), DefaultMaxRetryAttempts )
121
+ log .Printf ("MaxRetryAttempts env value found and set to: %d" , config .ClientOptions .MaxRetryAttempts )
122
+
79
123
config .ClientOptions .EnableDynamicRateLimiting = parseBool (getEnvOrDefault ("ENABLE_DYNAMIC_RATE_LIMITING" , strconv .FormatBool (config .ClientOptions .EnableDynamicRateLimiting )))
124
+ log .Printf ("EnableDynamicRateLimiting env value found and set to: %t" , config .ClientOptions .EnableDynamicRateLimiting )
125
+
80
126
config .ClientOptions .MaxConcurrentRequests = parseInt (getEnvOrDefault ("MAX_CONCURRENT_REQUESTS" , strconv .Itoa (config .ClientOptions .MaxConcurrentRequests )), DefaultMaxConcurrentRequests )
127
+ log .Printf ("MaxConcurrentRequests env value found and set to: %d" , config .ClientOptions .MaxConcurrentRequests )
128
+
81
129
config .ClientOptions .TokenRefreshBufferPeriod = parseDuration (getEnvOrDefault ("TOKEN_REFRESH_BUFFER_PERIOD" , config .ClientOptions .TokenRefreshBufferPeriod .String ()), DefaultTokenBufferPeriod )
130
+ log .Printf ("TokenRefreshBufferPeriod env value found and set to: %s" , config .ClientOptions .TokenRefreshBufferPeriod )
131
+
82
132
config .ClientOptions .TotalRetryDuration = parseDuration (getEnvOrDefault ("TOTAL_RETRY_DURATION" , config .ClientOptions .TotalRetryDuration .String ()), DefaultTotalRetryDuration )
133
+ log .Printf ("TotalRetryDuration env value found and set to: %s" , config .ClientOptions .TotalRetryDuration )
134
+
83
135
config .ClientOptions .CustomTimeout = parseDuration (getEnvOrDefault ("CUSTOM_TIMEOUT" , config .ClientOptions .CustomTimeout .String ()), DefaultTimeout )
136
+ log .Printf ("CustomTimeout env value found and set to: %s" , config .ClientOptions .CustomTimeout )
137
+
138
+ // Set default values if necessary
139
+ setLoggerDefaultValues (config )
140
+ setClientDefaultValues (config )
141
+
142
+ // Validate final configuration
143
+ if err := validateMandatoryConfiguration (config ); err != nil {
144
+ return nil , err // Return the error if the configuration is incomplete
145
+ }
146
+
147
+ return config , nil
84
148
}
85
149
86
150
// Helper function to get environment variable or default value
@@ -118,14 +182,42 @@ func parseDuration(value string, defaultVal time.Duration) time.Duration {
118
182
return result
119
183
}
120
184
121
- // validateConfigCompletion checks if any essential configuration fields are missing,
122
- // indicating the configuration might be incomplete and may require loading from additional sources.
123
- func validateConfigCompletion (config * ClientConfig ) bool {
124
- // Check if essential fields are missing; additional fields can be checked as needed
125
- return config .Auth .ClientID == "" || config .Auth .ClientSecret == "" ||
126
- config .Environment .InstanceName == "" || config .Environment .APIType == "" ||
127
- config .ClientOptions .LogLevel == "" || config .ClientOptions .LogOutputFormat == "" ||
128
- config .ClientOptions .LogConsoleSeparator == ""
185
+ // validateMandatoryConfiguration checks if any essential configuration fields are missing,
186
+ // and returns an error with details about the missing configurations.
187
+ // This ensures the caller can understand what specific configurations need attention.
188
+ func validateMandatoryConfiguration (config * ClientConfig ) error {
189
+ var missingFields []string
190
+
191
+ // Check for missing mandatory fields and add them to the missingFields slice if necessary.
192
+ if config .Auth .ClientID == "" {
193
+ missingFields = append (missingFields , "Auth.ClientID" )
194
+ }
195
+ if config .Auth .ClientSecret == "" {
196
+ missingFields = append (missingFields , "Auth.ClientSecret" )
197
+ }
198
+ if config .Environment .InstanceName == "" {
199
+ missingFields = append (missingFields , "Environment.InstanceName" )
200
+ }
201
+ if config .Environment .APIType == "" {
202
+ missingFields = append (missingFields , "Environment.APIType" )
203
+ }
204
+ if config .ClientOptions .LogLevel == "" {
205
+ missingFields = append (missingFields , "ClientOptions.LogLevel" )
206
+ }
207
+ if config .ClientOptions .LogOutputFormat == "" {
208
+ missingFields = append (missingFields , "ClientOptions.LogOutputFormat" )
209
+ }
210
+ if config .ClientOptions .LogConsoleSeparator == "" {
211
+ missingFields = append (missingFields , "ClientOptions.LogConsoleSeparator" )
212
+ }
213
+
214
+ // If there are missing fields, return an error detailing what is missing.
215
+ if len (missingFields ) > 0 {
216
+ return fmt .Errorf ("mandatory configuration missing: %s" , strings .Join (missingFields , ", " ))
217
+ }
218
+
219
+ // If no fields are missing, return nil indicating the configuration is complete.
220
+ return nil
129
221
}
130
222
131
223
// setClientDefaultValues sets default values for the client configuration options if none are provided.
@@ -186,45 +278,3 @@ func setLoggerDefaultValues(config *ClientConfig) {
186
278
// Log completion of setting default values
187
279
log .Println ("Default values set for logger configuration" )
188
280
}
189
-
190
- // loadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
191
- // It opens the specified configuration file, reads its content, and unmarshals the JSON data
192
- // into the ClientConfig struct. This function is crucial for initializing the client configuration
193
- // with values that may not be provided through environment variables or default values.
194
- // It uses Go's standard log package for logging, as the zap logger is not yet initialized when
195
- // this function is called.
196
- func (config * ClientConfig ) loadConfigFromFile (filePath string ) error {
197
- // Open the configuration file
198
- file , err := os .Open (filePath )
199
- if err != nil {
200
- log .Printf ("Failed to open the configuration file: %s, error: %v" , filePath , err )
201
- return err
202
- }
203
- defer file .Close ()
204
-
205
- reader := bufio .NewReader (file )
206
- var builder strings.Builder
207
-
208
- // Read the file content
209
- for {
210
- part , _ , err := reader .ReadLine ()
211
- if err == io .EOF {
212
- break
213
- }
214
- if err != nil {
215
- log .Printf ("Failed to read the configuration file: %s, error: %v" , filePath , err )
216
- return err
217
- }
218
- builder .Write (part )
219
- }
220
-
221
- // Unmarshal JSON content into the ClientConfig struct
222
- err = json .Unmarshal ([]byte (builder .String ()), config )
223
- if err != nil {
224
- log .Printf ("Failed to unmarshal the configuration file: %s, error: %v" , filePath , err )
225
- return err
226
- }
227
-
228
- log .Printf ("Configuration successfully loaded from file: %s" , filePath )
229
- return nil
230
- }
0 commit comments