Skip to content

Commit e096766

Browse files
Gnoaleremyleone
andauthored
feat(meta): warn the user if there are multiple variable sources used (#3144)
* feat(meta): warn the user if there are multiple variable sources used * warn on error --------- Co-authored-by: Rémy Léone <[email protected]>
1 parent a71bb37 commit e096766

File tree

3 files changed

+126
-1
lines changed

3 files changed

+126
-1
lines changed

internal/meta/meta.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package meta
22

33
import (
4+
"bytes"
45
"context"
56
"errors"
67
"fmt"
78
"net/http"
89
"os"
10+
"strings"
11+
"text/tabwriter"
912

1013
"github.com/hashicorp/terraform-plugin-log/tflog"
1114
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -24,6 +27,7 @@ const (
2427
)
2528

2629
type CredentialsSource struct {
30+
Variables map[string][]string
2731
AccessKey string
2832
SecretKey string
2933
ProjectID string
@@ -73,6 +77,47 @@ func (m Meta) ZoneSource() string {
7377
return m.credentialsSource.DefaultZone
7478
}
7579

80+
// HasMultipleVariableSources return an informative message during the Provider initialization
81+
// if there are multiple sources of configuration that could confuse the user
82+
//
83+
// Variable AvailableSources Using
84+
// SCW_ACCESS_KEY Active Profile in config.yaml, Environment variable Environment variable
85+
// SCW_SECRET_KEY Active Profile in config.yaml, Environment variable Environment variable
86+
func (m Meta) HasMultipleVariableSources() (bool, string, error) {
87+
multiple := false
88+
89+
variables := []string{scw.ScwAccessKeyEnv, scw.ScwSecretKeyEnv, scw.ScwDefaultProjectIDEnv, scw.ScwDefaultRegionEnv, scw.ScwDefaultZoneEnv}
90+
91+
w := new(tabwriter.Writer)
92+
buf := &bytes.Buffer{}
93+
w.Init(buf, 0, 8, 0, '\t', 0)
94+
95+
_, err := fmt.Fprintln(w, "Variable\tAvailableSources\tUsing")
96+
if err != nil {
97+
return false, "", err
98+
}
99+
100+
for _, variable := range variables {
101+
values, ok := m.credentialsSource.Variables[variable]
102+
if ok {
103+
if len(values) > 1 {
104+
_, err := fmt.Fprintf(w, "%s\t%s\t%s\n", variable, strings.Join(values, ", "), values[len(values)-1])
105+
if err != nil {
106+
return false, "", err
107+
}
108+
109+
multiple = true
110+
}
111+
}
112+
}
113+
114+
if err := w.Flush(); err != nil {
115+
return false, "", err
116+
}
117+
118+
return multiple, buf.String(), nil
119+
}
120+
76121
type Config struct {
77122
ProviderSchema *schema.ResourceData
78123
HTTPClient *http.Client
@@ -270,29 +315,39 @@ func GetCredentialsSource(defaultZoneProfile, activeProfile, providerProfile, en
270315
},
271316
}
272317
credentialsSource := &CredentialsSource{}
318+
credentialsSource.Variables = map[string][]string{}
273319

274320
for _, pair := range profilesInOrder {
275321
source := pair.Source
276322
profile := pair.Profile
277323

278324
if profile.AccessKey != nil {
279325
credentialsSource.AccessKey = source
326+
credentialsSource.Variables[scw.ScwAccessKeyEnv] = append(credentialsSource.Variables[scw.ScwAccessKeyEnv], source)
280327
}
281328

282329
if profile.SecretKey != nil {
283330
credentialsSource.SecretKey = source
331+
credentialsSource.Variables[scw.ScwSecretKeyEnv] = append(credentialsSource.Variables[scw.ScwSecretKeyEnv], source)
284332
}
285333

286334
if profile.DefaultProjectID != nil {
287335
credentialsSource.ProjectID = source
336+
credentialsSource.Variables[scw.ScwDefaultProjectIDEnv] = append(credentialsSource.Variables[scw.ScwDefaultProjectIDEnv], source)
288337
}
289338

290339
if profile.DefaultRegion != nil {
291340
credentialsSource.DefaultRegion = source
341+
if source != CredentialsSourceDefault {
342+
credentialsSource.Variables[scw.ScwDefaultRegionEnv] = append(credentialsSource.Variables[scw.ScwDefaultRegionEnv], source)
343+
}
292344
}
293345

294346
if profile.DefaultZone != nil {
295347
credentialsSource.DefaultZone = source
348+
if source != CredentialsSourceDefault {
349+
credentialsSource.Variables[scw.ScwDefaultZoneEnv] = append(credentialsSource.Variables[scw.ScwDefaultZoneEnv], source)
350+
}
296351
}
297352
}
298353

internal/meta/meta_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package meta_test
2+
3+
import (
4+
"os"
5+
"path"
6+
"testing"
7+
8+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestHasMultipleVariableSources(t *testing.T) {
14+
ctx := t.Context()
15+
16+
cfg := &meta.Config{}
17+
18+
scwConfigigFile := `profiles:
19+
test:
20+
access_key: SCWXXXXXXXXXXXXXXXXX
21+
secret_key: 866F4A9A-D058-4D3C-A39F-86930849CCC0
22+
default_project_id: 866F4A9A-D058-4D3C-A39F-86930849CCC0
23+
`
24+
25+
dir := t.TempDir()
26+
27+
err := os.WriteFile(path.Join(dir, "config.yaml"), []byte(scwConfigigFile), 0o644)
28+
require.NoError(t, err)
29+
30+
t.Setenv("SCW_CONFIG_PATH", path.Join(dir, "config.yaml"))
31+
t.Setenv("SCW_PROFILE", "test")
32+
t.Setenv("SCW_ACCESS_KEY", "SCWXXXXXXXXXXXXXXXXX")
33+
t.Setenv("SCW_SECRET_KEY", "866F4A9A-D058-4D3C-A39F-86930849CCC0")
34+
t.Setenv("SCW_DEFAULT_PROJECT_ID", "866F4A9A-D058-4D3C-A39F-86930849CCC0")
35+
36+
m, err := meta.NewMeta(ctx, cfg)
37+
require.NoError(t, err)
38+
39+
ok, message, err := m.HasMultipleVariableSources()
40+
require.NoError(t, err)
41+
assert.True(t, ok)
42+
43+
expectedMessage := `Variable AvailableSources Using
44+
SCW_ACCESS_KEY Active Profile in config.yaml, Environment variable Environment variable
45+
SCW_SECRET_KEY Active Profile in config.yaml, Environment variable Environment variable
46+
SCW_DEFAULT_PROJECT_ID Active Profile in config.yaml, Environment variable Environment variable
47+
`
48+
assert.Equal(t, expectedMessage, message)
49+
}

internal/provider/provider.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,28 @@ func Provider(config *Config) plugin.ProviderFunc {
357357
return nil, diag.FromErr(err)
358358
}
359359

360-
return m, nil
360+
var diags diag.Diagnostics
361+
362+
ok, message, err := m.HasMultipleVariableSources()
363+
if err != nil {
364+
diags = append(diags, diag.Diagnostic{
365+
Severity: diag.Warning,
366+
Summary: "Error checking multiple variable sources",
367+
Detail: err.Error(),
368+
})
369+
370+
return m, diags
371+
}
372+
373+
if ok && err == nil {
374+
diags = append(diags, diag.Diagnostic{
375+
Severity: diag.Warning,
376+
Summary: "Multiple variable sources detected, please make sure the right credentials are used",
377+
Detail: message,
378+
})
379+
}
380+
381+
return m, diags
361382
}
362383

363384
return p

0 commit comments

Comments
 (0)