feat(azure.ai.agents): add ConnectionManager for CRUD on Foundry project connections#8030
feat(azure.ai.agents): add ConnectionManager for CRUD on Foundry project connections#8030Nathandrake229 wants to merge 1 commit intoAzure:mainfrom
Conversation
…ect connections Add ConnectionManager struct that combines the ARM SDK (ProjectConnectionsClient) for create/get/update/delete/list operations with the data-plane client (FoundryProjectsClient) for reading credentials/secrets. Key components: - ConnectionManager with List, Get, GetWithCredentials, Create, Update, Delete - Clean domain types (ConnectionInfo, ConnectionDetail, CreateConnectionParams, UpdateConnectionParams) that don't leak ARM SDK types to callers - Support for ApiKey, CustomKeys, and None auth types - GET-then-PUT pattern for Update (ARM doesn't support PATCH on connections) - Raw JSON credential parsing to extract arbitrary custom key names - Refactored FoundryProjectsClient.GetConnectionWithCredentials to expose a raw response variant for flexible credential parsing Includes 14 unit tests covering body construction, credential parsing, helper functions, and ARM response conversion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jongio
left a comment
There was a problem hiding this comment.
4 findings on the new ConnectionManager.
The main issue: fetchCredentials hits the same data-plane endpoint twice for non-ApiKey connections - once parsed, once raw. Since getConnectionWithCredentialsRaw already exists, you can call it once and parse from those bytes. That cuts the round-trips in half.
CI's go-fix check is also failing. Run go fix ./... from the extension directory to replace to.Ptr() with new().
| // fetchCredentials calls the data-plane getConnectionWithCredentials endpoint | ||
| // and returns the credential fields as a flat map (excluding the "type" discriminator). | ||
| func (m *ConnectionManager) fetchCredentials(ctx context.Context, name string) (map[string]string, error) { | ||
| conn, err := m.dpClient.GetConnectionWithCredentials(ctx, name) |
There was a problem hiding this comment.
This calls GetConnectionWithCredentials (which internally calls getConnectionWithCredentialsRaw + unmarshal), then for non-ApiKey types, fetchRawCredentials calls getConnectionWithCredentialsRaw again. That's two HTTP round-trips to the same endpoint.
Since you need the raw bytes for CustomKeys anyway, consider calling getConnectionWithCredentialsRaw once and parsing both the Connection struct (for type detection) and the raw credentials from the same bytes:
func (m *ConnectionManager) fetchCredentials(ctx context.Context, name string) (map[string]string, error) {
raw, err := m.dpClient.getConnectionWithCredentialsRaw(ctx, name)
if err != nil {
return nil, err
}
var conn Connection
if err := json.Unmarshal(raw, &conn); err != nil {
return nil, fmt.Errorf("parsing connection response: %w", err)
}
if conn.Credentials.Type == CredentialTypeApiKey && conn.Credentials.Key != "" {
return map[string]string{"key": conn.Credentials.Key}, nil
}
return parseRawCredentials(raw)
}This also lets you extract parseRawCredentials as a standalone function that's directly testable (see comment on the test file).
| } | ||
| var s string | ||
| if err := json.Unmarshal(v, &s); err != nil { | ||
| continue // skip non-string values |
There was a problem hiding this comment.
Silently skipping non-string values could hide credential data the caller needs. Consider at minimum a log.Printf here so unexpected credential formats don't go unnoticed during debugging.
| } | ||
| } | ||
|
|
||
| func TestParseRawCredentials(t *testing.T) { |
There was a problem hiding this comment.
These tests duplicate the credential-parsing logic inline instead of calling the actual code. If fetchRawCredentials changes, these tests still pass because they're testing a copy of the algorithm, not the real thing.
If you extract the parsing into a standalone parseRawCredentials(raw []byte) (map[string]string, error) function (as suggested on the other comment), these tests can call it directly and verify the real code path.
| Properties: &armcognitiveservices.APIKeyAuthConnectionProperties{ | ||
| AuthType: &authType, | ||
| Category: &category, | ||
| Target: to.Ptr(params.Target), |
There was a problem hiding this comment.
CI's go-fix check is failing because Go 1.26 prefers new(val) over to.Ptr(val). This applies to all 7 to.Ptr call sites in this file. Run go fix ./... from the extension directory - it'll auto-fix these and likely remove the now-unused to import.
Summary
Add a \ConnectionManager\ service layer that provides CRUD operations on connected resources (connections) in a Foundry project.
What's included
New: \connection_manager.go\
New: \connection_manager_test.go\
Modified: \oundry_projects_client.go\
Design context
Testing
All 40 tests pass (14 new + 26 existing in the azure package).