Skip to content

Commit a5ef660

Browse files
userclaude
andcommitted
feat(cli,sdk): credential name resolution + FindByName across all subcommands
Add resolveCredentialID helper to credential subcommand (get, update, delete, token) enabling name-based lookups with ID fallback. Add FindByName to SDK credential_extensions.go using TSL search. Fix apply to use FindByName for upsert. Add platform-managed pod ingress rule to runner NetworkPolicy. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 744567d commit a5ef660

8 files changed

Lines changed: 94 additions & 10 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ scripts/feedback-loop/.last-run
138138
**/minio-credentials-secret.yaml
139139
**/postgresql-credentials-secret.yaml
140140
**/unleash-credentials-secret.yaml
141+
.secrets/
141142

142143
# One-off analysis and experiments
143144
repomix-analysis/

components/ambient-cli/cmd/acpctl/apply/cmd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func applyProject(ctx context.Context, client *sdkclient.Client, doc resource) (
243243
}
244244

245245
func applyCredential(ctx context.Context, client *sdkclient.Client, doc resource) (applyResult, error) {
246-
existing, err := client.Credentials().Get(ctx, doc.Name)
246+
existing, err := client.Credentials().FindByName(ctx, doc.Name)
247247
if err != nil {
248248
token := os.ExpandEnv(doc.Token)
249249
builder := sdktypes.NewCredentialBuilder().
@@ -271,7 +271,7 @@ func applyCredential(ctx context.Context, client *sdkclient.Client, doc resource
271271
if buildErr != nil {
272272
return applyResult{}, buildErr
273273
}
274-
if _, createErr := client.Credentials().Create(ctx, cred); createErr != nil {
274+
if _, createErr := client.Credentials().CreateCompat(ctx, cred); createErr != nil {
275275
return applyResult{}, createErr
276276
}
277277
return applyResult{Kind: "Credential", Name: doc.Name, Status: "created"}, nil

components/ambient-cli/cmd/acpctl/credential/cmd.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/ambient-code/platform/components/ambient-cli/pkg/config"
1010
"github.com/ambient-code/platform/components/ambient-cli/pkg/connection"
1111
"github.com/ambient-code/platform/components/ambient-cli/pkg/output"
12+
sdkclient "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/client"
1213
sdktypes "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types"
1314
"github.com/spf13/cobra"
1415
)
@@ -103,7 +104,11 @@ var getCmd = &cobra.Command{
103104
ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout())
104105
defer cancel()
105106

106-
credential, err := client.Credentials().Get(ctx, args[0])
107+
credID, err := resolveCredentialID(ctx, client, args[0])
108+
if err != nil {
109+
return err
110+
}
111+
credential, err := client.Credentials().Get(ctx, credID)
107112
if err != nil {
108113
return fmt.Errorf("get credential %q: %w", args[0], err)
109114
}
@@ -187,7 +192,7 @@ var createCmd = &cobra.Command{
187192
return fmt.Errorf("build credential: %w", err)
188193
}
189194

190-
created, err := client.Credentials().Create(ctx, cred)
195+
created, err := client.Credentials().CreateCompat(ctx, cred)
191196
if err != nil {
192197
return fmt.Errorf("create credential: %w", err)
193198
}
@@ -259,7 +264,11 @@ var updateCmd = &cobra.Command{
259264
patch = patch.Annotations(updateArgs.annotations)
260265
}
261266

262-
updated, err := client.Credentials().Update(ctx, args[0], patch.Build())
267+
credID, err := resolveCredentialID(ctx, client, args[0])
268+
if err != nil {
269+
return err
270+
}
271+
updated, err := client.Credentials().Update(ctx, credID, patch.Build())
263272
if err != nil {
264273
return fmt.Errorf("update credential: %w", err)
265274
}
@@ -296,7 +305,11 @@ var deleteCmd = &cobra.Command{
296305
ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout())
297306
defer cancel()
298307

299-
if err := client.Credentials().Delete(ctx, args[0]); err != nil {
308+
credID, err := resolveCredentialID(ctx, client, args[0])
309+
if err != nil {
310+
return err
311+
}
312+
if err := client.Credentials().Delete(ctx, credID); err != nil {
300313
return fmt.Errorf("delete credential: %w", err)
301314
}
302315

@@ -329,7 +342,11 @@ var tokenCmd = &cobra.Command{
329342
ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout())
330343
defer cancel()
331344

332-
resp, err := client.Credentials().GetToken(ctx, args[0])
345+
credID, err := resolveCredentialID(ctx, client, args[0])
346+
if err != nil {
347+
return err
348+
}
349+
resp, err := client.Credentials().GetToken(ctx, credID)
333350
if err != nil {
334351
return fmt.Errorf("get token for credential %q: %w", args[0], err)
335352
}
@@ -451,6 +468,18 @@ func init() {
451468
bindCmd.Flags().StringVar(&bindArgs.project, "project", "", "Project to bind the credential to (required)")
452469
}
453470

471+
func resolveCredentialID(ctx context.Context, client *sdkclient.Client, nameOrID string) (string, error) {
472+
cred, err := client.Credentials().Get(ctx, nameOrID)
473+
if err == nil {
474+
return cred.ID, nil
475+
}
476+
cred, err = client.Credentials().FindByName(ctx, nameOrID)
477+
if err != nil {
478+
return "", fmt.Errorf("credential %q not found by ID or name", nameOrID)
479+
}
480+
return cred.ID, nil
481+
}
482+
454483
func printCredentialTable(printer *output.Printer, credentials []sdktypes.Credential) error {
455484
columns := []output.Column{
456485
{Name: "ID", Width: 27},

components/ambient-cli/cmd/acpctl/delete/cmd.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ func run(cmd *cobra.Command, cmdArgs []string) error {
132132
return nil
133133

134134
case "credential", "credentials", "cred", "creds":
135-
if err := client.Credentials().Delete(ctx, name); err != nil {
135+
deleteID := name
136+
if cred, findErr := client.Credentials().FindByName(ctx, name); findErr == nil {
137+
deleteID = cred.ID
138+
}
139+
if err := client.Credentials().Delete(ctx, deleteID); err != nil {
136140
return fmt.Errorf("delete credential %q: %w", name, err)
137141
}
138142
fmt.Fprintf(cmd.OutOrStdout(), "credential/%s deleted\n", name)

components/ambient-cli/cmd/acpctl/describe/cmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ func run(cmd *cobra.Command, cmdArgs []string) error {
102102
case "credential", "credentials", "cred", "creds":
103103
cred, err := client.Credentials().Get(ctx, name)
104104
if err != nil {
105-
return fmt.Errorf("describe credential %q: %w", name, err)
105+
cred, err = client.Credentials().FindByName(ctx, name)
106+
if err != nil {
107+
return fmt.Errorf("describe credential %q: %w", name, err)
108+
}
106109
}
107110
return printer.PrintJSON(cred)
108111

components/ambient-cli/cmd/acpctl/get/cmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,10 @@ func getCredentials(ctx context.Context, client *sdkclient.Client, printer *outp
472472
if name != "" {
473473
cred, err := client.Credentials().Get(ctx, name)
474474
if err != nil {
475-
return fmt.Errorf("get credential %q: %w", name, err)
475+
cred, err = client.Credentials().FindByName(ctx, name)
476+
if err != nil {
477+
return fmt.Errorf("get credential %q: %w", name, err)
478+
}
476479
}
477480
if printer.Format() == output.FormatJSON {
478481
return printer.PrintJSON(cred)

components/ambient-sdk/go-sdk/client/credential_extensions.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package client
22

33
import (
44
"context"
5+
"encoding/json"
6+
"fmt"
57
"net/http"
68
"net/url"
79

@@ -15,3 +17,40 @@ func (a *CredentialAPI) GetToken(ctx context.Context, id string) (*types.Credent
1517
}
1618
return &result, nil
1719
}
20+
21+
func (a *CredentialAPI) FindByName(ctx context.Context, name string) (*types.Credential, error) {
22+
opts := types.NewListOptions().Size(100).Build()
23+
opts.Search = fmt.Sprintf("name = '%s'", name)
24+
list, err := a.List(ctx, opts)
25+
if err != nil {
26+
return nil, err
27+
}
28+
for _, c := range list.Items {
29+
if c.Name == name {
30+
return &c, nil
31+
}
32+
}
33+
return nil, fmt.Errorf("credential with name %q not found", name)
34+
}
35+
36+
// CreateCompat creates a credential with project_id for backward compatibility
37+
// with server images that predate migration 202505120001 (drop project_id column).
38+
// Remove once all environments run the updated server.
39+
func (a *CredentialAPI) CreateCompat(ctx context.Context, resource *types.Credential) (*types.Credential, error) {
40+
payload := struct {
41+
*types.Credential
42+
ProjectID string `json:"project_id,omitempty"`
43+
}{
44+
Credential: resource,
45+
ProjectID: a.client.project,
46+
}
47+
body, err := json.Marshal(payload)
48+
if err != nil {
49+
return nil, fmt.Errorf("marshal credential: %w", err)
50+
}
51+
var result types.Credential
52+
if err := a.client.do(ctx, http.MethodPost, "/credentials", body, http.StatusCreated, &result); err != nil {
53+
return nil, err
54+
}
55+
return &result, nil
56+
}

components/manifests/base/runner-networkpolicy.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ spec:
1818
podSelector:
1919
matchLabels:
2020
app: ambient-code-runner
21+
- from:
22+
- namespaceSelector: {}
23+
podSelector:
24+
matchLabels:
25+
ambient-code.io/managed: "true"

0 commit comments

Comments
 (0)