@@ -24,65 +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
- // Check if the configuration is complete; if not, load from file
38
- if ! validateConfigCompletion (config ) {
39
- if configFilePath != "" {
40
- if err := config .loadConfigFromFile (configFilePath ); err != nil {
41
- return nil , err
42
- }
43
- } else {
44
- return nil , fmt .Errorf ("http client configuration is incomplete. Required environment variables are missing, and no configuration file path is provided. Please set the necessary environment variables or provide a valid configuration file path" )
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
45
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 )
46
56
}
47
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
+
48
67
// Set default values if necessary
49
68
setLoggerDefaultValues (config )
50
69
setClientDefaultValues (config )
51
70
52
- // Recheck if config values are still incomplete after setting defaults
53
- if validateConfigCompletion (config ) {
54
- 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 )
55
74
}
56
75
57
- return config , nil
76
+ return nil
58
77
}
59
78
60
- // loadConfigFromEnv populates the ClientConfig structure with values from environment variables.
79
+ // LoadConfigFromEnv populates the ClientConfig structure with values from environment variables.
61
80
// It updates the configuration for authentication, environment specifics, and client options
62
81
// based on the presence of environment variables. For each configuration option, if an environment
63
82
// variable is set, its value is used; otherwise, the existing value in the ClientConfig structure
64
- // is retained.
65
- 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
+
66
90
// AuthConfig
67
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
+
68
94
config .Auth .ClientSecret = getEnvOrDefault ("CLIENT_SECRET" , config .Auth .ClientSecret )
95
+ log .Printf ("ClientSecret env value found and set" )
69
96
70
97
// EnvironmentConfig
71
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
+
72
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
+
73
104
config .Environment .APIType = getEnvOrDefault ("API_TYPE" , config .Environment .APIType )
105
+ log .Printf ("APIType env value found and set to: %s" , config .Environment .APIType )
74
106
75
107
// ClientOptions
76
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
+
77
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
+
78
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
+
79
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
+
80
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
+
81
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
+
82
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
+
83
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
+
84
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
+
85
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
86
148
}
87
149
88
150
// Helper function to get environment variable or default value
@@ -120,14 +182,42 @@ func parseDuration(value string, defaultVal time.Duration) time.Duration {
120
182
return result
121
183
}
122
184
123
- // validateConfigCompletion checks if any essential configuration fields are missing,
124
- // indicating the configuration might be incomplete and may require loading from additional sources.
125
- func validateConfigCompletion (config * ClientConfig ) bool {
126
- // Check if essential fields are missing; additional fields can be checked as needed
127
- return config .Auth .ClientID == "" || config .Auth .ClientSecret == "" ||
128
- config .Environment .InstanceName == "" || config .Environment .APIType == "" ||
129
- config .ClientOptions .LogLevel == "" || config .ClientOptions .LogOutputFormat == "" ||
130
- 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
131
221
}
132
222
133
223
// setClientDefaultValues sets default values for the client configuration options if none are provided.
@@ -188,45 +278,3 @@ func setLoggerDefaultValues(config *ClientConfig) {
188
278
// Log completion of setting default values
189
279
log .Println ("Default values set for logger configuration" )
190
280
}
191
-
192
- // loadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
193
- // It opens the specified configuration file, reads its content, and unmarshals the JSON data
194
- // into the ClientConfig struct. This function is crucial for initializing the client configuration
195
- // with values that may not be provided through environment variables or default values.
196
- // It uses Go's standard log package for logging, as the zap logger is not yet initialized when
197
- // this function is called.
198
- func (config * ClientConfig ) loadConfigFromFile (filePath string ) error {
199
- // Open the configuration file
200
- file , err := os .Open (filePath )
201
- if err != nil {
202
- log .Printf ("Failed to open the configuration file: %s, error: %v" , filePath , err )
203
- return err
204
- }
205
- defer file .Close ()
206
-
207
- reader := bufio .NewReader (file )
208
- var builder strings.Builder
209
-
210
- // Read the file content
211
- for {
212
- part , _ , err := reader .ReadLine ()
213
- if err == io .EOF {
214
- break
215
- }
216
- if err != nil {
217
- log .Printf ("Failed to read the configuration file: %s, error: %v" , filePath , err )
218
- return err
219
- }
220
- builder .Write (part )
221
- }
222
-
223
- // Unmarshal JSON content into the ClientConfig struct
224
- err = json .Unmarshal ([]byte (builder .String ()), config )
225
- if err != nil {
226
- log .Printf ("Failed to unmarshal the configuration file: %s, error: %v" , filePath , err )
227
- return err
228
- }
229
-
230
- log .Printf ("Configuration successfully loaded from file: %s" , filePath )
231
- return nil
232
- }
0 commit comments