@@ -4,20 +4,21 @@ import (
4
4
"fmt"
5
5
"os"
6
6
"os/user"
7
- "path/filepath"
8
7
"strings"
9
8
10
9
"gopkg.in/ini.v1"
11
10
)
12
11
13
- // Use variables for easier test overload
14
- var (
15
- systemConfigPath = "/etc/ovh.conf"
16
- userConfigPath = "/.ovh.conf" // prefixed with homeDir
17
- localConfigPath = "./ovh.conf"
18
- )
12
+ var configPaths = []string {
13
+ // System wide configuration
14
+ "/etc/ovh.com" ,
15
+ // Configuration in user's home
16
+ "~/.ovh.conf" ,
17
+ // Configuration in local folder
18
+ "./ovh.conf" ,
19
+ }
19
20
20
- // currentUserHome attempts to get current user's home directory
21
+ // currentUserHome attempts to get current user's home directory.
21
22
func currentUserHome () (string , error ) {
22
23
usr , err := user .Current ()
23
24
if err != nil {
@@ -31,14 +32,43 @@ func currentUserHome() (string, error) {
31
32
return usr .HomeDir , nil
32
33
}
33
34
34
- // appendConfigurationFile only if it exists. We need to do this because
35
- // ini package will fail to load configuration at all if a configuration
36
- // file is missing. This is racy, but better than always failing.
37
- func appendConfigurationFile (cfg * ini.File , path string ) {
38
- if file , err := os .Open (path ); err == nil {
39
- defer file .Close ()
40
- _ = cfg .Append (path )
35
+ // configPaths returns configPaths, with ~/ prefix expanded.
36
+ func expandConfigPaths () []interface {} {
37
+ paths := []interface {}{}
38
+
39
+ // Will be initialized on first use
40
+ var home string
41
+ var homeErr error
42
+
43
+ for _ , path := range configPaths {
44
+ if strings .HasPrefix (path , "~/" ) {
45
+ // Find home if needed
46
+ if home == "" && homeErr == nil {
47
+ home , homeErr = currentUserHome ()
48
+ }
49
+ // Ignore file in HOME if we cannot find it
50
+ if homeErr != nil {
51
+ continue
52
+ }
53
+
54
+ path = home + path [1 :]
55
+ }
56
+
57
+ paths = append (paths , path )
58
+ }
59
+
60
+ return paths
61
+ }
62
+
63
+ // loadINI builds a ini.File from the configuration paths provided in configPaths.
64
+ // It's a helper for loadConfig.
65
+ func loadINI () (* ini.File , error ) {
66
+ paths := expandConfigPaths ()
67
+ if len (paths ) == 0 {
68
+ return ini .Empty (), nil
41
69
}
70
+
71
+ return ini .LooseLoad (paths [0 ], paths [1 :]... )
42
72
}
43
73
44
74
// loadConfig loads client configuration from params, environments or configuration
@@ -58,13 +88,10 @@ func appendConfigurationFile(cfg *ini.File, path string) {
58
88
func (c * Client ) loadConfig (endpointName string ) error {
59
89
// Load configuration files by order of increasing priority. All configuration
60
90
// files are optional. Only load file from user home if home could be resolve
61
- cfg := ini .Empty ()
62
- appendConfigurationFile (cfg , systemConfigPath )
63
- if home , err := currentUserHome (); err == nil {
64
- userConfigFullPath := filepath .Join (home , userConfigPath )
65
- appendConfigurationFile (cfg , userConfigFullPath )
91
+ cfg , err := loadINI ()
92
+ if err != nil {
93
+ return fmt .Errorf ("cannot load configuration: %w" , err )
66
94
}
67
- appendConfigurationFile (cfg , localConfigPath )
68
95
69
96
// Canonicalize configuration
70
97
if endpointName == "" {
0 commit comments