Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data source for AppHub discovered workload #17553

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/10107.txt
@@ -0,0 +1,3 @@
```release-note:new-datasource
`google_apphub_discovered_workload`
```
1 change: 1 addition & 0 deletions google/provider/provider_mmv1_resources.go
Expand Up @@ -137,6 +137,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
"google_alloydb_locations": alloydb.DataSourceAlloydbLocations(),
"google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(),
"google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(),
"google_apphub_discovered_workload": apphub.DataSourceApphubDiscoveredWorkload(),
"google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(),
"google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(),
"google_beyondcorp_app_connection": beyondcorp.DataSourceGoogleBeyondcorpAppConnection(),
Expand Down
164 changes: 164 additions & 0 deletions google/services/apphub/data_source_apphub_discovered_workload.go
@@ -0,0 +1,164 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package apphub

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
)

func DataSourceApphubDiscoveredWorkload() *schema.Resource {
return &schema.Resource{
Read: dataSourceApphubDiscoveredWorkloadRead,
Schema: map[string]*schema.Schema{
"project": {
Type: schema.TypeString,
Optional: true,
},
"location": {
Type: schema.TypeString,
Required: true,
},
"workload_uri": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"workload_reference": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"uri": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"workload_properties": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"gcp_project": {
Type: schema.TypeString,
Computed: true,
},
"location": {
Type: schema.TypeString,
Computed: true,
},
"zone": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataSourceApphubDiscoveredWorkloadRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}

url, err := tpgresource.ReplaceVars(d, config, fmt.Sprintf("{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredWorkloads:lookup?uri={{workload_uri}}"))
if err != nil {
return err
}

billingProject := ""

// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
})

if err != nil {
return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("ApphubDiscoveredWorkload %q", d.Id()), url)
}

if err := d.Set("name", flattenApphubDiscoveredWorkloadName(res["discoveredWorkload"].(map[string]interface{})["name"], d, config)); err != nil {
return fmt.Errorf("Error setting workload name: %s", err)
}

if err := d.Set("workload_reference", flattenApphubDiscoveredWorkloadReference(res["discoveredWorkload"].(map[string]interface{})["workloadReference"], d, config)); err != nil {
return fmt.Errorf("Error setting service reference: %s", err)
}

if err := d.Set("workload_properties", flattenApphubDiscoveredWorkloadProperties(res["discoveredWorkload"].(map[string]interface{})["workloadProperties"], d, config)); err != nil {
return fmt.Errorf("Error setting workload properties: %s", err)
}

d.SetId(res["discoveredWorkload"].(map[string]interface{})["name"].(string))

return nil

}

func flattenApphubDiscoveredWorkloadReference(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["uri"] = flattenApphubDiscoveredWorkloadDataUri(original["uri"], d, config)
return []interface{}{transformed}
}

func flattenApphubDiscoveredWorkloadProperties(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["gcp_project"] = flattenApphubDiscoveredWorkloadDataGcpProject(original["gcpProject"], d, config)
transformed["location"] = flattenApphubDiscoveredWorkloadDataLocation(original["location"], d, config)
transformed["zone"] = flattenApphubDiscoveredWorkloadDataZone(original["zone"], d, config)
return []interface{}{transformed}
}

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

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

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

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

func flattenApphubDiscoveredWorkloadDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
147 changes: 147 additions & 0 deletions google/services/apphub/data_source_apphub_discovered_workload_test.go
@@ -0,0 +1,147 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package apphub_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
)

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

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

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
ExternalProviders: map[string]resource.ExternalProvider{
"time": {},
},
Steps: []resource.TestStep{
{
Config: testDataSourceApphubDiscoveredWorkload_basic(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.google_apphub_discovered_workload.catalog-workload", "name"),
),
},
},
})
}

func testDataSourceApphubDiscoveredWorkload_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_project" "service_project" {
project_id ="tf-test-ah-%{random_suffix}"
name = "Service Project"
org_id = "%{org_id}"
billing_account = "%{billing_account}"
}

# Enable Compute API
resource "google_project_service" "compute_service_project" {
project = google_project.service_project.project_id
service = "compute.googleapis.com"
}

resource "time_sleep" "wait_120s" {
depends_on = [google_project_service.compute_service_project]
create_duration = "120s"
}

resource "google_apphub_service_project_attachment" "service_project_attachment" {
service_project_attachment_id = google_project.service_project.project_id
depends_on = [time_sleep.wait_120s]
}

data "google_apphub_discovered_workload" "catalog-workload" {
location = "us-central1"
workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}"
depends_on = [time_sleep.wait_120s_for_resource_ingestion]
}

# VPC network
resource "google_compute_network" "ilb_network" {
name = "l7-ilb-network-%{random_suffix}"
project = google_project.service_project.project_id
auto_create_subnetworks = false
depends_on = [time_sleep.wait_120s]
}

# backend subnet
resource "google_compute_subnetwork" "ilb_subnet" {
name = "l7-ilb-subnetwork-%{random_suffix}"
project = google_project.service_project.project_id
ip_cidr_range = "10.0.1.0/24"
region = "us-central1"
network = google_compute_network.ilb_network.id
}

resource "time_sleep" "wait_120s_for_resource_ingestion" {
depends_on = [google_compute_region_instance_group_manager.mig]
create_duration = "120s"
}

# instance template
resource "google_compute_instance_template" "instance_template" {
name = "l7-ilb-mig-template-%{random_suffix}"
project = google_project.service_project.project_id
machine_type = "e2-small"
tags = ["http-server"]
network_interface {
network = google_compute_network.ilb_network.id
subnetwork = google_compute_subnetwork.ilb_subnet.id
access_config {
# add external ip to fetch packages
}
}
disk {
source_image = "debian-cloud/debian-10"
auto_delete = true
boot = true
}
# install nginx and serve a simple web page
metadata = {
startup-script = <<-EOF1
#! /bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y nginx-light jq
NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname")
IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip")
METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])')
cat <<EOF > /var/www/html/index.html
<pre>
Name: $NAME
IP: $IP
Metadata: $METADATA
</pre>
EOF
EOF1
}
lifecycle {
create_before_destroy = true
}
}

resource "google_compute_region_instance_group_manager" "mig" {
name = "l7-ilb-mig1-%{random_suffix}"
project = google_project.service_project.project_id
region = "us-central1"
version {
instance_template = google_compute_instance_template.instance_template.id
name = "primary"
}
base_instance_name = "vm"
target_size = 2
}
`, context)
}
50 changes: 50 additions & 0 deletions website/docs/d/apphub_discovered_workload.html.markdown
@@ -0,0 +1,50 @@
---
subcategory: "Apphub"
description: |-
Get information about a discovered workload.
---

# google\_apphub\_discovered_workload

Get information about a discovered workload from its uri.


## Example Usage


```hcl
data "google_apphub_discovered_workload" "my-workload" {
location = "us-central1"
workload_uri = "my-workload-uri"
}
```

## Argument Reference

The following arguments are supported:

* `project` - The host project of the discovered workload.
* `workload_uri` - (Required) The uri of the workload (instance group managed by the Instance Group Manager). Example: "//compute.googleapis.com/projects/1/regions/us-east1/instanceGroups/id1"
* `location` - (Required) The location of the discovered workload.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are exported:

* `name` - Resource name of a Workload. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/workloads/{workload-id}".

* `workload_reference` - Reference to an underlying networking resource that can comprise a Workload. Structure is [documented below](#nested_workload_reference)

<a name="nested_workload_reference"></a>The `workload_reference` block supports:

* `uri` - The underlying resource URI.

* `workload_properties` - Properties of an underlying compute resource that can comprise a Workload. Structure is [documented below](#nested_workload_properties)

<a name="nested_workload_properties"></a>The `workload_properties` block supports:

* `gcp_project` - The service project identifier that the underlying cloud resource resides in.

* `location` - The location that the underlying resource resides in.

* `zone` - The location that the underlying resource resides in if it is zonal.