diff --git a/.changelog/10105.txt b/.changelog/10105.txt
new file mode 100644
index 00000000000..e618b65aef2
--- /dev/null
+++ b/.changelog/10105.txt
@@ -0,0 +1,3 @@
+```release-note:new-datasource
+`google_apphub_discovered_service`
+```
\ No newline at end of file
diff --git a/google/provider/provider_mmv1_resources.go b/google/provider/provider_mmv1_resources.go
index 4b7c627352f..81d3339ab44 100644
--- a/google/provider/provider_mmv1_resources.go
+++ b/google/provider/provider_mmv1_resources.go
@@ -138,6 +138,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
"google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(),
"google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(),
"google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(),
+ "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(),
"google_beyondcorp_app_connection": beyondcorp.DataSourceGoogleBeyondcorpAppConnection(),
"google_beyondcorp_app_connector": beyondcorp.DataSourceGoogleBeyondcorpAppConnector(),
"google_beyondcorp_app_gateway": beyondcorp.DataSourceGoogleBeyondcorpAppGateway(),
diff --git a/google/services/apphub/data_source_apphub_discovered_service.go b/google/services/apphub/data_source_apphub_discovered_service.go
new file mode 100644
index 00000000000..ae590982a49
--- /dev/null
+++ b/google/services/apphub/data_source_apphub_discovered_service.go
@@ -0,0 +1,173 @@
+// 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 DataSourceApphubDiscoveredService() *schema.Resource {
+ return &schema.Resource{
+ Read: dataSourceApphubDiscoveredServiceRead,
+ Schema: map[string]*schema.Schema{
+ "project": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "location": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "service_uri": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "service_reference": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "uri": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "path": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ "service_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 dataSourceApphubDiscoveredServiceRead(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, "{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredServices:lookup?uri={{service_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("ApphubDiscoveredService %q", d.Id()), url)
+ }
+
+ if err := d.Set("name", flattenApphubDiscoveredServiceName(res["discoveredService"].(map[string]interface{})["name"], d, config)); err != nil {
+ return fmt.Errorf("Error setting service name: %s", err)
+ }
+
+ if err := d.Set("service_reference", flattenApphubDiscoveredServiceReference(res["discoveredService"].(map[string]interface{})["serviceReference"], d, config)); err != nil {
+ return fmt.Errorf("Error setting service reference: %s", err)
+ }
+
+ if err := d.Set("service_properties", flattenApphubDiscoveredServiceProperties(res["discoveredService"].(map[string]interface{})["serviceProperties"], d, config)); err != nil {
+ return fmt.Errorf("Error setting service properties: %s", err)
+ }
+
+ d.SetId(res["discoveredService"].(map[string]interface{})["name"].(string))
+
+ return nil
+
+}
+
+func flattenApphubDiscoveredServiceReference(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"] = flattenApphubDiscoveredServiceDataUri(original["uri"], d, config)
+ transformed["path"] = flattenApphubDiscoveredServiceDataPath(original["path"], d, config)
+ return []interface{}{transformed}
+}
+
+func flattenApphubDiscoveredServiceProperties(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"] = flattenApphubDiscoveredServiceDataGcpProject(original["gcpProject"], d, config)
+ transformed["location"] = flattenApphubDiscoveredServiceDataLocation(original["location"], d, config)
+ transformed["zone"] = flattenApphubDiscoveredServiceDataZone(original["zone"], d, config)
+ return []interface{}{transformed}
+}
+
+func flattenApphubDiscoveredServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
+
+func flattenApphubDiscoveredServiceDataUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
+
+func flattenApphubDiscoveredServiceDataPath(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
+
+func flattenApphubDiscoveredServiceDataGcpProject(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
+
+func flattenApphubDiscoveredServiceDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
+
+func flattenApphubDiscoveredServiceDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
+ return v
+}
diff --git a/google/services/apphub/data_source_apphub_discovered_service_test.go b/google/services/apphub/data_source_apphub_discovered_service_test.go
new file mode 100644
index 00000000000..2f1b900d237
--- /dev/null
+++ b/google/services/apphub/data_source_apphub_discovered_service_test.go
@@ -0,0 +1,130 @@
+// 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 TestAccDataSourceApphubDiscoveredService_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: testDataSourceApphubDiscoveredService_basic(context),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet("data.google_apphub_discovered_service.catalog-service", "name"),
+ ),
+ },
+ },
+ })
+}
+
+func testDataSourceApphubDiscoveredService_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]
+}
+
+# discovered service block
+data "google_apphub_discovered_service" "catalog-service" {
+ location = "us-central1"
+ # ServiceReference | Application Hub | Google Cloud
+ # Using this reference means that this resource will not be provisioned until the forwarding rule is fully created
+ service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}"
+ depends_on = [time_sleep.wait_120s_for_resource_ingestion]
+}
+
+# VPC network
+resource "google_compute_network" "ilb_network" {
+ name = "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 = "ilb-subnet-%{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
+}
+
+# forwarding rule
+resource "google_compute_forwarding_rule" "forwarding_rule" {
+ name = "forwarding-rule-%{random_suffix}"
+ project = google_project.service_project.project_id
+ region = "us-central1"
+ ip_version = "IPV4"
+ load_balancing_scheme = "INTERNAL"
+ all_ports = true
+ backend_service = google_compute_region_backend_service.backend.id
+ network = google_compute_network.ilb_network.id
+ subnetwork = google_compute_subnetwork.ilb_subnet.id
+}
+
+resource "time_sleep" "wait_120s_for_resource_ingestion" {
+ depends_on = [google_compute_forwarding_rule.forwarding_rule]
+ create_duration = "120s"
+}
+
+# backend service
+resource "google_compute_region_backend_service" "backend" {
+ name = "backend-service-%{random_suffix}"
+ project = google_project.service_project.project_id
+ region = "us-central1"
+ health_checks = [google_compute_health_check.default.id]
+}
+
+# health check
+resource "google_compute_health_check" "default" {
+ name = "health-check-%{random_suffix}"
+ project = google_project.service_project.project_id
+ check_interval_sec = 1
+ timeout_sec = 1
+
+ tcp_health_check {
+ port = "80"
+ }
+ depends_on = [time_sleep.wait_120s]
+}
+`, context)
+}
diff --git a/website/docs/d/apphub_discovered_service.html.markdown b/website/docs/d/apphub_discovered_service.html.markdown
new file mode 100644
index 00000000000..272491b8d08
--- /dev/null
+++ b/website/docs/d/apphub_discovered_service.html.markdown
@@ -0,0 +1,52 @@
+---
+subcategory: "Apphub"
+description: |-
+ Get information about a discovered service.
+---
+
+# google\_apphub\_discovered_service
+
+Get information about a discovered service from its uri.
+
+
+## Example Usage
+
+
+```hcl
+data "google_apphub_discovered_service" "my-service" {
+ location = "my-location"
+ service_uri = "my-service-uri"
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `project` - The host project of the discovered service.
+* `service_uri` - (Required) The uri of the service.
+* `location` - (Required) The location of the discovered service.
+
+## Attributes Reference
+
+In addition to the arguments listed above, the following computed attributes are exported:
+
+* `name` - Resource name of a Service. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}".
+
+* `service_reference` - Reference to an underlying networking resource that can comprise a Service. Structure is [documented below](#nested_service_reference)
+
+A `service_reference` object would contain the following fields:
+
+* `uri` - The underlying resource URI.
+
+* `path` - Additional path under the resource URI.
+
+* `service_properties` - Properties of an underlying compute resource that can comprise a Service. Structure is [documented below](#nested_service_properties)
+
+A `service_properties` object would contain the following fields:
+
+* `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.
\ No newline at end of file