Skip to content

Commit

Permalink
feat(organization): application user tokens support (#1522)
Browse files Browse the repository at this point in the history
  • Loading branch information
Serpentiel authored Jan 12, 2024
1 parent d06749e commit 89689cc
Show file tree
Hide file tree
Showing 15 changed files with 678 additions and 208 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ nav_order: 1
## [MAJOR.MINOR.PATCH] - YYYY-MM-DD

- Add organization application users support
- Add organization application user tokens support
- Configure "insufficient broker" error retries timeout
- Enable `local_retention_*` fields in `aiven_kafka_topic` resource
- Validate that `local_retention_bytes` is not bigger than `retention_bytes`
Expand Down
53 changes: 53 additions & 0 deletions docs/resources/organization_application_user_token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "aiven_organization_application_user_token Resource - terraform-provider-aiven"
subcategory: ""
description: |-
Creates and manages an organization application user token in Aiven. Please note that this resource is in beta and may change without notice. To use this resource, please set the PROVIDERAIVENENABLE_BETA environment variable.
---

# aiven_organization_application_user_token (Resource)

Creates and manages an organization application user token in Aiven. Please note that this resource is in beta and may change without notice. To use this resource, please set the PROVIDER_AIVEN_ENABLE_BETA environment variable.



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

### Required

- `organization_id` (String) Identifier of the organization the application user token belongs to.
- `user_id` (String) Identifier of the application user the token belongs to.

### Optional

- `description` (String) Description of the token.
- `extend_when_used` (Boolean) True to extend token expiration time when token is used. Only applicable if max_age_seconds is specified.
- `max_age_seconds` (Number) Time the token remains valid since creation (or since last use if extend_when_used is true).
- `scopes` (Set of String) Scopes this token is restricted to if specified.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `create_time` (String) Time when the token was created.
- `created_manually` (Boolean) True for tokens explicitly created via the access_tokens API, false for tokens created via login.
- `currently_active` (Boolean) True if API request was made with this access token.
- `expiry_time` (String) Timestamp when the access token will expire unless extended, if ever.
- `full_token` (String, Sensitive) Full token.
- `id` (String) Compound identifier of the organization application user token.
- `last_ip` (String) IP address of the last request made with this token.
- `last_used_time` (String) Timestamp when the access token was last used, if ever.
- `last_user_agent` (String) User agent of the last request made with this token.
- `last_user_agent_human_readable` (String) User agent of the last request made with this token in human-readable format.
- `token_prefix` (String) Prefix of the token.

<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs.
- `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled.
- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
1 change: 1 addition & 0 deletions docs/resources/organization_user_group_member.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Adds and manages users in a user group. Please note that this resource is in bet

### Read-Only

- `id` (String) Compound identifier of the organization user group member.
- `last_activity_time` (String) Last activity time of the user group member.

<a id="nestedblock--timeouts"></a>
Expand Down
10 changes: 10 additions & 0 deletions internal/plugin/errmsg/errmsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ const (
// SummaryErrorDeletingResource is the error summary for when a resource cannot be deleted.
SummaryErrorDeletingResource = "Error Deleting Resource"

// SummaryErrorImportingResource is the error summary for when a resource cannot be imported.
SummaryErrorImportingResource = "Error Importing Resource"

// SummaryDuplicateFoundByName is the error summary for when a duplicate resource is found by name.
SummaryDuplicateFoundByName = "Duplicate Found By Name"

Expand Down Expand Up @@ -86,6 +89,10 @@ var (
// DetailErrorDeletingResource is the detailed error message for when a resource cannot be deleted.
DetailErrorDeletingResource = "An unexpected error occurred while deleting the resource (%s): %s."

// DetailErrorImportingResourceNotSupported is the detailed error message for when a resource cannot be imported
// because it is not supported.
DetailErrorImportingResourceNotSupported = "Importing the resource (%s) is not supported."

// DetailDuplicateFoundByName is the detailed error message for when a duplicate resource is found by name.
DetailDuplicateFoundByName = "Multiple resources with the same name (%s) were found. Please use the ID to " +
"uniquely identify the resource."
Expand All @@ -108,4 +115,7 @@ var (

// AivenResourceNotFound is the error message for when an Aiven resource cannot be found.
AivenResourceNotFound = "aiven resource %s with compound ID %s not found"

// UnableToSetValueFrom is the error message for when a Set cannot be created from a value.
UnableToSetValueFrom = "unable to set value from %v"
)
1 change: 1 addition & 0 deletions internal/plugin/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (p *AivenProvider) Resources(context.Context) []func() resource.Resource {
organization.NewOrganizationUserGroupMembersResource,
organization.NewOrganizationGroupProjectResource,
organization.NewOrganizationApplicationUser,
organization.NewOrganizationApplicationUserToken,
}

resources = append(resources, betaResources...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ type organizationApplicationUser struct {
type organizationApplicationUserModel struct {
// ID is the identifier of the organization application user.
ID types.String `tfsdk:"id"`
// UserID is the identifier of the organization application user.
UserID types.String `tfsdk:"user_id"`
// OrganizationID is the identifier of the organization the application user belongs to.
OrganizationID types.String `tfsdk:"organization_id"`
// UserID is the identifier of the organization application user.
UserID types.String `tfsdk:"user_id"`
// Name is the name of the organization application user.
Name types.String `tfsdk:"name"`
// Email is the email of the organization application user.
Expand Down Expand Up @@ -87,17 +87,20 @@ func (r *organizationApplicationUser) Schema(
stringplanmodifier.UseStateForUnknown(),
},
},
"organization_id": schema.StringAttribute{
Description: "Identifier of the organization the application user belongs to.",
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"user_id": schema.StringAttribute{
Description: "Identifier of the organization application user.",
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"organization_id": schema.StringAttribute{
Description: "Identifier of the organization the application user belongs to.",
Required: true,
},
"name": schema.StringAttribute{
Description: "Name of the organization application user.",
Required: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ type organizationApplicationUserDataSource struct {

// organizationApplicationUserDataSourceModel is the model for the organization application user data source.
type organizationApplicationUserDataSourceModel struct {
// UserID is the identifier of the organization application user.
UserID types.String `tfsdk:"user_id"`
// OrganizationID is the identifier of the organization the application user belongs to.
OrganizationID types.String `tfsdk:"organization_id"`
// UserID is the identifier of the organization application user.
UserID types.String `tfsdk:"user_id"`
// Name is the name of the organization application user.
Name types.String `tfsdk:"name"`
// Email is the email of the organization application user.
Expand Down Expand Up @@ -69,14 +69,14 @@ func (r *organizationApplicationUserDataSource) Schema(
resp.Schema = schema.Schema{
Description: "Retrieves information about an organization application user from Aiven.",
Attributes: map[string]schema.Attribute{
"user_id": schema.StringAttribute{
Description: "Identifier of the organization application user.",
Required: true,
},
"organization_id": schema.StringAttribute{
Description: "Identifier of the organization the application user belongs to.",
Required: true,
},
"user_id": schema.StringAttribute{
Description: "Identifier of the organization application user.",
Required: true,
},
"name": schema.StringAttribute{
Description: "Name of the organization application user.",
Computed: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ func TestAccOrganizationApplicationUserResourceDataSource(t *testing.T) {

deps.IsBeta(true)

name := "aiven_organization_application_user.foo"
names := []string{
"aiven_organization_application_user.foo",
"aiven_organization_application_user_token.foo",
}

dname := "data.aiven_organization_application_user.foo"

suffix := acctest.RandStringFromCharSet(acc.DefaultRandomSuffixLength, acctest.CharSetAlphaNum)
Expand All @@ -41,19 +45,19 @@ resource "aiven_organization_application_user" "foo" {
`, acc.DefaultResourceNamePrefix, suffix, deps.OrganizationName()),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
name,
names[0],
"name",
fmt.Sprintf("%s-org-appuser-%s", acc.DefaultResourceNamePrefix, suffix),
),
resource.TestCheckResourceAttrSet(name, "id"),
resource.TestCheckResourceAttrSet(names[0], "id"),
),
},
{
ResourceName: name,
ResourceName: names[0],
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: func(state *terraform.State) (string, error) {
rs, err := acc.ResourceFromState(state, name)
rs, err := acc.ResourceFromState(state, names[0])
if err != nil {
return "", err
}
Expand All @@ -76,7 +80,7 @@ resource "aiven_organization_application_user" "foo" {
`, acc.DefaultResourceNamePrefix, suffix, deps.OrganizationName()),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
name,
names[0],
"name",
fmt.Sprintf("%s-org-appuser-%s-1", acc.DefaultResourceNamePrefix, suffix),
),
Expand All @@ -94,8 +98,8 @@ resource "aiven_organization_application_user" "foo" {
}
data "aiven_organization_application_user" "foo" {
user_id = aiven_organization_application_user.foo.user_id
organization_id = data.aiven_organization.foo.id
user_id = aiven_organization_application_user.foo.user_id
}
`, acc.DefaultResourceNamePrefix, suffix, deps.OrganizationName()),
Check: resource.ComposeAggregateTestCheckFunc(
Expand All @@ -106,6 +110,33 @@ data "aiven_organization_application_user" "foo" {
),
),
},
{
Config: fmt.Sprintf(`
data "aiven_organization" "foo" {
name = "%[3]s"
}
resource "aiven_organization_application_user" "foo" {
organization_id = data.aiven_organization.foo.id
name = "%[1]s-org-appuser-%[2]s-1"
}
resource "aiven_organization_application_user_token" "foo" {
organization_id = aiven_organization_application_user.foo.organization_id
user_id = aiven_organization_application_user.foo.user_id
description = "Terraform acceptance tests"
max_age_seconds = 3600
extend_when_used = true
scopes = ["user:read"]
}
`, acc.DefaultResourceNamePrefix, suffix, deps.OrganizationName()),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(names[1], "description", "Terraform acceptance tests"),
resource.TestCheckResourceAttr(names[1], "max_age_seconds", "3600"),
resource.TestCheckResourceAttr(names[1], "extend_when_used", "true"),
resource.TestCheckResourceAttr(names[1], "scopes.#", "1"),
),
},
},
})
}
Loading

0 comments on commit 89689cc

Please sign in to comment.