Skip to content

Commit

Permalink
Add data source for SYSTEM$GET_PRIVATELINK_CONFIG() function (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
robbruce authored May 17, 2021
1 parent 624c2b3 commit e860561
Show file tree
Hide file tree
Showing 7 changed files with 393 additions and 5 deletions.
84 changes: 84 additions & 0 deletions docs/data-sources/system_get_privatelink_config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "snowflake_system_get_privatelink_config Data Source - terraform-provider-snowflake"
subcategory: ""
description: |-
---

# snowflake_system_get_privatelink_config (Data Source)



## Example Usage

```terraform
data "system_get_privatelink_config" "snowflake_private_link" {}
resource "aws_security_group" "snowflake_private_link" {
vpc_id = var.vpc_id
ingress {
from_port = 80
to_port = 80
cidr_blocks = var.vpc_cidr
protocol = "tcp"
}
ingress {
from_port = 443
to_port = 443
cidr_blocks = var.vpc_cidr
protocol = "tcp"
}
}
resource "aws_vpc_endpoint" "snowflake_private_link" {
vpc_id = var.vpc_id
service_name = data.system_get_privatelink_config.aws_vpce_id
vpc_endpoint_type = "Interface"
security_group_ids = [aws_security_group.snowflake_private_link.id]
private_dns_enabled = false
}
resource "aws_route53_zone" "snowflake_private_link" {
name = "privatelink.snowflakecomputing.com"
vpc {
vpc_id = var.vpc_id
}
}
resource "aws_route53_record" "snowflake_private_link_url" {
zone_id = aws_route53_zone.snowflake_private_link.zone_id
name = data.system_get_privatelink_config.snowflake_private_link.account_url
type = "CNAME"
ttl = "300"
records = [aws_vpc_endpoint.snowflake_private_link.dns_entry[0]["dns_name"]]
}
resource "aws_route53_record" "snowflake_private_link_oscp_url" {
zone_id = aws_route53_zone.snowflake_private_link_url.zone_id
name = data.system_get_privatelink_config.snowflake_private_link.oscp_url
type = "CNAME"
ttl = "300"
records = [aws_vpc_endpoint.snowflake_private_link.dns_entry[0]["dns_name"]]
}
```

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

### Optional

- **id** (String) The ID of this resource.

### Read-Only

- **account_name** (String) The name of your Snowflake account.
- **account_url** (String) The URL used to connect to Snowflake through AWS PrivateLink or Azure Private Link.
- **aws_vpce_id** (String) The AWS VPCE ID for your account.
- **azure_pls_id** (String) The Azure Private Link Service ID for your account.
- **oscp_url** (String) The OCSP URL corresponding to your Snowflake account that uses AWS PrivateLink or Azure Private Link.


Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
data "system_get_privatelink_config" "snowflake_private_link" {}

resource "aws_security_group" "snowflake_private_link" {
vpc_id = var.vpc_id

ingress {
from_port = 80
to_port = 80
cidr_blocks = var.vpc_cidr
protocol = "tcp"
}

ingress {
from_port = 443
to_port = 443
cidr_blocks = var.vpc_cidr
protocol = "tcp"
}
}

resource "aws_vpc_endpoint" "snowflake_private_link" {
vpc_id = var.vpc_id
service_name = data.system_get_privatelink_config.aws_vpce_id
vpc_endpoint_type = "Interface"
security_group_ids = [aws_security_group.snowflake_private_link.id]
private_dns_enabled = false
}

resource "aws_route53_zone" "snowflake_private_link" {
name = "privatelink.snowflakecomputing.com"

vpc {
vpc_id = var.vpc_id
}
}

resource "aws_route53_record" "snowflake_private_link_url" {
zone_id = aws_route53_zone.snowflake_private_link.zone_id
name = data.system_get_privatelink_config.snowflake_private_link.account_url
type = "CNAME"
ttl = "300"
records = [aws_vpc_endpoint.snowflake_private_link.dns_entry[0]["dns_name"]]
}

resource "aws_route53_record" "snowflake_private_link_oscp_url" {
zone_id = aws_route53_zone.snowflake_private_link_url.zone_id
name = data.system_get_privatelink_config.snowflake_private_link.oscp_url
type = "CNAME"
ttl = "300"
records = [aws_vpc_endpoint.snowflake_private_link.dns_entry[0]["dns_name"]]
}
86 changes: 86 additions & 0 deletions pkg/datasources/system_get_privatelink_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package datasources

import (
"database/sql"
"log"

"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var systemGetPrivateLinkConfigSchema = map[string]*schema.Schema{
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "The name of your Snowflake account.",
},

"account_url": {
Type: schema.TypeString,
Computed: true,
Description: "The URL used to connect to Snowflake through AWS PrivateLink or Azure Private Link.",
},

"oscp_url": {
Type: schema.TypeString,
Computed: true,
Description: "The OCSP URL corresponding to your Snowflake account that uses AWS PrivateLink or Azure Private Link.",
},

"aws_vpce_id": {
Type: schema.TypeString,
Computed: true,
Description: "The AWS VPCE ID for your account.",
},

"azure_pls_id": {
Type: schema.TypeString,
Computed: true,
Description: "The Azure Private Link Service ID for your account.",
},
}

func SystemGetPrivateLinkConfig() *schema.Resource {
return &schema.Resource{
Read: ReadSystemGetPrivateLinkConfig,
Schema: systemGetPrivateLinkConfigSchema,
}
}

// ReadSystemGetPrivateLinkConfig implements schema.ReadFunc
func ReadSystemGetPrivateLinkConfig(d *schema.ResourceData, meta interface{}) error {
db := meta.(*sql.DB)

sel := snowflake.SystemGetPrivateLinkConfigQuery()
row := snowflake.QueryRow(db, sel)
rawConfig, err := snowflake.ScanPrivateLinkConfig(row)

if err == sql.ErrNoRows {
// If not found, mark resource to be removed from statefile during apply or refresh
log.Print("[DEBUG] system_get_privatelink_config not found")
d.SetId("")
return nil
}

config, err := rawConfig.GetStructuredConfig()
if err != nil {
log.Printf("[DEBUG] system_get_privatelink_config failed to decode")
d.SetId("")
return nil
}

d.SetId(config.AccountName)
d.Set("account_name", config.AccountName)
d.Set("account_url", config.AccountURL)
d.Set("oscp_url", config.OSCPURL)

if config.AwsVpceID != "" {
d.Set("aws_vpce_id", config.AwsVpceID)
}

if config.AzurePrivateLinkServiceID != "" {
d.Set("azure_pls_id", config.AzurePrivateLinkServiceID)
}

return nil
}
31 changes: 31 additions & 0 deletions pkg/datasources/system_get_privatelink_config_acceptance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package datasources_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccSystemGetPrivateLinkConfig_aws(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
Providers: providers(),
Steps: []resource.TestStep{
{
Config: privateLinkConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.snowflake_system_get_privatelink_config.p", "account_name"),
resource.TestCheckResourceAttrSet("data.snowflake_system_get_privatelink_config.p", "account_url"),
resource.TestCheckResourceAttrSet("data.snowflake_system_get_privatelink_config.p", "oscp_url"),
resource.TestCheckResourceAttrSet("data.snowflake_system_get_privatelink_config.p", "aws_vpce_id"),
),
},
},
})
}

func privateLinkConfig() string {
s := `
data snowflake_system_get_privatelink_config p {}
`
return s
}
17 changes: 12 additions & 5 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,9 @@ func Provider() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_REGION", "us-west-2"),
},
},
ResourcesMap: getResources(),
DataSourcesMap: map[string]*schema.Resource{
"snowflake_system_get_aws_sns_iam_policy": datasources.SystemGetAWSSNSIAMPolicy(),
},
ConfigureFunc: ConfigureProvider,
ResourcesMap: getResources(),
DataSourcesMap: getDataSources(),
ConfigureFunc: ConfigureProvider,
}
}

Expand Down Expand Up @@ -188,6 +186,15 @@ func getResources() map[string]*schema.Resource {
)
}

func getDataSources() map[string]*schema.Resource {
dataSources := map[string]*schema.Resource{
"snowflake_system_get_aws_sns_iam_policy": datasources.SystemGetAWSSNSIAMPolicy(),
"snowflake_system_get_privatelink_config": datasources.SystemGetPrivateLinkConfig(),
}

return dataSources
}

func ConfigureProvider(s *schema.ResourceData) (interface{}, error) {
account := s.Get("account").(string)
user := s.Get("username").(string)
Expand Down
64 changes: 64 additions & 0 deletions pkg/snowflake/system_get_privatelink_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package snowflake

import (
"encoding/json"

"github.com/jmoiron/sqlx"
)

func SystemGetPrivateLinkConfigQuery() string {
return `SELECT SYSTEM$GET_PRIVATELINK_CONFIG() AS "config"`
}

type RawPrivateLinkConfig struct {
Config string `db:"config"`
}

type privateLinkConfigInternal struct {
AccountName string `json:"privatelink-account-name"`
AwsVpceID string `json:"privatelink-vpce-id,omitempty"`
AzurePrivateLinkServiceID string `json:"privatelink-pls-id,omitempty"`
AccountURL string `json:"privatelink-account-url"`
OSCPURL string `json:"privatelink-ocsp-url,omitempty"`
TypodOSCPURL string `json:"privatelink_ocsp-url,omitempty"` // because snowflake returns this for AWS, but don't have an Azure account to verify against
}

type PrivateLinkConfig struct {
AccountName string
AwsVpceID string
AzurePrivateLinkServiceID string
AccountURL string
OSCPURL string
}

func ScanPrivateLinkConfig(row *sqlx.Row) (*RawPrivateLinkConfig, error) {
config := &RawPrivateLinkConfig{}
err := row.StructScan(config)
return config, err
}

func (r *RawPrivateLinkConfig) GetStructuredConfig() (*PrivateLinkConfig, error) {
config := &privateLinkConfigInternal{}
err := json.Unmarshal([]byte(r.Config), config)
if err != nil {
return nil, err
}

return config.getPrivateLinkConfig()
}

func (i *privateLinkConfigInternal) getPrivateLinkConfig() (*PrivateLinkConfig, error) {
config := &PrivateLinkConfig{
i.AccountName,
i.AwsVpceID,
i.AzurePrivateLinkServiceID,
i.AccountURL,
i.OSCPURL,
}

if i.TypodOSCPURL != "" {
config.OSCPURL = i.TypodOSCPURL
}

return config, nil
}
Loading

0 comments on commit e860561

Please sign in to comment.