Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions docs/data-sources/service_accounts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_service_accounts Data Source - stackit"
subcategory: ""
description: |-
Service accounts plural data source schema. Returns a list of all service accounts in a project, optionally filtered.
---

# stackit_service_accounts (Data Source)

Service accounts plural data source schema. Returns a list of all service accounts in a project, optionally filtered.

## Example Usage

```terraform
data "stackit_service_accounts" "all_sas" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

data "stackit_service_accounts" "sas_default_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@sa.stackit.cloud"
}

data "stackit_service_accounts" "sas_default_suffix_sort_asc" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@sa.stackit.cloud"
sort_ascending = true
}

data "stackit_service_accounts" "sas_ske_regex" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_regex = ".*@ske\\.sa\\.stackit\\.cloud$"
}

data "stackit_service_accounts" "sas_ske_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@ske.sa.stackit.cloud"
}
```

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

### Required

- `project_id` (String) STACKIT project ID.

### Optional

- `email_regex` (String) Optional regular expression to filter service accounts by email.
- `email_suffix` (String) Optional suffix to filter service accounts by email (e.g.,`@sa.stackit.cloud`, `@ske.sa.stackit.cloud`).
- `sort_ascending` (Boolean) If set to `true`, service accounts are sorted in ascending lexicographical order by email. Defaults to `false` (descending).

### Read-Only

- `id` (String) Terraform's internal resource ID, structured as "`project_id`".
- `items` (Attributes List) The list of service accounts matching the provided filters. (see [below for nested schema](#nestedatt--items))

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

Read-Only:

- `email` (String) Email of the service account.
- `name` (String) Name of the service account.
24 changes: 24 additions & 0 deletions examples/data-sources/stackit_service_accounts/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
data "stackit_service_accounts" "all_sas" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

data "stackit_service_accounts" "sas_default_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@sa.stackit.cloud"
}

data "stackit_service_accounts" "sas_default_suffix_sort_asc" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@sa.stackit.cloud"
sort_ascending = true
}

data "stackit_service_accounts" "sas_ske_regex" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_regex = ".*@ske\\.sa\\.stackit\\.cloud$"
}

data "stackit_service_accounts" "sas_ske_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@ske.sa.stackit.cloud"
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (r *serviceAccountDataSource) Read(ctx context.Context, req datasource.Read
}

// Try to parse the name from the provided email address
name, err := parseNameFromEmail(model.Email.ValueString())
name, err := serviceaccountUtils.ParseNameFromEmail(model.Email.ValueString())
if name != "" && err == nil {
model.Name = types.StringValue(name)
}
Expand Down
18 changes: 1 addition & 17 deletions stackit/internal/services/serviceaccount/account/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func (r *serviceAccountResource) ImportState(ctx context.Context, req resource.I
email := idParts[1]

// Attempt to parse the name from the email if valid.
name, err := parseNameFromEmail(email)
name, err := serviceaccountUtils.ParseNameFromEmail(email)
if name != "" && err == nil {
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("name"), name)...)
}
Expand Down Expand Up @@ -322,19 +322,3 @@ func mapFields(resp *serviceaccount.ServiceAccount, model *Model) error {

return nil
}

// parseNameFromEmail extracts the name component from an email address.
// The email format must be `name-<random7characters>@sa.stackit.cloud`.
func parseNameFromEmail(email string) (string, error) {
namePattern := `^([a-z][a-z0-9]*(?:-[a-z0-9]+)*)-\w{7}@sa\.stackit\.cloud$`
re := regexp.MustCompile(namePattern)
match := re.FindStringSubmatch(email)

// If a match is found, return the name component
if len(match) > 1 {
return match[1], nil
}

// If no match is found, return an error
return "", fmt.Errorf("unable to parse name from email")
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,39 +123,3 @@ func TestMapFields(t *testing.T) {
})
}
}

func TestParseNameFromEmail(t *testing.T) {
testCases := []struct {
email string
expected string
shouldError bool
}{
{"test03-8565oq1@sa.stackit.cloud", "test03", false},
{"import-test-vshp191@sa.stackit.cloud", "import-test", false},
{"sa-test-01-acfj2s1@sa.stackit.cloud", "sa-test-01", false},
{"invalid-email@sa.stackit.cloud", "", true},
{"missingcode-@sa.stackit.cloud", "", true},
{"nohyphen8565oq1@sa.stackit.cloud", "", true},
{"eu01-qnmbwo1@unknown.stackit.cloud", "", true},
{"eu01-qnmbwo1@ske.stackit.com", "", true},
{"someotherformat@sa.stackit.cloud", "", true},
}

for _, tc := range testCases {
t.Run(tc.email, func(t *testing.T) {
name, err := parseNameFromEmail(tc.email)
if tc.shouldError {
if err == nil {
t.Errorf("expected an error for email: %s, but got none", tc.email)
}
} else {
if err != nil {
t.Errorf("did not expect an error for email: %s, but got: %v", tc.email, err)
}
if name != tc.expected {
t.Errorf("expected name: %s, got: %s for email: %s", tc.expected, name, tc.email)
}
}
})
}
}
Loading
Loading