The gcp:bigqueryanalyticshub/listing:Listing resource, part of the Pulumi GCP provider, defines a listing within an Analytics Hub data exchange: what data source it shares, who can discover it, and what restrictions apply. This guide focuses on three capabilities: BigQuery dataset and Pub/Sub topic sharing, export restrictions and query logging, and public discovery and regional replication.
Listings belong to DataExchange resources and reference BigQuery datasets, tables, or Pub/Sub topics. The examples are intentionally small. Combine them with your own data exchanges, datasets, and access policies.
Share a BigQuery dataset through Analytics Hub
Most Analytics Hub deployments begin by making a BigQuery dataset discoverable and subscribable within a data exchange.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "US",
dataExchangeId: "my_data_exchange",
displayName: "my_data_exchange",
description: "example data exchange",
});
const listingDataset = new gcp.bigquery.Dataset("listing", {
datasetId: "my_listing",
friendlyName: "my_listing",
description: "example data exchange",
location: "US",
});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listing.dataExchangeId,
listingId: "my_listing",
displayName: "my_listing",
description: "example data exchange",
bigqueryDataset: {
dataset: listingDataset.id,
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="US",
data_exchange_id="my_data_exchange",
display_name="my_data_exchange",
description="example data exchange")
listing_dataset = gcp.bigquery.Dataset("listing",
dataset_id="my_listing",
friendly_name="my_listing",
description="example data exchange",
location="US")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing.data_exchange_id,
listing_id="my_listing",
display_name="my_listing",
description="example data exchange",
bigquery_dataset={
"dataset": listing_dataset.id,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("my_data_exchange"),
DisplayName: pulumi.String("my_data_exchange"),
Description: pulumi.String("example data exchange"),
})
if err != nil {
return err
}
listingDataset, err := bigquery.NewDataset(ctx, "listing", &bigquery.DatasetArgs{
DatasetId: pulumi.String("my_listing"),
FriendlyName: pulumi.String("my_listing"),
Description: pulumi.String("example data exchange"),
Location: pulumi.String("US"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("my_listing"),
DisplayName: pulumi.String("my_listing"),
Description: pulumi.String("example data exchange"),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: listingDataset.ID(),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "US",
DataExchangeId = "my_data_exchange",
DisplayName = "my_data_exchange",
Description = "example data exchange",
});
var listingDataset = new Gcp.BigQuery.Dataset("listing", new()
{
DatasetId = "my_listing",
FriendlyName = "my_listing",
Description = "example data exchange",
Location = "US",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listing.DataExchangeId,
ListingId = "my_listing",
DisplayName = "my_listing",
Description = "example data exchange",
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = listingDataset.Id,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("my_data_exchange")
.displayName("my_data_exchange")
.description("example data exchange")
.build());
var listingDataset = new Dataset("listingDataset", DatasetArgs.builder()
.datasetId("my_listing")
.friendlyName("my_listing")
.description("example data exchange")
.location("US")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("US")
.dataExchangeId(listing.dataExchangeId())
.listingId("my_listing")
.displayName("my_listing")
.description("example data exchange")
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset(listingDataset.id())
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: US
dataExchangeId: my_data_exchange
displayName: my_data_exchange
description: example data exchange
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: US
dataExchangeId: ${listing.dataExchangeId}
listingId: my_listing
displayName: my_listing
description: example data exchange
bigqueryDataset:
dataset: ${listingDataset.id}
listingDataset:
type: gcp:bigquery:Dataset
name: listing
properties:
datasetId: my_listing
friendlyName: my_listing
description: example data exchange
location: US
The dataExchangeId connects the listing to its parent exchange. The bigqueryDataset property points to the dataset you’re sharing by its resource ID. Subscribers can then create linked datasets in their own projects that query your data.
Restrict data export from subscribed datasets
Organizations sharing sensitive data often prevent subscribers from exporting query results outside Analytics Hub.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "US",
dataExchangeId: "my_data_exchange",
displayName: "my_data_exchange",
description: "example data exchange",
});
const listingDataset = new gcp.bigquery.Dataset("listing", {
datasetId: "my_listing",
friendlyName: "my_listing",
description: "example data exchange",
location: "US",
});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listing.dataExchangeId,
listingId: "my_listing",
displayName: "my_listing",
description: "example data exchange",
bigqueryDataset: {
dataset: listingDataset.id,
},
restrictedExportConfig: {
enabled: true,
restrictQueryResult: true,
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="US",
data_exchange_id="my_data_exchange",
display_name="my_data_exchange",
description="example data exchange")
listing_dataset = gcp.bigquery.Dataset("listing",
dataset_id="my_listing",
friendly_name="my_listing",
description="example data exchange",
location="US")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing.data_exchange_id,
listing_id="my_listing",
display_name="my_listing",
description="example data exchange",
bigquery_dataset={
"dataset": listing_dataset.id,
},
restricted_export_config={
"enabled": True,
"restrict_query_result": True,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("my_data_exchange"),
DisplayName: pulumi.String("my_data_exchange"),
Description: pulumi.String("example data exchange"),
})
if err != nil {
return err
}
listingDataset, err := bigquery.NewDataset(ctx, "listing", &bigquery.DatasetArgs{
DatasetId: pulumi.String("my_listing"),
FriendlyName: pulumi.String("my_listing"),
Description: pulumi.String("example data exchange"),
Location: pulumi.String("US"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("my_listing"),
DisplayName: pulumi.String("my_listing"),
Description: pulumi.String("example data exchange"),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: listingDataset.ID(),
},
RestrictedExportConfig: &bigqueryanalyticshub.ListingRestrictedExportConfigArgs{
Enabled: pulumi.Bool(true),
RestrictQueryResult: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "US",
DataExchangeId = "my_data_exchange",
DisplayName = "my_data_exchange",
Description = "example data exchange",
});
var listingDataset = new Gcp.BigQuery.Dataset("listing", new()
{
DatasetId = "my_listing",
FriendlyName = "my_listing",
Description = "example data exchange",
Location = "US",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listing.DataExchangeId,
ListingId = "my_listing",
DisplayName = "my_listing",
Description = "example data exchange",
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = listingDataset.Id,
},
RestrictedExportConfig = new Gcp.BigQueryAnalyticsHub.Inputs.ListingRestrictedExportConfigArgs
{
Enabled = true,
RestrictQueryResult = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingRestrictedExportConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("my_data_exchange")
.displayName("my_data_exchange")
.description("example data exchange")
.build());
var listingDataset = new Dataset("listingDataset", DatasetArgs.builder()
.datasetId("my_listing")
.friendlyName("my_listing")
.description("example data exchange")
.location("US")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("US")
.dataExchangeId(listing.dataExchangeId())
.listingId("my_listing")
.displayName("my_listing")
.description("example data exchange")
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset(listingDataset.id())
.build())
.restrictedExportConfig(ListingRestrictedExportConfigArgs.builder()
.enabled(true)
.restrictQueryResult(true)
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: US
dataExchangeId: my_data_exchange
displayName: my_data_exchange
description: example data exchange
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: US
dataExchangeId: ${listing.dataExchangeId}
listingId: my_listing
displayName: my_listing
description: example data exchange
bigqueryDataset:
dataset: ${listingDataset.id}
restrictedExportConfig:
enabled: true
restrictQueryResult: true
listingDataset:
type: gcp:bigquery:Dataset
name: listing
properties:
datasetId: my_listing
friendlyName: my_listing
description: example data exchange
location: US
The restrictedExportConfig property controls data movement. When enabled is true, subscribers cannot export query results to external storage. Setting restrictQueryResult to true blocks all query result exports, not just table exports.
Share specific tables in a DCR exchange
Data Clean Room (DCR) exchanges require explicit resource selection rather than sharing entire datasets.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "US",
dataExchangeId: "dcr_data_exchange",
displayName: "dcr_data_exchange",
description: "example dcr data exchange",
sharingEnvironmentConfig: {
dcrExchangeConfig: {},
},
});
const listingDataset = new gcp.bigquery.Dataset("listing", {
datasetId: "dcr_listing",
friendlyName: "dcr_listing",
description: "example dcr data exchange",
location: "US",
});
const listingTable = new gcp.bigquery.Table("listing", {
deletionProtection: false,
tableId: "dcr_listing",
datasetId: listingDataset.datasetId,
schema: `[
{
\\"name\\": \\"name\\",
\\"type\\": \\"STRING\\",
\\"mode\\": \\"NULLABLE\\"
},
{
\\"name\\": \\"post_abbr\\",
\\"type\\": \\"STRING\\",
\\"mode\\": \\"NULLABLE\\"
},
{
\\"name\\": \\"date\\",
\\"type\\": \\"DATE\\",
\\"mode\\": \\"NULLABLE\\"
}
]
`,
});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listing.dataExchangeId,
listingId: "dcr_listing",
displayName: "dcr_listing",
description: "example dcr data exchange",
bigqueryDataset: {
dataset: listingDataset.id,
selectedResources: [{
table: listingTable.id,
}],
},
restrictedExportConfig: {
enabled: true,
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="US",
data_exchange_id="dcr_data_exchange",
display_name="dcr_data_exchange",
description="example dcr data exchange",
sharing_environment_config={
"dcr_exchange_config": {},
})
listing_dataset = gcp.bigquery.Dataset("listing",
dataset_id="dcr_listing",
friendly_name="dcr_listing",
description="example dcr data exchange",
location="US")
listing_table = gcp.bigquery.Table("listing",
deletion_protection=False,
table_id="dcr_listing",
dataset_id=listing_dataset.dataset_id,
schema="""[
{
\"name\": \"name\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"post_abbr\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"date\",
\"type\": \"DATE\",
\"mode\": \"NULLABLE\"
}
]
""")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing.data_exchange_id,
listing_id="dcr_listing",
display_name="dcr_listing",
description="example dcr data exchange",
bigquery_dataset={
"dataset": listing_dataset.id,
"selected_resources": [{
"table": listing_table.id,
}],
},
restricted_export_config={
"enabled": True,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("dcr_data_exchange"),
DisplayName: pulumi.String("dcr_data_exchange"),
Description: pulumi.String("example dcr data exchange"),
SharingEnvironmentConfig: &bigqueryanalyticshub.DataExchangeSharingEnvironmentConfigArgs{
DcrExchangeConfig: &bigqueryanalyticshub.DataExchangeSharingEnvironmentConfigDcrExchangeConfigArgs{},
},
})
if err != nil {
return err
}
listingDataset, err := bigquery.NewDataset(ctx, "listing", &bigquery.DatasetArgs{
DatasetId: pulumi.String("dcr_listing"),
FriendlyName: pulumi.String("dcr_listing"),
Description: pulumi.String("example dcr data exchange"),
Location: pulumi.String("US"),
})
if err != nil {
return err
}
listingTable, err := bigquery.NewTable(ctx, "listing", &bigquery.TableArgs{
DeletionProtection: pulumi.Bool(false),
TableId: pulumi.String("dcr_listing"),
DatasetId: listingDataset.DatasetId,
Schema: pulumi.String(`[
{
\"name\": \"name\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"post_abbr\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"date\",
\"type\": \"DATE\",
\"mode\": \"NULLABLE\"
}
]
`),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("dcr_listing"),
DisplayName: pulumi.String("dcr_listing"),
Description: pulumi.String("example dcr data exchange"),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: listingDataset.ID(),
SelectedResources: bigqueryanalyticshub.ListingBigqueryDatasetSelectedResourceArray{
&bigqueryanalyticshub.ListingBigqueryDatasetSelectedResourceArgs{
Table: listingTable.ID(),
},
},
},
RestrictedExportConfig: &bigqueryanalyticshub.ListingRestrictedExportConfigArgs{
Enabled: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "US",
DataExchangeId = "dcr_data_exchange",
DisplayName = "dcr_data_exchange",
Description = "example dcr data exchange",
SharingEnvironmentConfig = new Gcp.BigQueryAnalyticsHub.Inputs.DataExchangeSharingEnvironmentConfigArgs
{
DcrExchangeConfig = null,
},
});
var listingDataset = new Gcp.BigQuery.Dataset("listing", new()
{
DatasetId = "dcr_listing",
FriendlyName = "dcr_listing",
Description = "example dcr data exchange",
Location = "US",
});
var listingTable = new Gcp.BigQuery.Table("listing", new()
{
DeletionProtection = false,
TableId = "dcr_listing",
DatasetId = listingDataset.DatasetId,
Schema = @"[
{
\""name\"": \""name\"",
\""type\"": \""STRING\"",
\""mode\"": \""NULLABLE\""
},
{
\""name\"": \""post_abbr\"",
\""type\"": \""STRING\"",
\""mode\"": \""NULLABLE\""
},
{
\""name\"": \""date\"",
\""type\"": \""DATE\"",
\""mode\"": \""NULLABLE\""
}
]
",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listing.DataExchangeId,
ListingId = "dcr_listing",
DisplayName = "dcr_listing",
Description = "example dcr data exchange",
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = listingDataset.Id,
SelectedResources = new[]
{
new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetSelectedResourceArgs
{
Table = listingTable.Id,
},
},
},
RestrictedExportConfig = new Gcp.BigQueryAnalyticsHub.Inputs.ListingRestrictedExportConfigArgs
{
Enabled = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.DataExchangeSharingEnvironmentConfigArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.DataExchangeSharingEnvironmentConfigDcrExchangeConfigArgs;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.Table;
import com.pulumi.gcp.bigquery.TableArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingRestrictedExportConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("dcr_data_exchange")
.displayName("dcr_data_exchange")
.description("example dcr data exchange")
.sharingEnvironmentConfig(DataExchangeSharingEnvironmentConfigArgs.builder()
.dcrExchangeConfig(DataExchangeSharingEnvironmentConfigDcrExchangeConfigArgs.builder()
.build())
.build())
.build());
var listingDataset = new Dataset("listingDataset", DatasetArgs.builder()
.datasetId("dcr_listing")
.friendlyName("dcr_listing")
.description("example dcr data exchange")
.location("US")
.build());
var listingTable = new Table("listingTable", TableArgs.builder()
.deletionProtection(false)
.tableId("dcr_listing")
.datasetId(listingDataset.datasetId())
.schema("""
[
{
\"name\": \"name\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"post_abbr\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"date\",
\"type\": \"DATE\",
\"mode\": \"NULLABLE\"
}
]
""")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("US")
.dataExchangeId(listing.dataExchangeId())
.listingId("dcr_listing")
.displayName("dcr_listing")
.description("example dcr data exchange")
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset(listingDataset.id())
.selectedResources(ListingBigqueryDatasetSelectedResourceArgs.builder()
.table(listingTable.id())
.build())
.build())
.restrictedExportConfig(ListingRestrictedExportConfigArgs.builder()
.enabled(true)
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: US
dataExchangeId: dcr_data_exchange
displayName: dcr_data_exchange
description: example dcr data exchange
sharingEnvironmentConfig:
dcrExchangeConfig: {}
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: US
dataExchangeId: ${listing.dataExchangeId}
listingId: dcr_listing
displayName: dcr_listing
description: example dcr data exchange
bigqueryDataset:
dataset: ${listingDataset.id}
selectedResources:
- table: ${listingTable.id}
restrictedExportConfig:
enabled: true
listingDataset:
type: gcp:bigquery:Dataset
name: listing
properties:
datasetId: dcr_listing
friendlyName: dcr_listing
description: example dcr data exchange
location: US
listingTable:
type: gcp:bigquery:Table
name: listing
properties:
deletionProtection: false
tableId: dcr_listing
datasetId: ${listingDataset.datasetId}
schema: |
[
{
\"name\": \"name\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"post_abbr\",
\"type\": \"STRING\",
\"mode\": \"NULLABLE\"
},
{
\"name\": \"date\",
\"type\": \"DATE\",
\"mode\": \"NULLABLE\"
}
]
DCR exchanges use sharingEnvironmentConfig with dcrExchangeConfig to enable privacy-preserving analytics. The selectedResources array specifies individual tables or routines to share. This granular control supports compliance requirements where only certain columns or aggregations should be accessible.
Log subscriber email addresses for queries
Compliance requirements sometimes mandate tracking which users query shared datasets.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listingLogEmail = new gcp.bigqueryanalyticshub.DataExchange("listing_log_email", {
location: "US",
dataExchangeId: "tf_test_log_email_de",
displayName: "tf_test_log_email_de",
description: "Example for log email test",
});
const listingLogEmailDataset = new gcp.bigquery.Dataset("listing_log_email", {
datasetId: "tf_test_log_email_ds",
friendlyName: "tf_test_log_email_ds",
description: "Example for log email test",
location: "US",
});
const listing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listingLogEmail.dataExchangeId,
listingId: "tf_test_log_email_listing",
displayName: "tf_test_log_email_listing",
description: "Example for log email test",
logLinkedDatasetQueryUserEmail: true,
bigqueryDataset: {
dataset: listingLogEmailDataset.id,
},
});
import pulumi
import pulumi_gcp as gcp
listing_log_email = gcp.bigqueryanalyticshub.DataExchange("listing_log_email",
location="US",
data_exchange_id="tf_test_log_email_de",
display_name="tf_test_log_email_de",
description="Example for log email test")
listing_log_email_dataset = gcp.bigquery.Dataset("listing_log_email",
dataset_id="tf_test_log_email_ds",
friendly_name="tf_test_log_email_ds",
description="Example for log email test",
location="US")
listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing_log_email.data_exchange_id,
listing_id="tf_test_log_email_listing",
display_name="tf_test_log_email_listing",
description="Example for log email test",
log_linked_dataset_query_user_email=True,
bigquery_dataset={
"dataset": listing_log_email_dataset.id,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listingLogEmail, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing_log_email", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("tf_test_log_email_de"),
DisplayName: pulumi.String("tf_test_log_email_de"),
Description: pulumi.String("Example for log email test"),
})
if err != nil {
return err
}
listingLogEmailDataset, err := bigquery.NewDataset(ctx, "listing_log_email", &bigquery.DatasetArgs{
DatasetId: pulumi.String("tf_test_log_email_ds"),
FriendlyName: pulumi.String("tf_test_log_email_ds"),
Description: pulumi.String("Example for log email test"),
Location: pulumi.String("US"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listingLogEmail.DataExchangeId,
ListingId: pulumi.String("tf_test_log_email_listing"),
DisplayName: pulumi.String("tf_test_log_email_listing"),
Description: pulumi.String("Example for log email test"),
LogLinkedDatasetQueryUserEmail: pulumi.Bool(true),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: listingLogEmailDataset.ID(),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listingLogEmail = new Gcp.BigQueryAnalyticsHub.DataExchange("listing_log_email", new()
{
Location = "US",
DataExchangeId = "tf_test_log_email_de",
DisplayName = "tf_test_log_email_de",
Description = "Example for log email test",
});
var listingLogEmailDataset = new Gcp.BigQuery.Dataset("listing_log_email", new()
{
DatasetId = "tf_test_log_email_ds",
FriendlyName = "tf_test_log_email_ds",
Description = "Example for log email test",
Location = "US",
});
var listing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listingLogEmail.DataExchangeId,
ListingId = "tf_test_log_email_listing",
DisplayName = "tf_test_log_email_listing",
Description = "Example for log email test",
LogLinkedDatasetQueryUserEmail = true,
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = listingLogEmailDataset.Id,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listingLogEmail = new DataExchange("listingLogEmail", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("tf_test_log_email_de")
.displayName("tf_test_log_email_de")
.description("Example for log email test")
.build());
var listingLogEmailDataset = new Dataset("listingLogEmailDataset", DatasetArgs.builder()
.datasetId("tf_test_log_email_ds")
.friendlyName("tf_test_log_email_ds")
.description("Example for log email test")
.location("US")
.build());
var listing = new Listing("listing", ListingArgs.builder()
.location("US")
.dataExchangeId(listingLogEmail.dataExchangeId())
.listingId("tf_test_log_email_listing")
.displayName("tf_test_log_email_listing")
.description("Example for log email test")
.logLinkedDatasetQueryUserEmail(true)
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset(listingLogEmailDataset.id())
.build())
.build());
}
}
resources:
listingLogEmail:
type: gcp:bigqueryanalyticshub:DataExchange
name: listing_log_email
properties:
location: US
dataExchangeId: tf_test_log_email_de
displayName: tf_test_log_email_de
description: Example for log email test
listing:
type: gcp:bigqueryanalyticshub:Listing
properties:
location: US
dataExchangeId: ${listingLogEmail.dataExchangeId}
listingId: tf_test_log_email_listing
displayName: tf_test_log_email_listing
description: Example for log email test
logLinkedDatasetQueryUserEmail: true
bigqueryDataset:
dataset: ${listingLogEmailDataset.id}
listingLogEmailDataset:
type: gcp:bigquery:Dataset
name: listing_log_email
properties:
datasetId: tf_test_log_email_ds
friendlyName: tf_test_log_email_ds
description: Example for log email test
location: US
The logLinkedDatasetQueryUserEmail property enables audit logging. When set to true, every query against the linked dataset logs the subscriber’s email address. This setting cannot be disabled once enabled.
Share Pub/Sub topics as data sources
Analytics Hub can share streaming data sources, not just static datasets.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "US",
dataExchangeId: "tf_test_pubsub_data_exchange",
displayName: "tf_test_pubsub_data_exchange",
description: "Example for pubsub topic source",
});
const tfTestPubsubTopic = new gcp.pubsub.Topic("tf_test_pubsub_topic", {name: "test_pubsub"});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listing.dataExchangeId,
listingId: "tf_test_pubsub_listing",
displayName: "tf_test_pubsub_listing",
description: "Example for pubsub topic source",
pubsubTopic: {
topic: tfTestPubsubTopic.id,
dataAffinityRegions: [
"us-central1",
"europe-west1",
],
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="US",
data_exchange_id="tf_test_pubsub_data_exchange",
display_name="tf_test_pubsub_data_exchange",
description="Example for pubsub topic source")
tf_test_pubsub_topic = gcp.pubsub.Topic("tf_test_pubsub_topic", name="test_pubsub")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing.data_exchange_id,
listing_id="tf_test_pubsub_listing",
display_name="tf_test_pubsub_listing",
description="Example for pubsub topic source",
pubsub_topic={
"topic": tf_test_pubsub_topic.id,
"data_affinity_regions": [
"us-central1",
"europe-west1",
],
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/pubsub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("tf_test_pubsub_data_exchange"),
DisplayName: pulumi.String("tf_test_pubsub_data_exchange"),
Description: pulumi.String("Example for pubsub topic source"),
})
if err != nil {
return err
}
tfTestPubsubTopic, err := pubsub.NewTopic(ctx, "tf_test_pubsub_topic", &pubsub.TopicArgs{
Name: pulumi.String("test_pubsub"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("tf_test_pubsub_listing"),
DisplayName: pulumi.String("tf_test_pubsub_listing"),
Description: pulumi.String("Example for pubsub topic source"),
PubsubTopic: &bigqueryanalyticshub.ListingPubsubTopicArgs{
Topic: tfTestPubsubTopic.ID(),
DataAffinityRegions: pulumi.StringArray{
pulumi.String("us-central1"),
pulumi.String("europe-west1"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "US",
DataExchangeId = "tf_test_pubsub_data_exchange",
DisplayName = "tf_test_pubsub_data_exchange",
Description = "Example for pubsub topic source",
});
var tfTestPubsubTopic = new Gcp.PubSub.Topic("tf_test_pubsub_topic", new()
{
Name = "test_pubsub",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listing.DataExchangeId,
ListingId = "tf_test_pubsub_listing",
DisplayName = "tf_test_pubsub_listing",
Description = "Example for pubsub topic source",
PubsubTopic = new Gcp.BigQueryAnalyticsHub.Inputs.ListingPubsubTopicArgs
{
Topic = tfTestPubsubTopic.Id,
DataAffinityRegions = new[]
{
"us-central1",
"europe-west1",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.pubsub.Topic;
import com.pulumi.gcp.pubsub.TopicArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingPubsubTopicArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("tf_test_pubsub_data_exchange")
.displayName("tf_test_pubsub_data_exchange")
.description("Example for pubsub topic source")
.build());
var tfTestPubsubTopic = new Topic("tfTestPubsubTopic", TopicArgs.builder()
.name("test_pubsub")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("US")
.dataExchangeId(listing.dataExchangeId())
.listingId("tf_test_pubsub_listing")
.displayName("tf_test_pubsub_listing")
.description("Example for pubsub topic source")
.pubsubTopic(ListingPubsubTopicArgs.builder()
.topic(tfTestPubsubTopic.id())
.dataAffinityRegions(
"us-central1",
"europe-west1")
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: US
dataExchangeId: tf_test_pubsub_data_exchange
displayName: tf_test_pubsub_data_exchange
description: Example for pubsub topic source
tfTestPubsubTopic:
type: gcp:pubsub:Topic
name: tf_test_pubsub_topic
properties:
name: test_pubsub
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: US
dataExchangeId: ${listing.dataExchangeId}
listingId: tf_test_pubsub_listing
displayName: tf_test_pubsub_listing
description: Example for pubsub topic source
pubsubTopic:
topic: ${tfTestPubsubTopic.id}
dataAffinityRegions:
- us-central1
- europe-west1
The pubsubTopic property specifies a Pub/Sub topic instead of a BigQuery dataset. The dataAffinityRegions array controls where subscribers can consume messages, supporting data residency requirements for streaming workloads.
Make listings publicly discoverable
Public listings appear on the Analytics Hub discovery page for all users, enabling broad data sharing.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "US",
dataExchangeId: "my_data_exchange",
displayName: "my_data_exchange",
description: "example public listing",
discoveryType: "DISCOVERY_TYPE_PUBLIC",
});
const listingDataset = new gcp.bigquery.Dataset("listing", {
datasetId: "my_listing",
friendlyName: "my_listing",
description: "example public listing",
location: "US",
});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "US",
dataExchangeId: listing.dataExchangeId,
listingId: "my_listing",
displayName: "my_listing",
description: "example public listing",
discoveryType: "DISCOVERY_TYPE_PUBLIC",
allowOnlyMetadataSharing: false,
bigqueryDataset: {
dataset: listingDataset.id,
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="US",
data_exchange_id="my_data_exchange",
display_name="my_data_exchange",
description="example public listing",
discovery_type="DISCOVERY_TYPE_PUBLIC")
listing_dataset = gcp.bigquery.Dataset("listing",
dataset_id="my_listing",
friendly_name="my_listing",
description="example public listing",
location="US")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="US",
data_exchange_id=listing.data_exchange_id,
listing_id="my_listing",
display_name="my_listing",
description="example public listing",
discovery_type="DISCOVERY_TYPE_PUBLIC",
allow_only_metadata_sharing=False,
bigquery_dataset={
"dataset": listing_dataset.id,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("US"),
DataExchangeId: pulumi.String("my_data_exchange"),
DisplayName: pulumi.String("my_data_exchange"),
Description: pulumi.String("example public listing"),
DiscoveryType: pulumi.String("DISCOVERY_TYPE_PUBLIC"),
})
if err != nil {
return err
}
listingDataset, err := bigquery.NewDataset(ctx, "listing", &bigquery.DatasetArgs{
DatasetId: pulumi.String("my_listing"),
FriendlyName: pulumi.String("my_listing"),
Description: pulumi.String("example public listing"),
Location: pulumi.String("US"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("US"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("my_listing"),
DisplayName: pulumi.String("my_listing"),
Description: pulumi.String("example public listing"),
DiscoveryType: pulumi.String("DISCOVERY_TYPE_PUBLIC"),
AllowOnlyMetadataSharing: pulumi.Bool(false),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: listingDataset.ID(),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "US",
DataExchangeId = "my_data_exchange",
DisplayName = "my_data_exchange",
Description = "example public listing",
DiscoveryType = "DISCOVERY_TYPE_PUBLIC",
});
var listingDataset = new Gcp.BigQuery.Dataset("listing", new()
{
DatasetId = "my_listing",
FriendlyName = "my_listing",
Description = "example public listing",
Location = "US",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "US",
DataExchangeId = listing.DataExchangeId,
ListingId = "my_listing",
DisplayName = "my_listing",
Description = "example public listing",
DiscoveryType = "DISCOVERY_TYPE_PUBLIC",
AllowOnlyMetadataSharing = false,
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = listingDataset.Id,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("US")
.dataExchangeId("my_data_exchange")
.displayName("my_data_exchange")
.description("example public listing")
.discoveryType("DISCOVERY_TYPE_PUBLIC")
.build());
var listingDataset = new Dataset("listingDataset", DatasetArgs.builder()
.datasetId("my_listing")
.friendlyName("my_listing")
.description("example public listing")
.location("US")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("US")
.dataExchangeId(listing.dataExchangeId())
.listingId("my_listing")
.displayName("my_listing")
.description("example public listing")
.discoveryType("DISCOVERY_TYPE_PUBLIC")
.allowOnlyMetadataSharing(false)
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset(listingDataset.id())
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: US
dataExchangeId: my_data_exchange
displayName: my_data_exchange
description: example public listing
discoveryType: DISCOVERY_TYPE_PUBLIC
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: US
dataExchangeId: ${listing.dataExchangeId}
listingId: my_listing
displayName: my_listing
description: example public listing
discoveryType: DISCOVERY_TYPE_PUBLIC
allowOnlyMetadataSharing: false
bigqueryDataset:
dataset: ${listingDataset.id}
listingDataset:
type: gcp:bigquery:Dataset
name: listing
properties:
datasetId: my_listing
friendlyName: my_listing
description: example public listing
location: US
The discoveryType property controls visibility. DISCOVERY_TYPE_PUBLIC makes the listing discoverable to anyone, while DISCOVERY_TYPE_PRIVATE restricts discovery to users with explicit IAM permissions. The allowOnlyMetadataSharing property, when false, allows full data subscription rather than just metadata access.
Replicate datasets across regions
Global data sharing often requires replicating datasets to multiple regions for performance and compliance.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const listing = new gcp.bigqueryanalyticshub.DataExchange("listing", {
location: "us",
dataExchangeId: "my_data_exchange",
displayName: "my_data_exchange",
});
const listingListing = new gcp.bigqueryanalyticshub.Listing("listing", {
location: "us",
dataExchangeId: listing.dataExchangeId,
listingId: "my_listing",
displayName: "my_listing",
bigqueryDataset: {
dataset: "projects/project_id/datasets/my_listing_example2",
replicaLocations: ["eu"],
},
});
import pulumi
import pulumi_gcp as gcp
listing = gcp.bigqueryanalyticshub.DataExchange("listing",
location="us",
data_exchange_id="my_data_exchange",
display_name="my_data_exchange")
listing_listing = gcp.bigqueryanalyticshub.Listing("listing",
location="us",
data_exchange_id=listing.data_exchange_id,
listing_id="my_listing",
display_name="my_listing",
bigquery_dataset={
"dataset": "projects/project_id/datasets/my_listing_example2",
"replica_locations": ["eu"],
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
listing, err := bigqueryanalyticshub.NewDataExchange(ctx, "listing", &bigqueryanalyticshub.DataExchangeArgs{
Location: pulumi.String("us"),
DataExchangeId: pulumi.String("my_data_exchange"),
DisplayName: pulumi.String("my_data_exchange"),
})
if err != nil {
return err
}
_, err = bigqueryanalyticshub.NewListing(ctx, "listing", &bigqueryanalyticshub.ListingArgs{
Location: pulumi.String("us"),
DataExchangeId: listing.DataExchangeId,
ListingId: pulumi.String("my_listing"),
DisplayName: pulumi.String("my_listing"),
BigqueryDataset: &bigqueryanalyticshub.ListingBigqueryDatasetArgs{
Dataset: pulumi.String("projects/project_id/datasets/my_listing_example2"),
ReplicaLocations: pulumi.StringArray{
pulumi.String("eu"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var listing = new Gcp.BigQueryAnalyticsHub.DataExchange("listing", new()
{
Location = "us",
DataExchangeId = "my_data_exchange",
DisplayName = "my_data_exchange",
});
var listingListing = new Gcp.BigQueryAnalyticsHub.Listing("listing", new()
{
Location = "us",
DataExchangeId = listing.DataExchangeId,
ListingId = "my_listing",
DisplayName = "my_listing",
BigqueryDataset = new Gcp.BigQueryAnalyticsHub.Inputs.ListingBigqueryDatasetArgs
{
Dataset = "projects/project_id/datasets/my_listing_example2",
ReplicaLocations = new[]
{
"eu",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchange;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeArgs;
import com.pulumi.gcp.bigqueryanalyticshub.Listing;
import com.pulumi.gcp.bigqueryanalyticshub.ListingArgs;
import com.pulumi.gcp.bigqueryanalyticshub.inputs.ListingBigqueryDatasetArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var listing = new DataExchange("listing", DataExchangeArgs.builder()
.location("us")
.dataExchangeId("my_data_exchange")
.displayName("my_data_exchange")
.build());
var listingListing = new Listing("listingListing", ListingArgs.builder()
.location("us")
.dataExchangeId(listing.dataExchangeId())
.listingId("my_listing")
.displayName("my_listing")
.bigqueryDataset(ListingBigqueryDatasetArgs.builder()
.dataset("projects/project_id/datasets/my_listing_example2")
.replicaLocations("eu")
.build())
.build());
}
}
resources:
listing:
type: gcp:bigqueryanalyticshub:DataExchange
properties:
location: us
dataExchangeId: my_data_exchange
displayName: my_data_exchange
listingListing:
type: gcp:bigqueryanalyticshub:Listing
name: listing
properties:
location: us
dataExchangeId: ${listing.dataExchangeId}
listingId: my_listing
displayName: my_listing
bigqueryDataset:
dataset: projects/project_id/datasets/my_listing_example2
replicaLocations:
- eu
The replicaLocations array specifies where Analytics Hub should replicate the dataset. Subscribers in different regions access local replicas, reducing query latency and supporting data residency requirements. The location property uses multi-region identifiers like “us” or “eu” rather than specific zones.
Beyond these examples
These snippets focus on specific listing-level features: BigQuery dataset and Pub/Sub topic sharing, export restrictions and query logging, and DCR exchanges and public discovery. They’re intentionally minimal rather than full data sharing solutions.
The examples may reference pre-existing infrastructure such as DataExchange resources, BigQuery datasets and tables, and Pub/Sub topics. They focus on configuring the listing rather than provisioning the underlying data sources.
To keep things focused, common listing patterns are omitted, including:
- Publisher and data provider metadata (publisher, dataProvider)
- Categorization and documentation (categories, documentation, icon)
- Access request workflows (requestAccess, primaryContact)
- Commercial marketplace configuration (deleteCommercial)
These omissions are intentional: the goal is to illustrate how each listing feature is wired, not provide drop-in data sharing modules. See the BigQuery Analytics Hub Listing resource reference for all available configuration options.
Let's create GCP BigQuery Analytics Hub Listings
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Immutability & Lifecycle
dataExchangeId, listingId, location, project, and allowOnlyMetadataSharing. You’ll need to recreate the listing to change any of these.deleteCommercial to be set to true before deletion. This acts as a safety guard to prevent accidental deletion of commercial listings.logLinkedDatasetQueryUserEmail to true, it cannot be turned off. All queries on the linked dataset will permanently log the querying user’s email address.Data Sources & Configuration
bigqueryDataset shares BigQuery datasets (tables, views, routines), while pubsubTopic shares Pub/Sub topics. Choose based on your data source type; you can only configure one per listing.selectedResources within bigqueryDataset to specify individual tables or routines by their IDs.replicaLocations within bigqueryDataset to specify additional regions where the listing should be available.Discovery & Access Control
DISCOVERY_TYPE_PUBLIC makes the listing visible on the discovery page, while DISCOVERY_TYPE_PRIVATE restricts visibility. IAM permissions still control actual access regardless of discovery type.discoveryType cannot be set for listings with restrictedExportConfig enabled.true, the listing becomes non-subscribable and only metadata is available. Users can view information about the listing but cannot access the actual data.Using a different cloud?
Explore analytics guides for other cloud providers: