Skip to content

Commit e9a3e37

Browse files
authored
Merge pull request #2983 from fabriziopandini/fix-clusterctl-read-config
🐛Fix clusterctl error when reading default config file
2 parents 7cda00b + 751be4e commit e9a3e37

File tree

2 files changed

+86
-21
lines changed

2 files changed

+86
-21
lines changed

Diff for: cmd/clusterctl/client/config/reader_viper.go

+18-16
Original file line numberDiff line numberDiff line change
@@ -64,39 +64,41 @@ func newViperReader(opts ...viperReaderOption) Reader {
6464
func (v *viperReader) Init(path string) error {
6565
log := logf.Log
6666

67+
// Configure viper for reading environment variables as well, and more specifically:
68+
// AutomaticEnv force viper to check for an environment variable any time a viper.Get request is made.
69+
// It will check for a environment variable with a name matching the key uppercased; in case name use the - delimiter,
70+
// the SetEnvKeyReplacer forces matching to name use the _ delimiter instead (- is not allowed in linux env variable names).
71+
replacer := strings.NewReplacer("-", "_")
72+
viper.SetEnvKeyReplacer(replacer)
73+
viper.AllowEmptyEnv(true)
74+
viper.AutomaticEnv()
75+
76+
// Reads the clusterctl config file
6777
if path != "" {
6878
if _, err := os.Stat(path); err != nil {
6979
return err
7080
}
7181
// Use path file from the flag.
7282
viper.SetConfigFile(path)
7383
} else {
74-
// Configure for searching .cluster-api/clusterctl{.extension} in home directory
75-
viper.SetConfigName(ConfigName)
76-
for _, p := range v.configPaths {
77-
viper.AddConfigPath(p)
78-
}
84+
// Checks if there is a default .cluster-api/clusterctl{.extension} file in home directory
7985
if !v.checkDefaultConfig() {
8086
// since there is no default config to read from, just skip
8187
// reading in config
8288
log.V(5).Info("No default config file available")
8389
return nil
8490
}
91+
// Configure viper for reading .cluster-api/clusterctl{.extension} in home directory
92+
viper.SetConfigName(ConfigName)
93+
for _, p := range v.configPaths {
94+
viper.AddConfigPath(p)
95+
}
8596
}
8697

87-
// Configure for reading environment variables as well, and more specifically:
88-
// AutomaticEnv force viper to check for an environment variable any time a viper.Get request is made.
89-
// It will check for a environment variable with a name matching the key uppercased; in case name use the - delimiter,
90-
// the SetEnvKeyReplacer forces matching to name use the _ delimiter instead (- is not allowed in linux env variable names).
91-
replacer := strings.NewReplacer("-", "_")
92-
viper.SetEnvKeyReplacer(replacer)
93-
viper.AllowEmptyEnv(true)
94-
viper.AutomaticEnv()
95-
9698
if err := viper.ReadInConfig(); err != nil {
9799
return err
98100
}
99-
log.V(5).Info("Reading configuration", "File", viper.ConfigFileUsed())
101+
log.V(5).Info("Using configuration", "File", viper.ConfigFileUsed())
100102
return nil
101103
}
102104

@@ -121,7 +123,7 @@ func (v *viperReader) UnmarshalKey(key string, rawval interface{}) error {
121123
func (v *viperReader) checkDefaultConfig() bool {
122124
for _, path := range v.configPaths {
123125
for _, ext := range viper.SupportedExts {
124-
f := fmt.Sprintf("%s%s.%s", path, ConfigName, ext)
126+
f := filepath.Join(path, fmt.Sprintf("%s.%s", ConfigName, ext))
125127
_, err := os.Stat(f)
126128
if err == nil {
127129
return true

Diff for: cmd/clusterctl/client/config/reader_viper_test.go

+68-5
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ limitations under the License.
1717
package config
1818

1919
import (
20+
"fmt"
2021
"io/ioutil"
2122
"os"
2223
"path/filepath"
24+
"strings"
2325
"testing"
2426

2527
. "github.com/onsi/gomega"
@@ -38,10 +40,10 @@ func Test_viperReader_Init(t *testing.T) {
3840
g.Expect(err).NotTo(HaveOccurred())
3941
defer os.RemoveAll(dir)
4042

41-
configFile := filepath.Join(dir, ".clusterctl.yaml")
43+
configFile := filepath.Join(dir, "clusterctl.yaml")
4244
g.Expect(ioutil.WriteFile(configFile, []byte("bar: bar"), 0640)).To(Succeed())
4345

44-
configFileBadContents := filepath.Join(dir, ".clusterctl-bad.yaml")
46+
configFileBadContents := filepath.Join(dir, "clusterctl-bad.yaml")
4547
g.Expect(ioutil.WriteFile(configFileBadContents, []byte("bad-contents"), 0640)).To(Succeed())
4648

4749
tests := []struct {
@@ -99,7 +101,7 @@ func Test_viperReader_Get(t *testing.T) {
99101

100102
os.Setenv("FOO", "foo")
101103

102-
configFile := filepath.Join(dir, ".clusterctl.yaml")
104+
configFile := filepath.Join(dir, "clusterctl.yaml")
103105
g.Expect(ioutil.WriteFile(configFile, []byte("bar: bar"), 0640)).To(Succeed())
104106

105107
type args struct {
@@ -140,7 +142,7 @@ func Test_viperReader_Get(t *testing.T) {
140142
t.Run(tt.name, func(t *testing.T) {
141143
gs := NewWithT(t)
142144

143-
v := &viperReader{}
145+
v := newViperReader(InjectConfigPaths([]string{dir}))
144146

145147
gs.Expect(v.Init(configFile)).To(Succeed())
146148

@@ -156,6 +158,22 @@ func Test_viperReader_Get(t *testing.T) {
156158
}
157159
}
158160

161+
func Test_viperReader_GetWithoutDefaultConfig(t *testing.T) {
162+
g := NewWithT(t)
163+
dir, err := ioutil.TempDir("", "clusterctl")
164+
g.Expect(err).NotTo(HaveOccurred())
165+
defer os.RemoveAll(dir)
166+
167+
os.Setenv("FOO_FOO", "bar")
168+
169+
v := newViperReader(InjectConfigPaths([]string{dir}))
170+
g.Expect(v.Init("")).To(Succeed())
171+
172+
got, err := v.Get("FOO_FOO")
173+
g.Expect(err).NotTo(HaveOccurred())
174+
g.Expect(got).To(Equal("bar"))
175+
}
176+
159177
func Test_viperReader_Set(t *testing.T) {
160178
g := NewWithT(t)
161179

@@ -165,7 +183,7 @@ func Test_viperReader_Set(t *testing.T) {
165183

166184
os.Setenv("FOO", "foo")
167185

168-
configFile := filepath.Join(dir, ".clusterctl.yaml")
186+
configFile := filepath.Join(dir, "clusterctl.yaml")
169187

170188
g.Expect(ioutil.WriteFile(configFile, []byte("bar: bar"), 0640)).To(Succeed())
171189

@@ -203,3 +221,48 @@ func Test_viperReader_Set(t *testing.T) {
203221
})
204222
}
205223
}
224+
225+
func Test_viperReader_checkDefaultConfig(t *testing.T) {
226+
g := NewWithT(t)
227+
dir, err := ioutil.TempDir("", "clusterctl")
228+
g.Expect(err).NotTo(HaveOccurred())
229+
defer os.RemoveAll(dir)
230+
dir = strings.TrimSuffix(dir, "/")
231+
232+
configFile := filepath.Join(dir, "clusterctl.yaml")
233+
g.Expect(ioutil.WriteFile(configFile, []byte("bar: bar"), 0640)).To(Succeed())
234+
235+
type fields struct {
236+
configPaths []string
237+
}
238+
tests := []struct {
239+
name string
240+
fields fields
241+
want bool
242+
}{
243+
{
244+
name: "tmp path without final /",
245+
fields: fields{
246+
configPaths: []string{dir},
247+
},
248+
want: true,
249+
},
250+
{
251+
name: "tmp path with final /",
252+
fields: fields{
253+
configPaths: []string{fmt.Sprintf("%s/", dir)},
254+
},
255+
want: true,
256+
},
257+
}
258+
for _, tt := range tests {
259+
t.Run(tt.name, func(t *testing.T) {
260+
gs := NewWithT(t)
261+
262+
v := &viperReader{
263+
configPaths: tt.fields.configPaths,
264+
}
265+
gs.Expect(v.checkDefaultConfig()).To(Equal(tt.want))
266+
})
267+
}
268+
}

0 commit comments

Comments
 (0)