Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
make cobra sub commands
  • Loading branch information
Emyrk committed Sep 17, 2024
commit ec78d0091f98c4c01a14cb1d4c9abf695c4b671f
228 changes: 139 additions & 89 deletions cli/organizationsettings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,80 @@ package cli

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"strings"

"github.com/google/uuid"
"golang.org/x/xerrors"

"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)

func (r *RootCmd) organizationSettings(orgContext *OrganizationContext) *serpent.Command {
settings := []organizationSetting{
{
Name: "group-sync",
Aliases: []string{"groupsync"},
Short: "Group sync settings to sync groups from an IdP.",
Patch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error) {
var req codersdk.GroupSyncSettings
err := json.Unmarshal(input, &req)
if err != nil {
return nil, xerrors.Errorf("unmarshalling group sync settings: %w", err)
}
return cli.PatchGroupIDPSyncSettings(ctx, org.String(), req)
},
Fetch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error) {
return cli.GroupIDPSyncSettings(ctx, org.String())
},
},
{
Name: "role-sync",
Aliases: []string{"rolesync"},
Short: "Role sync settings to sync organization roles from an IdP.",
Patch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error) {
var req codersdk.RoleSyncSettings
err := json.Unmarshal(input, &req)
if err != nil {
return nil, xerrors.Errorf("unmarshalling role sync settings: %w", err)
}
return cli.PatchRoleIDPSyncSettings(ctx, org.String(), req)
},
Fetch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error) {
return cli.RoleIDPSyncSettings(ctx, org.String())
},
},
}
cmd := &serpent.Command{
Use: "settings",
Short: "Manage organization settings.",
Aliases: []string{"setting"},
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Hidden: true,
Children: []*serpent.Command{
r.printOrganizationSetting(orgContext),
r.updateOrganizationSetting(orgContext),
r.printOrganizationSetting(orgContext, settings),
r.setOrganizationSettings(orgContext, settings),
},
}
return cmd
}

func (r *RootCmd) updateOrganizationSetting(orgContext *OrganizationContext) *serpent.Command {
type organizationSetting struct {
Name string
Aliases []string
Short string
Patch func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error)
Fetch func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error)
}

func (r *RootCmd) setOrganizationSettings(orgContext *OrganizationContext, settings []organizationSetting) *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Command{
Use: "set <groupsync | rolesync>",
Use: "set",
Short: "Update specified organization setting.",
Long: FormatExamples(
Example{
Expand All @@ -43,69 +85,68 @@ func (r *RootCmd) updateOrganizationSetting(orgContext *OrganizationContext) *se
),
Options: []serpent.Option{},
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
serpent.RequireNArgs(0),
r.InitClient(client),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
org, err := orgContext.Selected(inv, client)
if err != nil {
return err
}
return inv.Command.HelpHandler(inv)
},
}

// Read in the json
inputData, err := io.ReadAll(inv.Stdin)
if err != nil {
return xerrors.Errorf("reading stdin: %w", err)
}
for _, set := range settings {
set := set
patch := set.Patch
cmd.Children = append(cmd.Children, &serpent.Command{
Use: set.Name,
Aliases: set.Aliases,
Short: set.Short,
Options: []serpent.Option{},
Middleware: serpent.Chain(
serpent.RequireNArgs(0),
r.InitClient(client),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
org, err := orgContext.Selected(inv, client)
if err != nil {
return err
}

var setting any
switch strings.ToLower(inv.Args[0]) {
case "groupsync", "group-sync":
var req codersdk.GroupSyncSettings
err = json.Unmarshal(inputData, &req)
// Read in the json
inputData, err := io.ReadAll(inv.Stdin)
if err != nil {
return xerrors.Errorf("unmarshalling group sync settings: %w", err)
return xerrors.Errorf("reading stdin: %w", err)
}
setting, err = client.PatchGroupIDPSyncSettings(ctx, org.ID.String(), req)
case "rolesync", "role-sync":
var req codersdk.RoleSyncSettings
err = json.Unmarshal(inputData, &req)

output, err := patch(ctx, client, org.ID, inputData)
if err != nil {
return xerrors.Errorf("unmarshalling role sync settings: %w", err)
return xerrors.Errorf("patching %q: %w", set.Name, err)
}
setting, err = client.PatchRoleIDPSyncSettings(ctx, org.ID.String(), req)
default:
_, _ = fmt.Fprintln(inv.Stderr, "Valid organization settings are: 'groupsync', 'rolesync'")
return fmt.Errorf("unknown organization setting %s", inv.Args[0])
}

if err != nil {
return fmt.Errorf("failed to get organization setting %s: %w", inv.Args[0], err)
}

settingJSON, err := json.Marshal(setting)
if err != nil {
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
}

var dst bytes.Buffer
err = json.Indent(&dst, settingJSON, "", "\t")
if err != nil {
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
}

_, err = fmt.Fprintln(inv.Stdout, dst.String())
return err
},

settingJSON, err := json.Marshal(output)
if err != nil {
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
}

var dst bytes.Buffer
err = json.Indent(&dst, settingJSON, "", "\t")
if err != nil {
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
}

_, err = fmt.Fprintln(inv.Stdout, dst.String())
return err
},
})
}

return cmd
}

func (r *RootCmd) printOrganizationSetting(orgContext *OrganizationContext) *serpent.Command {
func (r *RootCmd) printOrganizationSetting(orgContext *OrganizationContext, settings []organizationSetting) *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Command{
Use: "show <groupsync | rolesync>",
Use: "show",
Short: "Outputs specified organization setting.",
Long: FormatExamples(
Example{
Expand All @@ -115,45 +156,54 @@ func (r *RootCmd) printOrganizationSetting(orgContext *OrganizationContext) *ser
),
Options: []serpent.Option{},
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
serpent.RequireNArgs(0),
r.InitClient(client),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
org, err := orgContext.Selected(inv, client)
if err != nil {
return err
}

var setting any
switch strings.ToLower(inv.Args[0]) {
case "groupsync", "group-sync":
setting, err = client.GroupIDPSyncSettings(ctx, org.ID.String())
case "rolesync", "role-sync":
setting, err = client.RoleIDPSyncSettings(ctx, org.ID.String())
default:
_, _ = fmt.Fprintln(inv.Stderr, "Valid organization settings are: 'groupsync', 'rolesync'")
return fmt.Errorf("unknown organization setting %s", inv.Args[0])
}

if err != nil {
return fmt.Errorf("failed to get organization setting %s: %w", inv.Args[0], err)
}

settingJSON, err := json.Marshal(setting)
if err != nil {
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
}

var dst bytes.Buffer
err = json.Indent(&dst, settingJSON, "", "\t")
if err != nil {
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
}

_, err = fmt.Fprintln(inv.Stdout, dst.String())
return err
return inv.Command.HelpHandler(inv)
},
}

for _, set := range settings {
set := set
fetch := set.Fetch
cmd.Children = append(cmd.Children, &serpent.Command{
Use: set.Name,
Aliases: set.Aliases,
Short: set.Short,
Options: []serpent.Option{},
Middleware: serpent.Chain(
serpent.RequireNArgs(0),
r.InitClient(client),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
org, err := orgContext.Selected(inv, client)
if err != nil {
return err
}

output, err := fetch(ctx, client, org.ID)
if err != nil {
return xerrors.Errorf("patching %q: %w", set.Name, err)
}

settingJSON, err := json.Marshal(output)
if err != nil {
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
}

var dst bytes.Buffer
err = json.Indent(&dst, settingJSON, "", "\t")
if err != nil {
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
}

_, err = fmt.Fprintln(inv.Stdout, dst.String())
return err
},
})
}

return cmd
}
1 change: 1 addition & 0 deletions cli/testdata/coder_organizations_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ SUBCOMMANDS:
create Create a new organization.
members Manage organization members
roles Manage organization roles.
settings Manage organization settings.
show Show the organization. Using "selected" will show the selected
organization from the "--org" flag. Using "me" will show all
organizations you are a member of.
Expand Down
15 changes: 15 additions & 0 deletions cli/testdata/coder_organizations_settings_--help.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
coder v0.0.0-devel

USAGE:
coder organizations settings

Manage organization settings.

Aliases: setting

SUBCOMMANDS:
set Update specified organization setting.
show Outputs specified organization setting.

———
Run `coder --help` for a list of global options.
17 changes: 17 additions & 0 deletions cli/testdata/coder_organizations_settings_set_--help.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
coder v0.0.0-devel

USAGE:
coder organizations settings set

Update specified organization setting.

- Update group sync settings.:

$ coder organization settings set groupsync < input.json

SUBCOMMANDS:
group-sync Group sync settings to sync groups from an IdP.
role-sync Role sync settings to sync organization roles from an IdP.

———
Run `coder --help` for a list of global options.
17 changes: 17 additions & 0 deletions cli/testdata/coder_organizations_settings_set_--help_--help.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
coder v0.0.0-devel

USAGE:
coder organizations settings set

Update specified organization setting.

- Update group sync settings.:

$ coder organization settings set groupsync < input.json

SUBCOMMANDS:
group-sync Group sync settings to sync groups from an IdP.
role-sync Role sync settings to sync organization roles from an IdP.

———
Run `coder --help` for a list of global options.
17 changes: 17 additions & 0 deletions cli/testdata/coder_organizations_settings_show_--help.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
coder v0.0.0-devel

USAGE:
coder organizations settings show

Outputs specified organization setting.

- Output group sync settings.:

$ coder organization settings show groupsync

SUBCOMMANDS:
group-sync Group sync settings to sync groups from an IdP.
role-sync Role sync settings to sync organization roles from an IdP.

———
Run `coder --help` for a list of global options.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
coder v0.0.0-devel

USAGE:
coder organizations settings show

Outputs specified organization setting.

- Output group sync settings.:

$ coder organization settings show groupsync

SUBCOMMANDS:
group-sync Group sync settings to sync groups from an IdP.
role-sync Role sync settings to sync organization roles from an IdP.

———
Run `coder --help` for a list of global options.
Loading