Skip to content

Commit

Permalink
feat: add describe/update command, adapt create (#1060)
Browse files Browse the repository at this point in the history
Co-authored-by: David Ragot <[email protected]>
  • Loading branch information
Dav-14 and David Ragot authored Dec 29, 2023
1 parent 250f4e9 commit 73af204
Show file tree
Hide file tree
Showing 19 changed files with 1,017 additions and 358 deletions.
21 changes: 10 additions & 11 deletions components/fctl/cmd/cloud/organizations/create.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package organizations

import (
"github.com/formancehq/fctl/cmd/cloud/organizations/internal"
"github.com/formancehq/fctl/membershipclient"
fctl "github.com/formancehq/fctl/pkg"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
)

type CreateStore struct {
OrganizationId string `json:"organizationId"`
OrganizationName string `json:"organizationName"`
Organization *membershipclient.Organization `json:"organization"`
}
type CreateController struct {
store *CreateStore
Expand All @@ -28,10 +27,12 @@ func NewCreateController() *CreateController {
}

func NewCreateCommand() *cobra.Command {
return fctl.NewCommand("create <name>",
return fctl.NewCommand("create <name> --default-stack-role <defaultStackRole...> --default-organization-role <defaultOrganizationRole...>",
fctl.WithAliases("cr", "c"),
fctl.WithShortDescription("Create organization"),
fctl.WithArgs(cobra.ExactArgs(1)),
fctl.WithStringSliceFlag("default-stack-role", []string{}, "Default Stack Role"),
fctl.WithStringSliceFlag("default-organization-role", []string{}, "Default Organization Role"),
fctl.WithConfirmFlag(),
fctl.WithController[*CreateStore](NewCreateController()),
)
Expand Down Expand Up @@ -60,21 +61,19 @@ func (c *CreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
response, _, err := apiClient.DefaultApi.
CreateOrganization(cmd.Context()).
Body(membershipclient.OrganizationData{
Name: args[0],
Name: args[0],
DefaultOrganizationAccess: fctl.GetStringSlice(cmd, "default-organization-role"),
DefaultStackAccess: fctl.GetStringSlice(cmd, "default-stack-role"),
}).Execute()
if err != nil {
return nil, err
}

c.store.OrganizationId = response.Data.Id
c.store.OrganizationName = args[0]
c.store.Organization = response.Data

return c, nil
}

func (c *CreateController) Render(cmd *cobra.Command, args []string) error {
pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Organization '%s' created with ID: %s", c.store.OrganizationName, c.store.OrganizationId)

return nil

return internal.PrintOrganization(c.store.Organization)
}
67 changes: 67 additions & 0 deletions components/fctl/cmd/cloud/organizations/describe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package organizations

import (
"github.com/formancehq/fctl/cmd/cloud/organizations/internal"
"github.com/formancehq/fctl/membershipclient"
fctl "github.com/formancehq/fctl/pkg"
"github.com/spf13/cobra"
)

type DescribeStore struct {
Organization *membershipclient.Organization `json:"organization"`
}
type DescribeController struct {
store *DescribeStore
}

var _ fctl.Controller[*DescribeStore] = (*DescribeController)(nil)

func NewDefaultDescribeStore() *DescribeStore {
return &DescribeStore{}
}

func NewDescribeController() *DescribeController {
return &DescribeController{
store: NewDefaultDescribeStore(),
}
}

func NewDescribeCommand() *cobra.Command {
return fctl.NewCommand("describe <organizationId>",
fctl.WithShortDescription("Describe organization"),
fctl.WithArgs(cobra.ExactArgs(1)),
fctl.WithConfirmFlag(),
fctl.WithController[*DescribeStore](NewDescribeController()),
)
}

func (c *DescribeController) GetStore() *DescribeStore {
return c.store
}

func (c *DescribeController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) {

cfg, err := fctl.GetConfig(cmd)
if err != nil {
return nil, err
}

apiClient, err := fctl.NewMembershipClient(cmd, cfg)
if err != nil {
return nil, err
}

response, _, err := apiClient.DefaultApi.
ReadOrganization(cmd.Context(), args[0]).Execute()
if err != nil {
return nil, err
}

c.store.Organization = response.Data

return c, nil
}

func (c *DescribeController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintOrganization(c.store.Organization)
}
31 changes: 31 additions & 0 deletions components/fctl/cmd/cloud/organizations/internal/print.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package internal

import (
"strings"

"github.com/formancehq/fctl/membershipclient"
"github.com/pterm/pterm"
)

func PrintOrganization(organization *membershipclient.Organization) error {
pterm.DefaultSection.Println("Organization")

data := pterm.TableData{
{"ID", organization.Id},
{"Name", organization.Name},
{"Default Stack Role", func() string {
if len(organization.DefaultStackAccess) == 0 {
return "None"
}
return strings.Join(organization.DefaultStackAccess, ", ")
}()},
{"Default Organization Role", func() string {
if len(organization.DefaultOrganizationAccess) == 0 {
return "None"
}
return strings.Join(organization.DefaultOrganizationAccess, ", ")
}()},
}

return pterm.DefaultTable.WithHasHeader().WithData(data).Render()
}
2 changes: 2 additions & 0 deletions components/fctl/cmd/cloud/organizations/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ func NewCommand() *cobra.Command {
NewListCommand(),
NewCreateCommand(),
NewDeleteCommand(),
NewUpdateCommand(),
NewDescribeCommand(),
users.NewCommand(),
invitations.NewCommand(),
),
Expand Down
102 changes: 102 additions & 0 deletions components/fctl/cmd/cloud/organizations/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package organizations

import (
"github.com/formancehq/fctl/cmd/cloud/organizations/internal"
"github.com/formancehq/fctl/membershipclient"
fctl "github.com/formancehq/fctl/pkg"
"github.com/spf13/cobra"
)

type UpdateStore struct {
Organization *membershipclient.Organization `json:"organization"`
}
type UpdateController struct {
store *UpdateStore
}

var _ fctl.Controller[*UpdateStore] = (*UpdateController)(nil)

func NewDefaultUpdateStore() *UpdateStore {
return &UpdateStore{}
}

func NewUpdateController() *UpdateController {
return &UpdateController{
store: NewDefaultUpdateStore(),
}
}

func NewUpdateCommand() *cobra.Command {
return fctl.NewCommand("update <organizationId> --name <name> --default-stack-role <defaultStackRole...> --default-organization-role <defaultOrganizationRole...>",
fctl.WithAliases("update"),
fctl.WithShortDescription("Update organization"),
fctl.WithArgs(cobra.ExactArgs(1)),
fctl.WithConfirmFlag(),
fctl.WithStringFlag("name", "", "Organization Name"),
fctl.WithStringSliceFlag("default-stack-role", []string{}, "Default Stack Role"),
fctl.WithStringSliceFlag("default-organization-role", []string{}, "Default Organization Role"),
fctl.WithController[*UpdateStore](NewUpdateController()),
)
}

func (c *UpdateController) GetStore() *UpdateStore {
return c.store
}

func (c *UpdateController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) {

cfg, err := fctl.GetConfig(cmd)
if err != nil {
return nil, err
}

apiClient, err := fctl.NewMembershipClient(cmd, cfg)
if err != nil {
return nil, err
}

if !fctl.CheckOrganizationApprobation(cmd, "You are about to update an organization") {
return nil, fctl.ErrMissingApproval
}

org, _, err := apiClient.DefaultApi.ReadOrganization(cmd.Context(), args[0]).Execute()
if err != nil {
return nil, err
}

preparedData := membershipclient.OrganizationData{
Name: func() string {
if cmd.Flags().Changed("name") {
return cmd.Flag("name").Value.String()
}
return org.Data.Name
}(),
DefaultOrganizationAccess: func() []string {
if cmd.Flags().Changed("default-organization-role") {
return fctl.GetStringSlice(cmd, "default-organization-role")
}
return org.Data.DefaultOrganizationAccess
}(),
DefaultStackAccess: func() []string {
if cmd.Flags().Changed("default-stack-role") {
return fctl.GetStringSlice(cmd, "default-stack-role")
}
return org.Data.DefaultStackAccess
}(),
}

response, _, err := apiClient.DefaultApi.
UpdateOrganization(cmd.Context(), args[0]).OrganizationData(preparedData).Execute()

if err != nil {
return nil, err
}

c.store.Organization = response.Data

return c, nil
}

func (c *UpdateController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintOrganization(c.store.Organization)
}
51 changes: 51 additions & 0 deletions components/fctl/membership-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ReadOrganizationResponse'
put:
summary: Update organization
operationId: updateOrganization
parameters:
- name: organizationId
in: path
schema:
type: string
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OrganizationData'
responses:
200:
description: Organization updated
content:
application/json:
schema:
$ref: '#/components/schemas/ReadOrganizationResponse'
400:
description: Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Delete organization
operationId: deleteOrganization
Expand Down Expand Up @@ -1067,6 +1094,18 @@ components:
name:
type: string
description: Organization name
defaultOrganizationAccess:
type: array
items:
allOf:
- type: string
enum: [ADMIN, GUEST]
defaultStackAccess:
type: array
items:
allOf:
- type: string
enum: [ADMIN, GUEST]
Organization:
allOf:
- $ref: '#/components/schemas/OrganizationData'
Expand All @@ -1087,6 +1126,18 @@ components:
availableSandboxes:
type: integer
description: Number of available sandboxes
defaultOrganizationAccess:
type: array
items:
allOf:
- type: string
enum: [ADMIN, GUEST]
defaultStackAccess:
type: array
items:
allOf:
- type: string
enum: [ADMIN, GUEST]
StackData:
type: object
required:
Expand Down
1 change: 1 addition & 0 deletions components/fctl/membershipclient/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Class | Method | HTTP request | Description
*DefaultApi* | [**ReadOrganization**](docs/DefaultApi.md#readorganization) | **Get** /organizations/{organizationId} | Read organization
*DefaultApi* | [**ReadUserOfOrganization**](docs/DefaultApi.md#readuseroforganization) | **Get** /organizations/{organizationId}/users/{userId} | Read user of organization
*DefaultApi* | [**RestoreStack**](docs/DefaultApi.md#restorestack) | **Put** /organizations/{organizationId}/stacks/{stackId}/restore | Restore stack
*DefaultApi* | [**UpdateOrganization**](docs/DefaultApi.md#updateorganization) | **Put** /organizations/{organizationId} | Update organization
*DefaultApi* | [**UpsertOrganizationUser**](docs/DefaultApi.md#upsertorganizationuser) | **Put** /organizations/{organizationId}/users/{userId} | Update user role within an organization
*DefaultApi* | [**UpsertStackUserAccess**](docs/DefaultApi.md#upsertstackuseraccess) | **Put** /organizations/{organizationId}/stacks/{stackId}/users/{userId} | Update stack user access role within an organization

Expand Down
Loading

0 comments on commit 73af204

Please sign in to comment.