Skip to content

Commit

Permalink
fix tests and add validator for scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
BBBmau committed Nov 6, 2024
1 parent ceff86f commit 79a87d0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"
"time"

"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
"github.com/hashicorp/terraform-plugin-framework/ephemeral/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
Expand Down Expand Up @@ -62,11 +63,16 @@ func (p *googleEphemeralServiceAccountAccessToken) Schema(ctx context.Context, r
"scopes": schema.SetAttribute{
Required: true,
ElementType: types.StringType,
// ValidateFunc is not yet supported on lists or sets.
Validators: []validator.Set{
setvalidator.ValueStringsAre(ServiceScopeValidator{}),
},
},
"delegates": schema.SetAttribute{
Optional: true,
ElementType: types.StringType,
Validators: []validator.Set{
setvalidator.ValueStringsAre(serviceAccountNameValidator{}),
},
},
},
}
Expand Down Expand Up @@ -231,3 +237,39 @@ func (v durationValidator) ValidateString(ctx context.Context, req validator.Str
)
}
}

// ServiceScopeValidator validates that a service scope is in canonical form
var _ validator.String = &ServiceScopeValidator{}

// ServiceScopeValidator validates service scope strings
type ServiceScopeValidator struct {
}

// Description returns a plain text description of the validator's behavior
func (v ServiceScopeValidator) Description(ctx context.Context) string {
return "service scope must be in canonical form"
}

// MarkdownDescription returns a markdown formatted description of the validator's behavior
func (v ServiceScopeValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

// ValidateString performs the validation
func (v ServiceScopeValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}

canonicalized := tpgresource.CanonicalizeServiceScope(req.ConfigValue.ValueString())
if req.ConfigValue.ValueString() != canonicalized {
resp.Diagnostics.AddAttributeWarning(
req.Path,
"Non-canonical service scope",
fmt.Sprintf("Service scope %q will be canonicalized to %q",
req.ConfigValue.ValueString(),
canonicalized,
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestEphemeralServiceAccountToken_basic(t *testing.T) {
t.Parallel()

serviceAccount := envvar.GetTestServiceAccountFromEnv(t)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "acctoken", serviceAccount)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "basic", serviceAccount)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
Expand All @@ -23,7 +23,7 @@ func TestEphemeralServiceAccountToken_basic(t *testing.T) {
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccEphemeralServiceAccountToken_basic(targetServiceAccountEmail, serviceAccount),
Config: testAccEphemeralServiceAccountToken_basic(targetServiceAccountEmail),
},
},
})
Expand All @@ -33,8 +33,7 @@ func TestEphemeralServiceAccountToken_withDelegates(t *testing.T) {
t.Parallel()

serviceAccount := envvar.GetTestServiceAccountFromEnv(t)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "acctoken-delegate", serviceAccount)
delegateServiceAccountEmail := acctest.BootstrapServiceAccount(t, "acctoken-delegate-sa", serviceAccount)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "delegates", serviceAccount)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
Expand All @@ -44,7 +43,7 @@ func TestEphemeralServiceAccountToken_withDelegates(t *testing.T) {
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccEphemeralServiceAccountToken_withDelegates(targetServiceAccountEmail, delegateServiceAccountEmail),
Config: testAccEphemeralServiceAccountToken_withDelegates(targetServiceAccountEmail),
},
},
})
Expand All @@ -54,7 +53,7 @@ func TestEphemeralServiceAccountToken_withCustomLifetime(t *testing.T) {
t.Parallel()

serviceAccount := envvar.GetTestServiceAccountFromEnv(t)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "acctoken-lifetime", serviceAccount)
targetServiceAccountEmail := acctest.BootstrapServiceAccount(t, "lifetime", serviceAccount)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
Expand All @@ -64,78 +63,38 @@ func TestEphemeralServiceAccountToken_withCustomLifetime(t *testing.T) {
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccEphemeralServiceAccountToken_withCustomLifetime(targetServiceAccountEmail, serviceAccount),
Config: testAccEphemeralServiceAccountToken_withCustomLifetime(targetServiceAccountEmail),
},
},
})
}

func testAccEphemeralServiceAccountToken_basic(serviceAccountEmail, serviceAccountId string) string {
func testAccEphemeralServiceAccountToken_basic(serviceAccountEmail string) string {
return fmt.Sprintf(`
resource "google_service_account_iam_member" "token_creator" {
service_account_id = "projects/%s/serviceAccounts/%s"
role = "roles/iam.serviceAccountTokenCreator"
member = "serviceAccount:%s"
}
// Add a time delay to allow IAM changes to propagate
resource "time_sleep" "wait_30_seconds" {
depends_on = [google_service_account_iam_member.token_creator]
create_duration = "20s"
}
// Tests default value of lifetime
ephemeral "google_service_account_token" "token" {
target_service_account = %q
target_service_account = "%s"
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
depends_on = [time_sleep.wait_30_seconds]
}
`, envvar.GetTestProjectFromEnv(), serviceAccountEmail, serviceAccountId, serviceAccountEmail)
`, serviceAccountEmail)
}

func testAccEphemeralServiceAccountToken_withDelegates(serviceAccountEmail, delegateEmail string) string {
func testAccEphemeralServiceAccountToken_withDelegates(serviceAccountEmail string) string {
return fmt.Sprintf(`
resource "google_service_account_iam_member" "token_creator" {
service_account_id = "projects/%s/serviceAccounts/%s"
role = "roles/iam.serviceAccountTokenCreator"
member = "serviceAccount:%s"
}
// Add a time delay to allow IAM changes to propagate
resource "time_sleep" "wait_30_seconds" {
depends_on = [google_service_account_iam_member.token_creator]
create_duration = "20s"
}
ephemeral "google_service_account_token" "token" {
target_service_account = %q
delegates = [%q]
target_service_account = "%s"
delegates = ["%[1]s"]
lifetime = "1200s"
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
depends_on = [time_sleep.wait_30_seconds]
}
`, envvar.GetTestProjectFromEnv(), serviceAccountEmail, delegateEmail, serviceAccountEmail, delegateEmail)
`, serviceAccountEmail)
}

func testAccEphemeralServiceAccountToken_withCustomLifetime(serviceAccountEmail, serviceAccountId string) string {
func testAccEphemeralServiceAccountToken_withCustomLifetime(serviceAccountEmail string) string {
return fmt.Sprintf(`
resource "google_service_account_iam_member" "token_creator" {
service_account_id = "projects/%s/serviceAccounts/%s"
role = "roles/iam.serviceAccountTokenCreator"
member = "serviceAccount:%s"
}
// Add a time delay to allow IAM changes to propagate
resource "time_sleep" "wait_30_seconds" {
depends_on = [google_service_account_iam_member.token_creator]
create_duration = "20s"
}
ephemeral "google_service_account_token" "token" {
target_service_account = %q
target_service_account = "%s"
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
lifetime = "3600s"
depends_on = [time_sleep.wait_30_seconds]
}
`, envvar.GetTestProjectFromEnv(), serviceAccountEmail, serviceAccountId, serviceAccountEmail)
`, serviceAccountEmail)
}

0 comments on commit 79a87d0

Please sign in to comment.