diff --git a/examples/data-sources/system_get_snowflake_platform_info/data-source.tf b/examples/data-sources/system_get_snowflake_platform_info/data-source.tf new file mode 100644 index 0000000000..22687d0b29 --- /dev/null +++ b/examples/data-sources/system_get_snowflake_platform_info/data-source.tf @@ -0,0 +1 @@ +data "snowflake_system_get_snowflake_platform_info" "current" {} \ No newline at end of file diff --git a/pkg/datasources/system_get_snowflake_platform_info.go b/pkg/datasources/system_get_snowflake_platform_info.go new file mode 100644 index 0000000000..886582438d --- /dev/null +++ b/pkg/datasources/system_get_snowflake_platform_info.go @@ -0,0 +1,74 @@ +package datasources + +import ( + "database/sql" + "fmt" + "log" + + "github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pkg/errors" +) + +var systemGetSnowflakePlatformInfoSchema = map[string]*schema.Schema{ + "azure_vnet_subnet_ids": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + Description: "Snowflake Azure Virtual Network Subnet IDs", + }, + "aws_vpc_ids": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + Description: "Snowflake AWS Virtual Private Cloud IDs", + }, +} + +func SystemGetSnowflakePlatformInfo() *schema.Resource { + return &schema.Resource{ + Read: ReadSystemGetSnowflakePlatformInfo, + Schema: systemGetSnowflakePlatformInfoSchema, + } +} + +// ReadSystemGetSnowflakePlatformInfo implements schema.ReadFunc +func ReadSystemGetSnowflakePlatformInfo(d *schema.ResourceData, meta interface{}) error { + db := meta.(*sql.DB) + sel := snowflake.SystemGetSnowflakePlatformInfoQuery() + row := snowflake.QueryRow(db, sel) + + acc, err := snowflake.ReadCurrentAccount(db) + if err != nil { + // If not found, mark resource to be removed from statefile during apply or refresh + d.SetId("") + log.Printf("[DEBUG] current_account failed to decode") + return errors.Wrap(err, "error current_account") + } + + d.SetId(fmt.Sprintf("%s.%s", acc.Account, acc.Region)) + + rawInfo, err := snowflake.ScanSnowflakePlatformInfo(row) + if err == sql.ErrNoRows { + // If not found, mark resource to be removed from statefile during apply or refresh + log.Print("[DEBUG] system_get_snowflake_platform_info not found") + return errors.Wrap(err, "error system_get_snowflake_platform_info") + } + + info, err := rawInfo.GetStructuredConfig() + if err != nil { + log.Printf("[DEBUG] system_get_snowflake_platform_info failed to decode") + d.SetId("") + return errors.Wrap(err, "error system_get_snowflake_platform_info") + } + + if err = d.Set("azure_vnet_subnet_ids", info.AzureVnetSubnetIds); err != nil { + return errors.Wrap(err, "error system_get_snowflake_platform_info") + } + + if err = d.Set("aws_vpc_ids", info.AwsVpcIds); err != nil { + return errors.Wrap(err, "error system_get_snowflake_platform_info") + } + + return nil +} diff --git a/pkg/datasources/system_get_snowflake_platform_info_acceptance_test.go b/pkg/datasources/system_get_snowflake_platform_info_acceptance_test.go new file mode 100644 index 0000000000..dc196d8ab8 --- /dev/null +++ b/pkg/datasources/system_get_snowflake_platform_info_acceptance_test.go @@ -0,0 +1,29 @@ +package datasources_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccSystemGetSnowflakePlatformInfo(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + Providers: providers(), + Steps: []resource.TestStep{ + { + Config: snowflakePlatformInfo(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.snowflake_system_get_snowflake_platform_info.p", "aws_vpc_ids.#"), + resource.TestCheckResourceAttrSet("data.snowflake_system_get_snowflake_platform_info.p", "azure_vnet_subnet_ids.#"), + ), + }, + }, + }) +} + +func snowflakePlatformInfo() string { + s := ` + data snowflake_system_get_snowflake_platform_info "p" {} + ` + return s +} diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index 5cca7479df..2673bf947e 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -192,10 +192,11 @@ func getResources() map[string]*schema.Resource { func getDataSources() map[string]*schema.Resource { dataSources := map[string]*schema.Resource{ - "snowflake_current_account": datasources.CurrentAccount(), - "snowflake_system_generate_scim_access_token": datasources.SystemGenerateSCIMAccessToken(), - "snowflake_system_get_aws_sns_iam_policy": datasources.SystemGetAWSSNSIAMPolicy(), - "snowflake_system_get_privatelink_config": datasources.SystemGetPrivateLinkConfig(), + "snowflake_current_account": datasources.CurrentAccount(), + "snowflake_system_generate_scim_access_token": datasources.SystemGenerateSCIMAccessToken(), + "snowflake_system_get_aws_sns_iam_policy": datasources.SystemGetAWSSNSIAMPolicy(), + "snowflake_system_get_privatelink_config": datasources.SystemGetPrivateLinkConfig(), + "snowflake_system_get_snowflake_platform_info": datasources.SystemGetSnowflakePlatformInfo(), } return dataSources diff --git a/pkg/snowflake/system_get_snowflake_platform_info.go b/pkg/snowflake/system_get_snowflake_platform_info.go new file mode 100644 index 0000000000..dd204ab510 --- /dev/null +++ b/pkg/snowflake/system_get_snowflake_platform_info.go @@ -0,0 +1,50 @@ +package snowflake + +import ( + "encoding/json" + + "github.com/jmoiron/sqlx" +) + +func SystemGetSnowflakePlatformInfoQuery() string { + return `SELECT SYSTEM$GET_SNOWFLAKE_PLATFORM_INFO() AS "info"` +} + +type RawSnowflakePlatformInfo struct { + Info string `db:"info"` +} + +type snowflakePlatformInfoInternal struct { + AzureVnetSubnetIds []string `json:"snowflake-vnet-subnet-id,omitempty"` + AwsVpcIds []string `json:"snowflake-vpc-id,omitempty"` +} + +type SnowflakePlatformInfo struct { + AzureVnetSubnetIds []string + AwsVpcIds []string +} + +func ScanSnowflakePlatformInfo(row *sqlx.Row) (*RawSnowflakePlatformInfo, error) { + info := &RawSnowflakePlatformInfo{} + err := row.StructScan(info) + return info, err +} + +func (r *RawSnowflakePlatformInfo) GetStructuredConfig() (*SnowflakePlatformInfo, error) { + info := &snowflakePlatformInfoInternal{} + err := json.Unmarshal([]byte(r.Info), info) + if err != nil { + return nil, err + } + + return info.getSnowflakePlatformInfo() +} + +func (i *snowflakePlatformInfoInternal) getSnowflakePlatformInfo() (*SnowflakePlatformInfo, error) { + config := &SnowflakePlatformInfo{ + i.AzureVnetSubnetIds, + i.AwsVpcIds, + } + + return config, nil +} diff --git a/pkg/snowflake/system_get_snowflake_platform_info_test.go b/pkg/snowflake/system_get_snowflake_platform_info_test.go new file mode 100644 index 0000000000..cad7240ee8 --- /dev/null +++ b/pkg/snowflake/system_get_snowflake_platform_info_test.go @@ -0,0 +1,42 @@ +package snowflake + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSystemGetSnowflakePlatformInfoQuery(t *testing.T) { + r := require.New(t) + sb := SystemGetSnowflakePlatformInfoQuery() + + r.Equal(sb, `SELECT SYSTEM$GET_SNOWFLAKE_PLATFORM_INFO() AS "info"`) +} + +func TestSystemGetSnowflakePlatformInfoGetStructuredConfigAws(t *testing.T) { + r := require.New(t) + + raw := &RawSnowflakePlatformInfo{ + Info: `{"snowflake-vpc-id": ["vpc-1", "vpc-2"]}`, + } + + c, e := raw.GetStructuredConfig() + r.Nil(e) + + r.Equal([]string{"vpc-1", "vpc-2"}, c.AwsVpcIds) + r.Equal([]string(nil), c.AzureVnetSubnetIds) +} + +func TestSystemGetSnowflakePlatformInfoGetStructuredConfigAzure(t *testing.T) { + r := require.New(t) + + raw := &RawSnowflakePlatformInfo{ + Info: `{"snowflake-vnet-subnet-id": ["/subscription/1/1", "/subscription/1/2"]}`, + } + + c, e := raw.GetStructuredConfig() + r.Nil(e) + + r.Equal([]string{"/subscription/1/1", "/subscription/1/2"}, c.AzureVnetSubnetIds) + r.Equal([]string(nil), c.AwsVpcIds) +}