diff --git a/cmd/admin/v1/commands.go b/cmd/admin/v1/commands.go index ddfef8c..997638a 100644 --- a/cmd/admin/v1/commands.go +++ b/cmd/admin/v1/commands.go @@ -14,8 +14,9 @@ func AddCmds(cmd *cobra.Command, c *config.Config) { Hidden: true, } - adminCmd.AddCommand(newTokenCmd(c)) adminCmd.AddCommand(newImageCmd(c)) + adminCmd.AddCommand(newTenantCmd(c)) + adminCmd.AddCommand(newTokenCmd(c)) cmd.AddCommand(adminCmd) } diff --git a/cmd/admin/v1/tenant.go b/cmd/admin/v1/tenant.go new file mode 100644 index 0000000..7c7895d --- /dev/null +++ b/cmd/admin/v1/tenant.go @@ -0,0 +1,105 @@ +package v1 + +import ( + "fmt" + + adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/cli/cmd/config" + "github.com/metal-stack/cli/cmd/sorters" + "github.com/metal-stack/metal-lib/pkg/genericcli" + "github.com/metal-stack/metal-lib/pkg/genericcli/printers" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type tenant struct { + c *config.Config +} + +func newTenantCmd(c *config.Config) *cobra.Command { + w := &tenant{ + c: c, + } + + cmdsConfig := &genericcli.CmdsConfig[*adminv2.TenantServiceCreateRequest, any, *apiv2.Tenant]{ + BinaryName: config.BinaryName, + GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs), + Singular: "tenant", + Plural: "tenants", + Description: "manage api tenants", + Sorter: sorters.TenantSorter(), + DescribePrinter: func() printers.Printer { return c.DescribePrinter }, + ListPrinter: func() printers.Printer { return c.ListPrinter }, + ListCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().String("name", "", "lists only tenants with the given name") + cmd.Flags().String("id", "", "lists only tenant with the given tenant id") + cmd.Flags().String("email", "", "lists only tenant with the given email address") + }, + CreateCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().String("name", "", "the name of the tenant to create") + cmd.Flags().String("description", "", "the description of the tenant to create") + cmd.Flags().String("email", "", "the email of the tenant to create") + cmd.Flags().String("avatar-url", "", "the avatar url of the tenant to create") + }, + CreateRequestFromCLI: func() (*adminv2.TenantServiceCreateRequest, error) { + return &adminv2.TenantServiceCreateRequest{ + Name: viper.GetString("name"), + Description: pointer.PointerOrNil(viper.GetString("description")), + Email: pointer.PointerOrNil(viper.GetString("email")), + AvatarUrl: pointer.PointerOrNil(viper.GetString("avatar-url")), + }, nil + }, + OnlyCmds: genericcli.OnlyCmds(genericcli.ListCmd, genericcli.CreateCmd), + ValidArgsFn: w.c.Completion.AdminTenantListCompletion, + } + + return genericcli.NewCmds(cmdsConfig) +} + +func (c *tenant) Get(id string) (*apiv2.Tenant, error) { + panic("unimplemented") +} + +func (c *tenant) List() ([]*apiv2.Tenant, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &adminv2.TenantServiceListRequest{ + Name: pointer.PointerOrNil(viper.GetString("name")), + Login: pointer.PointerOrNil(viper.GetString("id")), + Email: pointer.PointerOrNil(viper.GetString("email")), + } + + resp, err := c.c.Client.Adminv2().Tenant().List(ctx, req) + if err != nil { + return nil, fmt.Errorf("failed to list tenants: %w", err) + } + + return resp.GetTenants(), nil +} + +func (c *tenant) Create(rq *adminv2.TenantServiceCreateRequest) (*apiv2.Tenant, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + resp, err := c.c.Client.Adminv2().Tenant().Create(ctx, rq) + if err != nil { + return nil, fmt.Errorf("failed to create tenant: %w", err) + } + + return resp.Tenant, nil +} + +func (c *tenant) Delete(id string) (*apiv2.Tenant, error) { + panic("unimplemented") +} + +func (c *tenant) Convert(r *apiv2.Tenant) (string, *adminv2.TenantServiceCreateRequest, any, error) { + panic("unimplemented") +} + +func (c *tenant) Update(rq any) (*apiv2.Tenant, error) { + panic("unimplemented") +} diff --git a/cmd/api/v1/tenant.go b/cmd/api/v1/tenant.go index c26fe7e..f94258c 100644 --- a/cmd/api/v1/tenant.go +++ b/cmd/api/v1/tenant.go @@ -41,7 +41,6 @@ func newTenantCmd(c *config.Config) *cobra.Command { cmd.Flags().String("name", "", "the name of the tenant to create") cmd.Flags().String("description", "", "the description of the tenant to create") cmd.Flags().String("email", "", "the email of the tenant to create") - cmd.Flags().String("phone", "", "the phone number of the tenant to create") cmd.Flags().String("avatar-url", "", "the avatar url of the tenant to create") }, CreateRequestFromCLI: w.createRequestFromCLI, diff --git a/cmd/common_test.go b/cmd/common_test.go index ce7f960..bd80e37 100644 --- a/cmd/common_test.go +++ b/cmd/common_test.go @@ -8,11 +8,9 @@ import ( "os" "strings" "testing" - "time" "slices" - "bou.ke/monkey" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" apitests "github.com/metal-stack/api/go/tests" @@ -28,12 +26,6 @@ import ( "sigs.k8s.io/yaml" ) -var testTime = time.Date(2022, time.May, 19, 1, 2, 3, 4, time.UTC) - -func init() { - _ = monkey.Patch(time.Now, func() time.Time { return testTime }) -} - type Test[R any] struct { Name string Cmd func(want R) []string diff --git a/docs/metalctlv2_tenant_create.md b/docs/metalctlv2_tenant_create.md index 48b7a0e..86f7da7 100644 --- a/docs/metalctlv2_tenant_create.md +++ b/docs/metalctlv2_tenant_create.md @@ -27,7 +27,6 @@ metalctlv2 tenant create [flags] -h, --help help for create --name string the name of the tenant to create - --phone string the phone number of the tenant to create --skip-security-prompts skips security prompt for bulk operations --timestamps when used with --file (bulk operation): prints timestamps in-between the operations ``` diff --git a/go.mod b/go.mod index 1b2f7a0..fe32d8e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,6 @@ module github.com/metal-stack/cli go 1.25 require ( - bou.ke/monkey v1.0.2 - connectrpc.com/connect v1.19.1 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 @@ -23,6 +21,7 @@ require ( require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 // indirect + connectrpc.com/connect v1.19.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/clipperhouse/uax29/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect diff --git a/go.sum b/go.sum index 4846edb..1f721ba 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= -bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 h1:31on4W/yPcV4nZHL4+UCiCvLPsMqe/vJcNg8Rci0scc= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1/go.mod h1:fUl8CEN/6ZAMk6bP8ahBJPUJw7rbp+j4x+wCcYi2IG4= connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=