refactor(sources/alloydbadmin, sources/alloydbpg): move source implementation in Invoke() function to Source (#2226)

Move source-related queries from `Invoke()` function into Source.

This is an effort to generalizing tools to work with any Source that
implements a specific interface. This will provide a better segregation
of the roles for Tools vs Source.

Tool's role will be limited to the following:
* Resolve any pre-implementation steps or parameters (e.g. template
parameters)
* Retrieving Source
* Calling the source's implementation


Along with these updates, this PR also resolve some comments from
Gemini:
* update `fmt.Printf()` to logging as a Debug log -- within
`GetOperations()`
* update `fmt.Printf()` during failure to retrieve user agent into
throwing an error. UserAgent are expected to be retrieved successfully
during source initialization. Failure to retrieve will indicate a server
error.
This commit is contained in:
Yuan Teoh
2025-12-24 01:09:22 -08:00
committed by GitHub
parent 9695fc5eeb
commit 0202709efc
13 changed files with 348 additions and 299 deletions

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/alloydb/v1"
)
const kind string = "alloydb-create-instance"
@@ -44,7 +43,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T
type compatibleSource interface {
GetDefaultProject() string
UseClientAuthorization() bool
GetService(context.Context, string) (*alloydb.Service, error)
CreateInstance(context.Context, string, string, string, string, string, string, int, string) (any, error)
}
// Configuration for the create-instance tool.
@@ -155,45 +154,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
return nil, fmt.Errorf("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'")
}
service, err := source.GetService(ctx, string(accessToken))
if err != nil {
return nil, err
}
urlString := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", project, location, cluster)
// Build the request body using the type-safe Instance struct.
instance := &alloydb.Instance{
InstanceType: instanceType,
NetworkConfig: &alloydb.InstanceNetworkConfig{
EnablePublicIp: true,
},
DatabaseFlags: map[string]string{
"password.enforce_complexity": "on",
},
}
if displayName, ok := paramsMap["displayName"].(string); ok && displayName != "" {
instance.DisplayName = displayName
}
displayName, _ := paramsMap["displayName"].(string)
var nodeCount int
if instanceType == "READ_POOL" {
nodeCount, ok := paramsMap["nodeCount"].(int)
nodeCount, ok = paramsMap["nodeCount"].(int)
if !ok {
return nil, fmt.Errorf("invalid 'nodeCount' parameter; expected an integer for READ_POOL")
}
instance.ReadPoolConfig = &alloydb.ReadPoolConfig{
NodeCount: int64(nodeCount),
}
}
// The Create API returns a long-running operation.
resp, err := service.Projects.Locations.Clusters.Instances.Create(urlString, instance).InstanceId(instanceID).Do()
if err != nil {
return nil, fmt.Errorf("error creating AlloyDB instance: %w", err)
}
return resp, nil
return source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken))
}
// ParseParams parses the parameters for the tool.