Repository: apigee/registry (go)

Issue:
Configurations are read inconsistently in registry tool command implementations
Unfortunately #1230 didn't fully fix #1228.

This now works:
```
$ registry --config /tmp/apiz config list
registry.address = apiz.timbx.me:443
registry.insecure = false
registry.project = catalog
token-source = echo "ok"

Your active configuration is: "/tmp/apiz".
```

But this doesn't:
```
$ registry --config /tmp/apiz get projects
Usage:
...
Error: open /home/tim/.config/registry/apiz: no such file or directory
Run 'registry --help' for usage.
```

I can't explain why one of these commands should be getting its configuration differently from the other, but I observe that `registry config list`  calls `config.ActiveRaw()` [here](https://github.com/apigee/registry/blob/f805290353a4e31a3952cb084a38dc137230dd9e/cmd/registry/cmd/config/list.go#L31) and `registry get projects` calls `connection.ActiveConfig()` [here](https://github.com/apigee/registry/blob/f805290353a4e31a3952cb084a38dc137230dd9e/cmd/registry/cmd/get/get.go#L88).

Looking further, I see that `config.ActiveRaw()` is only used by the `registry config` subcommands and `registry auth print-token`, and all the others use `connection.ActiveConfig()`.

@theganyo do you know why we have two ways of doing this? Is there something to watch out for in merging them?

Pull request description:
connection.ActiveConfig() should use config.Active() instead of reading configuration directly
Fixes #1231

`config.Active()` [supports the `--config` flag](https://github.com/timburks/registry/blob/d0fe7e5d450b2f71fbaf1e24d62cea244928cfba/pkg/config/config.go#L115) where the previous code for `connection.ActiveConfig()` does not.

Patch:
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 3fd7f53..a00317d 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -161,7 +161,11 @@ func ReadValid(name string) (c Configuration, err error) {
 	var r io.Reader = &bytes.Buffer{}
 	if file != "" {
 		if dir == "" {
-			name = filepath.Join(Directory, file)
+			// If name refers to a local file, preferentially read the local file.
+			// Otherwise assume name refers to a file in the config directory.
+			if info, err := os.Stat(file); errors.Is(err, os.ErrNotExist) || info.IsDir() {
+				name = filepath.Join(Directory, file)
+			}
 		}
 		r, err = os.Open(name)
 		if err != nil {
diff --git a/pkg/connection/config.go b/pkg/connection/config.go
index 24c8abd..7f77b74 100644
--- a/pkg/connection/config.go
+++ b/pkg/connection/config.go
@@ -46,12 +46,17 @@ func ActiveConfig() (Config, error) {
 		return *active, nil
 	}
 
-	name, err := config.ActiveName()
+	c, err := config.Active()
 	if err != nil {
 		return Config{}, err
 	}
-
-	return ReadConfig(name)
+	return Config{
+		Address:  c.Registry.Address,
+		Insecure: c.Registry.Insecure,
+		Location: c.Registry.Location,
+		Project:  c.Registry.Project,
+		Token:    c.Registry.Token,
+	}, nil
 }
 
 // Reads a Config from a file. If name is empty, no


Test patch:
diff --git a/pkg/config/configuration_test.go b/pkg/config/configuration_test.go
index a20f163..2952be3 100644
--- a/pkg/config/configuration_test.go
+++ b/pkg/config/configuration_test.go
@@ -514,4 +514,21 @@ func TestReadExternalFile(t *testing.T) {
 	if c3.Registry.Address != c.Registry.Address {
 		t.Errorf("want: %s, got: %s", c3.Registry.Address, c.Registry.Address)
 	}
+	// Repeat the above with config.ReadValid
+	// Verify that we can read a file using its full path name.
+	c4, err := config.ReadValid(f.Name())
+	if err != nil {
+		t.Fatal(err)
+	}
+	if c4.Registry.Address != c.Registry.Address {
+		t.Errorf("want: %s, got: %s", c4.Registry.Address, c.Registry.Address)
+	}
+	// Verify that we can read a local file using its base name.
+	c5, err := config.ReadValid(filepath.Base(f.Name()))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if c5.Registry.Address != c.Registry.Address {
+		t.Errorf("want: %s, got: %s", c5.Registry.Address, c.Registry.Address)
+	}
 }