Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion commands/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,22 @@ func writeConfig() error {

// defaultConfigFileWriter returns a writer to a newly created config.yaml file in the default config home.
// When using the default config file path the default config home directory will be created; Otherwise
// the custom config home directory must exist and be writable to the user issuing the auth command.
// the custom config home directory will be created if it doesn't exist.
func defaultConfigFileWriter() (io.WriteCloser, error) {
cfgFile := viper.GetString("config")

defaultCfgFile := filepath.Join(defaultConfigHome(), defaultConfigName)
if cfgFile == defaultCfgFile {
configHome()
} else {
// For custom config paths, ensure the parent directory exists
parentDir := filepath.Dir(cfgFile)
if _, err := os.Stat(parentDir); os.IsNotExist(err) {
err = os.MkdirAll(parentDir, 0755)
if err != nil {
return nil, err
}
}
}

f, err := os.Create(cfgFile)
Expand Down
18 changes: 16 additions & 2 deletions commands/doit.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,22 @@ func defaultConfigHome() string {

func configHome() string {
ch := defaultConfigHome()
err := os.MkdirAll(ch, 0755)
checkErr(err)

// Get the parent directory to check if it exists
parentDir := filepath.Dir(ch)

// Check if parent directory exists (could be a symlink or directory)
if _, err := os.Stat(parentDir); os.IsNotExist(err) {
// Parent doesn't exist, create it with MkdirAll
err = os.MkdirAll(parentDir, 0755)
checkErr(err)
}

// Now create the final directory (doctl) if it doesn't exist
if _, err := os.Stat(ch); os.IsNotExist(err) {
err = os.Mkdir(ch, 0755)
checkErr(err)
}

return ch
}
Expand Down
73 changes: 28 additions & 45 deletions integration/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,68 +284,51 @@ context: default
)

output, err := cmd.CombinedOutput()
expect.NoError(err, string(output))

err = os.Remove(testConfig)
expect.NoError(err)

expect.Contains(string(output), "next (current)")
})
})

when("switching contexts containing a period", func() {
it("does not mangle that context", func() {
var testConfigBytes = []byte(`access-token: first-token
auth-contexts:
[email protected]: second-token
context: default
`)

when("config directory parent is a symlink", func() {
it("successfully creates config directory through symlink", func() {
tmpDir := t.TempDir()
testConfig := filepath.Join(tmpDir, "test-config.yml")
expect.NoError(os.WriteFile(testConfig, testConfigBytes, 0644))

cmd := exec.Command(builtBinaryPath,
"-u", server.URL,
"auth",
"switch",
"--config", testConfig,
)
_, err := cmd.CombinedOutput()
// Create actual config directory
actualConfigDir := filepath.Join(tmpDir, "actual-config")
err := os.MkdirAll(actualConfigDir, 0755)
expect.NoError(err)

fileBytes, err := os.ReadFile(testConfig)
// Create a symlink .config pointing to the actual config directory
symlinkConfigDir := filepath.Join(tmpDir, ".config")
err = os.Symlink(actualConfigDir, symlinkConfigDir)
expect.NoError(err)
expect.Contains(string(fileBytes), "[email protected]: second-token")

err = os.Remove(testConfig)
expect.NoError(err)
})
})

when("the DIGITALOCEAN_CONTEXT variable is set", func() {
it("uses that context for commands", func() {
var testConfigBytes = []byte(`access-token: first-token
auth-contexts:
next: second-token
context: default
`)

tmpDir := t.TempDir()
testConfig := filepath.Join(tmpDir, "test-config.yml")
expect.NoError(os.WriteFile(testConfig, testConfigBytes, 0644))
// Set up config path to use the symlink
configPath := filepath.Join(symlinkConfigDir, "doctl", "config.yml")

cmd := exec.Command(builtBinaryPath,
"-u", server.URL,
"--config", configPath,
"auth",
"list",
"--config", testConfig,
"init",
"--access-token", "some-magic-token",
"--token-validation-server", server.URL,
)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "DIGITALOCEAN_CONTEXT=next")

output, err := cmd.CombinedOutput()
expect.NoError(err, string(output))
_, err = cmd.CombinedOutput()
expect.NoError(err)

expect.Contains(string(output), "next (current)")
// Verify the config file was created
fileBytes, err := os.ReadFile(configPath)
expect.NoError(err)
expect.Contains(string(fileBytes), "access-token: some-magic-token")

// Verify the directory structure exists through the symlink
doctlDir := filepath.Join(symlinkConfigDir, "doctl")
info, err := os.Stat(doctlDir)
expect.NoError(err)
expect.True(info.IsDir())
})
})
})