@@ -153,6 +153,7 @@ func (r *RootCmd) editOrganizationRole(orgContext *OrganizationContext) *serpent
153
153
return err
154
154
}
155
155
156
+ createNewRole := true
156
157
var customRole codersdk.Role
157
158
if jsonInput {
158
159
// JSON Upload mode
@@ -174,17 +175,30 @@ func (r *RootCmd) editOrganizationRole(orgContext *OrganizationContext) *serpent
174
175
}
175
176
return xerrors .Errorf ("json input does not appear to be a valid role" )
176
177
}
178
+
179
+ existingRoles , err := client .ListOrganizationRoles (ctx , org .ID )
180
+ if err != nil {
181
+ return xerrors .Errorf ("listing existing roles: %w" , err )
182
+ }
183
+ for _ , existingRole := range existingRoles {
184
+ if strings .EqualFold (customRole .Name , existingRole .Name ) {
185
+ // Editing an existing role
186
+ createNewRole = false
187
+ break
188
+ }
189
+ }
177
190
} else {
178
191
if len (inv .Args ) == 0 {
179
192
return xerrors .Errorf ("missing role name argument, usage: \" coder organizations roles edit <role_name>\" " )
180
193
}
181
194
182
- interactiveRole , err := interactiveOrgRoleEdit (inv , org .ID , client )
195
+ interactiveRole , newRole , err := interactiveOrgRoleEdit (inv , org .ID , client )
183
196
if err != nil {
184
197
return xerrors .Errorf ("editing role: %w" , err )
185
198
}
186
199
187
200
customRole = * interactiveRole
201
+ createNewRole = newRole
188
202
189
203
preview := fmt .Sprintf ("permissions: %d site, %d org, %d user" ,
190
204
len (customRole .SitePermissions ), len (customRole .OrganizationPermissions ), len (customRole .UserPermissions ))
@@ -203,7 +217,12 @@ func (r *RootCmd) editOrganizationRole(orgContext *OrganizationContext) *serpent
203
217
// Do not actually post
204
218
updated = customRole
205
219
} else {
206
- updated , err = client .PatchOrganizationRole (ctx , customRole )
220
+ switch createNewRole {
221
+ case true :
222
+ updated , err = client .CreateOrganizationRole (ctx , customRole )
223
+ default :
224
+ updated , err = client .UpdateOrganizationRole (ctx , customRole )
225
+ }
207
226
if err != nil {
208
227
return xerrors .Errorf ("patch role: %w" , err )
209
228
}
@@ -223,11 +242,12 @@ func (r *RootCmd) editOrganizationRole(orgContext *OrganizationContext) *serpent
223
242
return cmd
224
243
}
225
244
226
- func interactiveOrgRoleEdit (inv * serpent.Invocation , orgID uuid.UUID , client * codersdk.Client ) (* codersdk.Role , error ) {
245
+ func interactiveOrgRoleEdit (inv * serpent.Invocation , orgID uuid.UUID , client * codersdk.Client ) (* codersdk.Role , bool , error ) {
246
+ newRole := false
227
247
ctx := inv .Context ()
228
248
roles , err := client .ListOrganizationRoles (ctx , orgID )
229
249
if err != nil {
230
- return nil , xerrors .Errorf ("listing roles: %w" , err )
250
+ return nil , newRole , xerrors .Errorf ("listing roles: %w" , err )
231
251
}
232
252
233
253
// Make sure the role actually exists first
@@ -246,22 +266,23 @@ func interactiveOrgRoleEdit(inv *serpent.Invocation, orgID uuid.UUID, client *co
246
266
IsConfirm : true ,
247
267
})
248
268
if err != nil {
249
- return nil , xerrors .Errorf ("abort: %w" , err )
269
+ return nil , newRole , xerrors .Errorf ("abort: %w" , err )
250
270
}
251
271
252
272
originalRole .Role = codersdk.Role {
253
273
Name : inv .Args [0 ],
254
274
OrganizationID : orgID .String (),
255
275
}
276
+ newRole = true
256
277
}
257
278
258
279
// Some checks since interactive mode is limited in what it currently sees
259
280
if len (originalRole .SitePermissions ) > 0 {
260
- return nil , xerrors .Errorf ("unable to edit role in interactive mode, it contains site wide permissions" )
281
+ return nil , newRole , xerrors .Errorf ("unable to edit role in interactive mode, it contains site wide permissions" )
261
282
}
262
283
263
284
if len (originalRole .UserPermissions ) > 0 {
264
- return nil , xerrors .Errorf ("unable to edit role in interactive mode, it contains user permissions" )
285
+ return nil , newRole , xerrors .Errorf ("unable to edit role in interactive mode, it contains user permissions" )
265
286
}
266
287
267
288
role := & originalRole .Role
@@ -283,13 +304,13 @@ customRoleLoop:
283
304
Options : append (permissionPreviews (role , allowedResources ), done , abort ),
284
305
})
285
306
if err != nil {
286
- return role , xerrors .Errorf ("selecting resource: %w" , err )
307
+ return role , newRole , xerrors .Errorf ("selecting resource: %w" , err )
287
308
}
288
309
switch selected {
289
310
case done :
290
311
break customRoleLoop
291
312
case abort :
292
- return role , xerrors .Errorf ("edit role %q aborted" , role .Name )
313
+ return role , newRole , xerrors .Errorf ("edit role %q aborted" , role .Name )
293
314
default :
294
315
strs := strings .Split (selected , "::" )
295
316
resource := strings .TrimSpace (strs [0 ])
@@ -300,7 +321,7 @@ customRoleLoop:
300
321
Defaults : defaultActions (role , resource ),
301
322
})
302
323
if err != nil {
303
- return role , xerrors .Errorf ("selecting actions for resource %q: %w" , resource , err )
324
+ return role , newRole , xerrors .Errorf ("selecting actions for resource %q: %w" , resource , err )
304
325
}
305
326
applyOrgResourceActions (role , resource , actions )
306
327
// back to resources!
@@ -309,7 +330,7 @@ customRoleLoop:
309
330
// This println is required because the prompt ends us on the same line as some text.
310
331
_ , _ = fmt .Println ()
311
332
312
- return role , nil
333
+ return role , newRole , nil
313
334
}
314
335
315
336
func applyOrgResourceActions (role * codersdk.Role , resource string , actions []string ) {
0 commit comments