Skip to content

Commit

Permalink
Add Private Service Connect to Looker (#11487) (#8211)
Browse files Browse the repository at this point in the history
[upstream:d65f0b7a1bf7a8d4c6aa02d9540542d3d8695429]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Sep 18, 2024
1 parent a34687d commit a1121de
Show file tree
Hide file tree
Showing 4 changed files with 361 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/11487.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
looker: added `psc_enabled` and `psc_config` to `google_looker_instance` resource
```
245 changes: 245 additions & 0 deletions google-beta/services/looker/resource_looker_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,58 @@ disrupt service.`,
Description: `Whether private IP is enabled on the Looker instance.`,
Default: false,
},
"psc_config": {
Type: schema.TypeList,
Optional: true,
Description: `Information for Private Service Connect (PSC) setup for a Looker instance.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"allowed_vpcs": {
Type: schema.TypeList,
Optional: true,
Description: `List of VPCs that are allowed ingress into the Looker instance.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"service_attachments": {
Type: schema.TypeList,
Optional: true,
Description: `List of egress service attachment configurations.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"local_fqdn": {
Type: schema.TypeString,
Optional: true,
Description: `Fully qualified domain name that will be used in the private DNS record created for the service attachment.`,
},
"target_service_attachment_uri": {
Type: schema.TypeString,
Optional: true,
Description: `URI of the service attachment to connect to.`,
},
"connection_status": {
Type: schema.TypeString,
Computed: true,
Description: `Status of the service attachment connection.`,
},
},
},
},
"looker_service_attachment_uri": {
Type: schema.TypeString,
Computed: true,
Description: `URI of the Looker service attachment.`,
},
},
},
},
"psc_enabled": {
Type: schema.TypeBool,
Optional: true,
Description: `Whether Public Service Connect (PSC) is enabled on the Looker instance`,
},
"public_ip_enabled": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -517,6 +569,18 @@ func resourceLookerInstanceCreate(d *schema.ResourceData, meta interface{}) erro
} else if v, ok := d.GetOkExists("private_ip_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(privateIpEnabledProp)) && (ok || !reflect.DeepEqual(v, privateIpEnabledProp)) {
obj["privateIpEnabled"] = privateIpEnabledProp
}
pscConfigProp, err := expandLookerInstancePscConfig(d.Get("psc_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("psc_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(pscConfigProp)) && (ok || !reflect.DeepEqual(v, pscConfigProp)) {
obj["pscConfig"] = pscConfigProp
}
pscEnabledProp, err := expandLookerInstancePscEnabled(d.Get("psc_enabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("psc_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(pscEnabledProp)) && (ok || !reflect.DeepEqual(v, pscEnabledProp)) {
obj["pscEnabled"] = pscEnabledProp
}
publicIpEnabledProp, err := expandLookerInstancePublicIpEnabled(d.Get("public_ip_enabled"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -694,6 +758,12 @@ func resourceLookerInstanceRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("private_ip_enabled", flattenLookerInstancePrivateIpEnabled(res["privateIpEnabled"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
if err := d.Set("psc_config", flattenLookerInstancePscConfig(res["pscConfig"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
if err := d.Set("psc_enabled", flattenLookerInstancePscEnabled(res["pscEnabled"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
if err := d.Set("public_ip_enabled", flattenLookerInstancePublicIpEnabled(res["publicIpEnabled"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
Expand Down Expand Up @@ -777,6 +847,18 @@ func resourceLookerInstanceUpdate(d *schema.ResourceData, meta interface{}) erro
} else if v, ok := d.GetOkExists("private_ip_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, privateIpEnabledProp)) {
obj["privateIpEnabled"] = privateIpEnabledProp
}
pscConfigProp, err := expandLookerInstancePscConfig(d.Get("psc_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("psc_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pscConfigProp)) {
obj["pscConfig"] = pscConfigProp
}
pscEnabledProp, err := expandLookerInstancePscEnabled(d.Get("psc_enabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("psc_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pscEnabledProp)) {
obj["pscEnabled"] = pscEnabledProp
}
publicIpEnabledProp, err := expandLookerInstancePublicIpEnabled(d.Get("public_ip_enabled"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -843,6 +925,15 @@ func resourceLookerInstanceUpdate(d *schema.ResourceData, meta interface{}) erro
updateMask = append(updateMask, "privateIpEnabled")
}

if d.HasChange("psc_config") {
updateMask = append(updateMask, "psc_config.allowed_vpcs",
"psc_config.service_attachments")
}

if d.HasChange("psc_enabled") {
updateMask = append(updateMask, "pscEnabled")
}

if d.HasChange("public_ip_enabled") {
updateMask = append(updateMask, "publicIpEnabled")
}
Expand Down Expand Up @@ -1412,6 +1503,67 @@ func flattenLookerInstancePrivateIpEnabled(v interface{}, d *schema.ResourceData
return v
}

func flattenLookerInstancePscConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["allowed_vpcs"] =
flattenLookerInstancePscConfigAllowedVpcs(original["allowedVpcs"], d, config)
transformed["looker_service_attachment_uri"] =
flattenLookerInstancePscConfigLookerServiceAttachmentUri(original["lookerServiceAttachmentUri"], d, config)
transformed["service_attachments"] =
flattenLookerInstancePscConfigServiceAttachments(original["serviceAttachments"], d, config)
return []interface{}{transformed}
}
func flattenLookerInstancePscConfigAllowedVpcs(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePscConfigLookerServiceAttachmentUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePscConfigServiceAttachments(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"connection_status": flattenLookerInstancePscConfigServiceAttachmentsConnectionStatus(original["connectionStatus"], d, config),
"local_fqdn": flattenLookerInstancePscConfigServiceAttachmentsLocalFqdn(original["localFqdn"], d, config),
"target_service_attachment_uri": flattenLookerInstancePscConfigServiceAttachmentsTargetServiceAttachmentUri(original["targetServiceAttachmentUri"], d, config),
})
}
return transformed
}
func flattenLookerInstancePscConfigServiceAttachmentsConnectionStatus(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePscConfigServiceAttachmentsLocalFqdn(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePscConfigServiceAttachmentsTargetServiceAttachmentUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePscEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenLookerInstancePublicIpEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
Expand Down Expand Up @@ -1898,6 +2050,99 @@ func expandLookerInstancePrivateIpEnabled(v interface{}, d tpgresource.Terraform
return v, nil
}

func expandLookerInstancePscConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedAllowedVpcs, err := expandLookerInstancePscConfigAllowedVpcs(original["allowed_vpcs"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAllowedVpcs); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["allowedVpcs"] = transformedAllowedVpcs
}

transformedLookerServiceAttachmentUri, err := expandLookerInstancePscConfigLookerServiceAttachmentUri(original["looker_service_attachment_uri"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedLookerServiceAttachmentUri); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["lookerServiceAttachmentUri"] = transformedLookerServiceAttachmentUri
}

transformedServiceAttachments, err := expandLookerInstancePscConfigServiceAttachments(original["service_attachments"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedServiceAttachments); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["serviceAttachments"] = transformedServiceAttachments
}

return transformed, nil
}

func expandLookerInstancePscConfigAllowedVpcs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePscConfigLookerServiceAttachmentUri(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePscConfigServiceAttachments(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedConnectionStatus, err := expandLookerInstancePscConfigServiceAttachmentsConnectionStatus(original["connection_status"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedConnectionStatus); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["connectionStatus"] = transformedConnectionStatus
}

transformedLocalFqdn, err := expandLookerInstancePscConfigServiceAttachmentsLocalFqdn(original["local_fqdn"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedLocalFqdn); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["localFqdn"] = transformedLocalFqdn
}

transformedTargetServiceAttachmentUri, err := expandLookerInstancePscConfigServiceAttachmentsTargetServiceAttachmentUri(original["target_service_attachment_uri"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedTargetServiceAttachmentUri); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["targetServiceAttachmentUri"] = transformedTargetServiceAttachmentUri
}

req = append(req, transformed)
}
return req, nil
}

func expandLookerInstancePscConfigServiceAttachmentsConnectionStatus(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePscConfigServiceAttachmentsLocalFqdn(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePscConfigServiceAttachmentsTargetServiceAttachmentUri(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePscEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandLookerInstancePublicIpEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,53 @@ resource "google_looker_instance" "looker-instance" {
`, context)
}

func TestAccLookerInstance_lookerInstancePscExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckLookerInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccLookerInstance_lookerInstancePscExample(context),
},
{
ResourceName: "google_looker_instance.looker-instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "oauth_config", "region"},
},
},
})
}

func testAccLookerInstance_lookerInstancePscExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_looker_instance" "looker-instance" {
name = "tf-test-my-instance%{random_suffix}"
platform_edition = "LOOKER_CORE_ENTERPRISE_ANNUAL"
region = "us-central1"
private_ip_enabled = false
public_ip_enabled = false
psc_enabled = true
oauth_config {
client_id = "tf-test-my-client-id%{random_suffix}"
client_secret = "tf-test-my-client-secret%{random_suffix}"
}
psc_config {
allowed_vpcs = ["projects/test-project/global/networks/test"]
# update only
# service_attachments = [{local_fqdn: "www.local-fqdn.com" target_service_attachment_uri: "projects/my-project/regions/us-east1/serviceAttachments/sa"}]
}
}
`, context)
}

func testAccCheckLookerInstanceDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
Expand Down
Loading

0 comments on commit a1121de

Please sign in to comment.