• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

astronomer / astro-cli / a0148992-dca3-4fc1-ac21-12621d5007e6

31 Mar 2026 09:15PM UTC coverage: 36.544% (-0.04%) from 36.583%
a0148992-dca3-4fc1-ac21-12621d5007e6

Pull #2063

circleci

jlaneve
fix: correct Pagnation -> Pagination typo in variable names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pull Request #2063: --json output and --format consistency pass

430 of 640 new or added lines in 14 files covered. (67.19%)

38 existing lines in 3 files now uncovered.

25131 of 68769 relevant lines covered (36.54%)

8.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.92
/cmd/cloud/workspace.go
1
package cloud
2

3
import (
4
        "fmt"
5
        "io"
6
        "os"
7
        "strconv"
8
        "strings"
9

10
        astrocore "github.com/astronomer/astro-cli/astro-client-core"
11
        "github.com/astronomer/astro-cli/cloud/organization"
12
        "github.com/astronomer/astro-cli/cloud/team"
13
        "github.com/astronomer/astro-cli/cloud/user"
14
        "github.com/astronomer/astro-cli/cloud/workspace"
15
        workspacetoken "github.com/astronomer/astro-cli/cloud/workspace-token"
16
        "github.com/astronomer/astro-cli/pkg/input"
17
        "github.com/astronomer/astro-cli/pkg/output"
18
        "github.com/astronomer/astro-cli/pkg/printutil"
19

20
        "github.com/pkg/errors"
21
        "github.com/spf13/cobra"
22
)
23

24
var (
25
        errInvalidWorkspaceRoleKey   = errors.New("invalid workspace role selection")
26
        workspaceID                  string
27
        addWorkspaceRole             string
28
        updateWorkspaceRole          string
29
        workspaceName                string
30
        workspaceDescription         string
31
        enforceCD                    string
32
        tokenName                    string
33
        tokenDescription             string
34
        tokenRole                    string
35
        orgTokenName                 string
36
        tokenID                      string
37
        orgTokenID                   string
38
        workspaceTokenID             string
39
        cleanTokenOutput             bool
40
        forceRotate                  bool
41
        tokenExpiration              int
42
        validWorkspaceRoles          []string
43
        workspaceListOutputFlags     output.Flags
44
        workspaceUserListOutputFlags output.Flags
45
        workspaceTeamListOutputFlags output.Flags
46
)
47

48
const (
49
        allowedWorkspaceRoleNames      = "WORKSPACE_MEMBER, WORKSPACE_AUTHOR, WORKSPACE_OPERATOR, WORKSPACE_OWNER"
50
        allowedWorkspaceRoleNamesProse = "WORKSPACE_MEMBER, WORKSPACE_AUTHOR, WORKSPACE_OPERATOR, and WORKSPACE_OWNER"
51
)
52

53
func init() {
1✔
54
        validWorkspaceRoles = []string{"WORKSPACE_MEMBER", "WORKSPACE_AUTHOR", "WORKSPACE_OPERATOR", "WORKSPACE_OWNER"}
1✔
55
}
1✔
56

57
func newWorkspaceCmd(out io.Writer) *cobra.Command {
90✔
58
        cmd := &cobra.Command{
90✔
59
                Use:     "workspace",
90✔
60
                Aliases: []string{"wo"},
90✔
61
                Short:   "Manage Astro Workspaces",
90✔
62
                Long:    "Create and manage Workspaces on Astro. Workspaces can contain multiple Deployments and can be shared across users.",
90✔
63
        }
90✔
64
        cmd.AddCommand(
90✔
65
                newWorkspaceListCmd(out),
90✔
66
                newWorkspaceSwitchCmd(out),
90✔
67
                newWorkspaceCreateCmd(out),
90✔
68
                newWorkspaceUpdateCmd(out),
90✔
69
                newWorkspaceDeleteCmd(out),
90✔
70
                newWorkspaceUserRootCmd(out),
90✔
71
                newWorkspaceTokenRootCmd(out),
90✔
72
                newWorkspaceTeamRootCmd(out),
90✔
73
        )
90✔
74
        return cmd
90✔
75
}
90✔
76

77
func newWorkspaceListCmd(out io.Writer) *cobra.Command {
90✔
78
        cmd := &cobra.Command{
90✔
79
                Use:     "list",
90✔
80
                Aliases: []string{"ls"},
90✔
81
                Short:   "List all Astro Workspaces in your organization",
90✔
82
                Long:    "List all Astro Workspaces you have access to in your current Organization. Use 'astro organization switch' to change Organizations.",
90✔
83
                Example: `  astro workspace list
90✔
84
  astro workspace list --json`,
90✔
85
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
86
                        return workspaceList(cmd, out)
2✔
87
                },
2✔
88
        }
89
        workspaceListOutputFlags.AddFlags(cmd)
90✔
90
        return cmd
90✔
91
}
92

93
func newWorkspaceSwitchCmd(out io.Writer) *cobra.Command {
90✔
94
        cmd := &cobra.Command{
90✔
95
                Use:     "switch [workspace name/id]",
90✔
96
                Aliases: []string{"sw"},
90✔
97
                Short:   "Switch to a different Astro Workspace",
90✔
98
                Long:    "Switch your active Astro Workspace. Subsequent deployment, user, and team commands run against the selected Workspace unless overridden with --workspace-id.",
90✔
99
                Args:    cobra.MaximumNArgs(1),
90✔
100
                Example: `
90✔
101
  $ astro workspace switch
90✔
102
  $ astro workspace switch my-workspace
90✔
103
`,
90✔
104
                RunE: func(cmd *cobra.Command, args []string) error {
91✔
105
                        return workspaceSwitch(cmd, out, args)
1✔
106
                },
1✔
107
        }
108
        return cmd
90✔
109
}
110

111
func newWorkspaceCreateCmd(out io.Writer) *cobra.Command {
90✔
112
        cmd := &cobra.Command{
90✔
113
                Use:     "create",
90✔
114
                Aliases: []string{"cr"},
90✔
115
                Short:   "Create an Astro Workspace",
90✔
116
                Long:    "Create a new Workspace in your current Organization. Workspaces group Deployments and control user access independently. Enable --enforce-cicd to require that all deploys to Deployments in this Workspace use an API token, blocking manual deploys from the CLI or UI.",
90✔
117
                Example: `
90✔
118
  $ astro workspace create --name "My Workspace" --description "Production pipelines"
90✔
119
  $ astro workspace create --name "My Workspace" --enforce-cicd ON
90✔
120
`,
90✔
121
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
122
                        return workspaceCreate(cmd, out)
4✔
123
                },
4✔
124
        }
125
        cmd.Flags().StringVarP(&workspaceName, "name", "n", "", "The Workspace's name. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
126
        cmd.Flags().StringVarP(&workspaceDescription, "description", "d", "", "Description of the Workspace. If the description contains a space, specify the entire description in quotes \"\"")
90✔
127
        cmd.Flags().StringVarP(&enforceCD, "enforce-cicd", "e", "OFF", "Provide this flag either ON/OFF. ON means deploys to deployments must use an API Key or Token. This essentially forces Deploys to happen through CI/CD")
90✔
128
        return cmd
90✔
129
}
130

131
func newWorkspaceUpdateCmd(out io.Writer) *cobra.Command {
90✔
132
        cmd := &cobra.Command{
90✔
133
                Use:     "update [workspace_id]",
90✔
134
                Aliases: []string{"up"},
90✔
135
                Short:   "Update an Astro Workspace",
90✔
136
                Long:    "Update a Workspace's name, description, or CI/CD enforcement policy. Changing --enforce-cicd affects all Deployments in the Workspace: when enabled, only API token-authenticated deploys are allowed. If no Workspace ID is provided, you will be prompted to select one.",
90✔
137
                Args:    cobra.MaximumNArgs(1),
90✔
138
                Example: `
90✔
139
  $ astro workspace update clxxxxxxxxx --name "New Name"
90✔
140
  $ astro workspace update clxxxxxxxxx --description "Updated description" --enforce-cicd ON
90✔
141
`,
90✔
142
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
143
                        return workspaceUpdate(cmd, out, args)
5✔
144
                },
5✔
145
        }
146
        cmd.Flags().StringVarP(&workspaceName, "name", "n", "", "The Workspace's name. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
147
        cmd.Flags().StringVarP(&workspaceDescription, "description", "d", "", "Description of the Workspace. If the description contains a space, specify the entire description in quotes \"\"")
90✔
148
        cmd.Flags().StringVarP(&enforceCD, "enforce-cicd", "e", "OFF", "Provide this flag either ON/OFF. ON means deploys to deployments must use an API Key or Token. This essentially forces Deploys to happen through CI/CD")
90✔
149
        return cmd
90✔
150
}
151

152
func newWorkspaceDeleteCmd(out io.Writer) *cobra.Command {
90✔
153
        cmd := &cobra.Command{
90✔
154
                Use:     "delete [workspace_id]",
90✔
155
                Aliases: []string{"de"},
90✔
156
                Short:   "Delete an Astro Workspace",
90✔
157
                Long:    "Permanently delete a Workspace. The Workspace must have zero Deployments — delete or transfer all Deployments first. Deletion also removes all Workspace-scoped API tokens and revokes Workspace-level roles from Organization tokens that had access. This action cannot be undone.",
90✔
158
                Args:    cobra.MaximumNArgs(1),
90✔
159
                Example: `
90✔
160
  $ astro workspace delete
90✔
161
  $ astro workspace delete clxxxxxxxxx
90✔
162
`,
90✔
163
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
164
                        return workspaceDelete(cmd, out, args)
5✔
165
                },
5✔
166
        }
167
        return cmd
90✔
168
}
169

170
func newWorkspaceUserRootCmd(out io.Writer) *cobra.Command {
90✔
171
        cmd := &cobra.Command{
90✔
172
                Use:     "user",
90✔
173
                Aliases: []string{"us", "users"},
90✔
174
                Short:   "Manage users in your Astro Workspace",
90✔
175
                Long:    "Manage users in your Astro Workspace.",
90✔
176
        }
90✔
177
        cmd.SetOut(out)
90✔
178
        cmd.AddCommand(
90✔
179
                newWorkspaceUserListCmd(out),
90✔
180
                newWorkspaceUserUpdateCmd(out),
90✔
181
                newWorkspaceUserRemoveCmd(out),
90✔
182
                newWorkspaceUserAddCmd(out),
90✔
183
        )
90✔
184
        cmd.PersistentFlags().StringVar(&workspaceID, "workspace-id", "", "workspace where you'd like to manage users")
90✔
185

90✔
186
        return cmd
90✔
187
}
90✔
188

189
func newWorkspaceUserAddCmd(out io.Writer) *cobra.Command {
90✔
190
        cmd := &cobra.Command{
90✔
191
                Use:   "add [email]",
90✔
192
                Short: "Add a user to an Astro Workspace with a specific role",
90✔
193
                Long:  "Add a user to an Astro Workspace with a specific role\n$astro workspace user add [email] --role [" + allowedWorkspaceRoleNames + "].",
90✔
194
                Example: `
90✔
195
  $ astro workspace user add user@company.com --role WORKSPACE_MEMBER
90✔
196
  $ astro workspace user add user@company.com --role WORKSPACE_OWNER
90✔
197
`,
90✔
198
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
199
                        return addWorkspaceUser(cmd, args, out)
5✔
200
                },
5✔
201
        }
202
        cmd.Flags().StringVarP(&addWorkspaceRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+
90✔
203
                "new user. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
204
        return cmd
90✔
205
}
206

207
func newWorkspaceUserListCmd(out io.Writer) *cobra.Command {
90✔
208
        cmd := &cobra.Command{
90✔
209
                Use:     "list",
90✔
210
                Aliases: []string{"ls"},
90✔
211
                Short:   "List all the users in an Astro Workspace",
90✔
212
                Long:    "List all users and their roles in a Workspace.",
90✔
213
                Example: `  astro workspace user list
90✔
214
  astro workspace user list --workspace-id clxxxxxxxxx
90✔
215
  astro workspace user list --json`,
90✔
216
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
217
                        return listWorkspaceUser(cmd, out)
2✔
218
                },
2✔
219
        }
220
        workspaceUserListOutputFlags.AddFlags(cmd)
90✔
221
        return cmd
90✔
222
}
223

224
func newWorkspaceUserUpdateCmd(out io.Writer) *cobra.Command {
90✔
225
        cmd := &cobra.Command{
90✔
226
                Use:     "update [email]",
90✔
227
                Aliases: []string{"up"},
90✔
228
                Short:   "Update the role of a user in an Astro Workspace",
90✔
229
                Long:    "Update the role of a user in an Astro Workspace\n$astro workspace user update [email] --role [" + allowedWorkspaceRoleNames + "].",
90✔
230
                Example: `
90✔
231
  $ astro workspace user update user@company.com --role WORKSPACE_OPERATOR
90✔
232
  $ astro workspace user update user@company.com --role WORKSPACE_OWNER
90✔
233
`,
90✔
234
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
235
                        return updateWorkspaceUser(cmd, args, out)
5✔
236
                },
5✔
237
        }
238
        cmd.Flags().StringVarP(&updateWorkspaceRole, "role", "r", "", "The new role for the "+
90✔
239
                "user. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
240
        return cmd
90✔
241
}
242

243
func newWorkspaceUserRemoveCmd(out io.Writer) *cobra.Command {
90✔
244
        cmd := &cobra.Command{
90✔
245
                Use:     "remove",
90✔
246
                Aliases: []string{"rm"},
90✔
247
                Short:   "Remove a user from an Astro Workspace",
90✔
248
                Long:    "Remove a user's role from a Workspace. The user loses access to all Deployments in the Workspace unless they have access through a team. This does not remove them from the Organization.",
90✔
249
                Example: `
90✔
250
  $ astro workspace user remove user@company.com
90✔
251
`,
90✔
252
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
253
                        return removeWorkspaceUser(cmd, args, out)
4✔
254
                },
4✔
255
        }
256
        return cmd
90✔
257
}
258

259
//nolint:dupl
260
func newWorkspaceTokenRootCmd(out io.Writer) *cobra.Command {
90✔
261
        cmd := &cobra.Command{
90✔
262
                Use:     "token",
90✔
263
                Aliases: []string{"to"},
90✔
264
                Short:   "Manage tokens in your Astro Workspace",
90✔
265
                Long:    "Manage tokens in your Astro Workspace.",
90✔
266
        }
90✔
267
        cmd.SetOut(out)
90✔
268
        cmd.AddCommand(
90✔
269
                newWorkspaceTokenListCmd(out),
90✔
270
                newWorkspaceTokenCreateCmd(out),
90✔
271
                newWorkspaceTokenUpdateCmd(out),
90✔
272
                newWorkspaceTokenRotateCmd(out),
90✔
273
                newWorkspaceTokenDeleteCmd(out),
90✔
274
                newWorkspaceTokenAddOrgTokenCmd(out),
90✔
275
                newWorkspaceOrgTokenManageCmd(out),
90✔
276
        )
90✔
277
        cmd.PersistentFlags().StringVar(&workspaceID, "workspace-id", "", "workspace where you would like to manage tokens")
90✔
278
        return cmd
90✔
279
}
90✔
280

281
//nolint:dupl
282
func newWorkspaceTokenListCmd(out io.Writer) *cobra.Command {
90✔
283
        cmd := &cobra.Command{
90✔
284
                Use:     "list",
90✔
285
                Aliases: []string{"ls"},
90✔
286
                Short:   "List all the API tokens in an Astro Workspace",
90✔
287
                Long:    "List all API tokens with a role in a Workspace, including both Workspace-scoped tokens and Organization-scoped tokens that have been granted a Workspace role.",
90✔
288
                Example: `
90✔
289
  $ astro workspace token list
90✔
290
  $ astro workspace token list --workspace-id clxxxxxxxxx
90✔
291
`,
90✔
292
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
293
                        return listWorkspaceToken(cmd, out)
4✔
294
                },
4✔
295
        }
296
        return cmd
90✔
297
}
298

299
//nolint:dupl
300
func newWorkspaceTeamRootCmd(out io.Writer) *cobra.Command {
90✔
301
        cmd := &cobra.Command{
90✔
302
                Use:     "team",
90✔
303
                Aliases: []string{"te", "teams"},
90✔
304
                Short:   "Manage teams in your Astro Workspace",
90✔
305
                Long:    "Manage teams in your Astro Workspace.",
90✔
306
        }
90✔
307
        cmd.SetOut(out)
90✔
308
        cmd.AddCommand(
90✔
309
                newWorkspaceTeamListCmd(out),
90✔
310
                newWorkspaceTeamUpdateCmd(out),
90✔
311
                newWorkspaceTeamRemoveCmd(out),
90✔
312
                newWorkspaceTeamAddCmd(out),
90✔
313
        )
90✔
314
        return cmd
90✔
315
}
90✔
316

317
func newWorkspaceTeamListCmd(out io.Writer) *cobra.Command {
90✔
318
        cmd := &cobra.Command{
90✔
319
                Use:     "list",
90✔
320
                Aliases: []string{"ls"},
90✔
321
                Short:   "List all the teams in an Astro Workspace",
90✔
322
                Long:    "List all teams and their assigned roles in a Workspace.",
90✔
323
                Example: `  astro workspace team list
90✔
324
  astro workspace team list --json`,
90✔
325
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
326
                        return listWorkspaceTeam(cmd, out)
2✔
327
                },
2✔
328
        }
329
        workspaceTeamListOutputFlags.AddFlags(cmd)
90✔
330
        return cmd
90✔
331
}
332

333
//nolint:dupl
334
func newWorkspaceTokenCreateCmd(out io.Writer) *cobra.Command {
90✔
335
        cmd := &cobra.Command{
90✔
336
                Use:     "create",
90✔
337
                Aliases: []string{"cr"},
90✔
338
                Short:   "Create an API token in an Astro Workspace",
90✔
339
                Long:    "Create an API token in an Astro Workspace\n$astro workspace token create --name [token name] --role [" + allowedWorkspaceRoleNames + "].",
90✔
340
                Example: `
90✔
341
  $ astro workspace token create --name "My Token" --role WORKSPACE_MEMBER
90✔
342
  $ astro workspace token create --name "CI Token" --role WORKSPACE_OPERATOR --expiration 30 --clean-output
90✔
343
`,
90✔
344
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
345
                        return createWorkspaceToken(cmd, out)
4✔
346
                },
4✔
347
        }
348
        cmd.Flags().StringVarP(&tokenName, "name", "n", "", "The token's name. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
349
        cmd.Flags().BoolVarP(&cleanTokenOutput, "clean-output", "c", false, "Print only the token as output. For use of the command in scripts")
90✔
350
        cmd.Flags().StringVarP(&tokenDescription, "description", "d", "", "Description of the token. If the description contains a space, specify the entire description within quotes \"\"")
90✔
351
        cmd.Flags().StringVarP(&tokenRole, "role", "r", "", "The role for the "+
90✔
352
                "token. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
353
        cmd.Flags().IntVarP(&tokenExpiration, "expiration", "e", 0, "Expiration of the token in days. If the flag isn't used the token won't have an expiration. Must be between 1 and 3650 days. ")
90✔
354
        return cmd
90✔
355
}
356

357
//nolint:dupl
358
func newWorkspaceTokenUpdateCmd(out io.Writer) *cobra.Command {
90✔
359
        cmd := &cobra.Command{
90✔
360
                Use:     "update [TOKEN_ID]",
90✔
361
                Aliases: []string{"up"},
90✔
362
                Short:   "Update a Workspace or Organization API token",
90✔
363
                Long:    "Update a Workspace or Organization API token that has a role in an Astro Workspace\n$astro workspace token update [TOKEN_ID] --name [new token name] --role [" + allowedWorkspaceRoleNames + "].",
90✔
364
                Example: `
90✔
365
  $ astro workspace token update clxxxxxxxxx --new-name "Updated Token" --role WORKSPACE_OPERATOR
90✔
366
  $ astro workspace token update --name "My Token" --new-name "Renamed Token" --description "Updated description"
90✔
367
`,
90✔
368
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
369
                        return updateWorkspaceToken(cmd, args, out)
4✔
370
                },
4✔
371
        }
372
        cmd.Flags().StringVarP(&name, "name", "t", "", "The current name of the token. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
373
        cmd.Flags().StringVarP(&tokenName, "new-name", "n", "", "The token's new name. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
374
        cmd.Flags().StringVarP(&tokenDescription, "description", "d", "", "updated description of the token. If the description contains a space, specify the entire description in quotes \"\"")
90✔
375
        cmd.Flags().StringVarP(&tokenRole, "role", "r", "", "The new role for the "+
90✔
376
                "token. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
377
        return cmd
90✔
378
}
379

380
//nolint:dupl
381
func newWorkspaceTokenRotateCmd(out io.Writer) *cobra.Command {
90✔
382
        cmd := &cobra.Command{
90✔
383
                Use:     "rotate [TOKEN_ID]",
90✔
384
                Aliases: []string{"ro"},
90✔
385
                Short:   "Rotate a Workspace API token",
90✔
386
                Long:    "Rotate a Workspace API token. You can only rotate Workspace API tokens. You cannot rotate Organization API tokens with this command",
90✔
387
                Example: `
90✔
388
  $ astro workspace token rotate clxxxxxxxxx
90✔
389
  $ astro workspace token rotate --name "My Token" --force --clean-output
90✔
390
`,
90✔
391
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
392
                        return rotateWorkspaceToken(cmd, args, out)
5✔
393
                },
5✔
394
        }
395
        cmd.Flags().BoolVarP(&cleanTokenOutput, "clean-output", "c", false, "Print only the token as output. For use of the command in scripts")
90✔
396
        cmd.Flags().StringVarP(&name, "name", "t", "", "The name of the token to be rotated. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
397
        cmd.Flags().BoolVarP(&forceRotate, "force", "f", false, "Rotate the Workspace API token without showing a warning")
90✔
398

90✔
399
        return cmd
90✔
400
}
401

402
//nolint:dupl
403
func newWorkspaceTokenDeleteCmd(out io.Writer) *cobra.Command {
90✔
404
        cmd := &cobra.Command{
90✔
405
                Use:     "delete [TOKEN_ID]",
90✔
406
                Aliases: []string{"de"},
90✔
407
                Short:   "Delete a Workspace API token or remove an Organization API token from a Workspace",
90✔
408
                Long:    "Delete a Workspace API token or remove an Organization token's Workspace role. Deleting a Workspace token revokes it permanently. Removing an Organization token only revokes its Workspace role — the token continues to work at other scopes.",
90✔
409
                Example: `
90✔
410
  $ astro workspace token delete clxxxxxxxxx
90✔
411
  $ astro workspace token delete --name "My Token" --force
90✔
412
`,
90✔
413
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
414
                        return deleteWorkspaceToken(cmd, args, out)
5✔
415
                },
5✔
416
        }
417
        cmd.Flags().StringVarP(&name, "name", "t", "", "The name of the token to be deleted. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
418
        cmd.Flags().BoolVarP(&forceDelete, "force", "f", false, "Delete or remove the API token without showing a warning")
90✔
419

90✔
420
        return cmd
90✔
421
}
422

423
//nolint:dupl
424
func newWorkspaceTokenAddOrgTokenCmd(out io.Writer) *cobra.Command {
90✔
425
        cmd := &cobra.Command{
90✔
426
                Use:   "add [ORG_TOKEN_ID]",
90✔
427
                Short: "Add an Organization API token to an Astro Workspace",
90✔
428
                Long:  "Add an Organization API token to an Astro Workspace\n$astro workspace token add [ORG_TOKEN_ID] --org-token-name [token name] --role [" + allowedWorkspaceRoleNames + "].",
90✔
429
                Example: `
90✔
430
  $ astro workspace token add clxxxxxxxxx --role WORKSPACE_MEMBER
90✔
431
  $ astro workspace token add --org-token-name "My Org Token" --role WORKSPACE_OPERATOR
90✔
432
`,
90✔
433
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
434
                        return addOrgTokenToWorkspace(cmd, args, out)
5✔
435
                },
5✔
436
        }
437
        cmd.Flags().StringVarP(&orgTokenName, "org-token-name", "n", "", "The name of the Organization API token you want to add to a Workspace. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
438
        cmd.Flags().StringVarP(&tokenRole, "role", "r", "", "The Workspace role to grant to the "+
90✔
439
                "Organization API token. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
440
        return cmd
90✔
441
}
442

443
//nolint:dupl
444
func newWorkspaceOrgTokenManageCmd(out io.Writer) *cobra.Command {
90✔
445
        cmd := &cobra.Command{
90✔
446
                Use:   "organization-token",
90✔
447
                Short: "Manage organization tokens in a workspace",
90✔
448
                Long:  "Manage organization tokens in a workspace",
90✔
449
        }
90✔
450
        cmd.SetOut(out)
90✔
451
        cmd.AddCommand(
90✔
452
                newAddOrganizationTokenWorkspaceRole(out),
90✔
453
                newUpdateOrganizationTokenWorkspaceRole(out),
90✔
454
                newRemoveOrganizationTokenWorkspaceRole(out),
90✔
455
                newListOrganizationTokensInWorkspace(out),
90✔
456
        )
90✔
457
        return cmd
90✔
458
}
90✔
459

460
func newAddOrganizationTokenWorkspaceRole(out io.Writer) *cobra.Command {
90✔
461
        cmd := &cobra.Command{
90✔
462
                Use:   "add [ORG_TOKEN_ID]",
90✔
463
                Short: "Add an Organization API token to a Workspace",
90✔
464
                Long:  "Add an Organization API token to a Workspace\n$astro workspace token organization-token add [ORG_TOKEN_ID] --org-token-name [token name] --role [" + allowedWorkspaceRoleNames + "].",
90✔
465
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
466
                        return addOrgTokenWorkspaceRole(cmd, args, out)
2✔
467
                },
2✔
468
        }
469
        cmd.Flags().StringVarP(&orgTokenName, "org-token-name", "n", "", "The name of the Organization API token you want to add to a Workspace. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
470
        cmd.Flags().StringVarP(&tokenRole, "role", "r", "", "The Workspace role to grant to the "+
90✔
471
                "Organization API token. Possible values are"+allowedWorkspaceRoleNamesProse)
90✔
472
        return cmd
90✔
473
}
474

475
func newUpdateOrganizationTokenWorkspaceRole(out io.Writer) *cobra.Command {
90✔
476
        cmd := &cobra.Command{
90✔
477
                Use:   "update [ORG_TOKEN_ID]",
90✔
478
                Short: "Update an Organization API token's Workspace Role",
90✔
479
                Long:  "Update an Organization API token's Workspace Role\n$astro workspace token organization-token update [ORG_TOKEN_ID] --org-token-name [token name] --role [" + allowedWorkspaceRoleNames + "].",
90✔
480
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
481
                        return updateOrgTokenWorkspaceRole(cmd, args, out)
2✔
482
                },
2✔
483
        }
484
        cmd.Flags().StringVarP(&orgTokenName, "org-token-name", "n", "", "The name of the Organization API token you want to update in a Workspace. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
485
        cmd.Flags().StringVarP(&tokenRole, "role", "r", "", "The Workspace role to update the "+
90✔
486
                "Organization API token. Possible values are"+allowedWorkspaceRoleNamesProse)
90✔
487
        return cmd
90✔
488
}
489

490
func addOrgTokenWorkspaceRole(cmd *cobra.Command, args []string, out io.Writer) error {
2✔
491
        // if an id was provided in the args we use it
2✔
492
        if len(args) > 0 {
3✔
493
                // make sure the id is lowercase
1✔
494
                orgTokenID = strings.ToLower(args[0])
1✔
495
        }
1✔
496
        if tokenRole == "" {
3✔
497
                // no role was provided so ask the user for it
1✔
498
                tokenRole = input.Text("Enter a role for the API token. Possible values are " + allowedWorkspaceRoleNamesProse + ": ")
1✔
499
        }
1✔
500
        cmd.SilenceUsage = true
2✔
501

2✔
502
        return workspacetoken.UpsertOrgTokenWorkspaceRole(orgTokenID, orgTokenName, tokenRole, workspaceID, "create", out, astroCoreClient, astroCoreIamClient)
2✔
503
}
504

505
func updateOrgTokenWorkspaceRole(cmd *cobra.Command, args []string, out io.Writer) error {
2✔
506
        // if an id was provided in the args we use it
2✔
507
        if len(args) > 0 {
3✔
508
                // make sure the id is lowercase
1✔
509
                orgTokenID = strings.ToLower(args[0])
1✔
510
        }
1✔
511
        if tokenRole == "" {
3✔
512
                // no role was provided so ask the user for it
1✔
513
                tokenRole = input.Text("Enter a role for the new Workspace API token. Possible values are " + allowedWorkspaceRoleNamesProse + ": ")
1✔
514
        }
1✔
515
        cmd.SilenceUsage = true
2✔
516

2✔
517
        return workspacetoken.UpsertOrgTokenWorkspaceRole(orgTokenID, orgTokenName, tokenRole, workspaceID, "update", out, astroCoreClient, astroCoreIamClient)
2✔
518
}
519

520
func newRemoveOrganizationTokenWorkspaceRole(out io.Writer) *cobra.Command {
90✔
521
        cmd := &cobra.Command{
90✔
522
                Use:   "remove [ORG_TOKEN_ID]",
90✔
523
                Short: "Remove an Organization API token's Workspace Role",
90✔
524
                Long:  "Remove an Organization API token's Workspace Role\n$astro workspace token organization-token remove [ORG_TOKEN_ID] --org-token-name [token name].",
90✔
525
                RunE: func(cmd *cobra.Command, args []string) error {
92✔
526
                        return removeOrganizationTokenWorkspaceRole(cmd, args, out)
2✔
527
                },
2✔
528
        }
529
        cmd.Flags().StringVarP(&orgTokenName, "org-token-name", "n", "", "The name of the Workspace API token you want to remove from a Deployment. If the name contains a space, specify the entire name within quotes \"\" ")
90✔
530
        return cmd
90✔
531
}
532

533
func removeOrganizationTokenWorkspaceRole(cmd *cobra.Command, args []string, out io.Writer) error {
2✔
534
        // if an id was provided in the args we use it
2✔
535
        if len(args) > 0 {
3✔
536
                // make sure the id is lowercase
1✔
537
                orgTokenID = strings.ToLower(args[0])
1✔
538
        }
1✔
539

540
        cmd.SilenceUsage = true
2✔
541
        return workspacetoken.RemoveOrgTokenWorkspaceRole(orgTokenID, orgTokenName, workspaceID, out, astroCoreClient, astroCoreIamClient)
2✔
542
}
543

544
func newListOrganizationTokensInWorkspace(out io.Writer) *cobra.Command {
90✔
545
        cmd := &cobra.Command{
90✔
546
                Use:   "list",
90✔
547
                Short: "List all Organization API tokens in a workspace",
90✔
548
                Long:  "List all Organization API tokens in a workspace\n$astro workspace token organization-token list",
90✔
549
                RunE: func(cmd *cobra.Command, args []string) error {
91✔
550
                        return listOrganizationTokensInWorkspace(cmd, out)
1✔
551
                },
1✔
552
        }
553
        return cmd
90✔
554
}
555

556
func listOrganizationTokensInWorkspace(cmd *cobra.Command, out io.Writer) error {
1✔
557
        cmd.SilenceUsage = true
1✔
558
        tokenTypes := []astrocore.ListWorkspaceApiTokensParamsTokenTypes{
1✔
559
                "ORGANIZATION",
1✔
560
        }
1✔
561
        return workspacetoken.ListTokens(astroCoreClient, deploymentID, &tokenTypes, out)
1✔
562
}
1✔
563

564
func newWorkspaceTeamRemoveCmd(out io.Writer) *cobra.Command {
90✔
565
        cmd := &cobra.Command{
90✔
566
                Use:     "remove",
90✔
567
                Aliases: []string{"rm"},
90✔
568
                Short:   "Remove a team from an Astro Workspace",
90✔
569
                Long:    "Remove a team from an Astro Workspace",
90✔
570
                Example: `
90✔
571
  $ astro workspace team remove clxxxxxxxxx
90✔
572
`,
90✔
573
                RunE: func(cmd *cobra.Command, args []string) error {
94✔
574
                        return removeWorkspaceTeam(cmd, args, out)
4✔
575
                },
4✔
576
        }
577
        return cmd
90✔
578
}
579

580
func listWorkspaceTeam(cmd *cobra.Command, out io.Writer) error {
2✔
581
        format, err := workspaceTeamListOutputFlags.Resolve()
2✔
582
        if err != nil {
2✔
NEW
583
                return err
×
NEW
584
        }
×
585

586
        cmd.SilenceUsage = true
2✔
587
        return team.ListWorkspaceTeamsWithFormat(astroCoreClient, "", format, workspaceTeamListOutputFlags.Template, out)
2✔
588
}
589

590
func removeWorkspaceTeam(cmd *cobra.Command, args []string, out io.Writer) error {
4✔
591
        var id string
4✔
592

4✔
593
        // if an id was provided in the args we use it
4✔
594
        if len(args) > 0 {
7✔
595
                // make sure the email is lowercase
3✔
596
                id = args[0]
3✔
597
        }
3✔
598
        cmd.SilenceUsage = true
4✔
599
        return team.RemoveWorkspaceTeam(id, "", out, astroCoreClient)
4✔
600
}
601

602
func newWorkspaceTeamAddCmd(out io.Writer) *cobra.Command {
90✔
603
        cmd := &cobra.Command{
90✔
604
                Use:   "add [id]",
90✔
605
                Short: "Add a team to an Astro Workspace with a specific role",
90✔
606
                Long:  "Add a team to an Astro Workspace with a specific role\n$astro workspace team add [id] --role [" + allowedWorkspaceRoleNames + "].",
90✔
607
                Example: `
90✔
608
  $ astro workspace team add clxxxxxxxxx --role WORKSPACE_MEMBER
90✔
609
  $ astro workspace team add clxxxxxxxxx --role WORKSPACE_OPERATOR --workspace-id clyyyyyyyyy
90✔
610
`,
90✔
611
                RunE: func(cmd *cobra.Command, args []string) error {
96✔
612
                        return addWorkspaceTeam(cmd, args, out)
6✔
613
                },
6✔
614
        }
615
        cmd.Flags().StringVarP(&workspaceID, "workspace-id", "w", "", "The Workspace's unique identifier")
90✔
616
        cmd.Flags().StringVarP(&addWorkspaceRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+
90✔
617
                "new team. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
618
        return cmd
90✔
619
}
620

621
func addWorkspaceTeam(cmd *cobra.Command, args []string, out io.Writer) error {
6✔
622
        var id string
6✔
623

6✔
624
        // if an email was provided in the args we use it
6✔
625
        if len(args) > 0 {
11✔
626
                // make sure the email is lowercase
5✔
627
                id = args[0]
5✔
628
        }
5✔
629
        cmd.SilenceUsage = true
6✔
630
        return team.AddWorkspaceTeam(id, addWorkspaceRole, workspaceID, out, astroCoreClient)
6✔
631
}
632

633
func newWorkspaceTeamUpdateCmd(out io.Writer) *cobra.Command {
90✔
634
        cmd := &cobra.Command{
90✔
635
                Use:     "update [id]",
90✔
636
                Aliases: []string{"up"},
90✔
637
                Short:   "Update the role of a team in an Astro Workspace",
90✔
638
                Long:    "Update the role of a team in an Astro Workspace\n$astro workspace team update [id] --role [" + allowedWorkspaceRoleNames + "].",
90✔
639
                Example: `
90✔
640
  $ astro workspace team update clxxxxxxxxx --role WORKSPACE_OPERATOR
90✔
641
  $ astro workspace team update clxxxxxxxxx --role WORKSPACE_OWNER
90✔
642
`,
90✔
643
                RunE: func(cmd *cobra.Command, args []string) error {
95✔
644
                        return updateWorkspaceTeam(cmd, args, out)
5✔
645
                },
5✔
646
        }
647
        cmd.Flags().StringVarP(&updateWorkspaceRole, "role", "r", "", "The new role for the "+
90✔
648
                "team. Possible values are "+allowedWorkspaceRoleNamesProse)
90✔
649
        return cmd
90✔
650
}
651

652
func updateWorkspaceTeam(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
653
        var id string
5✔
654

5✔
655
        // if an id was provided in the args we use it
5✔
656
        if len(args) > 0 {
9✔
657
                id = args[0]
4✔
658
        }
4✔
659
        var err error
5✔
660
        if updateWorkspaceRole == "" {
5✔
661
                // no role was provided so ask the user for it
×
662
                updateWorkspaceRole, err = selectWorkspaceRole()
×
663
                if err != nil {
×
664
                        return err
×
665
                }
×
666
        }
667

668
        cmd.SilenceUsage = true
5✔
669
        return team.UpdateWorkspaceTeamRole(id, updateWorkspaceRole, "", out, astroCoreClient)
5✔
670
}
671

672
func workspaceList(cmd *cobra.Command, out io.Writer) error {
2✔
673
        format, err := workspaceListOutputFlags.Resolve()
2✔
674
        if err != nil {
2✔
NEW
675
                return err
×
NEW
676
        }
×
677

678
        // Silence Usage as we have now validated command input
679
        cmd.SilenceUsage = true
2✔
680
        return workspace.ListWithFormat(astroCoreClient, format, workspaceListOutputFlags.Template, out)
2✔
681
}
682

683
func workspaceSwitch(cmd *cobra.Command, out io.Writer, args []string) error {
1✔
684
        // Silence Usage as we have now validated command input
1✔
685

1✔
686
        workspaceNameOrID := ""
1✔
687

1✔
688
        if len(args) == 1 {
1✔
689
                workspaceNameOrID = args[0]
×
690
        }
×
691
        cmd.SilenceUsage = true
1✔
692
        return workspace.Switch(workspaceNameOrID, astroCoreClient, out)
1✔
693
}
694

695
func workspaceCreate(cmd *cobra.Command, out io.Writer) error {
4✔
696
        cmd.SilenceUsage = true
4✔
697
        return workspace.Create(workspaceName, workspaceDescription, enforceCD, out, astroCoreClient)
4✔
698
}
4✔
699

700
func workspaceUpdate(cmd *cobra.Command, out io.Writer, args []string) error {
5✔
701
        id := ""
5✔
702

5✔
703
        if len(args) == 1 {
9✔
704
                id = args[0]
4✔
705
        }
4✔
706
        cmd.SilenceUsage = true
5✔
707
        return workspace.Update(id, workspaceName, workspaceDescription, enforceCD, out, astroCoreClient)
5✔
708
}
709

710
func workspaceDelete(cmd *cobra.Command, out io.Writer, args []string) error {
5✔
711
        id := ""
5✔
712

5✔
713
        if len(args) == 1 {
9✔
714
                id = args[0]
4✔
715
        }
4✔
716
        cmd.SilenceUsage = true
5✔
717
        return workspace.Delete(id, out, astroCoreClient)
5✔
718
}
719

720
func addWorkspaceUser(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
721
        var email string
5✔
722

5✔
723
        // if an email was provided in the args we use it
5✔
724
        if len(args) > 0 {
9✔
725
                // make sure the email is lowercase
4✔
726
                email = strings.ToLower(args[0])
4✔
727
        }
4✔
728

729
        cmd.SilenceUsage = true
5✔
730
        return user.AddWorkspaceUser(email, addWorkspaceRole, workspaceID, out, astroCoreClient)
5✔
731
}
732

733
func listWorkspaceUser(cmd *cobra.Command, out io.Writer) error {
2✔
734
        format, err := workspaceUserListOutputFlags.Resolve()
2✔
735
        if err != nil {
2✔
NEW
736
                return err
×
NEW
737
        }
×
738

739
        cmd.SilenceUsage = true
2✔
740
        return user.ListWorkspaceUsersWithFormat(astroCoreClient, workspaceID, format, workspaceUserListOutputFlags.Template, out)
2✔
741
}
742

743
func updateWorkspaceUser(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
744
        var email string
5✔
745

5✔
746
        // if an email was provided in the args we use it
5✔
747
        if len(args) > 0 {
9✔
748
                // make sure the email is lowercase
4✔
749
                email = strings.ToLower(args[0])
4✔
750
        }
4✔
751

752
        if updateWorkspaceRole == "" {
5✔
753
                // no role was provided so ask the user for it
×
754
                updateWorkspaceRole = input.Text("Enter a user Workspace role(" + allowedWorkspaceRoleNamesProse + ") to update user: ")
×
755
        }
×
756

757
        cmd.SilenceUsage = true
5✔
758
        return user.UpdateWorkspaceUserRole(email, updateWorkspaceRole, workspaceID, out, astroCoreClient)
5✔
759
}
760

761
func removeWorkspaceUser(cmd *cobra.Command, args []string, out io.Writer) error {
4✔
762
        var email string
4✔
763

4✔
764
        // if an email was provided in the args we use it
4✔
765
        if len(args) > 0 {
7✔
766
                // make sure the email is lowercase
3✔
767
                email = strings.ToLower(args[0])
3✔
768
        }
3✔
769

770
        cmd.SilenceUsage = true
4✔
771
        return user.RemoveWorkspaceUser(email, workspaceID, out, astroCoreClient)
4✔
772
}
773

774
func listWorkspaceToken(cmd *cobra.Command, out io.Writer) error {
4✔
775
        cmd.SilenceUsage = true
4✔
776
        return workspacetoken.ListTokens(astroCoreClient, workspaceID, nil, out)
4✔
777
}
4✔
778

779
func createWorkspaceToken(cmd *cobra.Command, out io.Writer) error {
4✔
780
        if tokenName == "" {
5✔
781
                // no role was provided so ask the user for it
1✔
782
                tokenName = input.Text("Enter a name for the new Workspace API token: ")
1✔
783
        }
1✔
784
        if tokenRole == "" {
5✔
785
                fmt.Println("select a Workspace Role for the new API token:")
1✔
786
                // no role was provided so ask the user for it
1✔
787
                var err error
1✔
788
                tokenRole, err = selectWorkspaceRole()
1✔
789
                if err != nil {
1✔
790
                        return err
×
791
                }
×
792
        }
793
        cmd.SilenceUsage = true
4✔
794

4✔
795
        return workspacetoken.CreateToken(tokenName, tokenDescription, tokenRole, workspaceID, tokenExpiration, cleanTokenOutput, out, astroCoreClient)
4✔
796
}
797

798
func updateWorkspaceToken(cmd *cobra.Command, args []string, out io.Writer) error {
4✔
799
        // if an id was provided in the args we use it
4✔
800
        if len(args) > 0 {
4✔
801
                // make sure the id is lowercase
×
802
                tokenID = strings.ToLower(args[0])
×
803
        }
×
804

805
        cmd.SilenceUsage = true
4✔
806
        return workspacetoken.UpdateToken(tokenID, name, tokenName, tokenDescription, tokenRole, workspaceID, out, astroCoreClient, astroCoreIamClient)
4✔
807
}
808

809
func rotateWorkspaceToken(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
810
        // if an id was provided in the args we use it
5✔
811
        if len(args) > 0 {
5✔
812
                // make sure the id is lowercase
×
813
                tokenID = strings.ToLower(args[0])
×
814
        }
×
815
        cmd.SilenceUsage = true
5✔
816
        return workspacetoken.RotateToken(tokenID, name, workspaceID, cleanTokenOutput, forceRotate, out, astroCoreClient, astroCoreIamClient)
5✔
817
}
818

819
func deleteWorkspaceToken(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
820
        // if an id was provided in the args we use it
5✔
821
        if len(args) > 0 {
5✔
822
                // make sure the id is lowercase
×
823
                tokenID = strings.ToLower(args[0])
×
824
        }
×
825

826
        cmd.SilenceUsage = true
5✔
827
        return workspacetoken.DeleteToken(tokenID, name, workspaceID, forceDelete, out, astroCoreClient, astroCoreIamClient)
5✔
828
}
829

830
func addOrgTokenToWorkspace(cmd *cobra.Command, args []string, out io.Writer) error {
5✔
831
        // if an id was provided in the args we use it
5✔
832
        if len(args) > 0 {
5✔
833
                // make sure the id is lowercase
×
834
                orgTokenID = strings.ToLower(args[0])
×
835
        }
×
836
        if tokenRole == "" {
6✔
837
                fmt.Println("select a Workspace Role for the Organization Token:")
1✔
838
                // no role was provided so ask the user for it
1✔
839
                var err error
1✔
840
                tokenRole, err = selectWorkspaceRole()
1✔
841
                if err != nil {
1✔
842
                        return err
×
843
                }
×
844
        }
845
        cmd.SilenceUsage = true
5✔
846
        return organization.AddOrgTokenToWorkspace(orgTokenID, orgTokenName, tokenRole, workspaceID, out, astroCoreClient, astroCoreIamClient)
5✔
847
}
848

849
func coalesceWorkspace() (string, error) {
138✔
850
        wsFlag := workspaceID
138✔
851
        wsCfg, err := workspace.GetCurrentWorkspace()
138✔
852
        if err != nil {
157✔
853
                return "", errors.Wrap(err, "failed to get current Workspace")
19✔
854
        }
19✔
855

856
        if wsFlag != "" {
146✔
857
                return wsFlag, nil
27✔
858
        }
27✔
859

860
        if wsCfg != "" {
184✔
861
                return wsCfg, nil
92✔
862
        }
92✔
863

864
        return "", errors.New("no valid Workspace source found")
×
865
}
866

867
func selectWorkspaceRole() (string, error) {
2✔
868
        tokenRolesMap := map[string]string{}
2✔
869
        tab := &printutil.Table{
2✔
870
                Padding:        []int{44, 50},
2✔
871
                DynamicPadding: true,
2✔
872
                Header:         []string{"#", "ROLE"},
2✔
873
        }
2✔
874
        for i := range validWorkspaceRoles {
10✔
875
                index := i + 1
8✔
876
                tab.AddRow([]string{
8✔
877
                        strconv.Itoa(index),
8✔
878
                        validWorkspaceRoles[i],
8✔
879
                }, false)
8✔
880
                tokenRolesMap[strconv.Itoa(index)] = validWorkspaceRoles[i]
8✔
881
        }
8✔
882

883
        tab.Print(os.Stdout)
2✔
884
        choice := input.Text("\n> ")
2✔
885
        selected, ok := tokenRolesMap[choice]
2✔
886
        if !ok {
2✔
887
                return "", errInvalidWorkspaceRoleKey
×
888
        }
×
889
        return selected, nil
2✔
890
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc