Skip to content

Commit d96adad

Browse files
authored
chore: add cli command to fetch group sync settings as json (#14694)
* chore: add cli command to fetch group sync settings as json
1 parent 45160c7 commit d96adad

20 files changed

+626
-13
lines changed

cli/organization.go

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func (r *RootCmd) organizations() *serpent.Command {
2626
r.createOrganization(),
2727
r.organizationMembers(orgContext),
2828
r.organizationRoles(orgContext),
29+
r.organizationSettings(orgContext),
2930
},
3031
}
3132

cli/organizationsettings.go

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package cli
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
10+
"github.com/google/uuid"
11+
"golang.org/x/xerrors"
12+
13+
"github.com/coder/coder/v2/codersdk"
14+
"github.com/coder/serpent"
15+
)
16+
17+
func (r *RootCmd) organizationSettings(orgContext *OrganizationContext) *serpent.Command {
18+
settings := []organizationSetting{
19+
{
20+
Name: "group-sync",
21+
Aliases: []string{"groupsync"},
22+
Short: "Group sync settings to sync groups from an IdP.",
23+
Patch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error) {
24+
var req codersdk.GroupSyncSettings
25+
err := json.Unmarshal(input, &req)
26+
if err != nil {
27+
return nil, xerrors.Errorf("unmarshalling group sync settings: %w", err)
28+
}
29+
return cli.PatchGroupIDPSyncSettings(ctx, org.String(), req)
30+
},
31+
Fetch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error) {
32+
return cli.GroupIDPSyncSettings(ctx, org.String())
33+
},
34+
},
35+
{
36+
Name: "role-sync",
37+
Aliases: []string{"rolesync"},
38+
Short: "Role sync settings to sync organization roles from an IdP.",
39+
Patch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error) {
40+
var req codersdk.RoleSyncSettings
41+
err := json.Unmarshal(input, &req)
42+
if err != nil {
43+
return nil, xerrors.Errorf("unmarshalling role sync settings: %w", err)
44+
}
45+
return cli.PatchRoleIDPSyncSettings(ctx, org.String(), req)
46+
},
47+
Fetch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error) {
48+
return cli.RoleIDPSyncSettings(ctx, org.String())
49+
},
50+
},
51+
}
52+
cmd := &serpent.Command{
53+
Use: "settings",
54+
Short: "Manage organization settings.",
55+
Aliases: []string{"setting"},
56+
Handler: func(inv *serpent.Invocation) error {
57+
return inv.Command.HelpHandler(inv)
58+
},
59+
Children: []*serpent.Command{
60+
r.printOrganizationSetting(orgContext, settings),
61+
r.setOrganizationSettings(orgContext, settings),
62+
},
63+
}
64+
return cmd
65+
}
66+
67+
type organizationSetting struct {
68+
Name string
69+
Aliases []string
70+
Short string
71+
Patch func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error)
72+
Fetch func(ctx context.Context, cli *codersdk.Client, org uuid.UUID) (any, error)
73+
}
74+
75+
func (r *RootCmd) setOrganizationSettings(orgContext *OrganizationContext, settings []organizationSetting) *serpent.Command {
76+
client := new(codersdk.Client)
77+
cmd := &serpent.Command{
78+
Use: "set",
79+
Short: "Update specified organization setting.",
80+
Long: FormatExamples(
81+
Example{
82+
Description: "Update group sync settings.",
83+
Command: "coder organization settings set groupsync < input.json",
84+
},
85+
),
86+
Options: []serpent.Option{},
87+
Middleware: serpent.Chain(
88+
serpent.RequireNArgs(0),
89+
r.InitClient(client),
90+
),
91+
Handler: func(inv *serpent.Invocation) error {
92+
return inv.Command.HelpHandler(inv)
93+
},
94+
}
95+
96+
for _, set := range settings {
97+
set := set
98+
patch := set.Patch
99+
cmd.Children = append(cmd.Children, &serpent.Command{
100+
Use: set.Name,
101+
Aliases: set.Aliases,
102+
Short: set.Short,
103+
Options: []serpent.Option{},
104+
Middleware: serpent.Chain(
105+
serpent.RequireNArgs(0),
106+
r.InitClient(client),
107+
),
108+
Handler: func(inv *serpent.Invocation) error {
109+
ctx := inv.Context()
110+
org, err := orgContext.Selected(inv, client)
111+
if err != nil {
112+
return err
113+
}
114+
115+
// Read in the json
116+
inputData, err := io.ReadAll(inv.Stdin)
117+
if err != nil {
118+
return xerrors.Errorf("reading stdin: %w", err)
119+
}
120+
121+
output, err := patch(ctx, client, org.ID, inputData)
122+
if err != nil {
123+
return xerrors.Errorf("patching %q: %w", set.Name, err)
124+
}
125+
126+
settingJSON, err := json.Marshal(output)
127+
if err != nil {
128+
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
129+
}
130+
131+
var dst bytes.Buffer
132+
err = json.Indent(&dst, settingJSON, "", "\t")
133+
if err != nil {
134+
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
135+
}
136+
137+
_, err = fmt.Fprintln(inv.Stdout, dst.String())
138+
return err
139+
},
140+
})
141+
}
142+
143+
return cmd
144+
}
145+
146+
func (r *RootCmd) printOrganizationSetting(orgContext *OrganizationContext, settings []organizationSetting) *serpent.Command {
147+
client := new(codersdk.Client)
148+
cmd := &serpent.Command{
149+
Use: "show",
150+
Short: "Outputs specified organization setting.",
151+
Long: FormatExamples(
152+
Example{
153+
Description: "Output group sync settings.",
154+
Command: "coder organization settings show groupsync",
155+
},
156+
),
157+
Options: []serpent.Option{},
158+
Middleware: serpent.Chain(
159+
serpent.RequireNArgs(0),
160+
r.InitClient(client),
161+
),
162+
Handler: func(inv *serpent.Invocation) error {
163+
return inv.Command.HelpHandler(inv)
164+
},
165+
}
166+
167+
for _, set := range settings {
168+
set := set
169+
fetch := set.Fetch
170+
cmd.Children = append(cmd.Children, &serpent.Command{
171+
Use: set.Name,
172+
Aliases: set.Aliases,
173+
Short: set.Short,
174+
Options: []serpent.Option{},
175+
Middleware: serpent.Chain(
176+
serpent.RequireNArgs(0),
177+
r.InitClient(client),
178+
),
179+
Handler: func(inv *serpent.Invocation) error {
180+
ctx := inv.Context()
181+
org, err := orgContext.Selected(inv, client)
182+
if err != nil {
183+
return err
184+
}
185+
186+
output, err := fetch(ctx, client, org.ID)
187+
if err != nil {
188+
return xerrors.Errorf("patching %q: %w", set.Name, err)
189+
}
190+
191+
settingJSON, err := json.Marshal(output)
192+
if err != nil {
193+
return fmt.Errorf("failed to marshal organization setting %s: %w", inv.Args[0], err)
194+
}
195+
196+
var dst bytes.Buffer
197+
err = json.Indent(&dst, settingJSON, "", "\t")
198+
if err != nil {
199+
return fmt.Errorf("failed to indent organization setting as json %s: %w", inv.Args[0], err)
200+
}
201+
202+
_, err = fmt.Fprintln(inv.Stdout, dst.String())
203+
return err
204+
},
205+
})
206+
}
207+
208+
return cmd
209+
}

cli/root.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"golang.org/x/mod/semver"
3030
"golang.org/x/xerrors"
3131

32+
"github.com/coder/coder/v2/coderd/database/db2sdk"
3233
"github.com/coder/pretty"
3334

3435
"github.com/coder/coder/v2/buildinfo"
@@ -657,7 +658,10 @@ func (o *OrganizationContext) Selected(inv *serpent.Invocation, client *codersdk
657658
}
658659

659660
// No org selected, and we are more than 1? Return an error.
660-
return codersdk.Organization{}, xerrors.Errorf("Must select an organization with --org=<org_name>.")
661+
validOrgs := db2sdk.List(orgs, func(org codersdk.Organization) string {
662+
return fmt.Sprintf("%q", org.Name)
663+
})
664+
return codersdk.Organization{}, xerrors.Errorf("Must select an organization with --org=<org_name>. Choose from: %s", strings.Join(validOrgs, ", "))
661665
}
662666

663667
func splitNamedWorkspace(identifier string) (owner string, workspaceName string, err error) {

cli/testdata/coder_organizations_--help.golden

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ USAGE:
88
Aliases: organization, org, orgs
99

1010
SUBCOMMANDS:
11-
create Create a new organization.
12-
members Manage organization members
13-
roles Manage organization roles.
14-
show Show the organization. Using "selected" will show the selected
15-
organization from the "--org" flag. Using "me" will show all
16-
organizations you are a member of.
11+
create Create a new organization.
12+
members Manage organization members
13+
roles Manage organization roles.
14+
settings Manage organization settings.
15+
show Show the organization. Using "selected" will show the selected
16+
organization from the "--org" flag. Using "me" will show all
17+
organizations you are a member of.
1718

1819
OPTIONS:
1920
-O, --org string, $CODER_ORGANIZATION
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
coder v0.0.0-devel
2+
3+
USAGE:
4+
coder organizations settings
5+
6+
Manage organization settings.
7+
8+
Aliases: setting
9+
10+
SUBCOMMANDS:
11+
set Update specified organization setting.
12+
show Outputs specified organization setting.
13+
14+
———
15+
Run `coder --help` for a list of global options.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
coder v0.0.0-devel
2+
3+
USAGE:
4+
coder organizations settings set
5+
6+
Update specified organization setting.
7+
8+
- Update group sync settings.:
9+
10+
$ coder organization settings set groupsync < input.json
11+
12+
SUBCOMMANDS:
13+
group-sync Group sync settings to sync groups from an IdP.
14+
role-sync Role sync settings to sync organization roles from an IdP.
15+
16+
———
17+
Run `coder --help` for a list of global options.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
coder v0.0.0-devel
2+
3+
USAGE:
4+
coder organizations settings set
5+
6+
Update specified organization setting.
7+
8+
- Update group sync settings.:
9+
10+
$ coder organization settings set groupsync < input.json
11+
12+
SUBCOMMANDS:
13+
group-sync Group sync settings to sync groups from an IdP.
14+
role-sync Role sync settings to sync organization roles from an IdP.
15+
16+
———
17+
Run `coder --help` for a list of global options.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
coder v0.0.0-devel
2+
3+
USAGE:
4+
coder organizations settings show
5+
6+
Outputs specified organization setting.
7+
8+
- Output group sync settings.:
9+
10+
$ coder organization settings show groupsync
11+
12+
SUBCOMMANDS:
13+
group-sync Group sync settings to sync groups from an IdP.
14+
role-sync Role sync settings to sync organization roles from an IdP.
15+
16+
———
17+
Run `coder --help` for a list of global options.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
coder v0.0.0-devel
2+
3+
USAGE:
4+
coder organizations settings show
5+
6+
Outputs specified organization setting.
7+
8+
- Output group sync settings.:
9+
10+
$ coder organization settings show groupsync
11+
12+
SUBCOMMANDS:
13+
group-sync Group sync settings to sync groups from an IdP.
14+
role-sync Role sync settings to sync organization roles from an IdP.
15+
16+
———
17+
Run `coder --help` for a list of global options.

docs/manifest.json

+35
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,41 @@
857857
"description": "Show role(s)",
858858
"path": "reference/cli/organizations_roles_show.md"
859859
},
860+
{
861+
"title": "organizations settings",
862+
"description": "Manage organization settings.",
863+
"path": "reference/cli/organizations_settings.md"
864+
},
865+
{
866+
"title": "organizations settings set",
867+
"description": "Update specified organization setting.",
868+
"path": "reference/cli/organizations_settings_set.md"
869+
},
870+
{
871+
"title": "organizations settings set group-sync",
872+
"description": "Group sync settings to sync groups from an IdP.",
873+
"path": "reference/cli/organizations_settings_set_group-sync.md"
874+
},
875+
{
876+
"title": "organizations settings set role-sync",
877+
"description": "Role sync settings to sync organization roles from an IdP.",
878+
"path": "reference/cli/organizations_settings_set_role-sync.md"
879+
},
880+
{
881+
"title": "organizations settings show",
882+
"description": "Outputs specified organization setting.",
883+
"path": "reference/cli/organizations_settings_show.md"
884+
},
885+
{
886+
"title": "organizations settings show group-sync",
887+
"description": "Group sync settings to sync groups from an IdP.",
888+
"path": "reference/cli/organizations_settings_show_group-sync.md"
889+
},
890+
{
891+
"title": "organizations settings show role-sync",
892+
"description": "Role sync settings to sync organization roles from an IdP.",
893+
"path": "reference/cli/organizations_settings_show_role-sync.md"
894+
},
860895
{
861896
"title": "organizations show",
862897
"description": "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.",

0 commit comments

Comments
 (0)