Add lookup by fully qualified name

This commit is contained in:
Pieter Noordhuis 2024-10-23 16:57:46 +02:00
parent 57cf0d634b
commit e6a8d8a4ca
No known key found for this signature in database
GPG Key ID: 12ACCCC104CF2930
3 changed files with 36 additions and 17 deletions

View File

@ -6,7 +6,8 @@ import "github.com/databricks/cli/bundle"
// that every key maps directly to a single reference. // that every key maps directly to a single reference.
func Completions(b *bundle.Bundle) map[string]Reference { func Completions(b *bundle.Bundle) map[string]Reference {
out := make(map[string]Reference) out := make(map[string]Reference)
for k, refs := range References(b) { keyOnlyRefs, _ := References(b)
for k, refs := range keyOnlyRefs {
if len(refs) != 1 { if len(refs) != 1 {
continue continue
} }

View File

@ -8,9 +8,8 @@ import (
) )
// Reference is a reference to a resource. // Reference is a reference to a resource.
// It includes the resource key, the resource type description, and a reference to the resource itself. // It includes the resource type description, and a reference to the resource itself.
type Reference struct { type Reference struct {
Key string
Description config.ResourceDescription Description config.ResourceDescription
Resource config.ConfigResource Resource config.ConfigResource
} }
@ -18,40 +17,51 @@ type Reference struct {
// Map is the core type for resource lookup and completion. // Map is the core type for resource lookup and completion.
type Map map[string][]Reference type Map map[string][]Reference
// References returns a map of resource keys to a slice of [Reference]. // References returns maps of resource keys to a slice of [Reference].
// While its return type allows for multiple resources to share the same key, //
// The first map is indexed by the resource key only.
// The second map is indexed by the resource type name and its key.
//
// While the return types allows for multiple resources to share the same key,
// this is confirmed not to happen in the [validate.UniqueResourceKeys] mutator. // this is confirmed not to happen in the [validate.UniqueResourceKeys] mutator.
func References(b *bundle.Bundle) Map { func References(b *bundle.Bundle) (Map, Map) {
output := make(Map) keyOnly := make(Map)
keyWithType := make(Map)
// Collect map of resource references indexed by their keys. // Collect map of resource references indexed by their keys.
for _, group := range b.Config.Resources.AllResources() { for _, group := range b.Config.Resources.AllResources() {
for k, v := range group.Resources { for k, v := range group.Resources {
output[k] = append(output[k], Reference{ ref := Reference{
Key: k,
Description: group.Description, Description: group.Description,
Resource: v, Resource: v,
}) }
kt := fmt.Sprintf("%s.%s", group.Description.PluralName, k)
keyOnly[k] = append(keyOnly[k], ref)
keyWithType[kt] = append(keyWithType[kt], ref)
} }
} }
return output return keyOnly, keyWithType
} }
// Lookup returns the resource with the specified key. // Lookup returns the resource with the specified key.
// If the key maps to more than one resource, an error is returned. // If the key maps to more than one resource, an error is returned.
// If the key does not map to any resource, an error is returned. // If the key does not map to any resource, an error is returned.
func Lookup(b *bundle.Bundle, key string) (config.ConfigResource, error) { func Lookup(b *bundle.Bundle, key string) (config.ConfigResource, error) {
refs := References(b) keyOnlyRefs, keyWithTypeRefs := References(b)
res, ok := refs[key] refs, ok := keyOnlyRefs[key]
if !ok {
refs, ok = keyWithTypeRefs[key]
if !ok { if !ok {
return nil, fmt.Errorf("resource with key %q not found", key) return nil, fmt.Errorf("resource with key %q not found", key)
} }
}
switch { switch {
case len(res) == 1: case len(refs) == 1:
return res[0].Resource, nil return refs[0].Resource, nil
case len(res) > 1: case len(refs) > 1:
return nil, fmt.Errorf("multiple resources with key %q found", key) return nil, fmt.Errorf("multiple resources with key %q found", key)
default: default:
panic("unreachable") panic("unreachable")

View File

@ -77,9 +77,17 @@ func TestLookup_Nominal(t *testing.T) {
}, },
} }
// Lookup by key only.
out, err := Lookup(b, "foo") out, err := Lookup(b, "foo")
require.NoError(t, err) require.NoError(t, err)
if assert.NotNil(t, out) { if assert.NotNil(t, out) {
assert.Equal(t, "Foo job", out.GetName()) assert.Equal(t, "Foo job", out.GetName())
} }
// Lookup by type and key.
out, err = Lookup(b, "jobs.foo")
require.NoError(t, err)
if assert.NotNil(t, out) {
assert.Equal(t, "Foo job", out.GetName())
}
} }