Skip to content

Commit

Permalink
Add API Token Resource (#110)
Browse files Browse the repository at this point in the history
Co-authored-by: Vandy Liu <[email protected]>
  • Loading branch information
ichung08 and vandyliu authored Jul 23, 2024
1 parent 56e00be commit 1697d2e
Show file tree
Hide file tree
Showing 15 changed files with 1,729 additions and 29 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/testacc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:
SKIP_CLUSTER_RESOURCE_TESTS: ${{ env.SKIP_CLUSTER_RESOURCE_TESTS }}
HOSTED_TEAM_ID: clx44rvzr01nc01o06pze6qb7
HOSTED_USER_ID: clhpichn8002m01mqa4ocs7g6
HOSTED_DEPLOYMENT_ID: clyd4zf7g01uu01oxpve7tfvx
HOSTED_DEPLOYMENT_ID: clyn6kxud003x01mtxmccegnh
HOSTED_WORKSPACE_ID: clx42sxw501gl01o0gjenthnh
HOSTED_API_TOKEN_ID: clxm4836f00ql01me3nigmcr6
TESTARGS: "-failfast"
Expand Down Expand Up @@ -186,7 +186,7 @@ jobs:
ASTRO_API_HOST: https://api.astronomer-dev.io
HOSTED_TEAM_ID: clx44rvzr01nc01o06pze6qb7
HOSTED_USER_ID: clhpichn8002m01mqa4ocs7g6
HOSTED_DEPLOYMENT_ID: clyd4zf7g01uu01oxpve7tfvx
HOSTED_DEPLOYMENT_ID: clyn6kxud003x01mtxmccegnh
HOSTED_WORKSPACE_ID: clx42sxw501gl01o0gjenthnh
HOSTED_API_TOKEN_ID: clxm4836f00ql01me3nigmcr6
TESTARGS: "-failfast"
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/api_token.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Read-Only:

- `entity_id` (String) The ID of the entity to assign the role to
- `entity_type` (String) The type of entity to assign the role to
- `role` (String) The role to assign to the deployment
- `role` (String) The role to assign to the entity


<a id="nestedatt--updated_by"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/api_tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Read-Only:

- `entity_id` (String) The ID of the entity to assign the role to
- `entity_type` (String) The type of entity to assign the role to
- `role` (String) The role to assign to the deployment
- `role` (String) The role to assign to the entity


<a id="nestedatt--api_tokens--updated_by"></a>
Expand Down
159 changes: 159 additions & 0 deletions docs/resources/api_token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astro_api_token Resource - astro"
subcategory: ""
description: |-
API Token resource
---

# astro_api_token (Resource)

API Token resource

## Example Usage

```terraform
resource "astro_api_token" "example_organization_token" {
name = "organization api token"
description = "organization api token description"
type = "ORGANIZATION"
roles = [{
"role" : "ORGANIZATION_OWNER",
"entity_id" : "clx42kkcm01fo01o06agtmshg",
"entity_type" : "ORGANIZATION"
}]
expiry_period_in_days = 30
}
resource "astro_api_token" "example_organization_token_with_multiple_roles" {
name = "organization api token with multiple roles"
description = "organization api token description"
type = "ORGANIZATION"
roles = [{
"role" : "ORGANIZATION_OWNER",
"entity_id" : "clx42kkcm01fo01o06agtmshg",
"entity_type" : "ORGANIZATION"
},
{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
},
{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}
resource "astro_api_token" "example_workspace_token" {
name = "workspace api token"
description = "workspace api token description"
type = "WORKSPACE"
roles = [{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
}]
}
resource "astro_api_token" "example_workspace_token_with_deployment_role" {
name = "workspace api token"
description = "workspace api token description"
type = "WORKSPACE"
roles = [{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
},
{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}
resource "astro_api_token" "example_deployment_token" {
name = "deployment api token"
description = "deployment api token description"
type = "DEPLOYMENT"
roles = [{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}
resource "astro_api_token" "example_deployment_token_with_custom_role" {
name = "deployment api token with custom role"
description = "deployment api token description"
type = "DEPLOYMENT"
roles = [{
"role" : "CUSTOM_ROLE",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) API Token name
- `roles` (Attributes Set) The roles assigned to the API Token (see [below for nested schema](#nestedatt--roles))
- `type` (String) API Token type - if changing this value, the API Token will be recreated with the new type

### Optional

- `description` (String) API Token description
- `expiry_period_in_days` (Number) API Token expiry period in days

### Read-Only

- `created_at` (String) API Token creation timestamp
- `created_by` (Attributes) API Token creator (see [below for nested schema](#nestedatt--created_by))
- `end_at` (String) time when the API token will expire in UTC
- `id` (String) API Token identifier
- `last_used_at` (String) API Token last used timestamp
- `short_token` (String) API Token short token
- `start_at` (String) time when the API token will become valid in UTC
- `token` (String, Sensitive) API Token value. Warning: This value will be saved in plaintext in the terraform state file.
- `updated_at` (String) API Token last updated timestamp
- `updated_by` (Attributes) API Token updater (see [below for nested schema](#nestedatt--updated_by))

<a id="nestedatt--roles"></a>
### Nested Schema for `roles`

Required:

- `entity_id` (String) The ID of the entity to assign the role to
- `entity_type` (String) The type of entity to assign the role to
- `role` (String) The role to assign to the entity


<a id="nestedatt--created_by"></a>
### Nested Schema for `created_by`

Read-Only:

- `api_token_name` (String)
- `avatar_url` (String)
- `full_name` (String)
- `id` (String)
- `subject_type` (String)
- `username` (String)


<a id="nestedatt--updated_by"></a>
### Nested Schema for `updated_by`

Read-Only:

- `api_token_name` (String)
- `avatar_url` (String)
- `full_name` (String)
- `id` (String)
- `subject_type` (String)
- `username` (String)
81 changes: 81 additions & 0 deletions examples/resources/astro_api_token/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
resource "astro_api_token" "example_organization_token" {
name = "organization api token"
description = "organization api token description"
type = "ORGANIZATION"
roles = [{
"role" : "ORGANIZATION_OWNER",
"entity_id" : "clx42kkcm01fo01o06agtmshg",
"entity_type" : "ORGANIZATION"
}]
expiry_period_in_days = 30
}

resource "astro_api_token" "example_organization_token_with_multiple_roles" {
name = "organization api token with multiple roles"
description = "organization api token description"
type = "ORGANIZATION"
roles = [{
"role" : "ORGANIZATION_OWNER",
"entity_id" : "clx42kkcm01fo01o06agtmshg",
"entity_type" : "ORGANIZATION"
},
{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
},
{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}

resource "astro_api_token" "example_workspace_token" {
name = "workspace api token"
description = "workspace api token description"
type = "WORKSPACE"
roles = [{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
}]
}

resource "astro_api_token" "example_workspace_token_with_deployment_role" {
name = "workspace api token"
description = "workspace api token description"
type = "WORKSPACE"
roles = [{
"role" : "WORKSPACE_OWNER",
"entity_id" : "clx42sxw501gl01o0gjenthnh",
"entity_type" : "WORKSPACE"
},
{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}

resource "astro_api_token" "example_deployment_token" {
name = "deployment api token"
description = "deployment api token description"
type = "DEPLOYMENT"
roles = [{
"role" : "DEPLOYMENT_ADMIN",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}

resource "astro_api_token" "example_deployment_token_with_custom_role" {
name = "deployment api token with custom role"
description = "deployment api token description"
type = "DEPLOYMENT"
roles = [{
"role" : "CUSTOM_ROLE",
"entity_id" : "clyn6kxud003x01mtxmccegnh",
"entity_type" : "DEPLOYMENT"
}]
}
4 changes: 2 additions & 2 deletions internal/provider/datasources/data_source_api_tokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func checkApiTokens(tfVarName string, input checkApiTokensInput) resource.TestCh
if entityId != input.workspaceId {
return fmt.Errorf("expected 'entity_id' to be set to workspace_id")
}
if utils.CheckRole(role, "workspace") {
if utils.ValidateRoleMatchesEntityType(role, "workspace") {
return fmt.Errorf("expected 'role' to be set as a workspace role")
}
}
Expand All @@ -183,7 +183,7 @@ func checkApiTokens(tfVarName string, input checkApiTokensInput) resource.TestCh
if entityId != input.organizationId {
return fmt.Errorf("expected 'entity_id' to be set to organization_id")
}
if utils.CheckRole(role, "organization") {
if utils.ValidateRoleMatchesEntityType(role, "organization") {
return fmt.Errorf("expected 'role' to be set as an organization role")
}
}
Expand Down
68 changes: 68 additions & 0 deletions internal/provider/models/api_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ type ApiTokenDataSource struct {
Roles types.Set `tfsdk:"roles"`
}

// ApiTokenResource defines the resource implementation.
type ApiTokenResource struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
ShortToken types.String `tfsdk:"short_token"`
Type types.String `tfsdk:"type"`
StartAt types.String `tfsdk:"start_at"`
EndAt types.String `tfsdk:"end_at"`
CreatedAt types.String `tfsdk:"created_at"`
UpdatedAt types.String `tfsdk:"updated_at"`
CreatedBy types.Object `tfsdk:"created_by"`
UpdatedBy types.Object `tfsdk:"updated_by"`
ExpiryPeriodInDays types.Int64 `tfsdk:"expiry_period_in_days"`
LastUsedAt types.String `tfsdk:"last_used_at"`
Roles types.Set `tfsdk:"roles"`
Token types.String `tfsdk:"token"`
}

func (data *ApiTokenDataSource) ReadFromResponse(ctx context.Context, apiToken *iam.ApiToken) diag.Diagnostics {
var diags diag.Diagnostics
data.Id = types.StringValue(apiToken.Id)
Expand Down Expand Up @@ -67,3 +86,52 @@ func (data *ApiTokenDataSource) ReadFromResponse(ctx context.Context, apiToken *
}
return diags
}

func (data *ApiTokenResource) ReadFromResponse(ctx context.Context, apiToken *iam.ApiToken, token string) diag.Diagnostics {
var diags diag.Diagnostics
data.Id = types.StringValue(apiToken.Id)
data.Name = types.StringValue(apiToken.Name)
if apiToken.Description == "" {
data.Description = types.StringValue("")
} else {
data.Description = types.StringValue(apiToken.Description)
}
data.ShortToken = types.StringValue(apiToken.ShortToken)
data.Type = types.StringValue(string(apiToken.Type))
data.StartAt = types.StringValue(apiToken.StartAt.String())
if apiToken.EndAt == nil {
data.EndAt = types.StringValue("")
} else {
data.EndAt = types.StringValue(apiToken.EndAt.String())
}
data.CreatedAt = types.StringValue(apiToken.CreatedAt.String())
data.UpdatedAt = types.StringValue(apiToken.UpdatedAt.String())
data.CreatedBy, diags = SubjectProfileTypesObject(ctx, apiToken.CreatedBy)
if diags.HasError() {
return diags
}
data.UpdatedBy, diags = SubjectProfileTypesObject(ctx, apiToken.UpdatedBy)
if diags.HasError() {
return diags
}
if apiToken.ExpiryPeriodInDays != nil {
data.ExpiryPeriodInDays = types.Int64Value(int64(*apiToken.ExpiryPeriodInDays))
}
if apiToken.LastUsedAt == nil {
data.LastUsedAt = types.StringValue("")
} else {
data.LastUsedAt = types.StringValue(apiToken.LastUsedAt.String())
}
data.Roles, diags = utils.ObjectSet(ctx, apiToken.Roles, schemas.ApiTokenRoleAttributeTypes(), ApiTokenRoleTypesObject)
if diags.HasError() {
return diags
}
if apiToken.Token != nil && len(*apiToken.Token) > 0 {
data.Token = types.StringValue(*apiToken.Token)
} else if token != "" {
data.Token = types.StringValue(token)
} else {
data.Token = types.StringNull()
}
return diags
}
5 changes: 2 additions & 3 deletions internal/provider/models/subject_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import (
"context"

"github.com/astronomer/terraform-provider-astro/internal/clients/iam"
"github.com/astronomer/terraform-provider-astro/internal/provider/schemas"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/astronomer/terraform-provider-astro/internal/clients/platform"
"github.com/astronomer/terraform-provider-astro/internal/provider/schemas"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

type SubjectProfile struct {
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func (p *AstroProvider) Resources(ctx context.Context) []func() resource.Resourc
resources.NewClusterResource,
resources.NewTeamRolesResource,
resources.NewHybridClusterWorkspaceAuthorizationResource,
resources.NewApiTokenResource,
}
}

Expand Down
Loading

0 comments on commit 1697d2e

Please sign in to comment.