From a2824d0ac675dce3aadbb95b35d0b93fb23e85c1 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Wed, 14 Feb 2024 17:08:41 -0500 Subject: [PATCH 01/21] add cmds for managing deployment user/teams --- cloud/team/team.go | 200 +++++++++++++++++++++++++++++ cloud/user/user.go | 156 +++++++++++++++++++++- cmd/cloud/deployment.go | 277 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 630 insertions(+), 3 deletions(-) diff --git a/cloud/team/team.go b/cloud/team/team.go index 8547bdebd..1d24b35b6 100644 --- a/cloud/team/team.go +++ b/cloud/team/team.go @@ -26,6 +26,7 @@ var ( ErrWrongEnforceInput = errors.New("the input to the `--enforce-cicd` flag") ErrNoTeamsFoundInOrg = errors.New("no teams found in your organization") ErrNoTeamsFoundInWorkspace = errors.New("no teams found in your workspace") + ErrNoTeamsFoundInDeployment = errors.New("no teams found in your deployment") ErrNoTeamMembersFoundInTeam = errors.New("no team members found in team") ErrNoUsersFoundInOrg = errors.New("no users found in your organization") ErrNoTeamNameProvided = errors.New("you must give your Team a name") @@ -757,3 +758,202 @@ func ListTeamUsers(teamID string, out io.Writer, client astrocore.CoreClient) (e fmt.Println("The selected team has no members") return nil } + +func GetDeploymentTeams(client astrocore.CoreClient, deployment string, limit int) ([]astrocore.Team, error) { + offset := 0 + var teams []astrocore.Team + ctx, err := context.GetCurrentContext() + if err != nil { + return nil, err + } + + for { + includeDeploymentRoles := true + resp, err := client.ListDeploymentTeamsWithResponse(httpContext.Background(), ctx.Organization, deployment, &astrocore.ListDeploymentTeamsParams{ + IncludeDeploymentRoles: &includeDeploymentRoles, + Offset: &offset, + Limit: &limit, + }) + if err != nil { + return nil, err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return nil, err + } + teams = append(teams, resp.JSON200.Teams...) + + if resp.JSON200.TotalCount <= offset { + break + } + + offset += limit + } + + return teams, nil +} + +// Prints a list of all of an organizations teams +func ListDeploymentTeams(out io.Writer, client astrocore.CoreClient, deployment string) error { + table := printutil.Table{ + DynamicPadding: true, + Header: []string{"ID", "Role", "Name", "Description", "Create Date"}, + } + teams, err := GetDeploymentTeams(client, deployment, teamPagnationLimit) + if err != nil { + return err + } + + for i := range teams { + var teamRole string + for _, role := range *teams[i].Roles { + if role.EntityType == "DEPLOYMENT" && role.EntityId == deployment { + teamRole = role.Role + } + } + table.AddRow([]string{ + teams[i].Id, + teamRole, + teams[i].Name, + *teams[i].Description, + teams[i].CreatedAt.Format(time.RFC3339), + }, false) + } + + table.Print(out) + return nil +} + +func AddDeploymentTeam(id, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + var team astrocore.Team + if id == "" { + // Get all org teams. Setting limit to 1000 for now + teams, err := GetOrgTeams(client) + if err != nil { + return err + } + if len(teams) == 0 { + return ErrNoTeamsFoundInOrg + } + team, err = selectTeam(teams) + if err != nil || team.Id == "" { + return ErrInvalidTeamKey + } + } else { + team, err = GetTeam(client, id) + + if err != nil { + return err + } + if team.Id == "" { + return ErrTeamNotFound + } + } + + teamID := team.Id + + mutateUserInput := astrocore.MutateDeploymentTeamRoleRequest{ + Role: role, + } + resp, err := client.MutateDeploymentTeamRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, teamID, mutateUserInput) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The team %s was successfully added to the deployment with the role %s\n", teamID, role) + return nil +} + +func UpdateDeploymentTeamRole(id, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + var team astrocore.Team + if id == "" { + teams, err := GetDeploymentTeams(client, deployment, teamPagnationLimit) + if err != nil { + return err + } + if len(teams) == 0 { + return ErrNoTeamsFoundInDeployment + } + team, err = selectTeam(teams) + if err != nil { + return err + } + } else { + team, err = GetTeam(client, id) + + if err != nil { + return err + } + if team.Id == "" { + return ErrTeamNotFound + } + } + teamID := team.Id + + teamMutateRequest := astrocore.MutateDeploymentTeamRoleRequest{Role: role} + resp, err := client.MutateDeploymentTeamRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, teamID, teamMutateRequest) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The deployment team %s role was successfully updated to %s\n", teamID, role) + return nil +} + +func RemoveDeploymentTeam(id, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + var team astrocore.Team + if id == "" { + teams, err := GetDeploymentTeams(client, deployment, teamPagnationLimit) + if err != nil { + return err + } + if len(teams) == 0 { + return ErrNoTeamsFoundInDeployment + } + team, err = selectTeam(teams) + if err != nil { + return err + } + } else { + team, err = GetTeam(client, id) + + if err != nil { + return err + } + if team.Id == "" { + return ErrTeamNotFound + } + } + teamID := team.Id + resp, err := client.DeleteDeploymentTeamWithResponse(httpContext.Background(), ctx.Organization, deployment, teamID) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "Astro Team %s was successfully removed from deployment %s\n", team.Name, deployment) + return nil +} diff --git a/cloud/user/user.go b/cloud/user/user.go index 697c3689b..d4dd9598f 100644 --- a/cloud/user/user.go +++ b/cloud/user/user.go @@ -338,7 +338,7 @@ func IsOrganizationRoleValid(role string) error { return ErrInvalidOrganizationRole } -// Returns a list of all of an organizations users +// Returns a list of all of a worksapces users func GetWorkspaceUsers(client astrocore.CoreClient, workspace string, limit int) ([]astrocore.User, error) { offset := 0 var users []astrocore.User @@ -375,7 +375,7 @@ func GetWorkspaceUsers(client astrocore.CoreClient, workspace string, limit int) return users, nil } -// Prints a list of all of an organizations users +// Prints a list of all of a workspaces users func ListWorkspaceUsers(out io.Writer, client astrocore.CoreClient, workspace string) error { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, @@ -467,3 +467,155 @@ func GetUser(client astrocore.CoreClient, userID string) (user astrocore.User, e return user, nil } + +func AddDeploymentUser(email, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + // Get all org users. Setting limit to 1000 for now + users, err := GetOrgUsers(client) + if err != nil { + return err + } + userID, email, err := getUserID(email, users, false) + if err != nil { + return err + } + mutateUserInput := astrocore.MutateDeploymentUserRoleRequest{ + Role: role, + } + resp, err := client.MutateDeploymentUserRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, userID, mutateUserInput) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The user %s was successfully added to the deployment with the role %s\n", email, role) + return nil +} + +func UpdateDeploymentUserRole(email, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + // Get all org users. Setting limit to 1000 for now + users, err := GetDeploymentUsers(client, deployment, userPagnationLimit) + if err != nil { + return err + } + userID, email, err := getUserID(email, users, true) + if err != nil { + return err + } + mutateUserInput := astrocore.MutateDeploymentUserRoleRequest{ + Role: role, + } + fmt.Println("deployment: " + deployment) + resp, err := client.MutateDeploymentUserRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, userID, mutateUserInput) + if err != nil { + fmt.Println("error in MutateDeploymentUserRoleWithResponse") + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + fmt.Println("error in NormalizeAPIError") + return err + } + fmt.Fprintf(out, "The deployment user %s role was successfully updated to %s\n", email, role) + return nil +} + +func RemoveDeploymentUser(email, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + // Get all org users. Setting limit to 1000 for now + users, err := GetDeploymentUsers(client, deployment, userPagnationLimit) + if err != nil { + return err + } + userID, email, err := getUserID(email, users, true) + if err != nil { + return err + } + resp, err := client.DeleteDeploymentUserWithResponse(httpContext.Background(), ctx.Organization, deployment, userID) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The user %s was successfully removed from the deployment\n", email) + return nil +} + +// Returns a list of all of a deployments users +func GetDeploymentUsers(client astrocore.CoreClient, deployment string, limit int) ([]astrocore.User, error) { + offset := 0 + var users []astrocore.User + + ctx, err := context.GetCurrentContext() + if err != nil { + return nil, err + } + + for { + includeDeploymentRoles := true + resp, err := client.ListDeploymentUsersWithResponse(httpContext.Background(), ctx.Organization, deployment, &astrocore.ListDeploymentUsersParams{ + IncludeDeploymentRoles: &includeDeploymentRoles, + Offset: &offset, + Limit: &limit, + }) + if err != nil { + return nil, err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return nil, err + } + users = append(users, resp.JSON200.Users...) + + if resp.JSON200.TotalCount <= offset { + break + } + + offset += limit + } + + return users, nil +} + +// Prints a list of all of an deployments users +func ListDeploymentUsers(out io.Writer, client astrocore.CoreClient, deployment string) error { + table := printutil.Table{ + Padding: []int{30, 50, 10, 50, 10, 10, 10}, + DynamicPadding: true, + Header: []string{"FULLNAME", "EMAIL", "ID", "DEPLOYMENT ROLE", "CREATE DATE"}, + } + users, err := GetDeploymentUsers(client, deployment, userPagnationLimit) + if err != nil { + return err + } + + for i := range users { + table.AddRow([]string{ + users[i].FullName, + users[i].Username, + users[i].Id, + *users[i].DeploymentRole, + users[i].CreatedAt.Format(time.RFC3339), + }, false) + } + + table.Print(out) + return nil +} diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 908fc9eb9..4f8cdeed0 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -2,6 +2,9 @@ package cloud import ( "fmt" + "github.com/astronomer/astro-cli/cloud/team" + "github.com/astronomer/astro-cli/cloud/user" + "github.com/astronomer/astro-cli/pkg/input" "io" "strings" @@ -60,6 +63,8 @@ var ( resourceQuotaCPU string resourceQuotaMemory string defaultTaskPodCPU string + addDeploymentRole string + updateDeploymentRole string deploymentType = standard deploymentVariableListExample = ` @@ -106,10 +111,219 @@ func newDeploymentRootCmd(out io.Writer) *cobra.Command { newDeploymentConnectionRootCmd(out), newDeploymentAirflowVariableRootCmd(out), newDeploymentPoolRootCmd(out), + newDeploymentUserRootCmd(out), + newDeploymentTeamRootCmd(out), ) return cmd } +//nolint:dupl +func newDeploymentTeamRootCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "team", + Aliases: []string{"te", "teams"}, + Short: "Manage teams in your Astro Deployment", + Long: "Manage teams in your Astro Deployment.", + } + cmd.SetOut(out) + cmd.AddCommand( + newDeploymentTeamListCmd(out), + newDeploymentTeamUpdateCmd(out), + newDeploymentTeamRemoveCmd(out), + newDeploymentTeamAddCmd(out), + ) + cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage teams") + return cmd +} + +//nolint:dupl +func newDeploymentTeamListCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List all the teams in an Astro Deployment", + Long: "List all the teams in an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return listDeploymentTeam(cmd, out) + }, + } + return cmd +} + +func newDeploymentTeamRemoveCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "remove", + Aliases: []string{"rm"}, + Short: "Remove a team from an Astro Deployment", + Long: "Remove a team from an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return removeDeploymentTeam(cmd, args, out) + }, + } + return cmd +} + +func listDeploymentTeam(cmd *cobra.Command, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + cmd.SilenceUsage = true + return team.ListDeploymentTeams(out, astroCoreClient, deploymentID) +} + +func removeDeploymentTeam(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var id string + + // if an id was provided in the args we use it + if len(args) > 0 { + // make sure the email is lowercase + id = args[0] + } + cmd.SilenceUsage = true + return team.RemoveDeploymentTeam(id, deploymentID, out, astroCoreClient) +} + +func newDeploymentTeamAddCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "add [id]", + Short: "Add a team to an Astro Deployment with a specific role", + Long: "Add a team to an Astro Deployment with a specific role\n$astro deployment team add [id] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return addDeploymentTeam(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&deploymentID, "deployment-id", "w", "", "The Deployment's unique identifier") + cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+ + "new team. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func addDeploymentTeam(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var id string + + // if an email was provided in the args we use it + if len(args) > 0 { + // make sure the email is lowercase + id = args[0] + } + cmd.SilenceUsage = true + return team.AddDeploymentTeam(id, addDeploymentRole, deploymentID, out, astroCoreClient) +} + +func newDeploymentTeamUpdateCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update [id]", + Aliases: []string{"up"}, + Short: "Update a the role of a team in an Astro Deployment", + Long: "Update the role of a team in an Astro Deployment\n$astro deployment team update [id] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return updateDeploymentTeam(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&updateDeploymentRole, "role", "r", "", "The new role for the "+ + "team. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func updateDeploymentTeam(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var id string + + // if an id was provided in the args we use it + if len(args) > 0 { + id = args[0] + } + if updateDeploymentRole == "" { + // no role was provided so ask the user for it + updateDeploymentRole = input.Text("Enter a user Deployment role or custom role name to update team: ") + } + + cmd.SilenceUsage = true + return team.UpdateDeploymentTeamRole(id, updateDeploymentRole, deploymentID, out, astroCoreClient) +} + +func newDeploymentUserRootCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "user", + Aliases: []string{"us", "users"}, + Short: "Manage users in your Astro Deployment", + Long: "Manage users in your Astro Deployment.", + } + cmd.SetOut(out) + cmd.AddCommand( + newDeploymentUserListCmd(out), + newDeploymentUserUpdateCmd(out), + newDeploymentUserRemoveCmd(out), + newDeploymentUserAddCmd(out), + ) + cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage users") + + return cmd +} + +func newDeploymentUserAddCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "add [email]", + Short: "Add a user to an Astro Deployment with a specific role", + Long: "Add a user to an Astro Deployment with a specific role\n$astro deployment user add [email] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return addDeploymentUser(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+ + "new user. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func newDeploymentUserListCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List all the users in an Astro Deployment", + Long: "List all the users in an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return listDeploymentUser(cmd, out) + }, + } + return cmd +} + +func newDeploymentUserUpdateCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update [email]", + Aliases: []string{"up"}, + Short: "Update a the role of a user in an Astro Deployment", + Long: "Update the role of a user in an Astro Deployment\n$astro deployment user update [email] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return updateDeploymentUser(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&updateDeploymentRole, "role", "r", "", "The new role for the "+ + "user. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func newDeploymentUserRemoveCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "remove", + Aliases: []string{"rm"}, + Short: "Remove a user from an Astro Deployment", + Long: "Remove a user from an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return removeDeploymentUser(cmd, args, out) + }, + } + return cmd +} + func newDeploymentListCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "list", @@ -120,7 +334,7 @@ func newDeploymentListCmd(out io.Writer) *cobra.Command { return deploymentList(cmd, out) }, } - cmd.Flags().BoolVarP(&allDeployments, "all", "a", false, "Show deployments across all workspaces") + cmd.Flags().BoolVarP(&allDeployments, "all", "a", false, "Show deployments across all deployments") return cmd } @@ -567,3 +781,64 @@ func isValidExecutor(executor string) bool { func isValidCloudProvider(cloudProvider astrocore.SharedClusterCloudProvider) bool { return cloudProvider == astrocore.SharedClusterCloudProviderGcp || cloudProvider == astrocore.SharedClusterCloudProviderAws } + +func addDeploymentUser(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var email string + + // if an email was provided in the args we use it + if len(args) > 0 { + // make sure the email is lowercase + email = strings.ToLower(args[0]) + } + + cmd.SilenceUsage = true + return user.AddDeploymentUser(email, addDeploymentRole, deploymentID, out, astroCoreClient) +} + +func listDeploymentUser(cmd *cobra.Command, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + cmd.SilenceUsage = true + return user.ListDeploymentUsers(out, astroCoreClient, deploymentID) +} + +func updateDeploymentUser(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var email string + + // if an email was provided in the args we use it + if len(args) > 0 { + // make sure the email is lowercase + email = strings.ToLower(args[0]) + } + + if updateDeploymentRole == "" { + // no role was provided so ask the user for it + updateDeploymentRole = input.Text("Enter a user Deployment role or custom role name to update user: ") + } + + cmd.SilenceUsage = true + return user.UpdateDeploymentUserRole(email, updateDeploymentRole, deploymentID, out, astroCoreClient) +} + +func removeDeploymentUser(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var email string + + // if an email was provided in the args we use it + if len(args) > 0 { + // make sure the email is lowercase + email = strings.ToLower(args[0]) + } + + cmd.SilenceUsage = true + return user.RemoveDeploymentUser(email, deploymentID, out, astroCoreClient) +} From 0b52477b2816d8f6befefa273d4e3b7bbcf7895b Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 15 Feb 2024 12:24:12 -0500 Subject: [PATCH 02/21] add unit testing and fix user select bug --- cloud/team/team.go | 2 +- cloud/team/team_test.go | 356 ++++++++++++++++++++++++++++++++++++++++ cloud/user/user.go | 35 ++-- cloud/user/user_test.go | 302 ++++++++++++++++++++++++++++++++++ 4 files changed, 682 insertions(+), 13 deletions(-) diff --git a/cloud/team/team.go b/cloud/team/team.go index 1d24b35b6..8a7a7884e 100644 --- a/cloud/team/team.go +++ b/cloud/team/team.go @@ -645,7 +645,7 @@ func AddUser(teamID, userID string, out io.Writer, client astrocore.CoreClient) if len(users) == 0 { return ErrNoUsersFoundInOrg } - userSelection, err = user.SelectUser(users, false) + userSelection, err = user.SelectUser(users, "organization") if err != nil { return err } diff --git a/cloud/team/team_test.go b/cloud/team/team_test.go index 201c8581d..19ffd0550 100644 --- a/cloud/team/team_test.go +++ b/cloud/team/team_test.go @@ -312,6 +312,66 @@ var ( } ) +// deployment teams variables + +var ( + deploymentID = "ck05r3bor07h40d02y2hw4n4d" + ListDeploymentTeamsResponseOK = astrocore.ListDeploymentTeamsResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.TeamsPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + Teams: workspaceTeams, + }, + } + ListDeploymentTeamsResponseEmpty = astrocore.ListDeploymentTeamsResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.TeamsPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + }, + } + ListDeploymentTeamsResponseError = astrocore.ListDeploymentTeamsResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyList, + JSON200: nil, + } + MutateDeploymentTeamRoleResponseOK = astrocore.MutateDeploymentTeamRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.TeamRole{ + Role: "DEPLOYMENT_ADMIN", + }, + } + MutateDeploymentTeamRoleResponseError = astrocore.MutateDeploymentTeamRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + JSON200: nil, + } + DeleteDeploymentTeamResponseOK = astrocore.DeleteDeploymentTeamResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentTeamResponseError = astrocore.DeleteDeploymentTeamResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + } +) + func TestListOrgTeam(t *testing.T) { t.Run("happy path TestListOrgTeam", func(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) @@ -1423,3 +1483,299 @@ func TestGetWorkspaceTeams(t *testing.T) { assert.Equal(t, expectedOutMessage, out.String()) }) } + +func TestListDeploymentTeam(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path TestListDeploymentTeam", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + err := ListDeploymentTeams(out, mockClient, deploymentID) + assert.NoError(t, err) + }) + + t.Run("error path when ListDeploymentTeamsWithResponse return network error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := ListDeploymentTeams(out, mockClient, deploymentID) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when ListDeploymentTeamsWithResponse returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseError, nil).Twice() + err := ListDeploymentTeams(out, mockClient, deploymentID) + assert.EqualError(t, err, "failed to list teams") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := ListDeploymentTeams(out, mockClient, deploymentID) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} + +func TestUpdateDeploymentTeamRole(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path UpdateDeploymentTeamRole", func(t *testing.T) { + expectedOutMessage := "The deployment team team1-id role was successfully updated to DEPLOYMENT_ADMIN\n" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + err := UpdateDeploymentTeamRole(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path no deployment teams found", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseEmpty, nil).Twice() + err := UpdateDeploymentTeamRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "no teams found in your deployment") + }) + + t.Run("error path when GetTeamWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Twice() + err := UpdateDeploymentTeamRole(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentTeamRoleWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := UpdateDeploymentTeamRole(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentTeamRoleWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseError, nil).Once() + err := UpdateDeploymentTeamRole(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update team") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := UpdateDeploymentTeamRole(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("UpdateDeploymentTeamRole no id passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The deployment team team1-id role was successfully updated to DEPLOYMENT_ADMIN\n" + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + + err = UpdateDeploymentTeamRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOut, out.String()) + }) +} + +func TestAddDeploymentTeam(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path AddDeploymentTeam", func(t *testing.T) { + expectedOutMessage := "The team team1-id was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + err := AddDeploymentTeam(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when GetTeamWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Twice() + err := AddDeploymentTeam(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentTeamRoleWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := AddDeploymentTeam(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentTeamRoleWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseError, nil).Once() + err := AddDeploymentTeam(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update team") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := AddDeploymentTeam(team1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("AddDeploymentTeam no id passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrganizationTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrganizationTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The team team1-id was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + + err = AddDeploymentTeam("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOut, out.String()) + }) +} + +func TestRemoveDeploymentTeam(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path DeleteDeploymentTeam", func(t *testing.T) { + expectedOutMessage := fmt.Sprintf("Astro Team %s was successfully removed from deployment %s\n", team1.Name, deploymentID) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseOK, nil).Once() + err := RemoveDeploymentTeam(team1.Id, deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when GetTeamWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Twice() + err := RemoveDeploymentTeam(team1.Id, deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when DeleteDeploymentTeamWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := RemoveDeploymentTeam(team1.Id, deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when DeleteDeploymentTeamWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseError, nil).Once() + err := RemoveDeploymentTeam(team1.Id, deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update team") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := RemoveDeploymentTeam(team1.Id, deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("RemoveDeploymentTeam no id passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOutMessage := fmt.Sprintf("Astro Team %s was successfully removed from deployment %s\n", team1.Name, deploymentID) + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseOK, nil).Once() + + err = RemoveDeploymentTeam("", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} + +func TestGetDeploymentTeams(t *testing.T) { + t.Run("happy path get DeploymentTeams pulls deployment from context", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + _, err := GetDeploymentTeams(mockClient, deploymentID, 10) + assert.NoError(t, err) + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + _, err := GetDeploymentTeams(mockClient, deploymentID, 10) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} diff --git a/cloud/user/user.go b/cloud/user/user.go index d4dd9598f..1de40c9d9 100644 --- a/cloud/user/user.go +++ b/cloud/user/user.go @@ -89,7 +89,7 @@ func UpdateUserRole(email, role string, out io.Writer, client astrocore.CoreClie return ErrUserNotFound } } else { - user, err := SelectUser(users, false) + user, err := SelectUser(users, "organization") userID = user.Id email = user.Username if err != nil { @@ -124,10 +124,12 @@ func IsRoleValid(role string) error { return ErrInvalidRole } -func SelectUser(users []astrocore.User, workspace bool) (astrocore.User, error) { +func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, error) { roleColumn := "ORGANIZATION ROLE" - if workspace { + if roleEntity == "workspace" { roleColumn = "WORKSPACE ROLE" + } else if roleEntity == "deployment" { + roleColumn = "DEPLOYMENT ROLE" } table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, @@ -140,7 +142,16 @@ func SelectUser(users []astrocore.User, workspace bool) (astrocore.User, error) userMap := map[string]astrocore.User{} for i := range users { index := i + 1 - if workspace { + if roleEntity == "deployment" { + table.AddRow([]string{ + strconv.Itoa(index), + users[i].FullName, + users[i].Username, + users[i].Id, + *users[i].DeploymentRole, + users[i].CreatedAt.Format(time.RFC3339), + }, false) + } else if roleEntity == "workspace" { table.AddRow([]string{ strconv.Itoa(index), users[i].FullName, @@ -254,7 +265,7 @@ func AddWorkspaceUser(email, role, workspace string, out io.Writer, client astro if err != nil { return err } - userID, email, err := getUserID(email, users, false) + userID, email, err := getUserID(email, users, "organization") if err != nil { return err } @@ -290,7 +301,7 @@ func UpdateWorkspaceUserRole(email, role, workspace string, out io.Writer, clien if err != nil { return err } - userID, email, err := getUserID(email, users, true) + userID, email, err := getUserID(email, users, "workspace") if err != nil { return err } @@ -414,7 +425,7 @@ func RemoveWorkspaceUser(email, workspace string, out io.Writer, client astrocor if err != nil { return err } - userID, email, err := getUserID(email, users, true) + userID, email, err := getUserID(email, users, "workspace") if err != nil { return err } @@ -430,9 +441,9 @@ func RemoveWorkspaceUser(email, workspace string, out io.Writer, client astrocor return nil } -func getUserID(email string, users []astrocore.User, workspace bool) (userID, newEmail string, err error) { +func getUserID(email string, users []astrocore.User, roleEntity string) (userID, newEmail string, err error) { if email == "" { - user, err := SelectUser(users, workspace) + user, err := SelectUser(users, roleEntity) userID = user.Id email = user.Username if err != nil { @@ -479,7 +490,7 @@ func AddDeploymentUser(email, role, deployment string, out io.Writer, client ast if err != nil { return err } - userID, email, err := getUserID(email, users, false) + userID, email, err := getUserID(email, users, "organization") if err != nil { return err } @@ -509,7 +520,7 @@ func UpdateDeploymentUserRole(email, role, deployment string, out io.Writer, cli if err != nil { return err } - userID, email, err := getUserID(email, users, true) + userID, email, err := getUserID(email, users, "deployment") if err != nil { return err } @@ -542,7 +553,7 @@ func RemoveDeploymentUser(email, deployment string, out io.Writer, client astroc if err != nil { return err } - userID, email, err := getUserID(email, users, true) + userID, email, err := getUserID(email, users, "deployment") if err != nil { return err } diff --git a/cloud/user/user_test.go b/cloud/user/user_test.go index 4e24b5864..9a9434f83 100644 --- a/cloud/user/user_test.go +++ b/cloud/user/user_test.go @@ -151,6 +151,67 @@ var ( } ) +// deployment users variables +var ( + deploymentID = "ck05r3bor07h40d02y2hw4n4d" + deploymentRole = "DEPLOYMENT_ADMIN" + deploymentUser1 = astrocore.User{ + CreatedAt: time.Now(), + FullName: "user 1", + Id: "user1-id", + DeploymentRole: &deploymentRole, + OrgUserRelationIsIdpManaged: &isIdpManaged, + Username: "user@1.com", + } + deploymentUsers = []astrocore.User{ + deploymentUser1, + } + ListDeploymentUsersResponseOK = astrocore.ListDeploymentUsersResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.UsersPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + Users: deploymentUsers, + }, + } + ListDeploymentUsersResponseError = astrocore.ListDeploymentUsersResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyList, + JSON200: nil, + } + MutateDeploymentUserRoleResponseOK = astrocore.MutateDeploymentUserRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.UserRole{ + Role: "DEPLOYMENT_ADMIN", + }, + } + MutateDeploymentUserRoleResponseError = astrocore.MutateDeploymentUserRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + JSON200: nil, + } + DeleteDeploymentUserResponseOK = astrocore.DeleteDeploymentUserResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentUserResponseError = astrocore.DeleteDeploymentUserResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + } +) + type testWriter struct { Error error } @@ -715,3 +776,244 @@ func TestIsOrganizationRoleValid(t *testing.T) { assert.Equal(t, ErrInvalidOrganizationRole, err) }) } + +func TestListDeploymentUser(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path TestListDeploymentUser", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + err := ListDeploymentUsers(out, mockClient, deploymentID) + assert.NoError(t, err) + }) + + t.Run("error path when ListDeploymentUsersWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := ListDeploymentUsers(out, mockClient, deploymentID) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when ListDeploymentUsersWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseError, nil).Twice() + err := ListDeploymentUsers(out, mockClient, deploymentID) + assert.EqualError(t, err, "failed to list users") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := ListDeploymentUsers(out, mockClient, deploymentID) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} + +func TestUpdateDeploymentUserRole(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path UpdateDeploymentUserRole", func(t *testing.T) { + expectedOutMessage := "The deployment user user@1.com role was successfully updated to DEPLOYMENT_ADMIN\n" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + err := UpdateDeploymentUserRole("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when MutateDeploymentUserRoleWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := UpdateDeploymentUserRole("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentUserRoleWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseError, nil).Once() + err := UpdateDeploymentUserRole("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update user") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := UpdateDeploymentUserRole("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("UpdateDeploymentUserRole no email passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The deployment user user@1.com role was successfully updated to DEPLOYMENT_ADMIN\n" + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + + err = UpdateDeploymentUserRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOut, out.String()) + }) +} + +func TestAddDeploymentUser(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path AddDeploymentUser", func(t *testing.T) { + expectedOutMessage := "The user user@1.com was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + err := AddDeploymentUser("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when MutateDeploymentUserRoleWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := AddDeploymentUser("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when MutateDeploymentUserRoleWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseError, nil).Once() + err := AddDeploymentUser("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update user") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := AddDeploymentUser("user@1.com", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("AddDeploymentUser no email passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The user user@1.com was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + + err = AddDeploymentUser("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOut, out.String()) + }) +} + +func TestDeleteDeploymentUser(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path DeleteDeploymentUser", func(t *testing.T) { + expectedOutMessage := "The user user@1.com was successfully removed from the deployment\n" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseOK, nil).Once() + err := RemoveDeploymentUser("user@1.com", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when DeleteDeploymentUserWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := RemoveDeploymentUser("user@1.com", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when DeleteDeploymentUserWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseError, nil).Once() + err := RemoveDeploymentUser("user@1.com", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update user") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := RemoveDeploymentUser("user@1.com", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("DeleteDeploymentUser no email passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The user user@1.com was successfully removed from the deployment\n" + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseOK, nil).Once() + + err = RemoveDeploymentUser("", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOut, out.String()) + }) +} From c05c266f9f3eb5286abed876886ace49f23f22dc Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 15 Feb 2024 12:52:24 -0500 Subject: [PATCH 03/21] add unit test to cmd files --- cmd/cloud/deployment_test.go | 624 +++++++++++++++++++++++++++++++++++ cmd/cloud/workspace_test.go | 4 +- 2 files changed, 626 insertions(+), 2 deletions(-) diff --git a/cmd/cloud/deployment_test.go b/cmd/cloud/deployment_test.go index b1e791ef7..4aac15c92 100644 --- a/cmd/cloud/deployment_test.go +++ b/cmd/cloud/deployment_test.go @@ -3,10 +3,12 @@ package cloud import ( "bytes" "encoding/json" + "fmt" "io" "net/http" "os" "testing" + "time" airflowversions "github.com/astronomer/astro-cli/airflow_versions" astrocore "github.com/astronomer/astro-cli/astro-client-core" @@ -1048,3 +1050,625 @@ func TestIsValidCloudProvider(t *testing.T) { assert.False(t, actual) }) } + +var ( + mockDeploymentID = "ck05r3bor07h40d02y2hw4n4v" + deploymentRole = "DEPLOYMENT_ADMIN" + deploymentUser1 = astrocore.User{ + CreatedAt: time.Now(), + FullName: "user 1", + Id: "user1-id", + DeploymentRole: &deploymentRole, + Username: "user@1.com", + } + deploymentUsers = []astrocore.User{ + deploymentUser1, + } + + deploymentTeams = []astrocore.Team{ + team1, + } + ListDeploymentUsersResponseOK = astrocore.ListDeploymentUsersResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.UsersPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + Users: deploymentUsers, + }, + } + ListDeploymentUsersResponseError = astrocore.ListDeploymentUsersResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyList, + JSON200: nil, + } + MutateDeploymentUserRoleResponseOK = astrocore.MutateDeploymentUserRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.UserRole{ + Role: "DEPLOYMENT_ADMIN", + }, + } + MutateDeploymentUserRoleResponseError = astrocore.MutateDeploymentUserRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + JSON200: nil, + } + DeleteDeploymentUserResponseOK = astrocore.DeleteDeploymentUserResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentUserResponseError = astrocore.DeleteDeploymentUserResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyUpdate, + } + ListDeploymentTeamsResponseOK = astrocore.ListDeploymentTeamsResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.TeamsPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + Teams: deploymentTeams, + }, + } + ListDeploymentTeamsResponseError = astrocore.ListDeploymentTeamsResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorBodyList, + JSON200: nil, + } + MutateDeploymentTeamRoleResponseOK = astrocore.MutateDeploymentTeamRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.TeamRole{ + Role: "DEPLOYMENT_ADMIN", + }, + } + MutateDeploymentTeamRoleResponseError = astrocore.MutateDeploymentTeamRoleResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorBodyUpdate, + JSON200: nil, + } + DeleteDeploymentTeamResponseOK = astrocore.DeleteDeploymentTeamResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentTeamResponseError = astrocore.DeleteDeploymentTeamResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorDelete, + } +) + +func TestDeploymentUserList(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints list help", func(t *testing.T) { + cmdArgs := []string{"user", "list", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"user", "list"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("any errors from api are returned and users are not listed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to list users") + }) + t.Run("any context errors from api are returned and users are not listed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) +} + +func TestDeploymentUserUpdate(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints update help", func(t *testing.T) { + cmdArgs := []string{"user", "update", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"user", "update", "user@1.com", "--role", "DEPLOYMENT_ADMIN"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid email with valid role updates user", func(t *testing.T) { + expectedOut := "The deployment user user@1.com role was successfully updated to DEPLOYMENT_ADMIN" + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "update", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + + t.Run("any errors from api are returned and role is not updated", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "update", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update user") + }) + + t.Run("any context errors from api are returned and role is not updated", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "update", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The deployment user user@1.com role was successfully updated to DEPLOYMENT_ADMIN" + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + + cmdArgs := []string{"user", "update", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentUserAdd(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints add help", func(t *testing.T) { + cmdArgs := []string{"user", "add", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"user", "add", "user@1.com", "--role", "DEPLOYMENT_ADMIN"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid email with valid role adds user", func(t *testing.T) { + expectedOut := "The user user@1.com was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "add", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and user is not added", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "add", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update user", "--deployment-id", mockDeploymentID) + }) + + t.Run("any context errors from api are returned and role is not added", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "add", "user@1.com", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrgUsersWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The user user@1.com was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n" + mockClient.On("MutateDeploymentUserRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentUserRoleResponseOK, nil).Once() + + cmdArgs := []string{"user", "add", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentUserRemove(t *testing.T) { + expectedHelp := "Remove a user from an Astro Deployment" + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints remove help", func(t *testing.T) { + cmdArgs := []string{"user", "remove", "-h"} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedHelp) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"user", "remove", "user@1.com"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid email removes user", func(t *testing.T) { + expectedOut := "The user user@1.com was successfully removed from the deployment" + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "remove", "user@1.com", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and user is not removed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "remove", "user@1.com", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update user") + }) + t.Run("any context errors from api are returned and the user is not removed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"user", "remove", "user@1.com", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentUsersWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentUsersResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := "The user user@1.com was successfully removed from the deployment" + mockClient.On("DeleteDeploymentUserWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentUserResponseOK, nil).Once() + + cmdArgs := []string{"user", "remove", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentTeamList(t *testing.T) { + expectedHelp := "List all the teams in an Astro Deployment" + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints list help", func(t *testing.T) { + cmdArgs := []string{"team", "list", "-h"} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedHelp) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"team", "list"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("any errors from api are returned and teams are not listed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to list teams") + }) + t.Run("any context errors from api are returned and teams are not listed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) +} + +func TestDeploymentTeamUpdate(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints update help", func(t *testing.T) { + cmdArgs := []string{"team", "update", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"team", "update", team1.Id, "--role", "DEPLOYMENT_ADMIN"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid id with valid role updates team", func(t *testing.T) { + expectedOut := fmt.Sprintf("The deployment team %s role was successfully updated to DEPLOYMENT_ADMIN", team1.Id) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "update", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and role is not updated", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "update", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update team") + }) + + t.Run("any context errors from api are returned and role is not updated", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "update", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := fmt.Sprintf("The deployment team %s role was successfully updated to DEPLOYMENT_ADMIN", team1.Id) + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + + cmdArgs := []string{"team", "update", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentTeamAdd(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints add help", func(t *testing.T) { + cmdArgs := []string{"team", "add", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("valid id with valid role adds team", func(t *testing.T) { + expectedOut := fmt.Sprintf("The team %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", team1.Id) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "add", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"team", "add", team1.Id} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("any errors from api are returned and team is not added", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "add", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update team") + }) + + t.Run("any context errors from api are returned and role is not added", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "add", team1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListOrganizationTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := fmt.Sprintf("The team %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", team1.Id) + mockClient.On("MutateDeploymentTeamRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentTeamRoleResponseOK, nil).Once() + astroCoreClient = mockClient + + cmdArgs := []string{"team", "add", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentTeamRemove(t *testing.T) { + expectedHelp := "Remove a team from an Astro Deployment" + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints remove help", func(t *testing.T) { + cmdArgs := []string{"team", "remove", "-h"} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedHelp) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"team", "remove", team1.Id} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid id removes team", func(t *testing.T) { + expectedOut := fmt.Sprintf("Astro Team %s was successfully removed from deployment %s\n", team1.Name, mockDeploymentID) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "remove", team1.Id, "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and team is not removed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "remove", team1.Id, "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to delete team") + }) + t.Run("any context errors from api are returned and the team is not removed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetTeamWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetTeamWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"team", "remove", team1.Id, "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no id is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentTeamsWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentTeamsResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := fmt.Sprintf("Astro Team %s was successfully removed from deployment %s", team1.Name, mockDeploymentID) + mockClient.On("DeleteDeploymentTeamWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentTeamResponseOK, nil).Once() + astroCoreClient = mockClient + + cmdArgs := []string{"team", "remove", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} diff --git a/cmd/cloud/workspace_test.go b/cmd/cloud/workspace_test.go index 445a4c6e5..db220c633 100644 --- a/cmd/cloud/workspace_test.go +++ b/cmd/cloud/workspace_test.go @@ -256,7 +256,7 @@ func TestWorkspaceUserList(t *testing.T) { }) } -func TestWorkspacUserUpdate(t *testing.T) { +func TestWorkspaceUserUpdate(t *testing.T) { expectedHelp := "astro workspace user update [email] --role [WORKSPACE_MEMBER, WORKSPACE_AUTHOR, WORKSPACE_OPERATOR, WORKSPACE_OWNER]" testUtil.InitTestConfig(testUtil.LocalPlatform) @@ -410,7 +410,7 @@ func TestWorkspaceUserAdd(t *testing.T) { }) } -func TestWorkspacUserRemove(t *testing.T) { +func TestWorkspaceUserRemove(t *testing.T) { expectedHelp := "Remove a user from an Astro Workspace" testUtil.InitTestConfig(testUtil.LocalPlatform) From 1b985fe3adae901bec6f137b3fe01de0e722c707 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 15 Feb 2024 16:21:38 -0500 Subject: [PATCH 04/21] lint --- cloud/user/user.go | 18 +++++++++++++----- cmd/cloud/deployment.go | 6 +++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cloud/user/user.go b/cloud/user/user.go index 1de40c9d9..80f719dc8 100644 --- a/cloud/user/user.go +++ b/cloud/user/user.go @@ -126,11 +126,13 @@ func IsRoleValid(role string) error { func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, error) { roleColumn := "ORGANIZATION ROLE" - if roleEntity == "workspace" { + switch r := roleEntity; r { + case "workspace": roleColumn = "WORKSPACE ROLE" - } else if roleEntity == "deployment" { + case "deployment": roleColumn = "DEPLOYMENT ROLE" } + table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, DynamicPadding: true, @@ -142,7 +144,8 @@ func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, erro userMap := map[string]astrocore.User{} for i := range users { index := i + 1 - if roleEntity == "deployment" { + switch r := roleEntity; r { + case "deployment": table.AddRow([]string{ strconv.Itoa(index), users[i].FullName, @@ -151,7 +154,7 @@ func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, erro *users[i].DeploymentRole, users[i].CreatedAt.Format(time.RFC3339), }, false) - } else if roleEntity == "workspace" { + case "workspace": table.AddRow([]string{ strconv.Itoa(index), users[i].FullName, @@ -160,7 +163,7 @@ func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, erro *users[i].WorkspaceRole, users[i].CreatedAt.Format(time.RFC3339), }, false) - } else { + default: table.AddRow([]string{ strconv.Itoa(index), users[i].FullName, @@ -170,6 +173,7 @@ func SelectUser(users []astrocore.User, roleEntity string) (astrocore.User, erro users[i].CreatedAt.Format(time.RFC3339), }, false) } + userMap[strconv.Itoa(index)] = users[i] } @@ -387,6 +391,8 @@ func GetWorkspaceUsers(client astrocore.CoreClient, workspace string, limit int) } // Prints a list of all of a workspaces users +// +//nolint:dupl func ListWorkspaceUsers(out io.Writer, client astrocore.CoreClient, workspace string) error { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, @@ -606,6 +612,8 @@ func GetDeploymentUsers(client astrocore.CoreClient, deployment string, limit in } // Prints a list of all of an deployments users +// +//nolint:dupl func ListDeploymentUsers(out io.Writer, client astrocore.CoreClient, deployment string) error { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 4f8cdeed0..88d8575dd 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -2,9 +2,6 @@ package cloud import ( "fmt" - "github.com/astronomer/astro-cli/cloud/team" - "github.com/astronomer/astro-cli/cloud/user" - "github.com/astronomer/astro-cli/pkg/input" "io" "strings" @@ -14,7 +11,10 @@ import ( "github.com/astronomer/astro-cli/cloud/deployment" "github.com/astronomer/astro-cli/cloud/deployment/fromfile" "github.com/astronomer/astro-cli/cloud/organization" + "github.com/astronomer/astro-cli/cloud/team" + "github.com/astronomer/astro-cli/cloud/user" "github.com/astronomer/astro-cli/pkg/httputil" + "github.com/astronomer/astro-cli/pkg/input" "github.com/pkg/errors" "github.com/spf13/cobra" ) From f8e7fe5b8d5966783ccc1381e0b2838da4d7d6b4 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 15 Feb 2024 17:55:20 -0500 Subject: [PATCH 05/21] fix default deployment role in add command --- cmd/cloud/deployment.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 88d8575dd..6a8c8a8f5 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -196,7 +196,7 @@ func newDeploymentTeamAddCmd(out io.Writer) *cobra.Command { }, } cmd.Flags().StringVarP(&deploymentID, "deployment-id", "w", "", "The Deployment's unique identifier") - cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+ + cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "DEPLOYMENT_ADMIN", "The role for the "+ "new team. Possible values are DEPLOYMENT_ADMIN or the custom role name.") return cmd } @@ -278,7 +278,7 @@ func newDeploymentUserAddCmd(out io.Writer) *cobra.Command { return addDeploymentUser(cmd, args, out) }, } - cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "WORKSPACE_MEMBER", "The role for the "+ + cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "DEPLOYMENT_ADMIN", "The role for the "+ "new user. Possible values are DEPLOYMENT_ADMIN or the custom role name.") return cmd } From 020d73579f750fe41a602c03ab53aa0361dafbfe Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 15 Feb 2024 17:54:13 -0500 Subject: [PATCH 06/21] wip --- cloud/apitoken/apitoken.go | 293 +++++++++++++++++++++++++++++++++++++ cmd/cloud/deployment.go | 137 +++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 cloud/apitoken/apitoken.go diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go new file mode 100644 index 000000000..afae06659 --- /dev/null +++ b/cloud/apitoken/apitoken.go @@ -0,0 +1,293 @@ +package apitoken + +import ( + httpContext "context" + "errors" + "fmt" + astrocore "github.com/astronomer/astro-cli/astro-client-core" + "github.com/astronomer/astro-cli/context" + "github.com/astronomer/astro-cli/pkg/input" + "github.com/astronomer/astro-cli/pkg/printutil" + "io" + "os" + "strconv" + "time" +) + +var ( + ErrInvalidApiTokenKey = errors.New("invalid ApiToken selected") + apiTokenPagnationLimit = 100 +) + +// Returns a list of all of an organizations apiTokens +func GetOrgApiTokens(client astrocore.CoreClient) ([]astrocore.ApiToken, error) { + offset := 0 + var apiTokens []astrocore.ApiToken + + ctx, err := context.GetCurrentContext() + if err != nil { + return nil, err + } + + for { + resp, err := client.ListOrganizationApiTokensWithResponse(httpContext.Background(), ctx.Organization, &astrocore.ListOrganizationApiTokensParams{ + Offset: &offset, + Limit: &apiTokenPagnationLimit, + }) + if err != nil { + return nil, err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return nil, err + } + apiTokens = append(apiTokens, resp.JSON200.ApiTokens...) + + if resp.JSON200.TotalCount <= offset { + break + } + + offset += apiTokenPagnationLimit + } + + return apiTokens, nil +} + +func AddDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + var apiToken *astrocore.ApiToken + + if apiTokenID == "" { + // Get all org apiTokens. Setting limit to 1000 for now + apiTokens, err := GetOrgApiTokens(client) + if err != nil { + return err + } + apiToken, err = getApiToken(apiTokens) + if err != nil { + return err + } + } else { + resp, err := client.GetDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiTokenID) + if err != nil { + fmt.Println("error in GetDeploymentApiTokenWithResponse") + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + fmt.Println("error in NormalizeAPIError") + return err + } + apiToken = resp.JSON200 + } + mutateApiTokenInput := astrocore.UpdateDeploymentApiTokenRequest{ + Role: role, + Name: apiToken.Name, + } + resp, err := client.UpdateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiToken.Id, mutateApiTokenInput) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The apiToken %s was successfully added to the deployment with the role %s\n", apiToken.Id, role) + return nil +} + +func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + var apiToken *astrocore.ApiToken + + if apiTokenID == "" { + // Get all org apiTokens. Setting limit to 1000 for now + apiTokens, err := GetOrgApiTokens(client) + if err != nil { + return err + } + apiToken, err = getApiToken(apiTokens) + if err != nil { + return err + } + } else { + resp, err := client.GetDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiTokenID) + if err != nil { + fmt.Println("error in GetDeploymentApiTokenWithResponse") + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + fmt.Println("error in NormalizeAPIError") + return err + } + apiToken = resp.JSON200 + } + + mutateApiTokenInput := astrocore.UpdateDeploymentApiTokenRequest{ + Role: role, + Name: apiToken.Name, + } + fmt.Println("deployment: " + deployment) + resp, err := client.UpdateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiToken.Id, mutateApiTokenInput) + if err != nil { + fmt.Println("error in MutateDeploymentApiTokenRoleWithResponse") + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + fmt.Println("error in NormalizeAPIError") + return err + } + fmt.Fprintf(out, "The deployment apiToken %s role was successfully updated to %s\n", apiTokenID, role) + return nil +} + +func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { + apiToken, err := SelectApiToken(apitokens) + if err != nil { + return nil, err + } + + return &apiToken, nil +} + +func SelectApiToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToken, error) { + + table := printutil.Table{ + Padding: []int{30, 50, 10, 50, 10, 10, 10}, + DynamicPadding: true, + Header: []string{"#", "NAME", "DESCRIPTION", "ID", "CREATE DATE", "UPDATE DATE"}, + } + + fmt.Println("\nPlease select the user:") + + apiTokenMap := map[string]astrocore.ApiToken{} + for i := range apiTokens { + index := i + 1 + table.AddRow([]string{ + strconv.Itoa(index), + apiTokens[i].Name, + apiTokens[i].Description, + apiTokens[i].Id, + apiTokens[i].CreatedAt.Format(time.RFC3339), + apiTokens[i].UpdatedAt.Format(time.RFC3339), + }, false) + + apiTokenMap[strconv.Itoa(index)] = apiTokens[i] + } + + table.Print(os.Stdout) + choice := input.Text("\n> ") + selected, ok := apiTokenMap[choice] + if !ok { + return astrocore.ApiToken{}, ErrInvalidApiTokenKey + } + return selected, nil +} + +func RemoveDeploymentApiToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { + ctx, err := context.GetCurrentContext() + if err != nil { + return err + } + + if apiTokenID == "" { + // Get all org apiTokens. Setting limit to 1000 for now + apiTokens, err := GetDeploymentApiTokens(client, deployment, apiTokenPagnationLimit) + if err != nil { + return err + } + apiToken, err := getApiToken(apiTokens) + if err != nil { + return err + } + apiTokenID = apiToken.Id + } + + resp, err := client.DeleteDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiTokenID) + if err != nil { + return err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return err + } + fmt.Fprintf(out, "The apiToken %s was successfully removed from the deployment\n", apiTokenID) + return nil +} + +// Returns a list of all of a deployments apiTokens +func GetDeploymentApiTokens(client astrocore.CoreClient, deployment string, limit int) ([]astrocore.ApiToken, error) { + offset := 0 + var apiTokens []astrocore.ApiToken + + ctx, err := context.GetCurrentContext() + if err != nil { + return nil, err + } + + for { + resp, err := client.ListDeploymentApiTokensWithResponse(httpContext.Background(), ctx.Organization, deployment, &astrocore.ListDeploymentApiTokensParams{ + Offset: &offset, + Limit: &limit, + }) + if err != nil { + return nil, err + } + err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) + if err != nil { + return nil, err + } + apiTokens = append(apiTokens, resp.JSON200.ApiTokens...) + + if resp.JSON200.TotalCount <= offset { + break + } + + offset += limit + } + + return apiTokens, nil +} + +// Prints a list of all of an deployments apiTokens +// +//nolint:dupl +func ListDeploymentApiTokens(out io.Writer, client astrocore.CoreClient, deployment string) error { + table := printutil.Table{ + Padding: []int{30, 50, 10, 50, 10, 10, 10}, + DynamicPadding: true, + Header: []string{"NAME", "DESCRIPTION", "ID", "DEPLOYMENT ROLE", "CREATE DATE", "UPDATE DATE"}, + } + apiTokens, err := GetDeploymentApiTokens(client, deployment, apiTokenPagnationLimit) + if err != nil { + return err + } + + for i := range apiTokens { + var deploymentRole string + for _, role := range apiTokens[i].Roles { + if role.EntityId == deployment { + deploymentRole = role.Role + } + } + table.AddRow([]string{ + apiTokens[i].Name, + apiTokens[i].Description, + apiTokens[i].Id, + deploymentRole, + apiTokens[i].CreatedAt.Format(time.RFC3339), + apiTokens[i].UpdatedAt.Format(time.RFC3339), + }, false) + } + + table.Print(out) + return nil +} diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 6a8c8a8f5..848d6fe66 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -2,6 +2,7 @@ package cloud import ( "fmt" + "github.com/astronomer/astro-cli/cloud/apitoken" "io" "strings" @@ -113,6 +114,7 @@ func newDeploymentRootCmd(out io.Writer) *cobra.Command { newDeploymentPoolRootCmd(out), newDeploymentUserRootCmd(out), newDeploymentTeamRootCmd(out), + newDeploymentApiTokenRootCmd(out), ) return cmd } @@ -842,3 +844,138 @@ func removeDeploymentUser(cmd *cobra.Command, args []string, out io.Writer) erro cmd.SilenceUsage = true return user.RemoveDeploymentUser(email, deploymentID, out, astroCoreClient) } + +//nolint:dupl +func newDeploymentApiTokenRootCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "api-token", + Aliases: []string{"at", "apiTokens"}, + Short: "Manage apiTokens in your Astro Deployment", + Long: "Manage apiTokens in your Astro Deployment.", + } + cmd.SetOut(out) + cmd.AddCommand( + newDeploymentApiTokenListCmd(out), + newDeploymentApiTokenUpdateCmd(out), + newDeploymentApiTokenRemoveCmd(out), + newDeploymentApiTokenAddCmd(out), + ) + cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage apiTokens") + return cmd +} + +func newDeploymentApiTokenAddCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "add [apiTokenID]", + Short: "Add a apiToken to an Astro Deployment with a specific role", + Long: "Add a apiToken to an Astro Deployment with a specific role\n$astro deployment apiToken add [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return addDeploymentApiToken(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "DEPLOYMENT_ADMIN", "The role for the "+ + "new apiToken. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func newDeploymentApiTokenListCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List all the apiTokens in an Astro Deployment", + Long: "List all the apiTokens in an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return listDeploymentApiToken(cmd, out) + }, + } + return cmd +} + +func newDeploymentApiTokenUpdateCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "update [apiTokenID]", + Aliases: []string{"up"}, + Short: "Update a the role of a apiToken in an Astro Deployment", + Long: "Update the role of a apiToken in an Astro Deployment\n$astro deployment apiToken update [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + RunE: func(cmd *cobra.Command, args []string) error { + return updateDeploymentApiToken(cmd, args, out) + }, + } + cmd.Flags().StringVarP(&updateDeploymentRole, "role", "r", "", "The new role for the "+ + "apiToken. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + return cmd +} + +func newDeploymentApiTokenRemoveCmd(out io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "remove", + Aliases: []string{"rm"}, + Short: "Remove a apiToken from an Astro Deployment", + Long: "Remove a apiToken from an Astro Deployment", + RunE: func(cmd *cobra.Command, args []string) error { + return removeDeploymentApiToken(cmd, args, out) + }, + } + return cmd +} + +func addDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var apiTokenID string + + // if an apiTokenID was provided in the args we use it + if len(args) > 0 { + // make sure the apiTokenID is lowercase + apiTokenID = strings.ToLower(args[0]) + } + + cmd.SilenceUsage = true + return apitoken.AddDeploymentApiToken(apiTokenID, addDeploymentRole, deploymentID, out, astroCoreClient) +} + +func listDeploymentApiToken(cmd *cobra.Command, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + cmd.SilenceUsage = true + return apitoken.ListDeploymentApiTokens(out, astroCoreClient, deploymentID) +} + +func updateDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var apiTokenID string + + // if an apiTokenID was provided in the args we use it + if len(args) > 0 { + // make sure the apiTokenID is lowercase + apiTokenID = strings.ToLower(args[0]) + } + + if updateDeploymentRole == "" { + // no role was provided so ask the apiToken for it + updateDeploymentRole = input.Text("Enter a apiToken Deployment role or custom role name to update apiToken: ") + } + + cmd.SilenceUsage = true + return apitoken.UpdateDeploymentApiTokenRole(apiTokenID, updateDeploymentRole, deploymentID, out, astroCoreClient) +} + +func removeDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { + if deploymentID == "" { + return errors.New("flag --deployment-id is required") + } + var apiTokenID string + + // if an apiTokenID was provided in the args we use it + if len(args) > 0 { + // make sure the apiTokenID is lowercase + apiTokenID = strings.ToLower(args[0]) + } + + cmd.SilenceUsage = true + return apitoken.RemoveDeploymentApiToken(apiTokenID, deploymentID, out, astroCoreClient) +} From 6a480eda0a50290f3df30bccdc7c0ea60a90bcc3 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Fri, 16 Feb 2024 08:13:57 -0500 Subject: [PATCH 07/21] wip --- cloud/apitoken/apitoken.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index afae06659..e585ca148 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -53,7 +53,7 @@ func GetOrgApiTokens(client astrocore.CoreClient) ([]astrocore.ApiToken, error) return apiTokens, nil } -func AddDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { +func CreateDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err @@ -83,11 +83,12 @@ func AddDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer, c } apiToken = resp.JSON200 } - mutateApiTokenInput := astrocore.UpdateDeploymentApiTokenRequest{ + mutateApiTokenInput := astrocore.CreateDeploymentApiTokenRequest{ Role: role, Name: apiToken.Name, + Description: } - resp, err := client.UpdateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiToken.Id, mutateApiTokenInput) + resp, err := client.CreateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, mutateApiTokenInput) if err != nil { return err } From 33b68e3666798eeafc5365f02455b3fc848ca0f5 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Fri, 16 Feb 2024 10:46:05 -0500 Subject: [PATCH 08/21] add crud methods for managing deployment api tokens --- cloud/apitoken/apitoken.go | 55 +++++++++++++------------------------- cmd/cloud/deployment.go | 38 ++++++++++++++++---------- 2 files changed, 43 insertions(+), 50 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index e585ca148..db2a9af8b 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -53,40 +53,16 @@ func GetOrgApiTokens(client astrocore.CoreClient) ([]astrocore.ApiToken, error) return apiTokens, nil } -func CreateDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { +func CreateDeploymentApiToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err } - var apiToken *astrocore.ApiToken - if apiTokenID == "" { - // Get all org apiTokens. Setting limit to 1000 for now - apiTokens, err := GetOrgApiTokens(client) - if err != nil { - return err - } - apiToken, err = getApiToken(apiTokens) - if err != nil { - return err - } - } else { - resp, err := client.GetDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiTokenID) - if err != nil { - fmt.Println("error in GetDeploymentApiTokenWithResponse") - return err - } - err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) - if err != nil { - fmt.Println("error in NormalizeAPIError") - return err - } - apiToken = resp.JSON200 - } mutateApiTokenInput := astrocore.CreateDeploymentApiTokenRequest{ - Role: role, - Name: apiToken.Name, - Description: + Role: role, + Name: name, + Description: &description, } resp, err := client.CreateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, mutateApiTokenInput) if err != nil { @@ -96,7 +72,7 @@ func CreateDeploymentApiToken(apiTokenID, role, deployment string, out io.Writer if err != nil { return err } - fmt.Fprintf(out, "The apiToken %s was successfully added to the deployment with the role %s\n", apiToken.Id, role) + fmt.Fprintf(out, "The apiToken %s was successfully added to the deployment with the role %s\n", name, role) return nil } @@ -108,8 +84,8 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr var apiToken *astrocore.ApiToken if apiTokenID == "" { - // Get all org apiTokens. Setting limit to 1000 for now - apiTokens, err := GetOrgApiTokens(client) + // Get all dep apiTokens. Setting limit to 1000 for now + apiTokens, err := GetDeploymentApiTokens(client, deployment, 1000) if err != nil { return err } @@ -151,7 +127,7 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr } func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { - apiToken, err := SelectApiToken(apitokens) + apiToken, err := SelectDeploymentApiToken(apitokens) if err != nil { return nil, err } @@ -159,22 +135,29 @@ func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { return &apiToken, nil } -func SelectApiToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToken, error) { - +func SelectDeploymentApiToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToken, error) { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, DynamicPadding: true, - Header: []string{"#", "NAME", "DESCRIPTION", "ID", "CREATE DATE", "UPDATE DATE"}, + Header: []string{"#", "NAME", "DEPLOYMENT_ROLE", "DESCRIPTION", "ID", "CREATE DATE", "UPDATE DATE"}, } - fmt.Println("\nPlease select the user:") + fmt.Println("\nPlease select the api token:") apiTokenMap := map[string]astrocore.ApiToken{} for i := range apiTokens { index := i + 1 + var role string + for _, tokenRole := range apiTokens[i].Roles { + if tokenRole.EntityType == "DEPLOYMENT" { + role = tokenRole.Role + } + } + table.AddRow([]string{ strconv.Itoa(index), apiTokens[i].Name, + role, apiTokens[i].Description, apiTokens[i].Id, apiTokens[i].CreatedAt.Format(time.RFC3339), diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 848d6fe66..f33c1fd46 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -28,6 +28,9 @@ const ( ) var ( + apiTokenName string + apiTokenRole string + apiTokenDescription string label string runtimeVersion string deploymentID string @@ -858,23 +861,27 @@ func newDeploymentApiTokenRootCmd(out io.Writer) *cobra.Command { newDeploymentApiTokenListCmd(out), newDeploymentApiTokenUpdateCmd(out), newDeploymentApiTokenRemoveCmd(out), - newDeploymentApiTokenAddCmd(out), + newDeploymentApiTokenCreateCmd(out), ) cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage apiTokens") return cmd } -func newDeploymentApiTokenAddCmd(out io.Writer) *cobra.Command { +func newDeploymentApiTokenCreateCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "add [apiTokenID]", - Short: "Add a apiToken to an Astro Deployment with a specific role", - Long: "Add a apiToken to an Astro Deployment with a specific role\n$astro deployment apiToken add [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", + Use: "create [apiTokenID]", + Short: "Create a apiToken in an Astro Deployment with a specific role", + Long: "Create a apiToken in an Astro Deployment with a specific role\n$astro deployment apiToken add [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", RunE: func(cmd *cobra.Command, args []string) error { - return addDeploymentApiToken(cmd, args, out) + return createDeploymentApiToken(cmd, args, out) }, } - cmd.Flags().StringVarP(&addDeploymentRole, "role", "r", "DEPLOYMENT_ADMIN", "The role for the "+ + cmd.Flags().StringVarP(&apiTokenRole, "role", "r", "", "The role for the "+ "new apiToken. Possible values are DEPLOYMENT_ADMIN or the custom role name.") + cmd.Flags().StringVarP(&apiTokenName, "name", "n", "", "The unique name for the "+ + "new apiToken.") + cmd.Flags().StringVarP(&apiTokenDescription, "description", "d", "", "A short description for the "+ + "new apiToken.") return cmd } @@ -919,20 +926,23 @@ func newDeploymentApiTokenRemoveCmd(out io.Writer) *cobra.Command { return cmd } -func addDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { +func createDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } - var apiTokenID string - // if an apiTokenID was provided in the args we use it - if len(args) > 0 { - // make sure the apiTokenID is lowercase - apiTokenID = strings.ToLower(args[0]) + if apiTokenName == "" { + // no name was provided so ask the user for it + apiTokenName = input.Text("Enter a unique name for the apiToken: ") + } + + if apiTokenRole == "" { + // no role was provided so ask the user for it + apiTokenRole = input.Text("Enter a Deployment role or custom role name to update apiToken. Can be DEPLOYMENT_ADMIN or the id of a custom role: ") } cmd.SilenceUsage = true - return apitoken.AddDeploymentApiToken(apiTokenID, addDeploymentRole, deploymentID, out, astroCoreClient) + return apitoken.CreateDeploymentApiToken(apiTokenName, apiTokenRole, apiTokenDescription, deploymentID, out, astroCoreClient) } func listDeploymentApiToken(cmd *cobra.Command, out io.Writer) error { From 0c3cbc0a00b9fb92020c72d43e7f0a6b0405aba0 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Fri, 16 Feb 2024 10:49:31 -0500 Subject: [PATCH 09/21] cleanup --- cloud/apitoken/apitoken.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index db2a9af8b..b049e34ae 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -19,7 +19,6 @@ var ( apiTokenPagnationLimit = 100 ) -// Returns a list of all of an organizations apiTokens func GetOrgApiTokens(client astrocore.CoreClient) ([]astrocore.ApiToken, error) { offset := 0 var apiTokens []astrocore.ApiToken From 3eaf09b856178a0d9b76148e816e7fefee6b2507 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Fri, 16 Feb 2024 11:57:33 -0500 Subject: [PATCH 10/21] wip --- cmd/cloud/deployment_test.go | 345 +++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) diff --git a/cmd/cloud/deployment_test.go b/cmd/cloud/deployment_test.go index 4aac15c92..6faedf715 100644 --- a/cmd/cloud/deployment_test.go +++ b/cmd/cloud/deployment_test.go @@ -1156,6 +1156,90 @@ var ( }, Body: teamRequestErrorDelete, } + + tokenDeploymentRole = astrocore.ApiTokenRole{ + EntityType: "DEPLOYMENT", + EntityId: deploymentID, + Role: "DEPLOYMENT_ADMIN", + } + + tokenDeploymentRole2 = astrocore.ApiTokenRole{ + EntityType: "DEPLOYMENT", + EntityId: deploymentID, + Role: "custom role", + } + + deploymentApiTokens = []astrocore.ApiToken{ + { + Name: "mock name", + Description: "mock description", + Roles: []astrocore.ApiTokenRole{ + tokenDeploymentRole, + }, + Id: "mock id", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + { + Name: "mock name2", + Description: "mock description2", + Roles: []astrocore.ApiTokenRole{ + tokenDeploymentRole2, + }, + Id: "mock id2", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + + ListDeploymentApiTokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &astrocore.ListApiTokensPaginated{ + Limit: 1, + Offset: 0, + TotalCount: 1, + ApiTokens: deploymentApiTokens, + }, + } + ListDeploymentApiTokensResponseError = astrocore.ListDeploymentApiTokensResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorBodyList, + JSON200: nil, + } + MutateDeploymentApiTokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiTokens[0], + } + MutateDeploymentApiTokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorBodyUpdate, + JSON200: nil, + } + DeleteDeploymentApiTokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentApiTokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: teamRequestErrorDelete, + } + GetDeploymentApiTokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiTokens[0], + } ) func TestDeploymentUserList(t *testing.T) { @@ -1672,3 +1756,264 @@ func TestDeploymentTeamRemove(t *testing.T) { assert.Contains(t, resp, expectedOut) }) } + +// TOP +func TestDeploymentApiTokenList(t *testing.T) { + expectedHelp := "List all the apiTokens in an Astro Deployment" + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints list help", func(t *testing.T) { + cmdArgs := []string{"api-token", "list", "-h"} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedHelp) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "list"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("any errors from api are returned and apiTokens are not listed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to list apiTokens") + }) + t.Run("any context errors from api are returned and apiTokens are not listed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "list", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) +} + +func TestDeploymentApiTokenUpdate(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints update help", func(t *testing.T) { + cmdArgs := []string{"api-token", "update", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN"} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid id with valid role updates apiToken", func(t *testing.T) { + expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", apiToken1.Id) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and role is not updated", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update apiToken") + }) + + t.Run("any context errors from api are returned and role is not updated", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", apiToken1.Id) + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + astroCoreClient = mockClient + + cmdArgs := []string{"api-token", "update", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} + +func TestDeploymentApiTokenCreate(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints add help", func(t *testing.T) { + cmdArgs := []string{"api-token", "add", "-h"} + _, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + }) + t.Run("valid id with valid role adds apiToken", func(t *testing.T) { + expectedOut := fmt.Sprintf("The apiToken %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", apiToken1.Id) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "add", apiToken1.Id} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("any errors from api are returned and apiToken is not added", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to update apiToken") + }) + + t.Run("any context errors from api are returned and role is not added", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + //t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + // testUtil.InitTestConfig(testUtil.LocalPlatform) + // + // mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + // mockClient.On("ListOrganizationApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgApiTokensResponseOK, nil).Twice() + // // mock os.Stdin + // expectedInput := []byte("1") + // r, w, err := os.Pipe() + // assert.NoError(t, err) + // _, err = w.Write(expectedInput) + // assert.NoError(t, err) + // w.Close() + // stdin := os.Stdin + // // Restore stdin right after the test. + // defer func() { os.Stdin = stdin }() + // os.Stdin = r + // + // expectedOut := fmt.Sprintf("The apiToken %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", apiToken1.Id) + // mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + // astroCoreClient = mockClient + // + // cmdArgs := []string{"api-token", "add", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + // resp, err := execDeploymentCmd(cmdArgs...) + // assert.NoError(t, err) + // assert.Contains(t, resp, expectedOut) + //}) +} + +func TestDeploymentApiTokenRemove(t *testing.T) { + expectedHelp := "Remove a apiToken from an Astro Deployment" + testUtil.InitTestConfig(testUtil.LocalPlatform) + + t.Run("-h prints remove help", func(t *testing.T) { + cmdArgs := []string{"api-token", "remove", "-h"} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedHelp) + }) + t.Run("will error if deployment id flag is not provided", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "remove", apiToken1.Id} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "flag --deployment-id is required") + }) + t.Run("valid id removes apiToken", func(t *testing.T) { + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", apiToken1.Name, mockDeploymentID) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) + t.Run("any errors from api are returned and apiToken is not removed", func(t *testing.T) { + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseError, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.EqualError(t, err, "failed to delete apiToken") + }) + t.Run("any context errors from api are returned and the apiToken is not removed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + astroCoreClient = mockClient + cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + _, err := execDeploymentCmd(cmdArgs...) + assert.Error(t, err) + }) + t.Run("command asks for input when no id is passed in as an arg", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s", apiToken1.Name, mockDeploymentID) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + astroCoreClient = mockClient + + cmdArgs := []string{"api-token", "remove", "--deployment-id", mockDeploymentID} + resp, err := execDeploymentCmd(cmdArgs...) + assert.NoError(t, err) + assert.Contains(t, resp, expectedOut) + }) +} From 53e66dec47b3d77c660a9442bb9c2fe8fd84a7a0 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Tue, 20 Feb 2024 10:50:06 -0500 Subject: [PATCH 11/21] add tests for cmd --- cloud/apitoken/apitoken.go | 3 +- cmd/cloud/deployment_test.go | 122 +++++++++++++++++------------------ 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index b049e34ae..f4efe4dc9 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -71,7 +71,7 @@ func CreateDeploymentApiToken(name, role, description, deployment string, out io if err != nil { return err } - fmt.Fprintf(out, "The apiToken %s was successfully added to the deployment with the role %s\n", name, role) + fmt.Fprintf(out, "The apiToken was successfully created with the role %s\n", role) return nil } @@ -92,6 +92,7 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr if err != nil { return err } + apiTokenID = apiToken.Id } else { resp, err := client.GetDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiTokenID) if err != nil { diff --git a/cmd/cloud/deployment_test.go b/cmd/cloud/deployment_test.go index 6faedf715..434a78490 100644 --- a/cmd/cloud/deployment_test.go +++ b/cmd/cloud/deployment_test.go @@ -1203,11 +1203,30 @@ var ( ApiTokens: deploymentApiTokens, }, } + apiTokenRequestErrorBodyList, _ = json.Marshal(astrocore.Error{ + Message: "failed to list api tokens", + }) ListDeploymentApiTokensResponseError = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: teamRequestErrorBodyList, + Body: apiTokenRequestErrorBodyList, + JSON200: nil, + } + CreateDeploymentApiTokenRoleResponseOK = astrocore.CreateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiTokens[0], + } + apiTokenRequestErrorBodyCreate, _ = json.Marshal(astrocore.Error{ + Message: "failed to create api token", + }) + CreateDeploymentApiTokenRoleResponseError = astrocore.CreateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: apiTokenRequestErrorBodyCreate, JSON200: nil, } MutateDeploymentApiTokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ @@ -1216,11 +1235,14 @@ var ( }, JSON200: &deploymentApiTokens[0], } + apiTokenRequestErrorBodyUpdate, _ = json.Marshal(astrocore.Error{ + Message: "failed to update api token", + }) MutateDeploymentApiTokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: teamRequestErrorBodyUpdate, + Body: apiTokenRequestErrorBodyUpdate, JSON200: nil, } DeleteDeploymentApiTokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ @@ -1228,11 +1250,15 @@ var ( StatusCode: 200, }, } + + apiTokenRequestErrorDelete, _ = json.Marshal(astrocore.Error{ + Message: "failed to delete api token", + }) DeleteDeploymentApiTokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: teamRequestErrorDelete, + Body: apiTokenRequestErrorDelete, } GetDeploymentApiTokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ @@ -1781,7 +1807,7 @@ func TestDeploymentApiTokenList(t *testing.T) { astroCoreClient = mockClient cmdArgs := []string{"api-token", "list", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) - assert.EqualError(t, err, "failed to list apiTokens") + assert.EqualError(t, err, "failed to list api tokens") }) t.Run("any context errors from api are returned and apiTokens are not listed", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) @@ -1812,8 +1838,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { t.Run("valid id with valid role updates apiToken", func(t *testing.T) { expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", apiToken1.Id) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) @@ -1822,25 +1848,25 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { }) t.Run("any errors from api are returned and role is not updated", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) - assert.EqualError(t, err, "failed to update apiToken") + assert.EqualError(t, err, "failed to update api token") }) t.Run("any context errors from api are returned and role is not updated", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) assert.Error(t, err) }) - t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { + t.Run("command asks for input when no api token name is passed in as an arg", func(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) @@ -1857,8 +1883,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", apiToken1.Id) - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", deploymentApiTokens[0].Id) + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} @@ -1872,17 +1898,17 @@ func TestDeploymentApiTokenCreate(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("-h prints add help", func(t *testing.T) { - cmdArgs := []string{"api-token", "add", "-h"} + cmdArgs := []string{"api-token", "create", "-h"} _, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) }) t.Run("valid id with valid role adds apiToken", func(t *testing.T) { - expectedOut := fmt.Sprintf("The apiToken %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", apiToken1.Id) + expectedOut := "The apiToken was successfully created with the role DEPLOYMENT_ADMIN\n" mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) assert.Contains(t, resp, expectedOut) @@ -1891,56 +1917,30 @@ func TestDeploymentApiTokenCreate(t *testing.T) { t.Run("will error if deployment id flag is not provided", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) astroCoreClient = mockClient - cmdArgs := []string{"api-token", "add", apiToken1.Id} + cmdArgs := []string{"api-token", "create", apiToken1.Id} _, err := execDeploymentCmd(cmdArgs...) assert.EqualError(t, err, "flag --deployment-id is required") }) - t.Run("any errors from api are returned and apiToken is not added", func(t *testing.T) { + t.Run("any errors from api are returned and apiToken is not created", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseError, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) - assert.EqualError(t, err, "failed to update apiToken") + assert.EqualError(t, err, "failed to create api token") }) - t.Run("any context errors from api are returned and role is not added", func(t *testing.T) { + t.Run("any context errors from api are returned and role is not created", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "add", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) assert.Error(t, err) }) - //t.Run("command asks for input when no email is passed in as an arg", func(t *testing.T) { - // testUtil.InitTestConfig(testUtil.LocalPlatform) - // - // mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - // mockClient.On("ListOrganizationApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&ListOrgApiTokensResponseOK, nil).Twice() - // // mock os.Stdin - // expectedInput := []byte("1") - // r, w, err := os.Pipe() - // assert.NoError(t, err) - // _, err = w.Write(expectedInput) - // assert.NoError(t, err) - // w.Close() - // stdin := os.Stdin - // // Restore stdin right after the test. - // defer func() { os.Stdin = stdin }() - // os.Stdin = r - // - // expectedOut := fmt.Sprintf("The apiToken %s was successfully added to the deployment with the role DEPLOYMENT_ADMIN\n", apiToken1.Id) - // mockClient.On("MutateDeploymentApiTokenRoleWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() - // astroCoreClient = mockClient - // - // cmdArgs := []string{"api-token", "add", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} - // resp, err := execDeploymentCmd(cmdArgs...) - // assert.NoError(t, err) - // assert.Contains(t, resp, expectedOut) - //}) } func TestDeploymentApiTokenRemove(t *testing.T) { @@ -1961,9 +1961,9 @@ func TestDeploymentApiTokenRemove(t *testing.T) { assert.EqualError(t, err, "flag --deployment-id is required") }) t.Run("valid id removes apiToken", func(t *testing.T) { - expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", apiToken1.Name, mockDeploymentID) + expectedOut := fmt.Sprintf("The apiToken %s was successfully removed from the deployment\n", apiToken1.Id) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} @@ -1973,17 +1973,17 @@ func TestDeploymentApiTokenRemove(t *testing.T) { }) t.Run("any errors from api are returned and apiToken is not removed", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) - assert.EqualError(t, err, "failed to delete apiToken") + assert.EqualError(t, err, "failed to delete api token") }) t.Run("any context errors from api are returned and the apiToken is not removed", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} @@ -2007,7 +2007,7 @@ func TestDeploymentApiTokenRemove(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s", apiToken1.Name, mockDeploymentID) + expectedOut := fmt.Sprintf("The apiToken %s was successfully removed from the deployment\n", deploymentApiTokens[0].Id) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() astroCoreClient = mockClient From 733d74b40eb232276ffcd5e11734ac7f9bb9b427 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Wed, 21 Feb 2024 08:49:43 -0500 Subject: [PATCH 12/21] wip --- cloud/apitoken/apitoken.go | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index f4efe4dc9..75c7a76fd 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -19,39 +19,6 @@ var ( apiTokenPagnationLimit = 100 ) -func GetOrgApiTokens(client astrocore.CoreClient) ([]astrocore.ApiToken, error) { - offset := 0 - var apiTokens []astrocore.ApiToken - - ctx, err := context.GetCurrentContext() - if err != nil { - return nil, err - } - - for { - resp, err := client.ListOrganizationApiTokensWithResponse(httpContext.Background(), ctx.Organization, &astrocore.ListOrganizationApiTokensParams{ - Offset: &offset, - Limit: &apiTokenPagnationLimit, - }) - if err != nil { - return nil, err - } - err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) - if err != nil { - return nil, err - } - apiTokens = append(apiTokens, resp.JSON200.ApiTokens...) - - if resp.JSON200.TotalCount <= offset { - break - } - - offset += apiTokenPagnationLimit - } - - return apiTokens, nil -} - func CreateDeploymentApiToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { From 7bc5277babb2fbc5cb302d805fe9f6a133d5f4f4 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 15:29:32 -0500 Subject: [PATCH 13/21] add tests to service layer --- cloud/apitoken/apitoken.go | 20 +- cloud/apitoken/apitoken_test.go | 386 ++++++++++++++++++++++++++++++++ 2 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 cloud/apitoken/apitoken_test.go diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index 75c7a76fd..361d45ca7 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -6,6 +6,7 @@ import ( "fmt" astrocore "github.com/astronomer/astro-cli/astro-client-core" "github.com/astronomer/astro-cli/context" + "github.com/astronomer/astro-cli/pkg/ansi" "github.com/astronomer/astro-cli/pkg/input" "github.com/astronomer/astro-cli/pkg/printutil" "io" @@ -15,8 +16,10 @@ import ( ) var ( - ErrInvalidApiTokenKey = errors.New("invalid ApiToken selected") - apiTokenPagnationLimit = 100 + ErrInvalidApiTokenKey = errors.New("invalid ApiToken selected") + ErrNoApiTokenNameProvided = errors.New("you must give your ApiToken a name") + ErrNoApiTokensFoundInDeployment = errors.New("no ApiTokens found in your deployment") + apiTokenPagnationLimit = 100 ) func CreateDeploymentApiToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { @@ -25,6 +28,14 @@ func CreateDeploymentApiToken(name, role, description, deployment string, out io return err } + if name == "" { + fmt.Println("Please specify a name for your ApiToken") + name = input.Text(ansi.Bold("\nApiToken name: ")) + if name == "" { + return ErrNoApiTokenNameProvided + } + } + mutateApiTokenInput := astrocore.CreateDeploymentApiTokenRequest{ Role: role, Name: name, @@ -94,6 +105,9 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr } func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { + if len(apitokens) == 0 { + return nil, ErrNoApiTokensFoundInDeployment + } apiToken, err := SelectDeploymentApiToken(apitokens) if err != nil { return nil, err @@ -170,7 +184,7 @@ func RemoveDeploymentApiToken(apiTokenID, deployment string, out io.Writer, clie if err != nil { return err } - fmt.Fprintf(out, "The apiToken %s was successfully removed from the deployment\n", apiTokenID) + fmt.Fprintf(out, "Astro ApiToken %s was successfully removed from deployment %s\n", apiTokenID, deployment) return nil } diff --git a/cloud/apitoken/apitoken_test.go b/cloud/apitoken/apitoken_test.go new file mode 100644 index 000000000..28fe79625 --- /dev/null +++ b/cloud/apitoken/apitoken_test.go @@ -0,0 +1,386 @@ +package apitoken + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + astrocore "github.com/astronomer/astro-cli/astro-client-core" + "net/http" + "os" + "testing" + "time" + + astrocore_mocks "github.com/astronomer/astro-cli/astro-client-core/mocks" + "github.com/stretchr/testify/mock" + + testUtil "github.com/astronomer/astro-cli/pkg/testing" + "github.com/stretchr/testify/assert" +) + +var ( + description1 = "Description 1" + description2 = "Description 2" + fullName1 = "User 1" + fullName2 = "User 2" + token = "token" + workspaceID = "ck05r3bor07h40d02y2hw4n4v" + deploymentID = "ck05r3bor07h40d02y2hw4n4d" + role = "DEPLOYMENT_ADMIN" + deploymentApiToken1 = astrocore.ApiToken{Id: "token1", Name: "Token 1", Token: &token, Description: description1, Type: "Type 1", Roles: []astrocore.ApiTokenRole{{EntityId: "DEPLOYMENT", Role: role}}, CreatedAt: time.Now(), CreatedBy: &astrocore.BasicSubjectProfile{FullName: &fullName1}} + errorNetwork = errors.New("network error") + CreateDeploymentApiTokenResponseOK = astrocore.CreateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiToken1, + } + errorBodyCreate, _ = json.Marshal(astrocore.Error{ + Message: "failed to create apiToken", + }) + CreateDeploymentApiTokenResponseError = astrocore.CreateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyCreate, + } + + errorBodyDelete, _ = json.Marshal(astrocore.Error{ + Message: "failed to delete apiToken", + }) + + DeleteDeploymentApiTokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + } + DeleteDeploymentApiTokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorBodyDelete, + } + + paginatedApitokens = astrocore.ListApiTokensPaginated{ + ApiTokens: []astrocore.ApiToken{ + deploymentApiToken1, + }, + } + + ListDeploymentApiTokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &paginatedApitokens, + } + + paginatedApitokensEmpty = astrocore.ListApiTokensPaginated{ + ApiTokens: []astrocore.ApiToken{}, + } + + ListDeploymentApiTokensResponseEmpty = astrocore.ListDeploymentApiTokensResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &paginatedApitokensEmpty, + } + + errorListDeploymentApiTokens, _ = json.Marshal(astrocore.Error{ + Message: "failed to list deployment apiTokens", + }) + ListDeploymentApiTokensResponseError = astrocore.ListDeploymentApiTokensResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorListDeploymentApiTokens, + } + GetDeploymentApiTokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiToken1, + } + errorGetDeploymentApiTokens, _ = json.Marshal(astrocore.Error{ + Message: "failed to get deployment apiToken", + }) + GetDeploymentApiTokenWithResponseError = astrocore.GetDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorGetDeploymentApiTokens, + } + + UpdateDeploymentApiTokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 200, + }, + JSON200: &deploymentApiToken1, + } + errorUpdateDeploymentApiToken, _ = json.Marshal(astrocore.Error{ + Message: "failed to update deployment apiToken", + }) + UpdateDeploymentApiTokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ + HTTPResponse: &http.Response{ + StatusCode: 500, + }, + Body: errorUpdateDeploymentApiToken, + } +) + +func TestCreateDeploymentApiToken(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path Create", func(t *testing.T) { + expectedOutMessage := fmt.Sprintf("The apiToken was successfully created with the role %s\n", role) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseOK, nil).Once() + err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("happy path no name passed so user types one in when prompted", func(t *testing.T) { + teamName := "Test ApiToken Name" + expectedOutMessage := fmt.Sprintf("The apiToken was successfully created with the role %s\n", role) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseOK, nil).Once() + defer testUtil.MockUserInput(t, teamName)() + err := CreateDeploymentApiToken("", role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when CreateDeploymentApiTokenWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when CreateDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseError, nil).Once() + err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to create apiToken") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + t.Run("error path no name passed in and user doesn't type one in when prompted", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := CreateDeploymentApiToken("", role, deploymentApiToken1.Description, deploymentID, out, mockClient) + assert.EqualError(t, err, "you must give your ApiToken a name") + }) +} + +func TestUpdateDeploymentApiTokenRole(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path UpdateDeploymentApiTokenRole", func(t *testing.T) { + expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentApiToken1.Id, role) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseOK, nil).Once() + err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path no deployment apiTokens found", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseEmpty, nil).Twice() + err := UpdateDeploymentApiTokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "no ApiTokens found in your deployment") + }) + + t.Run("error path when GetDeploymentApiTokenWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Twice() + err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when UpdateDeploymentApiTokenWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when UpdateDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseError, nil).Once() + err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to update deployment apiToken") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("UpdateDeploymentApiTokenRole no id passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentApiToken1.Id, role) + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseOK, nil).Once() + + err = UpdateDeploymentApiTokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} + +func TestRemoveDeploymentApiToken(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path DeleteDeploymentApiToken", func(t *testing.T) { + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentApiToken1.Id, deploymentID) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + err := RemoveDeploymentApiToken(deploymentApiToken1.Id, deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path when DeleteDeploymentApiTokenWithResponse return network error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when DeleteDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseError, nil).Once() + err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + assert.EqualError(t, err, "failed to delete apiToken") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("RemoveDeploymentApiToken no apiToken id passed", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + // mock os.Stdin + expectedInput := []byte("1") + r, w, err := os.Pipe() + assert.NoError(t, err) + _, err = w.Write(expectedInput) + assert.NoError(t, err) + w.Close() + stdin := os.Stdin + // Restore stdin right after the test. + defer func() { os.Stdin = stdin }() + os.Stdin = r + + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentApiToken1.Id, deploymentID) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + + err = RemoveDeploymentApiToken("", deploymentID, out, mockClient) + assert.NoError(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) + + t.Run("error path - RemoveDeploymentApiToken no apiToken id passed error on ListDeploymentApiTokensWithResponse", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Twice() + + err := RemoveDeploymentApiToken("", deploymentID, out, mockClient) + assert.EqualError(t, err, "failed to list deployment apiTokens") + }) +} + +func TestListDeploymentApiTokens(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + t.Run("happy path TestListDeploymentApiTokens", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + err := ListDeploymentApiTokens(out, mockClient, deploymentID) + assert.NoError(t, err) + }) + + t.Run("error path when ListDeploymentApiTokensWithResponse return network error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() + err := ListDeploymentApiTokens(out, mockClient, deploymentID) + assert.EqualError(t, err, "network error") + }) + + t.Run("error path when ListDeploymentApiTokensWithResponse returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.LocalPlatform) + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Twice() + err := ListDeploymentApiTokens(out, mockClient, deploymentID) + assert.EqualError(t, err, "failed to list deployment apiTokens") + }) + + t.Run("error path when getting current context returns an error", func(t *testing.T) { + testUtil.InitTestConfig(testUtil.Initial) + expectedOutMessage := "" + out := new(bytes.Buffer) + mockClient := new(astrocore_mocks.ClientWithResponsesInterface) + err := ListDeploymentApiTokens(out, mockClient, deploymentID) + assert.Error(t, err) + assert.Equal(t, expectedOutMessage, out.String()) + }) +} From 4b7f4258aaf640c090b4248a330ed5ab80732f78 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 15:44:40 -0500 Subject: [PATCH 14/21] cleanup --- cloud/team/team.go | 2 -- cloud/user/user.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/cloud/team/team.go b/cloud/team/team.go index eb98beb6f..0bdf2af19 100644 --- a/cloud/team/team.go +++ b/cloud/team/team.go @@ -778,7 +778,6 @@ func GetDeploymentTeams(client astrocore.CoreClient, deployment string, limit in if err != nil { return nil, err } - includeDeploymentRoles := true for { resp, err := client.ListDeploymentTeamsWithResponse(httpContext.Background(), ctx.Organization, deployment, &astrocore.ListDeploymentTeamsParams{ @@ -881,7 +880,6 @@ func AddDeploymentTeam(id, role, deployment string, out io.Writer, client astroc Role: role, } resp, err := client.MutateDeploymentTeamRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, teamID, mutateDeploymentTeamInput) - if err != nil { return err } diff --git a/cloud/user/user.go b/cloud/user/user.go index f744b2d48..8d14031e6 100644 --- a/cloud/user/user.go +++ b/cloud/user/user.go @@ -533,7 +533,6 @@ func UpdateDeploymentUserRole(email, role, deployment string, out io.Writer, cli mutateUserInput := astrocore.MutateDeploymentUserRoleRequest{ Role: role, } - resp, err := client.MutateDeploymentUserRoleWithResponse(httpContext.Background(), ctx.Organization, deployment, userID, mutateUserInput) if err != nil { fmt.Println("error in MutateDeploymentUserRoleWithResponse") @@ -584,7 +583,6 @@ func GetDeploymentUsers(client astrocore.CoreClient, deployment string, limit in if err != nil { return nil, err } - includeDeploymentRoles := true for { resp, err := client.ListDeploymentUsersWithResponse(httpContext.Background(), ctx.Organization, deployment, &astrocore.ListDeploymentUsersParams{ From af518d2009f18f7a263b4eddfa765fbc54fb22e4 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 15:45:55 -0500 Subject: [PATCH 15/21] cleanup --- cmd/cloud/deployment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 768c7cd50..d742c16f6 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -345,7 +345,7 @@ func newDeploymentListCmd(out io.Writer) *cobra.Command { return deploymentList(cmd, out) }, } - cmd.Flags().BoolVarP(&allDeployments, "all", "a", false, "Show deployments across all deployments") + cmd.Flags().BoolVarP(&allDeployments, "all", "a", false, "Show deployments across all workspaces") return cmd } From 3b12cbe74cf3201aa16d906b020066cbed882c81 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 16:22:42 -0500 Subject: [PATCH 16/21] lint --- cloud/apitoken/apitoken.go | 47 +++++----- cloud/apitoken/apitoken_test.go | 150 ++++++++++++++++---------------- cmd/cloud/deployment.go | 53 ++++++----- cmd/cloud/deployment_test.go | 86 +++++++++--------- 4 files changed, 168 insertions(+), 168 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index 361d45ca7..70c28e699 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -16,13 +16,13 @@ import ( ) var ( - ErrInvalidApiTokenKey = errors.New("invalid ApiToken selected") - ErrNoApiTokenNameProvided = errors.New("you must give your ApiToken a name") - ErrNoApiTokensFoundInDeployment = errors.New("no ApiTokens found in your deployment") + ErrInvalidAPITokenKey = errors.New("invalid ApiToken selected") + ErrNoAPITokenNameProvided = errors.New("you must give your ApiToken a name") + ErrNoAPITokensFoundInDeployment = errors.New("no ApiTokens found in your deployment") apiTokenPagnationLimit = 100 ) -func CreateDeploymentApiToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { +func CreateDeploymentAPIToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err @@ -32,16 +32,16 @@ func CreateDeploymentApiToken(name, role, description, deployment string, out io fmt.Println("Please specify a name for your ApiToken") name = input.Text(ansi.Bold("\nApiToken name: ")) if name == "" { - return ErrNoApiTokenNameProvided + return ErrNoAPITokenNameProvided } } - mutateApiTokenInput := astrocore.CreateDeploymentApiTokenRequest{ + mutateAPITokenInput := astrocore.CreateDeploymentApiTokenRequest{ Role: role, Name: name, Description: &description, } - resp, err := client.CreateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, mutateApiTokenInput) + resp, err := client.CreateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, mutateAPITokenInput) if err != nil { return err } @@ -53,7 +53,7 @@ func CreateDeploymentApiToken(name, role, description, deployment string, out io return nil } -func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { +func UpdateDeploymentAPITokenRole(apiTokenID, role, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err @@ -62,11 +62,12 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr if apiTokenID == "" { // Get all dep apiTokens. Setting limit to 1000 for now - apiTokens, err := GetDeploymentApiTokens(client, deployment, 1000) + limit := 1000 + apiTokens, err := GetDeploymentAPITokens(client, deployment, limit) if err != nil { return err } - apiToken, err = getApiToken(apiTokens) + apiToken, err = getAPIToken(apiTokens) if err != nil { return err } @@ -85,12 +86,12 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr apiToken = resp.JSON200 } - mutateApiTokenInput := astrocore.UpdateDeploymentApiTokenRequest{ + mutateAPITokenInput := astrocore.UpdateDeploymentApiTokenRequest{ Role: role, Name: apiToken.Name, } fmt.Println("deployment: " + deployment) - resp, err := client.UpdateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiToken.Id, mutateApiTokenInput) + resp, err := client.UpdateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, apiToken.Id, mutateAPITokenInput) if err != nil { fmt.Println("error in MutateDeploymentApiTokenRoleWithResponse") return err @@ -104,11 +105,11 @@ func UpdateDeploymentApiTokenRole(apiTokenID, role, deployment string, out io.Wr return nil } -func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { +func getAPIToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { if len(apitokens) == 0 { - return nil, ErrNoApiTokensFoundInDeployment + return nil, ErrNoAPITokensFoundInDeployment } - apiToken, err := SelectDeploymentApiToken(apitokens) + apiToken, err := SelectDeploymentAPIToken(apitokens) if err != nil { return nil, err } @@ -116,7 +117,7 @@ func getApiToken(apitokens []astrocore.ApiToken) (*astrocore.ApiToken, error) { return &apiToken, nil } -func SelectDeploymentApiToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToken, error) { +func SelectDeploymentAPIToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToken, error) { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, DynamicPadding: true, @@ -152,12 +153,12 @@ func SelectDeploymentApiToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToke choice := input.Text("\n> ") selected, ok := apiTokenMap[choice] if !ok { - return astrocore.ApiToken{}, ErrInvalidApiTokenKey + return astrocore.ApiToken{}, ErrInvalidAPITokenKey } return selected, nil } -func RemoveDeploymentApiToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { +func RemoveDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err @@ -165,11 +166,11 @@ func RemoveDeploymentApiToken(apiTokenID, deployment string, out io.Writer, clie if apiTokenID == "" { // Get all org apiTokens. Setting limit to 1000 for now - apiTokens, err := GetDeploymentApiTokens(client, deployment, apiTokenPagnationLimit) + apiTokens, err := GetDeploymentAPITokens(client, deployment, apiTokenPagnationLimit) if err != nil { return err } - apiToken, err := getApiToken(apiTokens) + apiToken, err := getAPIToken(apiTokens) if err != nil { return err } @@ -189,7 +190,7 @@ func RemoveDeploymentApiToken(apiTokenID, deployment string, out io.Writer, clie } // Returns a list of all of a deployments apiTokens -func GetDeploymentApiTokens(client astrocore.CoreClient, deployment string, limit int) ([]astrocore.ApiToken, error) { +func GetDeploymentAPITokens(client astrocore.CoreClient, deployment string, limit int) ([]astrocore.ApiToken, error) { offset := 0 var apiTokens []astrocore.ApiToken @@ -225,13 +226,13 @@ func GetDeploymentApiTokens(client astrocore.CoreClient, deployment string, limi // Prints a list of all of an deployments apiTokens // //nolint:dupl -func ListDeploymentApiTokens(out io.Writer, client astrocore.CoreClient, deployment string) error { +func ListDeploymentAPITokens(out io.Writer, client astrocore.CoreClient, deployment string) error { table := printutil.Table{ Padding: []int{30, 50, 10, 50, 10, 10, 10}, DynamicPadding: true, Header: []string{"NAME", "DESCRIPTION", "ID", "DEPLOYMENT ROLE", "CREATE DATE", "UPDATE DATE"}, } - apiTokens, err := GetDeploymentApiTokens(client, deployment, apiTokenPagnationLimit) + apiTokens, err := GetDeploymentAPITokens(client, deployment, apiTokenPagnationLimit) if err != nil { return err } diff --git a/cloud/apitoken/apitoken_test.go b/cloud/apitoken/apitoken_test.go index 28fe79625..01eaaee31 100644 --- a/cloud/apitoken/apitoken_test.go +++ b/cloud/apitoken/apitoken_test.go @@ -27,18 +27,18 @@ var ( workspaceID = "ck05r3bor07h40d02y2hw4n4v" deploymentID = "ck05r3bor07h40d02y2hw4n4d" role = "DEPLOYMENT_ADMIN" - deploymentApiToken1 = astrocore.ApiToken{Id: "token1", Name: "Token 1", Token: &token, Description: description1, Type: "Type 1", Roles: []astrocore.ApiTokenRole{{EntityId: "DEPLOYMENT", Role: role}}, CreatedAt: time.Now(), CreatedBy: &astrocore.BasicSubjectProfile{FullName: &fullName1}} + deploymentAPIToken1 = astrocore.ApiToken{Id: "token1", Name: "Token 1", Token: &token, Description: description1, Type: "Type 1", Roles: []astrocore.ApiTokenRole{{EntityId: "DEPLOYMENT", Role: role}}, CreatedAt: time.Now(), CreatedBy: &astrocore.BasicSubjectProfile{FullName: &fullName1}} errorNetwork = errors.New("network error") - CreateDeploymentApiTokenResponseOK = astrocore.CreateDeploymentApiTokenResponse{ + CreateDeploymentAPITokenResponseOK = astrocore.CreateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiToken1, + JSON200: &deploymentAPIToken1, } errorBodyCreate, _ = json.Marshal(astrocore.Error{ Message: "failed to create apiToken", }) - CreateDeploymentApiTokenResponseError = astrocore.CreateDeploymentApiTokenResponse{ + CreateDeploymentAPITokenResponseError = astrocore.CreateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, @@ -49,92 +49,92 @@ var ( Message: "failed to delete apiToken", }) - DeleteDeploymentApiTokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ + DeleteDeploymentAPITokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, } - DeleteDeploymentApiTokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ + DeleteDeploymentAPITokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, Body: errorBodyDelete, } - paginatedApitokens = astrocore.ListApiTokensPaginated{ + paginatedAPITokens = astrocore.ListApiTokensPaginated{ ApiTokens: []astrocore.ApiToken{ - deploymentApiToken1, + deploymentAPIToken1, }, } - ListDeploymentApiTokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ + ListDeploymentAPITokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &paginatedApitokens, + JSON200: &paginatedAPITokens, } - paginatedApitokensEmpty = astrocore.ListApiTokensPaginated{ + paginatedAPITokensEmpty = astrocore.ListApiTokensPaginated{ ApiTokens: []astrocore.ApiToken{}, } - ListDeploymentApiTokensResponseEmpty = astrocore.ListDeploymentApiTokensResponse{ + ListDeploymentAPITokensResponseEmpty = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &paginatedApitokensEmpty, + JSON200: &paginatedAPITokensEmpty, } - errorListDeploymentApiTokens, _ = json.Marshal(astrocore.Error{ + errorListDeploymentAPITokens, _ = json.Marshal(astrocore.Error{ Message: "failed to list deployment apiTokens", }) - ListDeploymentApiTokensResponseError = astrocore.ListDeploymentApiTokensResponse{ + ListDeploymentAPITokensResponseError = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: errorListDeploymentApiTokens, + Body: errorListDeploymentAPITokens, } - GetDeploymentApiTokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ + GetDeploymentAPITokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiToken1, + JSON200: &deploymentAPIToken1, } - errorGetDeploymentApiTokens, _ = json.Marshal(astrocore.Error{ + errorGetDeploymentAPITokens, _ = json.Marshal(astrocore.Error{ Message: "failed to get deployment apiToken", }) - GetDeploymentApiTokenWithResponseError = astrocore.GetDeploymentApiTokenResponse{ + GetDeploymentAPITokenWithResponseError = astrocore.GetDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: errorGetDeploymentApiTokens, + Body: errorGetDeploymentAPITokens, } - UpdateDeploymentApiTokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ + UpdateDeploymentAPITokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiToken1, + JSON200: &deploymentAPIToken1, } - errorUpdateDeploymentApiToken, _ = json.Marshal(astrocore.Error{ + errorUpdateDeploymentAPIToken, _ = json.Marshal(astrocore.Error{ Message: "failed to update deployment apiToken", }) - UpdateDeploymentApiTokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ + UpdateDeploymentAPITokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, - Body: errorUpdateDeploymentApiToken, + Body: errorUpdateDeploymentAPIToken, } ) -func TestCreateDeploymentApiToken(t *testing.T) { +func TestCreateDeploymentAPIToken(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("happy path Create", func(t *testing.T) { expectedOutMessage := fmt.Sprintf("The apiToken was successfully created with the role %s\n", role) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseOK, nil).Once() - err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenResponseOK, nil).Once() + err := CreateDeploymentAPIToken(deploymentAPIToken1.Name, role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -144,9 +144,9 @@ func TestCreateDeploymentApiToken(t *testing.T) { expectedOutMessage := fmt.Sprintf("The apiToken was successfully created with the role %s\n", role) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseOK, nil).Once() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenResponseOK, nil).Once() defer testUtil.MockUserInput(t, teamName)() - err := CreateDeploymentApiToken("", role, deploymentApiToken1.Description, deploymentID, out, mockClient) + err := CreateDeploymentAPIToken("", role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -155,15 +155,15 @@ func TestCreateDeploymentApiToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() - err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + err := CreateDeploymentAPIToken(deploymentAPIToken1.Name, role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.EqualError(t, err, "network error") }) t.Run("error path when CreateDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenResponseError, nil).Once() - err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenResponseError, nil).Once() + err := CreateDeploymentAPIToken(deploymentAPIToken1.Name, role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.EqualError(t, err, "failed to create apiToken") }) @@ -172,7 +172,7 @@ func TestCreateDeploymentApiToken(t *testing.T) { expectedOutMessage := "" out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := CreateDeploymentApiToken(deploymentApiToken1.Name, role, deploymentApiToken1.Description, deploymentID, out, mockClient) + err := CreateDeploymentAPIToken(deploymentAPIToken1.Name, role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.Error(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -180,20 +180,20 @@ func TestCreateDeploymentApiToken(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := CreateDeploymentApiToken("", role, deploymentApiToken1.Description, deploymentID, out, mockClient) + err := CreateDeploymentAPIToken("", role, deploymentAPIToken1.Description, deploymentID, out, mockClient) assert.EqualError(t, err, "you must give your ApiToken a name") }) } -func TestUpdateDeploymentApiTokenRole(t *testing.T) { +func TestUpdateDeploymentAPITokenRole(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("happy path UpdateDeploymentApiTokenRole", func(t *testing.T) { - expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentApiToken1.Id, role) + expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentAPIToken1.Id, role) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseOK, nil).Once() - err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentAPITokenRoleResponseOK, nil).Once() + err := UpdateDeploymentAPITokenRole(deploymentAPIToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -201,8 +201,8 @@ func TestUpdateDeploymentApiTokenRole(t *testing.T) { t.Run("error path no deployment apiTokens found", func(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseEmpty, nil).Twice() - err := UpdateDeploymentApiTokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseEmpty, nil).Twice() + err := UpdateDeploymentAPITokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.EqualError(t, err, "no ApiTokens found in your deployment") }) @@ -210,25 +210,25 @@ func TestUpdateDeploymentApiTokenRole(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Twice() - err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + err := UpdateDeploymentAPITokenRole(deploymentAPIToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.EqualError(t, err, "network error") }) t.Run("error path when UpdateDeploymentApiTokenWithResponse return network error", func(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() - err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + err := UpdateDeploymentAPITokenRole(deploymentAPIToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.EqualError(t, err, "network error") }) t.Run("error path when UpdateDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseError, nil).Once() - err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentAPITokenRoleResponseError, nil).Once() + err := UpdateDeploymentAPITokenRole(deploymentAPIToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.EqualError(t, err, "failed to update deployment apiToken") }) @@ -237,7 +237,7 @@ func TestUpdateDeploymentApiTokenRole(t *testing.T) { expectedOutMessage := "" out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := UpdateDeploymentApiTokenRole(deploymentApiToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + err := UpdateDeploymentAPITokenRole(deploymentAPIToken1.Id, "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.Error(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -247,7 +247,7 @@ func TestUpdateDeploymentApiTokenRole(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseOK, nil).Twice() // mock os.Stdin expectedInput := []byte("1") r, w, err := os.Pipe() @@ -260,23 +260,23 @@ func TestUpdateDeploymentApiTokenRole(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentApiToken1.Id, role) - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentApiTokenRoleResponseOK, nil).Once() + expectedOutMessage := fmt.Sprintf("The deployment apiToken %s role was successfully updated to %s\n", deploymentAPIToken1.Id, role) + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&UpdateDeploymentAPITokenRoleResponseOK, nil).Once() - err = UpdateDeploymentApiTokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) + err = UpdateDeploymentAPITokenRole("", "DEPLOYMENT_ADMIN", deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) } -func TestRemoveDeploymentApiToken(t *testing.T) { +func TestRemoveDeploymentAPIToken(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("happy path DeleteDeploymentApiToken", func(t *testing.T) { - expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentApiToken1.Id, deploymentID) + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPIToken1.Id, deploymentID) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() - err := RemoveDeploymentApiToken(deploymentApiToken1.Id, deploymentID, out, mockClient) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() + err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -285,15 +285,15 @@ func TestRemoveDeploymentApiToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() - err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.EqualError(t, err, "network error") }) t.Run("error path when DeleteDeploymentApiTokenWithResponse returns an error", func(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseError, nil).Once() - err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseError, nil).Once() + err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.EqualError(t, err, "failed to delete apiToken") }) @@ -302,7 +302,7 @@ func TestRemoveDeploymentApiToken(t *testing.T) { expectedOutMessage := "" out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := RemoveDeploymentApiToken(deploymentApiToken1.Id, "", out, mockClient) + err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.Error(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -312,7 +312,7 @@ func TestRemoveDeploymentApiToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseOK, nil).Twice() // mock os.Stdin expectedInput := []byte("1") r, w, err := os.Pipe() @@ -325,10 +325,10 @@ func TestRemoveDeploymentApiToken(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentApiToken1.Id, deploymentID) - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPIToken1.Id, deploymentID) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() - err = RemoveDeploymentApiToken("", deploymentID, out, mockClient) + err = RemoveDeploymentAPIToken("", deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -338,21 +338,21 @@ func TestRemoveDeploymentApiToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Twice() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseError, nil).Twice() - err := RemoveDeploymentApiToken("", deploymentID, out, mockClient) + err := RemoveDeploymentAPIToken("", deploymentID, out, mockClient) assert.EqualError(t, err, "failed to list deployment apiTokens") }) } -func TestListDeploymentApiTokens(t *testing.T) { +func TestListDeploymentAPITokens(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("happy path TestListDeploymentApiTokens", func(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() - err := ListDeploymentApiTokens(out, mockClient, deploymentID) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseOK, nil).Twice() + err := ListDeploymentAPITokens(out, mockClient, deploymentID) assert.NoError(t, err) }) @@ -361,7 +361,7 @@ func TestListDeploymentApiTokens(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() - err := ListDeploymentApiTokens(out, mockClient, deploymentID) + err := ListDeploymentAPITokens(out, mockClient, deploymentID) assert.EqualError(t, err, "network error") }) @@ -369,8 +369,8 @@ func TestListDeploymentApiTokens(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Twice() - err := ListDeploymentApiTokens(out, mockClient, deploymentID) + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseError, nil).Twice() + err := ListDeploymentAPITokens(out, mockClient, deploymentID) assert.EqualError(t, err, "failed to list deployment apiTokens") }) @@ -379,7 +379,7 @@ func TestListDeploymentApiTokens(t *testing.T) { expectedOutMessage := "" out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := ListDeploymentApiTokens(out, mockClient, deploymentID) + err := ListDeploymentAPITokens(out, mockClient, deploymentID) assert.Error(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index d742c16f6..fb388f97c 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -2,14 +2,10 @@ package cloud import ( "fmt" - "github.com/astronomer/astro-cli/cloud/apitoken" - "io" - "strings" - "time" - airflowversions "github.com/astronomer/astro-cli/airflow_versions" astrocore "github.com/astronomer/astro-cli/astro-client-core" astroplatformcore "github.com/astronomer/astro-cli/astro-client-platform-core" + "github.com/astronomer/astro-cli/cloud/apitoken" "github.com/astronomer/astro-cli/cloud/deployment" "github.com/astronomer/astro-cli/cloud/deployment/fromfile" "github.com/astronomer/astro-cli/cloud/organization" @@ -19,6 +15,9 @@ import ( "github.com/astronomer/astro-cli/pkg/input" "github.com/pkg/errors" "github.com/spf13/cobra" + "io" + "strings" + "time" ) const ( @@ -124,7 +123,7 @@ func newDeploymentRootCmd(out io.Writer) *cobra.Command { newDeploymentPoolRootCmd(out), newDeploymentUserRootCmd(out), newDeploymentTeamRootCmd(out), - newDeploymentApiTokenRootCmd(out), + newDeploymentAPITokenRootCmd(out), newDeploymentHibernateCmd(), newDeploymentWakeUpCmd(), ) @@ -926,7 +925,7 @@ func removeDeploymentUser(cmd *cobra.Command, args []string, out io.Writer) erro } //nolint:dupl -func newDeploymentApiTokenRootCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenRootCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "api-token", Aliases: []string{"at", "apiTokens"}, @@ -935,22 +934,22 @@ func newDeploymentApiTokenRootCmd(out io.Writer) *cobra.Command { } cmd.SetOut(out) cmd.AddCommand( - newDeploymentApiTokenListCmd(out), - newDeploymentApiTokenUpdateCmd(out), - newDeploymentApiTokenRemoveCmd(out), - newDeploymentApiTokenCreateCmd(out), + newDeploymentAPITokenListCmd(out), + newDeploymentAPITokenUpdateCmd(out), + newDeploymentAPITokenRemoveCmd(out), + newDeploymentAPITokenCreateCmd(out), ) cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage apiTokens") return cmd } -func newDeploymentApiTokenCreateCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenCreateCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "create [apiTokenID]", Short: "Create a apiToken in an Astro Deployment with a specific role", Long: "Create a apiToken in an Astro Deployment with a specific role\n$astro deployment apiToken add [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", RunE: func(cmd *cobra.Command, args []string) error { - return createDeploymentApiToken(cmd, args, out) + return createDeploymentAPIToken(cmd, nil, out) }, } cmd.Flags().StringVarP(&apiTokenRole, "role", "r", "", "The role for the "+ @@ -962,27 +961,27 @@ func newDeploymentApiTokenCreateCmd(out io.Writer) *cobra.Command { return cmd } -func newDeploymentApiTokenListCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenListCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "List all the apiTokens in an Astro Deployment", Long: "List all the apiTokens in an Astro Deployment", RunE: func(cmd *cobra.Command, args []string) error { - return listDeploymentApiToken(cmd, out) + return listDeploymentAPIToken(cmd, out) }, } return cmd } -func newDeploymentApiTokenUpdateCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenUpdateCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "update [apiTokenID]", Aliases: []string{"up"}, Short: "Update a the role of a apiToken in an Astro Deployment", Long: "Update the role of a apiToken in an Astro Deployment\n$astro deployment apiToken update [apiTokenID] --role [ DEPLOYMENT_ADMIN or the custom role name ].", RunE: func(cmd *cobra.Command, args []string) error { - return updateDeploymentApiToken(cmd, args, out) + return updateDeploymentAPIToken(cmd, args, out) }, } cmd.Flags().StringVarP(&updateDeploymentRole, "role", "r", "", "The new role for the "+ @@ -990,20 +989,20 @@ func newDeploymentApiTokenUpdateCmd(out io.Writer) *cobra.Command { return cmd } -func newDeploymentApiTokenRemoveCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenRemoveCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "remove", Aliases: []string{"rm"}, Short: "Remove a apiToken from an Astro Deployment", Long: "Remove a apiToken from an Astro Deployment", RunE: func(cmd *cobra.Command, args []string) error { - return removeDeploymentApiToken(cmd, args, out) + return removeDeploymentAPIToken(cmd, args, out) }, } return cmd } -func createDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { +func createDeploymentAPIToken(cmd *cobra.Command, _, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } @@ -1019,18 +1018,18 @@ func createDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) } cmd.SilenceUsage = true - return apitoken.CreateDeploymentApiToken(apiTokenName, apiTokenRole, apiTokenDescription, deploymentID, out, astroCoreClient) + return apitoken.CreateDeploymentAPIToken(apiTokenName, apiTokenRole, apiTokenDescription, deploymentID, out, astroCoreClient) } -func listDeploymentApiToken(cmd *cobra.Command, out io.Writer) error { +func listDeploymentAPIToken(cmd *cobra.Command, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } cmd.SilenceUsage = true - return apitoken.ListDeploymentApiTokens(out, astroCoreClient, deploymentID) + return apitoken.ListDeploymentAPITokens(out, astroCoreClient, deploymentID) } -func updateDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { +func updateDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } @@ -1048,10 +1047,10 @@ func updateDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) } cmd.SilenceUsage = true - return apitoken.UpdateDeploymentApiTokenRole(apiTokenID, updateDeploymentRole, deploymentID, out, astroCoreClient) + return apitoken.UpdateDeploymentAPITokenRole(apiTokenID, updateDeploymentRole, deploymentID, out, astroCoreClient) } -func removeDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) error { +func removeDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } @@ -1064,7 +1063,7 @@ func removeDeploymentApiToken(cmd *cobra.Command, args []string, out io.Writer) } cmd.SilenceUsage = true - return apitoken.RemoveDeploymentApiToken(apiTokenID, deploymentID, out, astroCoreClient) + return apitoken.RemoveDeploymentAPIToken(apiTokenID, deploymentID, out, astroCoreClient) } func getOverrideUntil(until, forDuration string) (*time.Time, error) { diff --git a/cmd/cloud/deployment_test.go b/cmd/cloud/deployment_test.go index 4dd6caa40..533af1caf 100644 --- a/cmd/cloud/deployment_test.go +++ b/cmd/cloud/deployment_test.go @@ -1355,7 +1355,7 @@ var ( Role: "custom role", } - deploymentApiTokens = []astrocore.ApiToken{ + deploymentAPITokens = []astrocore.ApiToken{ { Name: "mock name", Description: "mock description", @@ -1378,7 +1378,7 @@ var ( }, } - ListDeploymentApiTokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ + ListDeploymentAPITokensResponseOK = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, @@ -1386,52 +1386,52 @@ var ( Limit: 1, Offset: 0, TotalCount: 1, - ApiTokens: deploymentApiTokens, + ApiTokens: deploymentAPITokens, }, } apiTokenRequestErrorBodyList, _ = json.Marshal(astrocore.Error{ Message: "failed to list api tokens", }) - ListDeploymentApiTokensResponseError = astrocore.ListDeploymentApiTokensResponse{ + ListDeploymentAPITokensResponseError = astrocore.ListDeploymentApiTokensResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, Body: apiTokenRequestErrorBodyList, JSON200: nil, } - CreateDeploymentApiTokenRoleResponseOK = astrocore.CreateDeploymentApiTokenResponse{ + CreateDeploymentAPITokenRoleResponseOK = astrocore.CreateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiTokens[0], + JSON200: &deploymentAPITokens[0], } apiTokenRequestErrorBodyCreate, _ = json.Marshal(astrocore.Error{ Message: "failed to create api token", }) - CreateDeploymentApiTokenRoleResponseError = astrocore.CreateDeploymentApiTokenResponse{ + CreateDeploymentAPITokenRoleResponseError = astrocore.CreateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, Body: apiTokenRequestErrorBodyCreate, JSON200: nil, } - MutateDeploymentApiTokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ + MutateDeploymentAPITokenRoleResponseOK = astrocore.UpdateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiTokens[0], + JSON200: &deploymentAPITokens[0], } apiTokenRequestErrorBodyUpdate, _ = json.Marshal(astrocore.Error{ Message: "failed to update api token", }) - MutateDeploymentApiTokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ + MutateDeploymentAPITokenRoleResponseError = astrocore.UpdateDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, Body: apiTokenRequestErrorBodyUpdate, JSON200: nil, } - DeleteDeploymentApiTokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ + DeleteDeploymentAPITokenResponseOK = astrocore.DeleteDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, @@ -1440,17 +1440,17 @@ var ( apiTokenRequestErrorDelete, _ = json.Marshal(astrocore.Error{ Message: "failed to delete api token", }) - DeleteDeploymentApiTokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ + DeleteDeploymentAPITokenResponseError = astrocore.DeleteDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 500, }, Body: apiTokenRequestErrorDelete, } - GetDeploymentApiTokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ + GetDeploymentAPITokenWithResponseOK = astrocore.GetDeploymentApiTokenResponse{ HTTPResponse: &http.Response{ StatusCode: 200, }, - JSON200: &deploymentApiTokens[0], + JSON200: &deploymentAPITokens[0], } ) @@ -1991,7 +1991,7 @@ func TestDeploymentApiTokenList(t *testing.T) { }) t.Run("any errors from api are returned and apiTokens are not listed", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Once() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "list", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2000,7 +2000,7 @@ func TestDeploymentApiTokenList(t *testing.T) { t.Run("any context errors from api are returned and apiTokens are not listed", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseError, nil).Once() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "list", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2026,8 +2026,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { t.Run("valid id with valid role updates apiToken", func(t *testing.T) { expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", apiToken1.Id) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentAPITokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) @@ -2036,8 +2036,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { }) t.Run("any errors from api are returned and role is not updated", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseError, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentAPITokenRoleResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2047,8 +2047,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { t.Run("any context errors from api are returned and role is not updated", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentAPITokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2058,7 +2058,7 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseOK, nil).Twice() // mock os.Stdin expectedInput := []byte("1") r, w, err := os.Pipe() @@ -2071,8 +2071,8 @@ func TestDeploymentApiTokenUpdate(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", deploymentApiTokens[0].Id) - mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentApiTokenRoleResponseOK, nil).Once() + expectedOut := fmt.Sprintf("The deployment apiToken %s role was successfully updated to DEPLOYMENT_ADMIN", deploymentAPITokens[0].Id) + mockClient.On("UpdateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&MutateDeploymentAPITokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "update", "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} @@ -2093,10 +2093,10 @@ func TestDeploymentApiTokenCreate(t *testing.T) { t.Run("valid id with valid role adds apiToken", func(t *testing.T) { expectedOut := "The apiToken was successfully created with the role DEPLOYMENT_ADMIN\n" mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenRoleResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--name", "mockName", "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) assert.Contains(t, resp, expectedOut) @@ -2111,10 +2111,10 @@ func TestDeploymentApiTokenCreate(t *testing.T) { }) t.Run("any errors from api are returned and apiToken is not created", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseError, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenRoleResponseError, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--name", "mockName", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) assert.EqualError(t, err, "failed to create api token") }) @@ -2122,8 +2122,8 @@ func TestDeploymentApiTokenCreate(t *testing.T) { t.Run("any context errors from api are returned and role is not created", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentApiTokenRoleResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("CreateDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&CreateDeploymentAPITokenRoleResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "create", apiToken1.Id, "--role", "DEPLOYMENT_ADMIN", "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2149,10 +2149,10 @@ func TestDeploymentApiTokenRemove(t *testing.T) { assert.EqualError(t, err, "flag --deployment-id is required") }) t.Run("valid id removes apiToken", func(t *testing.T) { - expectedOut := fmt.Sprintf("The apiToken %s was successfully removed from the deployment\n", apiToken1.Id) + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", apiToken1.Id, mockDeploymentID) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) @@ -2161,8 +2161,8 @@ func TestDeploymentApiTokenRemove(t *testing.T) { }) t.Run("any errors from api are returned and apiToken is not removed", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseError, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseError, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2171,8 +2171,8 @@ func TestDeploymentApiTokenRemove(t *testing.T) { t.Run("any context errors from api are returned and the apiToken is not removed", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentApiTokenWithResponseOK, nil).Twice() - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) @@ -2182,7 +2182,7 @@ func TestDeploymentApiTokenRemove(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentApiTokensResponseOK, nil).Twice() + mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseOK, nil).Twice() // mock os.Stdin expectedInput := []byte("1") r, w, err := os.Pipe() @@ -2195,8 +2195,8 @@ func TestDeploymentApiTokenRemove(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOut := fmt.Sprintf("The apiToken %s was successfully removed from the deployment\n", deploymentApiTokens[0].Id) - mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentApiTokenResponseOK, nil).Once() + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPITokens[0].Id, mockDeploymentID) + mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient cmdArgs := []string{"api-token", "remove", "--deployment-id", mockDeploymentID} From 0f939da2c681a0463a1af6ab0cacc921ca6628a8 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 16:32:00 -0500 Subject: [PATCH 17/21] run go fumpt --- cloud/apitoken/apitoken.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index 70c28e699..e9b19faea 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -4,15 +4,16 @@ import ( httpContext "context" "errors" "fmt" + "io" + "os" + "strconv" + "time" + astrocore "github.com/astronomer/astro-cli/astro-client-core" "github.com/astronomer/astro-cli/context" "github.com/astronomer/astro-cli/pkg/ansi" "github.com/astronomer/astro-cli/pkg/input" "github.com/astronomer/astro-cli/pkg/printutil" - "io" - "os" - "strconv" - "time" ) var ( From 79c6718c73a531350db47a62589ac01be9b1d31b Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 16:33:01 -0500 Subject: [PATCH 18/21] go fumpt all files in need --- cloud/apitoken/apitoken_test.go | 3 ++- cmd/cloud/deployment.go | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cloud/apitoken/apitoken_test.go b/cloud/apitoken/apitoken_test.go index 01eaaee31..fe51a987f 100644 --- a/cloud/apitoken/apitoken_test.go +++ b/cloud/apitoken/apitoken_test.go @@ -5,12 +5,13 @@ import ( "encoding/json" "errors" "fmt" - astrocore "github.com/astronomer/astro-cli/astro-client-core" "net/http" "os" "testing" "time" + astrocore "github.com/astronomer/astro-cli/astro-client-core" + astrocore_mocks "github.com/astronomer/astro-cli/astro-client-core/mocks" "github.com/stretchr/testify/mock" diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index fb388f97c..9b7682815 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -2,6 +2,10 @@ package cloud import ( "fmt" + "io" + "strings" + "time" + airflowversions "github.com/astronomer/astro-cli/airflow_versions" astrocore "github.com/astronomer/astro-cli/astro-client-core" astroplatformcore "github.com/astronomer/astro-cli/astro-client-platform-core" @@ -15,9 +19,6 @@ import ( "github.com/astronomer/astro-cli/pkg/input" "github.com/pkg/errors" "github.com/spf13/cobra" - "io" - "strings" - "time" ) const ( From e91a8b1d8c972c718c96410b564336f63e60ee71 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Mon, 26 Feb 2024 18:41:13 -0500 Subject: [PATCH 19/21] remove uneeded comment --- cloud/apitoken/apitoken.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index e9b19faea..853e9fbf6 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -166,7 +166,6 @@ func RemoveDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, clie } if apiTokenID == "" { - // Get all org apiTokens. Setting limit to 1000 for now apiTokens, err := GetDeploymentAPITokens(client, deployment, apiTokenPagnationLimit) if err != nil { return err From 443e0bf79a39509f4deffb60ffa087357d88fc8f Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 29 Feb 2024 09:15:15 -0500 Subject: [PATCH 20/21] replace remove with delete --- cloud/apitoken/apitoken.go | 4 ++-- cloud/apitoken/apitoken_test.go | 18 +++++++++--------- cmd/cloud/deployment.go | 18 +++++++++--------- cmd/cloud/deployment_test.go | 28 ++++++++++++++-------------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index 853e9fbf6..002829d71 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -159,7 +159,7 @@ func SelectDeploymentAPIToken(apiTokens []astrocore.ApiToken) (astrocore.ApiToke return selected, nil } -func RemoveDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { +func DeleteDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { ctx, err := context.GetCurrentContext() if err != nil { return err @@ -185,7 +185,7 @@ func RemoveDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, clie if err != nil { return err } - fmt.Fprintf(out, "Astro ApiToken %s was successfully removed from deployment %s\n", apiTokenID, deployment) + fmt.Fprintf(out, "Astro ApiToken %s was successfully deleted from deployment %s\n", apiTokenID, deployment) return nil } diff --git a/cloud/apitoken/apitoken_test.go b/cloud/apitoken/apitoken_test.go index fe51a987f..89e071e32 100644 --- a/cloud/apitoken/apitoken_test.go +++ b/cloud/apitoken/apitoken_test.go @@ -270,14 +270,14 @@ func TestUpdateDeploymentAPITokenRole(t *testing.T) { }) } -func TestRemoveDeploymentAPIToken(t *testing.T) { +func TestDeleteDeploymentAPIToken(t *testing.T) { testUtil.InitTestConfig(testUtil.LocalPlatform) t.Run("happy path DeleteDeploymentApiToken", func(t *testing.T) { - expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPIToken1.Id, deploymentID) + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully deleted from deployment %s\n", deploymentAPIToken1.Id, deploymentID) out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() - err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, deploymentID, out, mockClient) + err := DeleteDeploymentAPIToken(deploymentAPIToken1.Id, deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -286,7 +286,7 @@ func TestRemoveDeploymentAPIToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errorNetwork).Once() - err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) + err := DeleteDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.EqualError(t, err, "network error") }) @@ -294,7 +294,7 @@ func TestRemoveDeploymentAPIToken(t *testing.T) { out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseError, nil).Once() - err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) + err := DeleteDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.EqualError(t, err, "failed to delete apiToken") }) @@ -303,7 +303,7 @@ func TestRemoveDeploymentAPIToken(t *testing.T) { expectedOutMessage := "" out := new(bytes.Buffer) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) - err := RemoveDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) + err := DeleteDeploymentAPIToken(deploymentAPIToken1.Id, "", out, mockClient) assert.Error(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -326,10 +326,10 @@ func TestRemoveDeploymentAPIToken(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPIToken1.Id, deploymentID) + expectedOutMessage := fmt.Sprintf("Astro ApiToken %s was successfully deleted from deployment %s\n", deploymentAPIToken1.Id, deploymentID) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() - err = RemoveDeploymentAPIToken("", deploymentID, out, mockClient) + err = DeleteDeploymentAPIToken("", deploymentID, out, mockClient) assert.NoError(t, err) assert.Equal(t, expectedOutMessage, out.String()) }) @@ -341,7 +341,7 @@ func TestRemoveDeploymentAPIToken(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("ListDeploymentApiTokensWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&ListDeploymentAPITokensResponseError, nil).Twice() - err := RemoveDeploymentAPIToken("", deploymentID, out, mockClient) + err := DeleteDeploymentAPIToken("", deploymentID, out, mockClient) assert.EqualError(t, err, "failed to list deployment apiTokens") }) } diff --git a/cmd/cloud/deployment.go b/cmd/cloud/deployment.go index 9b7682815..e8e4e62fd 100644 --- a/cmd/cloud/deployment.go +++ b/cmd/cloud/deployment.go @@ -937,7 +937,7 @@ func newDeploymentAPITokenRootCmd(out io.Writer) *cobra.Command { cmd.AddCommand( newDeploymentAPITokenListCmd(out), newDeploymentAPITokenUpdateCmd(out), - newDeploymentAPITokenRemoveCmd(out), + newDeploymentAPITokenDeleteCmd(out), newDeploymentAPITokenCreateCmd(out), ) cmd.PersistentFlags().StringVar(&deploymentID, "deployment-id", "", "deployment where you'd like to manage apiTokens") @@ -990,14 +990,14 @@ func newDeploymentAPITokenUpdateCmd(out io.Writer) *cobra.Command { return cmd } -func newDeploymentAPITokenRemoveCmd(out io.Writer) *cobra.Command { +func newDeploymentAPITokenDeleteCmd(out io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "remove", - Aliases: []string{"rm"}, - Short: "Remove a apiToken from an Astro Deployment", - Long: "Remove a apiToken from an Astro Deployment", + Use: "delete", + Aliases: []string{"d"}, + Short: "Delete a apiToken from an Astro Deployment", + Long: "Delete a apiToken from an Astro Deployment", RunE: func(cmd *cobra.Command, args []string) error { - return removeDeploymentAPIToken(cmd, args, out) + return deleteDeploymentAPIToken(cmd, args, out) }, } return cmd @@ -1051,7 +1051,7 @@ func updateDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) return apitoken.UpdateDeploymentAPITokenRole(apiTokenID, updateDeploymentRole, deploymentID, out, astroCoreClient) } -func removeDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) error { +func deleteDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) error { if deploymentID == "" { return errors.New("flag --deployment-id is required") } @@ -1064,7 +1064,7 @@ func removeDeploymentAPIToken(cmd *cobra.Command, args []string, out io.Writer) } cmd.SilenceUsage = true - return apitoken.RemoveDeploymentAPIToken(apiTokenID, deploymentID, out, astroCoreClient) + return apitoken.DeleteDeploymentAPIToken(apiTokenID, deploymentID, out, astroCoreClient) } func getOverrideUntil(until, forDuration string) (*time.Time, error) { diff --git a/cmd/cloud/deployment_test.go b/cmd/cloud/deployment_test.go index 533af1caf..d04d4b80c 100644 --- a/cmd/cloud/deployment_test.go +++ b/cmd/cloud/deployment_test.go @@ -2131,12 +2131,12 @@ func TestDeploymentApiTokenCreate(t *testing.T) { }) } -func TestDeploymentApiTokenRemove(t *testing.T) { - expectedHelp := "Remove a apiToken from an Astro Deployment" +func TestDeploymentApiTokenDelete(t *testing.T) { + expectedHelp := "Delete a apiToken from an Astro Deployment" testUtil.InitTestConfig(testUtil.LocalPlatform) - t.Run("-h prints remove help", func(t *testing.T) { - cmdArgs := []string{"api-token", "remove", "-h"} + t.Run("-h prints delete help", func(t *testing.T) { + cmdArgs := []string{"api-token", "delete", "-h"} resp, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) assert.Contains(t, resp, expectedHelp) @@ -2144,37 +2144,37 @@ func TestDeploymentApiTokenRemove(t *testing.T) { t.Run("will error if deployment id flag is not provided", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) astroCoreClient = mockClient - cmdArgs := []string{"api-token", "remove", apiToken1.Id} + cmdArgs := []string{"api-token", "delete", apiToken1.Id} _, err := execDeploymentCmd(cmdArgs...) assert.EqualError(t, err, "flag --deployment-id is required") }) - t.Run("valid id removes apiToken", func(t *testing.T) { - expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", apiToken1.Id, mockDeploymentID) + t.Run("valid id deletes apiToken", func(t *testing.T) { + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully deleted from deployment %s\n", apiToken1.Id, mockDeploymentID) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "delete", apiToken1.Id, "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) assert.Contains(t, resp, expectedOut) }) - t.Run("any errors from api are returned and apiToken is not removed", func(t *testing.T) { + t.Run("any errors from api are returned and apiToken is not deleted", func(t *testing.T) { mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseError, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "delete", apiToken1.Id, "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) assert.EqualError(t, err, "failed to delete api token") }) - t.Run("any context errors from api are returned and the apiToken is not removed", func(t *testing.T) { + t.Run("any context errors from api are returned and the apiToken is not deleted", func(t *testing.T) { testUtil.InitTestConfig(testUtil.Initial) mockClient := new(astrocore_mocks.ClientWithResponsesInterface) mockClient.On("GetDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&GetDeploymentAPITokenWithResponseOK, nil).Twice() mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "remove", apiToken1.Id, "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "delete", apiToken1.Id, "--deployment-id", mockDeploymentID} _, err := execDeploymentCmd(cmdArgs...) assert.Error(t, err) }) @@ -2195,11 +2195,11 @@ func TestDeploymentApiTokenRemove(t *testing.T) { defer func() { os.Stdin = stdin }() os.Stdin = r - expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully removed from deployment %s\n", deploymentAPITokens[0].Id, mockDeploymentID) + expectedOut := fmt.Sprintf("Astro ApiToken %s was successfully deleted from deployment %s\n", deploymentAPITokens[0].Id, mockDeploymentID) mockClient.On("DeleteDeploymentApiTokenWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&DeleteDeploymentAPITokenResponseOK, nil).Once() astroCoreClient = mockClient - cmdArgs := []string{"api-token", "remove", "--deployment-id", mockDeploymentID} + cmdArgs := []string{"api-token", "delete", "--deployment-id", mockDeploymentID} resp, err := execDeploymentCmd(cmdArgs...) assert.NoError(t, err) assert.Contains(t, resp, expectedOut) From e648de4965d40171b34fb0d04512f94e97833189 Mon Sep 17 00:00:00 2001 From: Alex Liotta Date: Thu, 29 Feb 2024 09:20:52 -0500 Subject: [PATCH 21/21] remove uneeded print lines --- cloud/apitoken/apitoken.go | 2 -- cloud/user/user.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/cloud/apitoken/apitoken.go b/cloud/apitoken/apitoken.go index 002829d71..79339fad4 100644 --- a/cloud/apitoken/apitoken.go +++ b/cloud/apitoken/apitoken.go @@ -81,7 +81,6 @@ func UpdateDeploymentAPITokenRole(apiTokenID, role, deployment string, out io.Wr } err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) if err != nil { - fmt.Println("error in NormalizeAPIError") return err } apiToken = resp.JSON200 @@ -99,7 +98,6 @@ func UpdateDeploymentAPITokenRole(apiTokenID, role, deployment string, out io.Wr } err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) if err != nil { - fmt.Println("error in NormalizeAPIError") return err } fmt.Fprintf(out, "The deployment apiToken %s role was successfully updated to %s\n", apiTokenID, role) diff --git a/cloud/user/user.go b/cloud/user/user.go index 8d14031e6..841bf3de0 100644 --- a/cloud/user/user.go +++ b/cloud/user/user.go @@ -320,7 +320,6 @@ func UpdateWorkspaceUserRole(email, role, workspace string, out io.Writer, clien } err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) if err != nil { - fmt.Println("error in NormalizeAPIError") return err } fmt.Fprintf(out, "The workspace user %s role was successfully updated to %s\n", email, role) @@ -540,7 +539,6 @@ func UpdateDeploymentUserRole(email, role, deployment string, out io.Writer, cli } err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) if err != nil { - fmt.Println("error in NormalizeAPIError") return err } fmt.Fprintf(out, "The deployment user %s role was successfully updated to %s\n", email, role)