From 7b71d49fa9488623bd2341c37430f65d1bffb535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Til=20Sch=C3=BCnemann?= <45126872+tilschuenemann@users.noreply.github.com> Date: Wed, 11 Jan 2023 11:44:27 +0100 Subject: [PATCH] feat: project flag accepts slug (#291) Co-authored-by: Patrik --- cmd/cloudx/client/client.go | 22 ++------------ cmd/cloudx/client/handler.go | 30 +++++++++++++++++-- cmd/cloudx/client/handler_test.go | 4 +++ cmd/cloudx/project/update_namespace_config.go | 4 +-- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/cmd/cloudx/client/client.go b/cmd/cloudx/client/client.go index a5263f3b..b8b69487 100644 --- a/cmd/cloudx/client/client.go +++ b/cmd/cloudx/client/client.go @@ -13,7 +13,6 @@ import ( cloud "github.com/ory/client-go" - "github.com/gofrs/uuid/v3" "github.com/hashicorp/go-retryablehttp" "github.com/spf13/cobra" flag "github.com/spf13/pflag" @@ -28,18 +27,7 @@ import ( const projectFlag = "project" func RegisterProjectFlag(f *flag.FlagSet) { - f.String(projectFlag, "", "The project to use") -} - -// ProjectID returns the ID the user set with the `--project` flag, or prints a warning and returns an error -// if none was set. -func ProjectID(cmd *cobra.Command) (uuid.UUID, error) { - project := uuid.FromStringOrNil(flagx.MustGetString(cmd, projectFlag)) - if project == uuid.Nil { - _, _ = fmt.Fprintf(os.Stderr, "No project selected! Please use the flag --%s to specify one.\n", projectFlag) - return uuid.Nil, cmdx.FailSilently(cmd) - } - return project, nil + f.String(projectFlag, "", "The project to use, either project ID or a (partial) slug.") } func Client(cmd *cobra.Command) (*retryablehttp.Client, *AuthContext, *cloud.Project, error) { @@ -54,12 +42,8 @@ func Client(cmd *cobra.Command) (*retryablehttp.Client, *AuthContext, *cloud.Pro return nil, nil, nil, err } - project, err := ProjectID(cmd) - if err != nil { - return nil, nil, nil, cmdx.FailSilently(cmd) - } - - p, err := sc.GetProject(project.String()) + projectOrSlug := flagx.MustGetString(cmd, projectFlag) + p, err := sc.GetProject(projectOrSlug) if err != nil { return nil, nil, nil, err } diff --git a/cmd/cloudx/client/handler.go b/cmd/cloudx/client/handler.go index c524bff0..a94dc23e 100644 --- a/cmd/cloudx/client/handler.go +++ b/cmd/cloudx/client/handler.go @@ -510,7 +510,11 @@ func (h *CommandHelper) ListProjects() ([]cloud.ProjectMetadata, error) { return projects, nil } -func (h *CommandHelper) GetProject(id string) (*cloud.Project, error) { +func (h *CommandHelper) GetProject(projectOrSlug string) (*cloud.Project, error) { + if projectOrSlug == "" { + return nil, errors.Errorf("No project selected! Please see the help message on how to set one.") + } + ac, err := h.EnsureContext() if err != nil { return nil, err @@ -521,7 +525,29 @@ func (h *CommandHelper) GetProject(id string) (*cloud.Project, error) { return nil, err } - project, res, err := c.ProjectApi.GetProject(h.Ctx, id).Execute() + id := uuid.FromStringOrNil(projectOrSlug) + if id == uuid.Nil { + pjs, err := h.ListProjects() + if err != nil { + return nil, err + } + + availableSlugs := make([]string, len(pjs)) + for i, pm := range pjs { + availableSlugs[i] = pm.GetSlug() + if strings.HasPrefix(pm.GetSlug(), projectOrSlug) { + if id != uuid.Nil { + return nil, errors.Errorf("The slug prefix %q is not unique, please use more characters. Found slugs:\n%s", projectOrSlug, strings.Join(availableSlugs, "\n")) + } + id = uuid.FromStringOrNil(pm.GetId()) + } + } + if id == uuid.Nil { + return nil, errors.Errorf("no project found with slug %s, only slugs known are: %v", projectOrSlug, availableSlugs) + } + } + + project, res, err := c.ProjectApi.GetProject(h.Ctx, id.String()).Execute() if err != nil { return nil, handleError("unable to get project", res, err) } diff --git a/cmd/cloudx/client/handler_test.go b/cmd/cloudx/client/handler_test.go index 353bc579..1352b092 100644 --- a/cmd/cloudx/client/handler_test.go +++ b/cmd/cloudx/client/handler_test.go @@ -75,6 +75,10 @@ func TestCommandHelper(t *testing.T) { p, err := loggedIn.GetProject(project) require.NoError(t, err) assertValidProject(t, p) + + actual, err := loggedIn.GetProject(p.Slug[0:4]) + require.NoError(t, err) + assert.Equal(t, p, actual) }) t.Run("is not able to list projects if not authenticated and quiet flag", func(t *testing.T) { diff --git a/cmd/cloudx/project/update_namespace_config.go b/cmd/cloudx/project/update_namespace_config.go index 382b02e9..c3e8d265 100644 --- a/cmd/cloudx/project/update_namespace_config.go +++ b/cmd/cloudx/project/update_namespace_config.go @@ -44,12 +44,12 @@ class Example implements Namespace {} patch := fmt.Sprintf(`/services/permission/config/namespaces={"location": "base64://%s"}`, base64.StdEncoding.EncodeToString(data)) - projectID, err := client.ProjectID(cmd) + project, err := h.GetProject(flagx.MustGetString(cmd, "project")) if err != nil { return err } - p, err := h.PatchProject(projectID.String(), nil, nil, []string{patch}, nil) + p, err := h.PatchProject(project.Id, nil, nil, []string{patch}, nil) if err != nil { return cmdx.PrintOpenAPIError(cmd, err) }