-
Notifications
You must be signed in to change notification settings - Fork 82
/
config.go
152 lines (119 loc) · 3 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package linodego
import (
"fmt"
"os"
"strings"
"gopkg.in/ini.v1"
)
const (
DefaultConfigProfile = "default"
)
var DefaultConfigPaths = []string{
"%s/.config/linode",
"%s/.config/linode-cli",
}
type ConfigProfile struct {
APIToken string `ini:"token"`
APIVersion string `ini:"api_version"`
APIURL string `ini:"api_url"`
}
type LoadConfigOptions struct {
Path string
Profile string
SkipLoadProfile bool
}
// LoadConfig loads a Linode config according to the option's argument.
// If no options are specified, the following defaults will be used:
// Path: ~/.config/linode
// Profile: default
func (c *Client) LoadConfig(options *LoadConfigOptions) error {
path, err := resolveValidConfigPath()
if err != nil {
return err
}
profileOption := DefaultConfigProfile
if options != nil {
if options.Path != "" {
path = options.Path
}
if options.Profile != "" {
profileOption = options.Profile
}
}
cfg, err := ini.Load(path)
if err != nil {
return err
}
defaultConfig := ConfigProfile{
APIToken: "",
APIURL: APIHost,
APIVersion: APIVersion,
}
if cfg.HasSection("default") {
err := cfg.Section("default").MapTo(&defaultConfig)
if err != nil {
return fmt.Errorf("failed to map default profile: %w", err)
}
}
result := make(map[string]ConfigProfile)
for _, profile := range cfg.Sections() {
name := strings.ToLower(profile.Name())
f := defaultConfig
if err := profile.MapTo(&f); err != nil {
return fmt.Errorf("failed to map values: %w", err)
}
result[name] = f
}
c.configProfiles = result
if !options.SkipLoadProfile {
if err := c.UseProfile(profileOption); err != nil {
return fmt.Errorf("unable to use profile %s: %w", profileOption, err)
}
}
return nil
}
// UseProfile switches client to use the specified profile.
// The specified profile must be already be loaded using client.LoadConfig(...)
func (c *Client) UseProfile(name string) error {
name = strings.ToLower(name)
profile, ok := c.configProfiles[name]
if !ok {
return fmt.Errorf("profile %s does not exist", name)
}
if profile.APIToken == "" {
return fmt.Errorf("unable to resolve linode_token for profile %s", name)
}
if profile.APIURL == "" {
return fmt.Errorf("unable to resolve linode_api_url for profile %s", name)
}
if profile.APIVersion == "" {
return fmt.Errorf("unable to resolve linode_api_version for profile %s", name)
}
c.SetToken(profile.APIToken)
c.SetBaseURL(profile.APIURL)
c.SetAPIVersion(profile.APIVersion)
c.selectedProfile = name
c.loadedProfile = name
return nil
}
func FormatConfigPath(path string) (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
return fmt.Sprintf(path, homeDir), nil
}
func resolveValidConfigPath() (string, error) {
for _, cfg := range DefaultConfigPaths {
p, err := FormatConfigPath(cfg)
if err != nil {
return "", err
}
if _, err = os.Stat(p); err != nil {
continue
}
return p, err
}
// An empty result may not be an error
return "", nil
}