-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dep api token crud #1564
Merged
Merged
Add dep api token crud #1564
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
a2824d0
add cmds for managing deployment user/teams
aliotta 0b52477
add unit testing and fix user select bug
aliotta c05c266
add unit test to cmd files
aliotta 7bc25dc
Merge branch 'main' into userAndTeamDeploymentRoleManagement
aliotta 1b985fe
lint
aliotta f8e7fe5
fix default deployment role in add command
aliotta 020d735
wip
aliotta 6a480ed
wip
aliotta 33b68e3
add crud methods for managing deployment api tokens
aliotta 0c3cbc0
cleanup
aliotta 3eaf09b
wip
aliotta 53e66de
add tests for cmd
aliotta 733d74b
wip
aliotta 7bc5277
add tests to service layer
aliotta 7ae0c5d
Merge branch 'main' into addDepApiTokenCrud
aliotta 4b7f425
cleanup
aliotta af518d2
cleanup
aliotta 3b12cbe
lint
aliotta 0f939da
run go fumpt
aliotta 79c6718
go fumpt all files in need
aliotta e91a8b1
remove uneeded comment
aliotta 443e0bf
replace remove with delete
aliotta e648de4
remove uneeded print lines
aliotta File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
package apitoken | ||
|
||
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" | ||
) | ||
|
||
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") | ||
apiTokenPagnationLimit = 100 | ||
) | ||
|
||
func CreateDeploymentAPIToken(name, role, description, deployment string, out io.Writer, client astrocore.CoreClient) error { | ||
ctx, err := context.GetCurrentContext() | ||
if err != nil { | ||
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, | ||
Description: &description, | ||
} | ||
resp, err := client.CreateDeploymentApiTokenWithResponse(httpContext.Background(), ctx.Organization, deployment, mutateAPITokenInput) | ||
if err != nil { | ||
return err | ||
} | ||
err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(out, "The apiToken was successfully created with the role %s\n", 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 dep apiTokens. Setting limit to 1000 for now | ||
limit := 1000 | ||
apiTokens, err := GetDeploymentAPITokens(client, deployment, limit) | ||
if err != nil { | ||
return err | ||
} | ||
apiToken, err = getAPIToken(apiTokens) | ||
if err != nil { | ||
return err | ||
} | ||
apiTokenID = apiToken.Id | ||
} 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 { | ||
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 { | ||
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) { | ||
if len(apitokens) == 0 { | ||
return nil, ErrNoAPITokensFoundInDeployment | ||
} | ||
apiToken, err := SelectDeploymentAPIToken(apitokens) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &apiToken, nil | ||
} | ||
|
||
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", "DEPLOYMENT_ROLE", "DESCRIPTION", "ID", "CREATE DATE", "UPDATE DATE"}, | ||
} | ||
|
||
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), | ||
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 DeleteDeploymentAPIToken(apiTokenID, deployment string, out io.Writer, client astrocore.CoreClient) error { | ||
ctx, err := context.GetCurrentContext() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if apiTokenID == "" { | ||
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, "Astro ApiToken %s was successfully deleted from deployment %s\n", apiTokenID, deployment) | ||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if there are no api tokens, we should display an error message, rather than an empty table with only headers |
||
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 | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should save the api token from response to ASTRO_API_TOKEN variable. Right now, the token gets created, but user cannot use the token value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will get a pr up for your comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of setting it we really want to print it to screen so they can use it where they want to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worried about the token leaking in ci cd logs...