Skip to content

Commit c537834

Browse files
CLOUDP-332913: [AtlasCLI] Decouple profile from viper (#4050)
Co-authored-by: Melanija Cvetic <[email protected]>
1 parent 2d6fbbf commit c537834

File tree

10 files changed

+786
-281
lines changed

10 files changed

+786
-281
lines changed

cmd/atlas/atlas.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package main
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"log"
2021
"os"
@@ -25,13 +26,13 @@ import (
2526
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/root"
2627
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2728
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/telemetry"
29+
"github.com/spf13/afero"
2830
"github.com/spf13/cobra"
2931
)
3032

3133
// Execute adds all child commands to the root command and sets flags appropriately.
3234
// This is called by main.main(). It only needs to happen once to the rootCmd.
33-
func execute(rootCmd *cobra.Command) {
34-
ctx := telemetry.NewContext()
35+
func execute(ctx context.Context, rootCmd *cobra.Command) {
3536
// append here to avoid a recursive link on generated docs
3637
rootCmd.Long += `
3738
@@ -51,12 +52,17 @@ To learn more, see our documentation: https://www.mongodb.com/docs/atlas/cli/sta
5152
}
5253

5354
// loadConfig reads in config file and ENV variables if set.
54-
func loadConfig() error {
55-
if err := config.LoadAtlasCLIConfig(); err != nil {
56-
return fmt.Errorf("error loading config: %w. Please run `atlas config init` to reconfigure your profile", err)
55+
func loadConfig() (*config.Profile, error) {
56+
configStore, initErr := config.NewViperStore(afero.NewOsFs())
57+
58+
if initErr != nil {
59+
return nil, fmt.Errorf("error loading config: %w. Please run `atlas auth login` to reconfigure your profile", initErr)
5760
}
5861

59-
return nil
62+
profile := config.NewProfile(config.DefaultProfile, configStore)
63+
64+
config.SetProfile(profile)
65+
return profile, nil
6066
}
6167

6268
func trackInitError(e error, rootCmd *cobra.Command) {
@@ -85,9 +91,18 @@ func main() {
8591
core.DisableColor = true
8692
}
8793

94+
// Load config
95+
profile, loadProfileErr := loadConfig()
96+
8897
rootCmd := root.Builder()
8998
initTrack(rootCmd)
90-
trackInitError(loadConfig(), rootCmd)
99+
trackInitError(loadProfileErr, rootCmd)
100+
101+
// Initialize context, attach
102+
// - telemetry
103+
// - profile
104+
ctx := telemetry.NewContext()
105+
config.WithProfile(ctx, profile)
91106

92-
execute(rootCmd)
107+
execute(ctx, rootCmd)
93108
}

internal/cli/config/edit.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ func (*editOpts) Run() error {
3333
} else if e := os.Getenv("EDITOR"); e != "" {
3434
editor = e
3535
}
36-
cmd := exec.Command(editor, config.Filename()) //nolint:gosec // it's ok to let users do this
36+
37+
// Get the viper config filename
38+
configDir, err := config.CLIConfigHome()
39+
if err != nil {
40+
return err
41+
}
42+
filename := config.ViperConfigStoreFilename(configDir)
43+
44+
cmd := exec.Command(editor, filename)
3745
cmd.Stdin = os.Stdin
3846
cmd.Stdout = os.Stdout
3947
cmd.Stderr = os.Stderr

internal/config/config.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2025 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"bytes"
19+
"os"
20+
"path"
21+
)
22+
23+
// CLIConfigHome retrieves configHome path.
24+
func CLIConfigHome() (string, error) {
25+
home, err := os.UserConfigDir()
26+
if err != nil {
27+
return "", err
28+
}
29+
30+
return path.Join(home, "atlascli"), nil
31+
}
32+
33+
func Path(f string) (string, error) {
34+
var p bytes.Buffer
35+
36+
h, err := CLIConfigHome()
37+
if err != nil {
38+
return "", err
39+
}
40+
41+
p.WriteString(h)
42+
p.WriteString(f)
43+
return p.String(), nil
44+
}

internal/config/identifiers.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2025 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"runtime"
21+
"strings"
22+
23+
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/version"
24+
)
25+
26+
var (
27+
CLIUserType = newCLIUserTypeFromEnvs()
28+
HostName = getConfigHostnameFromEnvs()
29+
UserAgent = fmt.Sprintf("%s/%s (%s;%s;%s)", AtlasCLI, version.Version, runtime.GOOS, runtime.GOARCH, HostName)
30+
)
31+
32+
// newCLIUserTypeFromEnvs patches the user type information based on set env vars.
33+
func newCLIUserTypeFromEnvs() string {
34+
if value, ok := os.LookupEnv(CLIUserTypeEnv); ok {
35+
return value
36+
}
37+
38+
return DefaultUser
39+
}
40+
41+
// getConfigHostnameFromEnvs patches the agent hostname based on set env vars.
42+
func getConfigHostnameFromEnvs() string {
43+
var builder strings.Builder
44+
45+
envVars := []struct {
46+
envName string
47+
hostName string
48+
}{
49+
{AtlasActionHostNameEnv, AtlasActionHostName},
50+
{GitHubActionsHostNameEnv, GitHubActionsHostName},
51+
{ContainerizedHostNameEnv, DockerContainerHostName},
52+
}
53+
54+
for _, envVar := range envVars {
55+
if envIsTrue(envVar.envName) {
56+
appendToHostName(&builder, envVar.hostName)
57+
} else {
58+
appendToHostName(&builder, "-")
59+
}
60+
}
61+
configHostName := builder.String()
62+
63+
if isDefaultHostName(configHostName) {
64+
return NativeHostName
65+
}
66+
return configHostName
67+
}
68+
69+
func appendToHostName(builder *strings.Builder, configVal string) {
70+
if builder.Len() > 0 {
71+
builder.WriteString("|")
72+
}
73+
builder.WriteString(configVal)
74+
}
75+
76+
// isDefaultHostName checks if the hostname is the default placeholder.
77+
func isDefaultHostName(hostname string) bool {
78+
// Using strings.Count for a more dynamic approach.
79+
return strings.Count(hostname, "-") == strings.Count(hostname, "|")+1
80+
}
81+
82+
func envIsTrue(env string) bool {
83+
return IsTrue(os.Getenv(env))
84+
}

0 commit comments

Comments
 (0)