Skip to content

Commit

Permalink
feat: Account v1 readiness (#3236)
Browse files Browse the repository at this point in the history
### Changes
- Adjust SDK to be up-to-date with Snowflake capabilities
- Update unit and integration tests
- Adjust the setup_test.go for integration tests, so it works for
clients that have orgadmin role (and accountadmin)

### Questions
- Do we want to use AccountIdentifier instead of AccountObjectIdentifier
in Account object? I was sceptic because mostly everywhere the account
name is sufficient. I can check if orgname is also acceptable and adjust
the identifier to AccountIdentifier one.
- What do we want to do with test that requires moving account between
organizations?

### Others
- I'll report the error with polaris, as I was unable to create an
account with polaris set to true.

### Next prs (in order)
Next pr: Re-generating all assertions, schema mappings, etc.
Next pr: Adjusting existing resource and data source.
...
  • Loading branch information
sfc-gh-jcieslak authored Dec 6, 2024
1 parent 05ada91 commit 5df33a8
Show file tree
Hide file tree
Showing 15 changed files with 1,106 additions and 296 deletions.
107 changes: 106 additions & 1 deletion pkg/acceptance/helpers/account_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ package helpers

import (
"context"
"fmt"
"strings"
"testing"
"time"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/snowflakeroles"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
"github.com/snowflakedb/gosnowflake"
"github.com/stretchr/testify/require"
)

type AccountClient struct {
context *TestClientContext
ids *IdsGenerator
}

func NewAccountClient(context *TestClientContext) *AccountClient {
func NewAccountClient(context *TestClientContext, idsGenerator *IdsGenerator) *AccountClient {
return &AccountClient{
context: context,
ids: idsGenerator,
}
}

Expand Down Expand Up @@ -42,3 +50,100 @@ func (c *AccountClient) GetAccountIdentifier(t *testing.T) sdk.AccountIdentifier
t.Fatal("could not find the account identifier for the locator")
return sdk.AccountIdentifier{}
}

func (c *AccountClient) Create(t *testing.T) (*sdk.Account, func()) {
t.Helper()
id := c.ids.RandomAccountObjectIdentifier()
name := c.ids.Alpha()
email := random.Email()
privateKey := random.GenerateRSAPrivateKey(t)
publicKey, _ := random.GenerateRSAPublicKeyFromPrivateKey(t, privateKey)

return c.CreateWithRequest(t, id, &sdk.CreateAccountOptions{
AdminName: name,
AdminRSAPublicKey: sdk.String(publicKey),
Email: email,
Edition: sdk.EditionStandard,
})
}

func (c *AccountClient) CreateWithRequest(t *testing.T, id sdk.AccountObjectIdentifier, opts *sdk.CreateAccountOptions) (*sdk.Account, func()) {
t.Helper()
err := c.client().Create(context.Background(), id, opts)
require.NoError(t, err)

account, err := c.client().ShowByID(context.Background(), id)
require.NoError(t, err)

return account, c.DropFunc(t, id)
}

func (c *AccountClient) Alter(t *testing.T, opts *sdk.AlterAccountOptions) {
t.Helper()
err := c.client().Alter(context.Background(), opts)
require.NoError(t, err)
}

func (c *AccountClient) DropFunc(t *testing.T, id sdk.AccountObjectIdentifier) func() {
t.Helper()
return func() {
require.NoError(t, c.Drop(t, id))
}
}

func (c *AccountClient) Drop(t *testing.T, id sdk.AccountObjectIdentifier) error {
t.Helper()
ctx := context.Background()

return c.client().Drop(ctx, id, 3, &sdk.DropAccountOptions{IfExists: sdk.Bool(true)})
}

type Region struct {
SnowflakeRegion string `db:"snowflake_region"`
Cloud string `db:"cloud"`
Region string `db:"region"`
DisplayName string `db:"display_name"`
}

func (c *AccountClient) ShowRegions(t *testing.T) []Region {
t.Helper()

var regions []Region
err := c.context.client.QueryForTests(context.Background(), &regions, "SHOW REGIONS")
require.NoError(t, err)

return regions
}

func (c *AccountClient) CreateAndLogIn(t *testing.T) (*sdk.Account, *sdk.Client, func()) {
t.Helper()
id := c.ids.RandomAccountObjectIdentifier()
name := c.ids.Alpha()
privateKey := random.GenerateRSAPrivateKey(t)
publicKey, _ := random.GenerateRSAPublicKeyFromPrivateKey(t, privateKey)
email := random.Email()

account, accountCleanup := c.CreateWithRequest(t, id, &sdk.CreateAccountOptions{
AdminName: name,
AdminRSAPublicKey: sdk.String(publicKey),
AdminUserType: sdk.Pointer(sdk.UserTypeService),
Email: email,
Edition: sdk.EditionStandard,
})

var client *sdk.Client
require.Eventually(t, func() bool {
newClient, err := sdk.NewClient(&gosnowflake.Config{
Account: fmt.Sprintf("%s-%s", account.OrganizationName, account.AccountName),
User: name,
Host: strings.TrimPrefix(*account.AccountLocatorURL, `https://`),
Authenticator: gosnowflake.AuthTypeJwt,
PrivateKey: privateKey,
Role: snowflakeroles.Accountadmin.Name(),
})
client = newClient
return err == nil
}, 2*time.Minute, time.Second*15)

return account, client, accountCleanup
}
10 changes: 10 additions & 0 deletions pkg/acceptance/helpers/context_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ func (c *ContextClient) CurrentAccountId(t *testing.T) sdk.AccountIdentifier {
return sdk.NewAccountIdentifier(currentSessionDetails.OrganizationName, currentSessionDetails.AccountName)
}

func (c *ContextClient) CurrentAccountName(t *testing.T) string {
t.Helper()
ctx := context.Background()

currentAccount, err := c.client().CurrentAccountName(ctx)
require.NoError(t, err)

return currentAccount
}

func (c *ContextClient) CurrentRole(t *testing.T) sdk.AccountObjectIdentifier {
t.Helper()
ctx := context.Background()
Expand Down
37 changes: 37 additions & 0 deletions pkg/acceptance/helpers/packages_policy_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package helpers

import (
"context"
"fmt"
"testing"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
"github.com/stretchr/testify/require"
)

type PackagesPolicyClient struct {
context *TestClientContext
ids *IdsGenerator
}

func NewPackagesPolicyClient(context *TestClientContext, idsGenerator *IdsGenerator) *PackagesPolicyClient {
return &PackagesPolicyClient{
context: context,
ids: idsGenerator,
}
}

func (c *PackagesPolicyClient) Create(t *testing.T) (sdk.SchemaObjectIdentifier, func()) {
t.Helper()

// TODO(SNOW-1348357): Replace raw SQL with SDK

id := c.ids.RandomSchemaObjectIdentifier()
_, err := c.context.client.ExecForTests(context.Background(), fmt.Sprintf("CREATE PACKAGES POLICY %s LANGUAGE PYTHON", id.FullyQualifiedName()))
require.NoError(t, err)

return id, func() {
_, err = c.context.client.ExecForTests(context.Background(), fmt.Sprintf("DROP PACKAGES POLICY IF EXISTS %s", id.FullyQualifiedName()))
require.NoError(t, err)
}
}
8 changes: 4 additions & 4 deletions pkg/acceptance/helpers/random/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ func GenerateRSAPublicKey(t *testing.T) (string, string) {
t.Helper()
key := GenerateRSAPrivateKey(t)

return generateRSAPublicKeyFromPrivateKey(t, key)
return GenerateRSAPublicKeyFromPrivateKey(t, key)
}

// GenerateRSAPublicKey returns an RSA public key without BEGIN and END markers, and key's hash.
func generateRSAPublicKeyFromPrivateKey(t *testing.T, key *rsa.PrivateKey) (string, string) {
// GenerateRSAPublicKeyFromPrivateKey returns an RSA public key without BEGIN and END markers, and key's hash.
func GenerateRSAPublicKeyFromPrivateKey(t *testing.T, key *rsa.PrivateKey) (string, string) {
t.Helper()

pub := key.Public()
Expand Down Expand Up @@ -82,7 +82,7 @@ func GenerateRSAKeyPair(t *testing.T, pass string) (string, string, string, stri
unencrypted := string(pem.EncodeToMemory(&privBlock))
encrypted := encrypt(t, privateKey, pass)

publicKey, keyHash := generateRSAPublicKeyFromPrivateKey(t, privateKey)
publicKey, keyHash := GenerateRSAPublicKeyFromPrivateKey(t, privateKey)
return unencrypted, encrypted, publicKey, keyHash
}

Expand Down
4 changes: 3 additions & 1 deletion pkg/acceptance/helpers/test_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type TestClient struct {
NetworkPolicy *NetworkPolicyClient
NetworkRule *NetworkRuleClient
NotificationIntegration *NotificationIntegrationClient
PackagesPolicy *PackagesPolicyClient
Parameter *ParameterClient
PasswordPolicy *PasswordPolicyClient
Pipe *PipeClient
Expand Down Expand Up @@ -82,7 +83,7 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri

Ids: idsGenerator,

Account: NewAccountClient(context),
Account: NewAccountClient(context, idsGenerator),
AggregationPolicy: NewAggregationPolicyClient(context, idsGenerator),
Alert: NewAlertClient(context, idsGenerator),
ApiIntegration: NewApiIntegrationClient(context, idsGenerator),
Expand Down Expand Up @@ -115,6 +116,7 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri
NetworkPolicy: NewNetworkPolicyClient(context, idsGenerator),
NetworkRule: NewNetworkRuleClient(context, idsGenerator),
NotificationIntegration: NewNotificationIntegrationClient(context, idsGenerator),
PackagesPolicy: NewPackagesPolicyClient(context, idsGenerator),
Parameter: NewParameterClient(context),
PasswordPolicy: NewPasswordPolicyClient(context, idsGenerator),
Pipe: NewPipeClient(context, idsGenerator),
Expand Down
7 changes: 3 additions & 4 deletions pkg/acceptance/testenvs/testing_environment_variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ type env string
const (
BusinessCriticalAccount env = "SNOWFLAKE_BUSINESS_CRITICAL_ACCOUNT"

TestAccountCreate env = "TEST_SF_TF_TEST_ACCOUNT_CREATE"
TestFailoverGroups env = "TEST_SF_TF_TEST_FAILOVER_GROUPS"
ResourceMonitorNotifyUsers env = "TEST_SF_TF_RESOURCE_MONITOR_NOTIFY_USERS"
TestAccountCreate env = "TEST_SF_TF_TEST_ACCOUNT_CREATE"
TestFailoverGroups env = "TEST_SF_TF_TEST_FAILOVER_GROUPS"

AwsExternalBucketUrl env = "TEST_SF_TF_AWS_EXTERNAL_BUCKET_URL"
AwsExternalKeyId env = "TEST_SF_TF_AWS_EXTERNAL_KEY_ID"
Expand All @@ -24,7 +23,7 @@ const (
AzureExternalBucketUrl env = "TEST_SF_TF_AZURE_EXTERNAL_BUCKET_URL"
AzureExternalTenantId env = "TEST_SF_TF_AZURE_EXTERNAL_TENANT_ID"
AzureExternalSasToken env = "TEST_SF_TF_AZURE_EXTERNAL_SAS_TOKEN" // #nosec G101
GcsExternalBuckerUrl env = "TEST_SF_TF_GCS_EXTERNAL_BUCKET_URL"
GcsExternalBucketUrl env = "TEST_SF_TF_GCS_EXTERNAL_BUCKET_URL"

EnableObjectRenamingTest env = "TEST_SF_TF_ENABLE_OBJECT_RENAMING"
SkipManagedAccountTest env = "TEST_SF_TF_SKIP_MANAGED_ACCOUNT_TEST"
Expand Down
2 changes: 1 addition & 1 deletion pkg/datasources/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func ReadAccounts(ctx context.Context, d *schema.ResourceData, meta any) diag.Di
m["account_name"] = account.AccountName
m["region_group"] = account.RegionGroup
m["snowflake_region"] = account.SnowflakeRegion
m["edition"] = string(account.Edition)
m["edition"] = string(*account.Edition)
m["account_url"] = account.AccountURL
m["created_on"] = account.CreatedOn.String()
m["comment"] = account.Comment
Expand Down
2 changes: 1 addition & 1 deletion pkg/schemas/account_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5df33a8

Please sign in to comment.