published on Wednesday, Jun 3, 2026 by redpanda-data
Redpanda Provider
published on Wednesday, Jun 3, 2026 by redpanda-data
Generate Provider
The Redpanda provider must be installed as a Local Package by following the instructions for Any Terraform Provider:
pulumi package add terraform-provider redpanda-data/redpanda
Overview
The Redpanda provider is designed for managing Redpanda clusters and Kafka resources in Redpanda Dedicated and Cloud environments. It supports the provisioning, management, and configuration of clusters and Kafka resources, facilitating seamless integration into Pulumi workflows.
Configuration Reference
accessToken(String, Sensitive) Redpanda client token. You need eitheraccessToken, or bothclientIdandclientSecretto use this provider. Can also be set with theREDPANDA_ACCESS_TOKENenvironment variable.awsAccessKeyId(String, Sensitive) AWS access key ID for BYOC clusters. Can also be set via AWS_ACCESS_KEY_ID.awsSecretAccessKey(String, Sensitive) AWS secret access key for BYOC clusters. Can also be set via AWS_SECRET_ACCESS_KEY.awsSessionToken(String, Sensitive) AWS session token for BYOC clusters (for temporary credentials). Can also be set via AWS_SESSION_TOKEN.azureClientId(String) Used for creating and managing BYOC and BYOVPC clusters. Can also be specified in the environment as AZURE_CLIENT_ID or ARM_CLIENT_IDazureClientSecret(String, Sensitive) Used for creating and managing BYOC and BYOVPC clusters. Can also be specified in the environment as AZURE_CLIENT_SECRET or ARM_CLIENT_SECRETazureSubscriptionId(String) The default Azure Subscription ID which should be used for Redpanda BYOC clusters. If another subscription is specified on a resource, it will take precedence. This can also be sourced from theARM_SUBSCRIPTION_IDenvironment variable.azureTenantId(String) Used for creating and managing BYOC and BYOVPC clusters. Can also be specified in the environment as AZURE_TENANT_ID or ARM_TENANT_IDclientId(String, Sensitive) The ID for the client. You need eitherclientIdANDclientSecret, oraccessToken, to use this provider. Can also be set with theREDPANDA_CLIENT_IDenvironment variable.clientSecret(String, Sensitive) Redpanda client secret. You need eitherclientIdANDclientSecret, oraccessToken, to use this provider. Can also be set with theREDPANDA_CLIENT_SECRETenvironment variable.gcpProjectId(String) The default Google Cloud Project ID to use for Redpanda BYOC clusters. If another project is specified on a resource, it will take precedence. This can also be sourced from theGOOGLE_PROJECTenvironment variable, or any of the following ordered by precedence:GOOGLE_PROJECT,GOOGLE_CLOUD_PROJECT,GCLOUD_PROJECT, orCLOUDSDK_CORE_PROJECT.googleCredentials(String, Sensitive) Used for creating and managing BYOC and BYOVPC clusters. Can also be specified in the environment as GOOGLE_CREDENTIALSgoogleCredentialsBase64(String, Sensitive) Used for creating and managing BYOC and BYOVPC clusters. Is a convenience passthrough for base64 encoded credentials intended for use in CI/CD. Can also be specified in the environment as GOOGLE_CREDENTIALS_BASE64
Authentication with Redpanda Cloud
This provider requires a clientId and clientSecret for authentication with Redpanda Cloud services, enabling users to securely manage their Redpanda resources. You can get these by creating an account in Redpanda Cloud and then creating a client in the Redpanda Cloud UI.
Token cache
The provider caches the OAuth2 access token to disk so that subsequent
pulumi invocations reuse it until expiry, instead of issuing a fresh
token on every plan or apply. This keeps usage well under the per-organization
daily token-issuance quota.
- Location:
<user-cache-dir>/redpanda/provider/creds-cache.json. The user cache directory is~/Library/Cacheson macOS,$XDG_CACHE_HOME(falling back to~/.cache) on Linux, and%LocalAppData%on Windows. - Permissions: the file is written with mode
0600; theredpanda/provider/directory is created with mode0755. - Cache key: tokens are keyed by
<audience>:<client_id>, so different Redpanda environments and clients each get their own entry. - Disable: set
REDPANDA_TOKEN_CACHE_DISABLE=1to skip the on-disk cache; a fresh token is fetched per provider invocation. - Clear: delete the file (
rm <user-cache-dir>/redpanda/provider/creds-cache.json). Useful if a server-side secret rotation invalidates the cached token before its local expiry.
Example Provider Configuration
Pulumi 1.0 or later:
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: nodejs
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
import * as pulumi from "@pulumi/pulumi";
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: python
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
import pulumi
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: dotnet
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
using System.Collections.Generic;
using System.Linq;
using Pulumi;
return await Deployment.RunAsync(() =>
{
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: go
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
return nil
})
}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: yaml
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
{}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: java
config:
redpanda:clientId:
value: your_client_id
redpanda:clientSecret:
value: your_client_secret
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
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) {
}
}
Example Usage for an AWS Dedicated Cluster
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: nodejs
import * as pulumi from "@pulumi/pulumi";
import * as redpanda from "@pulumi/redpanda";
const test = new redpanda.ResourceGroup("test", {name: resourceGroupName});
const testNetwork = new redpanda.Network("test", {
name: networkName,
resourceGroupId: test.id,
cloudProvider: cloudProvider,
region: region,
clusterType: "dedicated",
cidrBlock: "10.0.0.0/20",
timeouts: {
create: "20m",
"delete": "20m",
},
});
const testCluster = new redpanda.Cluster("test", {
name: clusterName,
resourceGroupId: test.id,
networkId: testNetwork.id,
cloudProvider: cloudProvider,
region: region,
clusterType: "dedicated",
connectionType: "public",
throughputTier: throughputTier,
zones: zones,
allowDeletion: clusterAllowDeletion,
clusterConfiguration: {
customPropertiesJson: JSON.stringify({
enable_shadow_linking: clusterEnableShadowLinking,
schema_registry_enable_authorization: true,
}),
},
maintenanceWindowConfig: {
dayHour: {
dayOfWeek: maintenanceDayOfWeek,
hourOfDay: maintenanceHourOfDay,
},
},
tags: clusterTags,
timeouts: {
create: "90m",
},
});
const testUser = new redpanda.User("test", {
name: userName,
password: userPasswordWo != null ? null : userPw,
passwordWo: userPasswordWo,
passwordWoVersion: userPasswordWoVersion,
mechanism: mechanism,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: userAllowDeletion,
});
const testTopic = new redpanda.Topic("test", {
name: topicName,
partitionCount: partitionCount,
replicationFactor: replicationFactor,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: true,
configuration: topicConfiguration != null ? topicConfiguration : {
"cleanup.policy": "delete",
"retention.ms": topicRetentionMs,
},
}, {
dependsOn: [testUser],
});
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// Two grants are required: the SUBJECT-scope grant authorizes
// POST /subjects/<subj>/versions; the REGISTRY-scope grant authorizes the
// follow-up GET /schemas/ids/<id>/versions that the SR client (franz-go) makes
// to fetch the full schema metadata after create. Without the REGISTRY grant,
// the schema is created but the follow-up GET 403s and the resource fails.
// User:* is broader than necessary; tighten once the exact principal is
// documented as discoverable.
const providerBootstrapSubject = new redpanda.SchemaRegistryAcl("provider_bootstrap_subject", {
clusterId: testCluster.id,
principal: "User:*",
resourceType: "SUBJECT",
resourceName: topicName,
patternType: "PREFIXED",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const providerBootstrapRegistry = new redpanda.SchemaRegistryAcl("provider_bootstrap_registry", {
clusterId: testCluster.id,
principal: "User:*",
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const clusterAdmin = new redpanda.Acl("cluster_admin", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALL",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const schemaRegistryAdmin = new redpanda.Acl("schema_registry_admin", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALTER",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const clusterAction = new redpanda.Acl("cluster_action", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "CLUSTER_ACTION",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const topicAccess = new redpanda.Acl("topic_access", {
resourceType: "TOPIC",
resourceName: testTopic.name,
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALL",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const allTestTopic = new redpanda.SchemaRegistryAcl("all_test_topic", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: `${topicName}-`,
patternType: "PREFIXED",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const describeRegistry = new redpanda.SchemaRegistryAcl("describe_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "DESCRIBE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const alterConfigsRegistry = new redpanda.SchemaRegistryAcl("alter_configs_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "ALTER_CONFIGS",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const readRegistry = new redpanda.SchemaRegistryAcl("read_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "READ",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const writeRegistry = new redpanda.SchemaRegistryAcl("write_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "WRITE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const userSchema = new redpanda.Schema("user_schema", {
clusterId: testCluster.id,
subject: `${topicName}-value`,
schemaType: schemaType,
schema: userSchemaDefinition,
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const userEventSchema = new redpanda.Schema("user_event_schema", {
clusterId: testCluster.id,
subject: `${topicName}-events-value`,
schemaType: schemaType,
schema: userEventSchemaDefinition,
allowDeletion: true,
references: [{
name: "User",
subject: userSchema.subject,
version: userSchema.version,
}],
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const productSchema = new redpanda.Schema("product_schema", {
clusterId: testCluster.id,
subject: `${topicName}-product-value`,
schemaType: schemaType,
schema: productSchemaDefinition,
compatibility: compatibilityLevel,
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const developer = new redpanda.Role("developer", {
name: roleName,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: roleAllowDeletion,
});
const roleTopicRead = new redpanda.Acl("role_topic_read", {
resourceType: "TOPIC",
resourceName: testTopic.name,
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`RedpandaRole:${developer.name}`,
host: "*",
operation: "READ",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const readProduct = new redpanda.SchemaRegistryAcl("read_product", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: "product-",
patternType: "PREFIXED",
host: "*",
operation: "READ",
permission: "ALLOW",
allowDeletion: srAclAllowDeletion,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const writeOrders = new redpanda.SchemaRegistryAcl("write_orders", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: "orders-value",
patternType: "LITERAL",
host: "*",
operation: "WRITE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const developerAssignment = new redpanda.RoleAssignment("developer_assignment", {
roleName: developer.name,
principal: pulumi.interpolate`User:${testUser.name}`,
clusterApiUrl: testCluster.clusterApiUrl,
}, {
dependsOn: [testUser],
});
export const userSchemaInfo = {
id: userSchema.schemaId,
subject: userSchema.subject,
version: userSchema.version,
type: userSchema.schemaType,
};
export const userEventSchemaInfo = {
id: userEventSchema.schemaId,
subject: userEventSchema.subject,
version: userEventSchema.version,
type: userEventSchema.schemaType,
references: userEventSchema.references,
};
export const productSchemaInfo = {
id: productSchema.schemaId,
subject: productSchema.subject,
version: productSchema.version,
type: productSchema.schemaType,
compatibility: productSchema.compatibility,
};
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: python
import pulumi
import json
import pulumi_redpanda as redpanda
test = redpanda.ResourceGroup("test", name=resource_group_name)
test_network = redpanda.Network("test",
name=network_name,
resource_group_id=test.id,
cloud_provider=cloud_provider,
region=region,
cluster_type="dedicated",
cidr_block="10.0.0.0/20",
timeouts={
"create": "20m",
"delete": "20m",
})
test_cluster = redpanda.Cluster("test",
name=cluster_name,
resource_group_id=test.id,
network_id=test_network.id,
cloud_provider=cloud_provider,
region=region,
cluster_type="dedicated",
connection_type="public",
throughput_tier=throughput_tier,
zones=zones,
allow_deletion=cluster_allow_deletion,
cluster_configuration={
"custom_properties_json": json.dumps({
"enable_shadow_linking": cluster_enable_shadow_linking,
"schema_registry_enable_authorization": True,
}),
},
maintenance_window_config={
"day_hour": {
"day_of_week": maintenance_day_of_week,
"hour_of_day": maintenance_hour_of_day,
},
},
tags=cluster_tags,
timeouts={
"create": "90m",
})
test_user = redpanda.User("test",
name=user_name,
password=None if user_password_wo != None else user_pw,
password_wo=user_password_wo,
password_wo_version=user_password_wo_version,
mechanism=mechanism,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=user_allow_deletion)
test_topic = redpanda.Topic("test",
name=topic_name,
partition_count=partition_count,
replication_factor=replication_factor,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=True,
configuration=topic_configuration if topic_configuration != None else {
"cleanup.policy": "delete",
"retention.ms": topic_retention_ms,
},
opts = pulumi.ResourceOptions(depends_on=[test_user]))
# Bootstrap SR ACL grants for the provider's own Bearer-token principal.
# Two grants are required: the SUBJECT-scope grant authorizes
# POST /subjects/<subj>/versions; the REGISTRY-scope grant authorizes the
# follow-up GET /schemas/ids/<id>/versions that the SR client (franz-go) makes
# to fetch the full schema metadata after create. Without the REGISTRY grant,
# the schema is created but the follow-up GET 403s and the resource fails.
# User:* is broader than necessary; tighten once the exact principal is
# documented as discoverable.
provider_bootstrap_subject = redpanda.SchemaRegistryAcl("provider_bootstrap_subject",
cluster_id=test_cluster.id,
principal="User:*",
resource_type="SUBJECT",
resource_name_=topic_name,
pattern_type="PREFIXED",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
provider_bootstrap_registry = redpanda.SchemaRegistryAcl("provider_bootstrap_registry",
cluster_id=test_cluster.id,
principal="User:*",
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
cluster_admin = redpanda.Acl("cluster_admin",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALL",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
schema_registry_admin = redpanda.Acl("schema_registry_admin",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALTER",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
cluster_action = redpanda.Acl("cluster_action",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="CLUSTER_ACTION",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
topic_access = redpanda.Acl("topic_access",
resource_type="TOPIC",
resource_name_=test_topic.name,
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALL",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
all_test_topic = redpanda.SchemaRegistryAcl("all_test_topic",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_=f"{topic_name}-",
pattern_type="PREFIXED",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
describe_registry = redpanda.SchemaRegistryAcl("describe_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="DESCRIBE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
alter_configs_registry = redpanda.SchemaRegistryAcl("alter_configs_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="ALTER_CONFIGS",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
read_registry = redpanda.SchemaRegistryAcl("read_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="READ",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
write_registry = redpanda.SchemaRegistryAcl("write_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="WRITE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
user_schema = redpanda.Schema("user_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-value",
schema_type=schema_type,
schema=user_schema_definition,
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
user_event_schema = redpanda.Schema("user_event_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-events-value",
schema_type=schema_type,
schema=user_event_schema_definition,
allow_deletion=True,
references=[{
"name": "User",
"subject": user_schema.subject,
"version": user_schema.version,
}],
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
product_schema = redpanda.Schema("product_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-product-value",
schema_type=schema_type,
schema=product_schema_definition,
compatibility=compatibility_level,
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
developer = redpanda.Role("developer",
name=role_name,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=role_allow_deletion)
role_topic_read = redpanda.Acl("role_topic_read",
resource_type="TOPIC",
resource_name_=test_topic.name,
resource_pattern_type="LITERAL",
principal=developer.name.apply(lambda name: f"RedpandaRole:{name}"),
host="*",
operation="READ",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
read_product = redpanda.SchemaRegistryAcl("read_product",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_="product-",
pattern_type="PREFIXED",
host="*",
operation="READ",
permission="ALLOW",
allow_deletion=sr_acl_allow_deletion,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
write_orders = redpanda.SchemaRegistryAcl("write_orders",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_="orders-value",
pattern_type="LITERAL",
host="*",
operation="WRITE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
developer_assignment = redpanda.RoleAssignment("developer_assignment",
role_name=developer.name,
principal=test_user.name.apply(lambda name: f"User:{name}"),
cluster_api_url=test_cluster.cluster_api_url,
opts = pulumi.ResourceOptions(depends_on=[test_user]))
pulumi.export("userSchemaInfo", {
"id": user_schema.schema_id,
"subject": user_schema.subject,
"version": user_schema.version,
"type": user_schema.schema_type,
})
pulumi.export("userEventSchemaInfo", {
"id": user_event_schema.schema_id,
"subject": user_event_schema.subject,
"version": user_event_schema.version,
"type": user_event_schema.schema_type,
"references": user_event_schema.references,
})
pulumi.export("productSchemaInfo", {
"id": product_schema.schema_id,
"subject": product_schema.subject,
"version": product_schema.version,
"type": product_schema.schema_type,
"compatibility": product_schema.compatibility,
})
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: dotnet
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Redpanda = Pulumi.Redpanda;
return await Deployment.RunAsync(() =>
{
var test = new Redpanda.ResourceGroup("test", new()
{
Name = resourceGroupName,
});
var testNetwork = new Redpanda.Network("test", new()
{
Name = networkName,
ResourceGroupId = test.Id,
CloudProvider = cloudProvider,
Region = region,
ClusterType = "dedicated",
CidrBlock = "10.0.0.0/20",
Timeouts = new Redpanda.Inputs.NetworkTimeoutsArgs
{
Create = "20m",
Delete = "20m",
},
});
var testCluster = new Redpanda.Cluster("test", new()
{
Name = clusterName,
ResourceGroupId = test.Id,
NetworkId = testNetwork.Id,
CloudProvider = cloudProvider,
Region = region,
ClusterType = "dedicated",
ConnectionType = "public",
ThroughputTier = throughputTier,
Zones = zones,
AllowDeletion = clusterAllowDeletion,
ClusterConfiguration = new Redpanda.Inputs.ClusterClusterConfigurationArgs
{
CustomPropertiesJson = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["enable_shadow_linking"] = clusterEnableShadowLinking,
["schema_registry_enable_authorization"] = true,
}),
},
MaintenanceWindowConfig = new Redpanda.Inputs.ClusterMaintenanceWindowConfigArgs
{
DayHour = new Redpanda.Inputs.ClusterMaintenanceWindowConfigDayHourArgs
{
DayOfWeek = maintenanceDayOfWeek,
HourOfDay = maintenanceHourOfDay,
},
},
Tags = clusterTags,
Timeouts = new Redpanda.Inputs.ClusterTimeoutsArgs
{
Create = "90m",
},
});
var testUser = new Redpanda.User("test", new()
{
Name = userName,
Password = userPasswordWo != null ? null : userPw,
PasswordWo = userPasswordWo,
PasswordWoVersion = userPasswordWoVersion,
Mechanism = mechanism,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = userAllowDeletion,
});
var testTopic = new Redpanda.Topic("test", new()
{
Name = topicName,
PartitionCount = partitionCount,
ReplicationFactor = replicationFactor,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = true,
Configuration = topicConfiguration != null ? topicConfiguration :
{
{ "cleanup.policy", "delete" },
{ "retention.ms", topicRetentionMs },
},
}, new CustomResourceOptions
{
DependsOn =
{
testUser,
},
});
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// Two grants are required: the SUBJECT-scope grant authorizes
// POST /subjects/<subj>/versions; the REGISTRY-scope grant authorizes the
// follow-up GET /schemas/ids/<id>/versions that the SR client (franz-go) makes
// to fetch the full schema metadata after create. Without the REGISTRY grant,
// the schema is created but the follow-up GET 403s and the resource fails.
// User:* is broader than necessary; tighten once the exact principal is
// documented as discoverable.
var providerBootstrapSubject = new Redpanda.SchemaRegistryAcl("provider_bootstrap_subject", new()
{
ClusterId = testCluster.Id,
Principal = "User:*",
ResourceType = "SUBJECT",
ResourceName = topicName,
PatternType = "PREFIXED",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var providerBootstrapRegistry = new Redpanda.SchemaRegistryAcl("provider_bootstrap_registry", new()
{
ClusterId = testCluster.Id,
Principal = "User:*",
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var clusterAdmin = new Redpanda.Acl("cluster_admin", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALL",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var schemaRegistryAdmin = new Redpanda.Acl("schema_registry_admin", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALTER",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var clusterAction = new Redpanda.Acl("cluster_action", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "CLUSTER_ACTION",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var topicAccess = new Redpanda.Acl("topic_access", new()
{
ResourceType = "TOPIC",
ResourceName = testTopic.Name,
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALL",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var allTestTopic = new Redpanda.SchemaRegistryAcl("all_test_topic", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = $"{topicName}-",
PatternType = "PREFIXED",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var describeRegistry = new Redpanda.SchemaRegistryAcl("describe_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "DESCRIBE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var alterConfigsRegistry = new Redpanda.SchemaRegistryAcl("alter_configs_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "ALTER_CONFIGS",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var readRegistry = new Redpanda.SchemaRegistryAcl("read_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "READ",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var writeRegistry = new Redpanda.SchemaRegistryAcl("write_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "WRITE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var userSchema = new Redpanda.Schema("user_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-value",
SchemaType = schemaType,
Schema = userSchemaDefinition,
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var userEventSchema = new Redpanda.Schema("user_event_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-events-value",
SchemaType = schemaType,
Schema = userEventSchemaDefinition,
AllowDeletion = true,
References = new[]
{
new Redpanda.Inputs.SchemaReferenceArgs
{
Name = "User",
Subject = userSchema.Subject,
Version = userSchema.Version,
},
},
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var productSchema = new Redpanda.Schema("product_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-product-value",
SchemaType = schemaType,
Schema = productSchemaDefinition,
Compatibility = compatibilityLevel,
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var developer = new Redpanda.Role("developer", new()
{
Name = roleName,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = roleAllowDeletion,
});
var roleTopicRead = new Redpanda.Acl("role_topic_read", new()
{
ResourceType = "TOPIC",
ResourceName = testTopic.Name,
ResourcePatternType = "LITERAL",
Principal = developer.Name.Apply(name => $"RedpandaRole:{name}"),
Host = "*",
Operation = "READ",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var readProduct = new Redpanda.SchemaRegistryAcl("read_product", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = "product-",
PatternType = "PREFIXED",
Host = "*",
Operation = "READ",
Permission = "ALLOW",
AllowDeletion = srAclAllowDeletion,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var writeOrders = new Redpanda.SchemaRegistryAcl("write_orders", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = "orders-value",
PatternType = "LITERAL",
Host = "*",
Operation = "WRITE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var developerAssignment = new Redpanda.RoleAssignment("developer_assignment", new()
{
RoleName = developer.Name,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ClusterApiUrl = testCluster.ClusterApiUrl,
}, new CustomResourceOptions
{
DependsOn =
{
testUser,
},
});
return new Dictionary<string, object?>
{
["userSchemaInfo"] =
{
{ "id", userSchema.SchemaId },
{ "subject", userSchema.Subject },
{ "version", userSchema.Version },
{ "type", userSchema.SchemaType },
},
["userEventSchemaInfo"] =
{
{ "id", userEventSchema.SchemaId },
{ "subject", userEventSchema.Subject },
{ "version", userEventSchema.Version },
{ "type", userEventSchema.SchemaType },
{ "references", userEventSchema.References },
},
["productSchemaInfo"] =
{
{ "id", productSchema.SchemaId },
{ "subject", productSchema.Subject },
{ "version", productSchema.Version },
{ "type", productSchema.SchemaType },
{ "compatibility", productSchema.Compatibility },
},
};
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: go
package main
import (
"encoding/json"
"fmt"
"github.com/pulumi/pulumi-pulumi-provider/sdks/go/redpanda/v2/redpanda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := redpanda.NewResourceGroup(ctx, "test", &redpanda.ResourceGroupArgs{
Name: pulumi.Any(resourceGroupName),
})
if err != nil {
return err
}
testNetwork, err := redpanda.NewNetwork(ctx, "test", &redpanda.NetworkArgs{
Name: pulumi.Any(networkName),
ResourceGroupId: test.ID(),
CloudProvider: pulumi.Any(cloudProvider),
Region: pulumi.Any(region),
ClusterType: pulumi.String("dedicated"),
CidrBlock: pulumi.String("10.0.0.0/20"),
Timeouts: &redpanda.NetworkTimeoutsArgs{
Create: pulumi.String("20m"),
Delete: pulumi.String("20m"),
},
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"enable_shadow_linking": clusterEnableShadowLinking,
"schema_registry_enable_authorization": true,
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
testCluster, err := redpanda.NewCluster(ctx, "test", &redpanda.ClusterArgs{
Name: pulumi.Any(clusterName),
ResourceGroupId: test.ID(),
NetworkId: testNetwork.ID(),
CloudProvider: pulumi.Any(cloudProvider),
Region: pulumi.Any(region),
ClusterType: pulumi.String("dedicated"),
ConnectionType: pulumi.String("public"),
ThroughputTier: pulumi.Any(throughputTier),
Zones: pulumi.Any(zones),
AllowDeletion: pulumi.Any(clusterAllowDeletion),
ClusterConfiguration: &redpanda.ClusterClusterConfigurationArgs{
CustomPropertiesJson: pulumi.String(json0),
},
MaintenanceWindowConfig: &redpanda.ClusterMaintenanceWindowConfigArgs{
DayHour: &redpanda.ClusterMaintenanceWindowConfigDayHourArgs{
DayOfWeek: pulumi.Any(maintenanceDayOfWeek),
HourOfDay: pulumi.Any(maintenanceHourOfDay),
},
},
Tags: pulumi.Any(clusterTags),
Timeouts: &redpanda.ClusterTimeoutsArgs{
Create: pulumi.String("90m"),
},
})
if err != nil {
return err
}
var tmp0 pulumi.String
if userPasswordWo != nil {
tmp0 = nil
} else {
tmp0 = pulumi.Any(userPw)
}
testUser, err := redpanda.NewUser(ctx, "test", &redpanda.UserArgs{
Name: pulumi.Any(userName),
Password: pulumi.String(tmp0),
PasswordWo: pulumi.Any(userPasswordWo),
PasswordWoVersion: pulumi.Any(userPasswordWoVersion),
Mechanism: pulumi.Any(mechanism),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(userAllowDeletion),
})
if err != nil {
return err
}
var tmp1 pulumi.StringMap
if topicConfiguration != nil {
tmp1 = pulumi.Any(topicConfiguration)
} else {
tmp1 = pulumi.StringMap{
"cleanup.policy": pulumi.String("delete"),
"retention.ms": pulumi.Any(topicRetentionMs),
}
}
testTopic, err := redpanda.NewTopic(ctx, "test", &redpanda.TopicArgs{
Name: pulumi.Any(topicName),
PartitionCount: pulumi.Any(partitionCount),
ReplicationFactor: pulumi.Any(replicationFactor),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Bool(true),
Configuration: pulumi.StringMap(tmp1),
}, pulumi.DependsOn([]pulumi.Resource{
testUser,
}))
if err != nil {
return err
}
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// Two grants are required: the SUBJECT-scope grant authorizes
// POST /subjects/<subj>/versions; the REGISTRY-scope grant authorizes the
// follow-up GET /schemas/ids/<id>/versions that the SR client (franz-go) makes
// to fetch the full schema metadata after create. Without the REGISTRY grant,
// the schema is created but the follow-up GET 403s and the resource fails.
// User:* is broader than necessary; tighten once the exact principal is
// documented as discoverable.
providerBootstrapSubject, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_subject", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Any(topicName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
providerBootstrapRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
clusterAdmin, err := redpanda.NewAcl(ctx, "cluster_admin", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
schemaRegistryAdmin, err := redpanda.NewAcl(ctx, "schema_registry_admin", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALTER"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
clusterAction, err := redpanda.NewAcl(ctx, "cluster_action", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("CLUSTER_ACTION"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
topicAccess, err := redpanda.NewAcl(ctx, "topic_access", &redpanda.AclArgs{
ResourceType: pulumi.String("TOPIC"),
ResourceName: testTopic.Name,
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
allTestTopic, err := redpanda.NewSchemaRegistryAcl(ctx, "all_test_topic", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Sprintf("%v-", topicName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
describeRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "describe_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("DESCRIBE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
alterConfigsRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "alter_configs_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALTER_CONFIGS"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
readRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "read_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
writeRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "write_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("WRITE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
userSchema, err := redpanda.NewSchema(ctx, "user_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(userSchemaDefinition),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
userEventSchema, err := redpanda.NewSchema(ctx, "user_event_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-events-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(userEventSchemaDefinition),
AllowDeletion: pulumi.Bool(true),
References: redpanda.SchemaReferenceArray{
&redpanda.SchemaReferenceArgs{
Name: pulumi.String("User"),
Subject: userSchema.Subject,
Version: userSchema.Version,
},
},
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
productSchema, err := redpanda.NewSchema(ctx, "product_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-product-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(productSchemaDefinition),
Compatibility: pulumi.Any(compatibilityLevel),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
developer, err := redpanda.NewRole(ctx, "developer", &redpanda.RoleArgs{
Name: pulumi.Any(roleName),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(roleAllowDeletion),
})
if err != nil {
return err
}
_, err = redpanda.NewAcl(ctx, "role_topic_read", &redpanda.AclArgs{
ResourceType: pulumi.String("TOPIC"),
ResourceName: testTopic.Name,
ResourcePatternType: pulumi.String("LITERAL"),
Principal: developer.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("RedpandaRole:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
_, err = redpanda.NewSchemaRegistryAcl(ctx, "read_product", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.String("product-"),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Any(srAclAllowDeletion),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
_, err = redpanda.NewSchemaRegistryAcl(ctx, "write_orders", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.String("orders-value"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("WRITE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
_, err = redpanda.NewRoleAssignment(ctx, "developer_assignment", &redpanda.RoleAssignmentArgs{
RoleName: developer.Name,
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ClusterApiUrl: testCluster.ClusterApiUrl,
}, pulumi.DependsOn([]pulumi.Resource{
testUser,
}))
if err != nil {
return err
}
ctx.Export("userSchemaInfo", pulumi.Map{
"id": userSchema.SchemaId,
"subject": userSchema.Subject,
"version": userSchema.Version,
"type": userSchema.SchemaType,
})
ctx.Export("userEventSchemaInfo", pulumi.Map{
"id": userEventSchema.SchemaId,
"subject": userEventSchema.Subject,
"version": userEventSchema.Version,
"type": userEventSchema.SchemaType,
"references": userEventSchema.References,
})
ctx.Export("productSchemaInfo", pulumi.Map{
"id": productSchema.SchemaId,
"subject": productSchema.Subject,
"version": productSchema.Version,
"type": productSchema.SchemaType,
"compatibility": productSchema.Compatibility,
})
return nil
})
}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: yaml
Example currently unavailable in this language
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: java
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.redpanda.ResourceGroup;
import com.pulumi.redpanda.ResourceGroupArgs;
import com.pulumi.redpanda.Network;
import com.pulumi.redpanda.NetworkArgs;
import com.pulumi.redpanda.inputs.NetworkTimeoutsArgs;
import com.pulumi.redpanda.Cluster;
import com.pulumi.redpanda.ClusterArgs;
import com.pulumi.redpanda.inputs.ClusterClusterConfigurationArgs;
import com.pulumi.redpanda.inputs.ClusterMaintenanceWindowConfigArgs;
import com.pulumi.redpanda.inputs.ClusterMaintenanceWindowConfigDayHourArgs;
import com.pulumi.redpanda.inputs.ClusterTimeoutsArgs;
import com.pulumi.redpanda.User;
import com.pulumi.redpanda.UserArgs;
import com.pulumi.redpanda.Topic;
import com.pulumi.redpanda.TopicArgs;
import com.pulumi.redpanda.SchemaRegistryAcl;
import com.pulumi.redpanda.SchemaRegistryAclArgs;
import com.pulumi.redpanda.Acl;
import com.pulumi.redpanda.AclArgs;
import com.pulumi.redpanda.Schema;
import com.pulumi.redpanda.SchemaArgs;
import com.pulumi.redpanda.inputs.SchemaReferenceArgs;
import com.pulumi.redpanda.Role;
import com.pulumi.redpanda.RoleArgs;
import com.pulumi.redpanda.RoleAssignment;
import com.pulumi.redpanda.RoleAssignmentArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import com.pulumi.resources.CustomResourceOptions;
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 test = new ResourceGroup("test", ResourceGroupArgs.builder()
.name(resourceGroupName)
.build());
var testNetwork = new Network("testNetwork", NetworkArgs.builder()
.name(networkName)
.resourceGroupId(test.id())
.cloudProvider(cloudProvider)
.region(region)
.clusterType("dedicated")
.cidrBlock("10.0.0.0/20")
.timeouts(NetworkTimeoutsArgs.builder()
.create("20m")
.delete("20m")
.build())
.build());
var testCluster = new Cluster("testCluster", ClusterArgs.builder()
.name(clusterName)
.resourceGroupId(test.id())
.networkId(testNetwork.id())
.cloudProvider(cloudProvider)
.region(region)
.clusterType("dedicated")
.connectionType("public")
.throughputTier(throughputTier)
.zones(zones)
.allowDeletion(clusterAllowDeletion)
.clusterConfiguration(ClusterClusterConfigurationArgs.builder()
.customPropertiesJson(serializeJson(
jsonObject(
jsonProperty("enable_shadow_linking", clusterEnableShadowLinking),
jsonProperty("schema_registry_enable_authorization", true)
)))
.build())
.maintenanceWindowConfig(ClusterMaintenanceWindowConfigArgs.builder()
.dayHour(ClusterMaintenanceWindowConfigDayHourArgs.builder()
.dayOfWeek(maintenanceDayOfWeek)
.hourOfDay(maintenanceHourOfDay)
.build())
.build())
.tags(clusterTags)
.timeouts(ClusterTimeoutsArgs.builder()
.create("90m")
.build())
.build());
var testUser = new User("testUser", UserArgs.builder()
.name(userName)
.password(userPasswordWo != null ? null : userPw)
.passwordWo(userPasswordWo)
.passwordWoVersion(userPasswordWoVersion)
.mechanism(mechanism)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(userAllowDeletion)
.build());
var testTopic = new Topic("testTopic", TopicArgs.builder()
.name(topicName)
.partitionCount(partitionCount)
.replicationFactor(replicationFactor)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(true)
.configuration(topicConfiguration != null ? topicConfiguration : Map.ofEntries(
Map.entry("cleanup.policy", "delete"),
Map.entry("retention.ms", topicRetentionMs)
))
.build(), CustomResourceOptions.builder()
.dependsOn(testUser)
.build());
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// Two grants are required: the SUBJECT-scope grant authorizes
// POST /subjects/<subj>/versions; the REGISTRY-scope grant authorizes the
// follow-up GET /schemas/ids/<id>/versions that the SR client (franz-go) makes
// to fetch the full schema metadata after create. Without the REGISTRY grant,
// the schema is created but the follow-up GET 403s and the resource fails.
// User:* is broader than necessary; tighten once the exact principal is
// documented as discoverable.
var providerBootstrapSubject = new SchemaRegistryAcl("providerBootstrapSubject", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal("User:*")
.resourceType("SUBJECT")
.resourceName(topicName)
.patternType("PREFIXED")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var providerBootstrapRegistry = new SchemaRegistryAcl("providerBootstrapRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal("User:*")
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var clusterAdmin = new Acl("clusterAdmin", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALL")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var schemaRegistryAdmin = new Acl("schemaRegistryAdmin", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALTER")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var clusterAction = new Acl("clusterAction", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("CLUSTER_ACTION")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var topicAccess = new Acl("topicAccess", AclArgs.builder()
.resourceType("TOPIC")
.resourceName(testTopic.name())
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALL")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var allTestTopic = new SchemaRegistryAcl("allTestTopic", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName(String.format("%s-", topicName))
.patternType("PREFIXED")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var describeRegistry = new SchemaRegistryAcl("describeRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("DESCRIBE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var alterConfigsRegistry = new SchemaRegistryAcl("alterConfigsRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("ALTER_CONFIGS")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var readRegistry = new SchemaRegistryAcl("readRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("READ")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var writeRegistry = new SchemaRegistryAcl("writeRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("WRITE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var userSchema = new Schema("userSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-value", topicName))
.schemaType(schemaType)
.schema(userSchemaDefinition)
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var userEventSchema = new Schema("userEventSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-events-value", topicName))
.schemaType(schemaType)
.schema(userEventSchemaDefinition)
.allowDeletion(true)
.references(SchemaReferenceArgs.builder()
.name("User")
.subject(userSchema.subject())
.version(userSchema.version())
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var productSchema = new Schema("productSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-product-value", topicName))
.schemaType(schemaType)
.schema(productSchemaDefinition)
.compatibility(compatibilityLevel)
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var developer = new Role("developer", RoleArgs.builder()
.name(roleName)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(roleAllowDeletion)
.build());
var roleTopicRead = new Acl("roleTopicRead", AclArgs.builder()
.resourceType("TOPIC")
.resourceName(testTopic.name())
.resourcePatternType("LITERAL")
.principal(developer.name().applyValue(_name -> String.format("RedpandaRole:%s", _name)))
.host("*")
.operation("READ")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var readProduct = new SchemaRegistryAcl("readProduct", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName("product-")
.patternType("PREFIXED")
.host("*")
.operation("READ")
.permission("ALLOW")
.allowDeletion(srAclAllowDeletion)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var writeOrders = new SchemaRegistryAcl("writeOrders", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName("orders-value")
.patternType("LITERAL")
.host("*")
.operation("WRITE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var developerAssignment = new RoleAssignment("developerAssignment", RoleAssignmentArgs.builder()
.roleName(developer.name())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.clusterApiUrl(testCluster.clusterApiUrl())
.build(), CustomResourceOptions.builder()
.dependsOn(testUser)
.build());
ctx.export("userSchemaInfo", Map.ofEntries(
Map.entry("id", userSchema.schemaId()),
Map.entry("subject", userSchema.subject()),
Map.entry("version", userSchema.version()),
Map.entry("type", userSchema.schemaType())
));
ctx.export("userEventSchemaInfo", Map.ofEntries(
Map.entry("id", userEventSchema.schemaId()),
Map.entry("subject", userEventSchema.subject()),
Map.entry("version", userEventSchema.version()),
Map.entry("type", userEventSchema.schemaType()),
Map.entry("references", userEventSchema.references())
));
ctx.export("productSchemaInfo", Map.ofEntries(
Map.entry("id", productSchema.schemaId()),
Map.entry("subject", productSchema.subject()),
Map.entry("version", productSchema.version()),
Map.entry("type", productSchema.schemaType()),
Map.entry("compatibility", productSchema.compatibility())
));
}
}
Example Usage for a GCP Dedicated Cluster
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: nodejs
import * as pulumi from "@pulumi/pulumi";
import * as redpanda from "@pulumi/redpanda";
const test = new redpanda.ResourceGroup("test", {name: resourceGroupName});
const testNetwork = new redpanda.Network("test", {
name: networkName,
resourceGroupId: test.id,
cloudProvider: cloudProvider,
region: region,
clusterType: "dedicated",
cidrBlock: "10.0.0.0/20",
timeouts: {
create: "20m",
"delete": "20m",
},
});
const testCluster = new redpanda.Cluster("test", {
name: clusterName,
resourceGroupId: test.id,
networkId: testNetwork.id,
cloudProvider: cloudProvider,
region: region,
clusterType: "dedicated",
connectionType: "public",
throughputTier: throughputTier,
zones: zones,
allowDeletion: clusterAllowDeletion,
clusterConfiguration: {
customPropertiesJson: JSON.stringify({
enable_shadow_linking: clusterEnableShadowLinking,
schema_registry_enable_authorization: true,
}),
},
maintenanceWindowConfig: {
dayHour: {
dayOfWeek: maintenanceDayOfWeek,
hourOfDay: maintenanceHourOfDay,
},
},
tags: clusterTags,
timeouts: {
create: "90m",
},
});
const testUser = new redpanda.User("test", {
name: userName,
password: userPw,
mechanism: mechanism,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: userAllowDeletion,
});
const testTopic = new redpanda.Topic("test", {
name: topicName,
partitionCount: partitionCount,
replicationFactor: replicationFactor,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: true,
configuration: topicConfiguration != null ? topicConfiguration : {
"cleanup.policy": "delete",
"retention.ms": topicRetentionMs,
},
}, {
dependsOn: [testUser],
});
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// SUBJECT grant authorizes POST /subjects/<subj>/versions; REGISTRY grant
// authorizes the franz-go follow-up GET /schemas/ids/<id>/versions.
const providerBootstrapSubject = new redpanda.SchemaRegistryAcl("provider_bootstrap_subject", {
clusterId: testCluster.id,
principal: "User:*",
resourceType: "SUBJECT",
resourceName: topicName,
patternType: "PREFIXED",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const providerBootstrapRegistry = new redpanda.SchemaRegistryAcl("provider_bootstrap_registry", {
clusterId: testCluster.id,
principal: "User:*",
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const clusterAdmin = new redpanda.Acl("cluster_admin", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALL",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const schemaRegistryAdmin = new redpanda.Acl("schema_registry_admin", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALTER",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const clusterAction = new redpanda.Acl("cluster_action", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "CLUSTER_ACTION",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const topicAccess = new redpanda.Acl("topic_access", {
resourceType: "TOPIC",
resourceName: testTopic.name,
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALL",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const allTestTopic = new redpanda.SchemaRegistryAcl("all_test_topic", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: `${topicName}-`,
patternType: "PREFIXED",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const describeRegistry = new redpanda.SchemaRegistryAcl("describe_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "DESCRIBE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const alterConfigsRegistry = new redpanda.SchemaRegistryAcl("alter_configs_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "ALTER_CONFIGS",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const readRegistry = new redpanda.SchemaRegistryAcl("read_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "READ",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const writeRegistry = new redpanda.SchemaRegistryAcl("write_registry", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "WRITE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const userSchema = new redpanda.Schema("user_schema", {
clusterId: testCluster.id,
subject: `${topicName}-value`,
schemaType: schemaType,
schema: userSchemaDefinition,
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const userEventSchema = new redpanda.Schema("user_event_schema", {
clusterId: testCluster.id,
subject: `${topicName}-events-value`,
schemaType: schemaType,
schema: userEventSchemaDefinition,
allowDeletion: true,
references: [{
name: "User",
subject: userSchema.subject,
version: userSchema.version,
}],
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const productSchema = new redpanda.Schema("product_schema", {
clusterId: testCluster.id,
subject: `${topicName}-product-value`,
schemaType: schemaType,
schema: productSchemaDefinition,
compatibility: compatibilityLevel,
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
],
});
const developer = new redpanda.Role("developer", {
name: roleName,
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: roleAllowDeletion,
});
const roleTopicRead = new redpanda.Acl("role_topic_read", {
resourceType: "TOPIC",
resourceName: testTopic.name,
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`RedpandaRole:${developer.name}`,
host: "*",
operation: "READ",
permissionType: "ALLOW",
clusterApiUrl: testCluster.clusterApiUrl,
allowDeletion: aclAllowDeletion,
});
const readProduct = new redpanda.SchemaRegistryAcl("read_product", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: "product-",
patternType: "PREFIXED",
host: "*",
operation: "READ",
permission: "ALLOW",
allowDeletion: srAclAllowDeletion,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const writeOrders = new redpanda.SchemaRegistryAcl("write_orders", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: "orders-value",
patternType: "LITERAL",
host: "*",
operation: "WRITE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const describeTestTopic = new redpanda.SchemaRegistryAcl("describe_test_topic", {
clusterId: testCluster.id,
principal: pulumi.interpolate`User:${testUser.name}`,
resourceType: "SUBJECT",
resourceName: `${topicName}-`,
patternType: "PREFIXED",
host: "*",
operation: "DESCRIBE",
permission: "ALLOW",
allowDeletion: true,
}, {
dependsOn: [
clusterAdmin,
schemaRegistryAdmin,
],
});
const developerAssignment = new redpanda.RoleAssignment("developer_assignment", {
roleName: developer.name,
principal: pulumi.interpolate`User:${testUser.name}`,
clusterApiUrl: testCluster.clusterApiUrl,
}, {
dependsOn: [testUser],
});
export const userSchemaInfo = {
id: userSchema.schemaId,
subject: userSchema.subject,
version: userSchema.version,
type: userSchema.schemaType,
};
export const userEventSchemaInfo = {
id: userEventSchema.schemaId,
subject: userEventSchema.subject,
version: userEventSchema.version,
type: userEventSchema.schemaType,
references: userEventSchema.references,
};
export const productSchemaInfo = {
id: productSchema.schemaId,
subject: productSchema.subject,
version: productSchema.version,
type: productSchema.schemaType,
compatibility: productSchema.compatibility,
};
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: python
import pulumi
import json
import pulumi_redpanda as redpanda
test = redpanda.ResourceGroup("test", name=resource_group_name)
test_network = redpanda.Network("test",
name=network_name,
resource_group_id=test.id,
cloud_provider=cloud_provider,
region=region,
cluster_type="dedicated",
cidr_block="10.0.0.0/20",
timeouts={
"create": "20m",
"delete": "20m",
})
test_cluster = redpanda.Cluster("test",
name=cluster_name,
resource_group_id=test.id,
network_id=test_network.id,
cloud_provider=cloud_provider,
region=region,
cluster_type="dedicated",
connection_type="public",
throughput_tier=throughput_tier,
zones=zones,
allow_deletion=cluster_allow_deletion,
cluster_configuration={
"custom_properties_json": json.dumps({
"enable_shadow_linking": cluster_enable_shadow_linking,
"schema_registry_enable_authorization": True,
}),
},
maintenance_window_config={
"day_hour": {
"day_of_week": maintenance_day_of_week,
"hour_of_day": maintenance_hour_of_day,
},
},
tags=cluster_tags,
timeouts={
"create": "90m",
})
test_user = redpanda.User("test",
name=user_name,
password=user_pw,
mechanism=mechanism,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=user_allow_deletion)
test_topic = redpanda.Topic("test",
name=topic_name,
partition_count=partition_count,
replication_factor=replication_factor,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=True,
configuration=topic_configuration if topic_configuration != None else {
"cleanup.policy": "delete",
"retention.ms": topic_retention_ms,
},
opts = pulumi.ResourceOptions(depends_on=[test_user]))
# Bootstrap SR ACL grants for the provider's own Bearer-token principal.
# SUBJECT grant authorizes POST /subjects/<subj>/versions; REGISTRY grant
# authorizes the franz-go follow-up GET /schemas/ids/<id>/versions.
provider_bootstrap_subject = redpanda.SchemaRegistryAcl("provider_bootstrap_subject",
cluster_id=test_cluster.id,
principal="User:*",
resource_type="SUBJECT",
resource_name_=topic_name,
pattern_type="PREFIXED",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
provider_bootstrap_registry = redpanda.SchemaRegistryAcl("provider_bootstrap_registry",
cluster_id=test_cluster.id,
principal="User:*",
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
cluster_admin = redpanda.Acl("cluster_admin",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALL",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
schema_registry_admin = redpanda.Acl("schema_registry_admin",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALTER",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
cluster_action = redpanda.Acl("cluster_action",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="CLUSTER_ACTION",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
topic_access = redpanda.Acl("topic_access",
resource_type="TOPIC",
resource_name_=test_topic.name,
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALL",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
all_test_topic = redpanda.SchemaRegistryAcl("all_test_topic",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_=f"{topic_name}-",
pattern_type="PREFIXED",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
describe_registry = redpanda.SchemaRegistryAcl("describe_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="DESCRIBE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
alter_configs_registry = redpanda.SchemaRegistryAcl("alter_configs_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="ALTER_CONFIGS",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
read_registry = redpanda.SchemaRegistryAcl("read_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="READ",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
write_registry = redpanda.SchemaRegistryAcl("write_registry",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="WRITE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
user_schema = redpanda.Schema("user_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-value",
schema_type=schema_type,
schema=user_schema_definition,
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
user_event_schema = redpanda.Schema("user_event_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-events-value",
schema_type=schema_type,
schema=user_event_schema_definition,
allow_deletion=True,
references=[{
"name": "User",
"subject": user_schema.subject,
"version": user_schema.version,
}],
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
product_schema = redpanda.Schema("product_schema",
cluster_id=test_cluster.id,
subject=f"{topic_name}-product-value",
schema_type=schema_type,
schema=product_schema_definition,
compatibility=compatibility_level,
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
cluster_action,
topic_access,
provider_bootstrap_subject,
provider_bootstrap_registry,
all_test_topic,
describe_registry,
alter_configs_registry,
read_registry,
write_registry,
]))
developer = redpanda.Role("developer",
name=role_name,
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=role_allow_deletion)
role_topic_read = redpanda.Acl("role_topic_read",
resource_type="TOPIC",
resource_name_=test_topic.name,
resource_pattern_type="LITERAL",
principal=developer.name.apply(lambda name: f"RedpandaRole:{name}"),
host="*",
operation="READ",
permission_type="ALLOW",
cluster_api_url=test_cluster.cluster_api_url,
allow_deletion=acl_allow_deletion)
read_product = redpanda.SchemaRegistryAcl("read_product",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_="product-",
pattern_type="PREFIXED",
host="*",
operation="READ",
permission="ALLOW",
allow_deletion=sr_acl_allow_deletion,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
write_orders = redpanda.SchemaRegistryAcl("write_orders",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_="orders-value",
pattern_type="LITERAL",
host="*",
operation="WRITE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
describe_test_topic = redpanda.SchemaRegistryAcl("describe_test_topic",
cluster_id=test_cluster.id,
principal=test_user.name.apply(lambda name: f"User:{name}"),
resource_type="SUBJECT",
resource_name_=f"{topic_name}-",
pattern_type="PREFIXED",
host="*",
operation="DESCRIBE",
permission="ALLOW",
allow_deletion=True,
opts = pulumi.ResourceOptions(depends_on=[
cluster_admin,
schema_registry_admin,
]))
developer_assignment = redpanda.RoleAssignment("developer_assignment",
role_name=developer.name,
principal=test_user.name.apply(lambda name: f"User:{name}"),
cluster_api_url=test_cluster.cluster_api_url,
opts = pulumi.ResourceOptions(depends_on=[test_user]))
pulumi.export("userSchemaInfo", {
"id": user_schema.schema_id,
"subject": user_schema.subject,
"version": user_schema.version,
"type": user_schema.schema_type,
})
pulumi.export("userEventSchemaInfo", {
"id": user_event_schema.schema_id,
"subject": user_event_schema.subject,
"version": user_event_schema.version,
"type": user_event_schema.schema_type,
"references": user_event_schema.references,
})
pulumi.export("productSchemaInfo", {
"id": product_schema.schema_id,
"subject": product_schema.subject,
"version": product_schema.version,
"type": product_schema.schema_type,
"compatibility": product_schema.compatibility,
})
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: dotnet
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Redpanda = Pulumi.Redpanda;
return await Deployment.RunAsync(() =>
{
var test = new Redpanda.ResourceGroup("test", new()
{
Name = resourceGroupName,
});
var testNetwork = new Redpanda.Network("test", new()
{
Name = networkName,
ResourceGroupId = test.Id,
CloudProvider = cloudProvider,
Region = region,
ClusterType = "dedicated",
CidrBlock = "10.0.0.0/20",
Timeouts = new Redpanda.Inputs.NetworkTimeoutsArgs
{
Create = "20m",
Delete = "20m",
},
});
var testCluster = new Redpanda.Cluster("test", new()
{
Name = clusterName,
ResourceGroupId = test.Id,
NetworkId = testNetwork.Id,
CloudProvider = cloudProvider,
Region = region,
ClusterType = "dedicated",
ConnectionType = "public",
ThroughputTier = throughputTier,
Zones = zones,
AllowDeletion = clusterAllowDeletion,
ClusterConfiguration = new Redpanda.Inputs.ClusterClusterConfigurationArgs
{
CustomPropertiesJson = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["enable_shadow_linking"] = clusterEnableShadowLinking,
["schema_registry_enable_authorization"] = true,
}),
},
MaintenanceWindowConfig = new Redpanda.Inputs.ClusterMaintenanceWindowConfigArgs
{
DayHour = new Redpanda.Inputs.ClusterMaintenanceWindowConfigDayHourArgs
{
DayOfWeek = maintenanceDayOfWeek,
HourOfDay = maintenanceHourOfDay,
},
},
Tags = clusterTags,
Timeouts = new Redpanda.Inputs.ClusterTimeoutsArgs
{
Create = "90m",
},
});
var testUser = new Redpanda.User("test", new()
{
Name = userName,
Password = userPw,
Mechanism = mechanism,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = userAllowDeletion,
});
var testTopic = new Redpanda.Topic("test", new()
{
Name = topicName,
PartitionCount = partitionCount,
ReplicationFactor = replicationFactor,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = true,
Configuration = topicConfiguration != null ? topicConfiguration :
{
{ "cleanup.policy", "delete" },
{ "retention.ms", topicRetentionMs },
},
}, new CustomResourceOptions
{
DependsOn =
{
testUser,
},
});
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// SUBJECT grant authorizes POST /subjects/<subj>/versions; REGISTRY grant
// authorizes the franz-go follow-up GET /schemas/ids/<id>/versions.
var providerBootstrapSubject = new Redpanda.SchemaRegistryAcl("provider_bootstrap_subject", new()
{
ClusterId = testCluster.Id,
Principal = "User:*",
ResourceType = "SUBJECT",
ResourceName = topicName,
PatternType = "PREFIXED",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var providerBootstrapRegistry = new Redpanda.SchemaRegistryAcl("provider_bootstrap_registry", new()
{
ClusterId = testCluster.Id,
Principal = "User:*",
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var clusterAdmin = new Redpanda.Acl("cluster_admin", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALL",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var schemaRegistryAdmin = new Redpanda.Acl("schema_registry_admin", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALTER",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var clusterAction = new Redpanda.Acl("cluster_action", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "CLUSTER_ACTION",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var topicAccess = new Redpanda.Acl("topic_access", new()
{
ResourceType = "TOPIC",
ResourceName = testTopic.Name,
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALL",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var allTestTopic = new Redpanda.SchemaRegistryAcl("all_test_topic", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = $"{topicName}-",
PatternType = "PREFIXED",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var describeRegistry = new Redpanda.SchemaRegistryAcl("describe_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "DESCRIBE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var alterConfigsRegistry = new Redpanda.SchemaRegistryAcl("alter_configs_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "ALTER_CONFIGS",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var readRegistry = new Redpanda.SchemaRegistryAcl("read_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "READ",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var writeRegistry = new Redpanda.SchemaRegistryAcl("write_registry", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "WRITE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var userSchema = new Redpanda.Schema("user_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-value",
SchemaType = schemaType,
Schema = userSchemaDefinition,
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var userEventSchema = new Redpanda.Schema("user_event_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-events-value",
SchemaType = schemaType,
Schema = userEventSchemaDefinition,
AllowDeletion = true,
References = new[]
{
new Redpanda.Inputs.SchemaReferenceArgs
{
Name = "User",
Subject = userSchema.Subject,
Version = userSchema.Version,
},
},
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var productSchema = new Redpanda.Schema("product_schema", new()
{
ClusterId = testCluster.Id,
Subject = $"{topicName}-product-value",
SchemaType = schemaType,
Schema = productSchemaDefinition,
Compatibility = compatibilityLevel,
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
},
});
var developer = new Redpanda.Role("developer", new()
{
Name = roleName,
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = roleAllowDeletion,
});
var roleTopicRead = new Redpanda.Acl("role_topic_read", new()
{
ResourceType = "TOPIC",
ResourceName = testTopic.Name,
ResourcePatternType = "LITERAL",
Principal = developer.Name.Apply(name => $"RedpandaRole:{name}"),
Host = "*",
Operation = "READ",
PermissionType = "ALLOW",
ClusterApiUrl = testCluster.ClusterApiUrl,
AllowDeletion = aclAllowDeletion,
});
var readProduct = new Redpanda.SchemaRegistryAcl("read_product", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = "product-",
PatternType = "PREFIXED",
Host = "*",
Operation = "READ",
Permission = "ALLOW",
AllowDeletion = srAclAllowDeletion,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var writeOrders = new Redpanda.SchemaRegistryAcl("write_orders", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = "orders-value",
PatternType = "LITERAL",
Host = "*",
Operation = "WRITE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var describeTestTopic = new Redpanda.SchemaRegistryAcl("describe_test_topic", new()
{
ClusterId = testCluster.Id,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ResourceType = "SUBJECT",
ResourceName = $"{topicName}-",
PatternType = "PREFIXED",
Host = "*",
Operation = "DESCRIBE",
Permission = "ALLOW",
AllowDeletion = true,
}, new CustomResourceOptions
{
DependsOn =
{
clusterAdmin,
schemaRegistryAdmin,
},
});
var developerAssignment = new Redpanda.RoleAssignment("developer_assignment", new()
{
RoleName = developer.Name,
Principal = testUser.Name.Apply(name => $"User:{name}"),
ClusterApiUrl = testCluster.ClusterApiUrl,
}, new CustomResourceOptions
{
DependsOn =
{
testUser,
},
});
return new Dictionary<string, object?>
{
["userSchemaInfo"] =
{
{ "id", userSchema.SchemaId },
{ "subject", userSchema.Subject },
{ "version", userSchema.Version },
{ "type", userSchema.SchemaType },
},
["userEventSchemaInfo"] =
{
{ "id", userEventSchema.SchemaId },
{ "subject", userEventSchema.Subject },
{ "version", userEventSchema.Version },
{ "type", userEventSchema.SchemaType },
{ "references", userEventSchema.References },
},
["productSchemaInfo"] =
{
{ "id", productSchema.SchemaId },
{ "subject", productSchema.Subject },
{ "version", productSchema.Version },
{ "type", productSchema.SchemaType },
{ "compatibility", productSchema.Compatibility },
},
};
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: go
package main
import (
"encoding/json"
"fmt"
"github.com/pulumi/pulumi-pulumi-provider/sdks/go/redpanda/v2/redpanda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := redpanda.NewResourceGroup(ctx, "test", &redpanda.ResourceGroupArgs{
Name: pulumi.Any(resourceGroupName),
})
if err != nil {
return err
}
testNetwork, err := redpanda.NewNetwork(ctx, "test", &redpanda.NetworkArgs{
Name: pulumi.Any(networkName),
ResourceGroupId: test.ID(),
CloudProvider: pulumi.Any(cloudProvider),
Region: pulumi.Any(region),
ClusterType: pulumi.String("dedicated"),
CidrBlock: pulumi.String("10.0.0.0/20"),
Timeouts: &redpanda.NetworkTimeoutsArgs{
Create: pulumi.String("20m"),
Delete: pulumi.String("20m"),
},
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"enable_shadow_linking": clusterEnableShadowLinking,
"schema_registry_enable_authorization": true,
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
testCluster, err := redpanda.NewCluster(ctx, "test", &redpanda.ClusterArgs{
Name: pulumi.Any(clusterName),
ResourceGroupId: test.ID(),
NetworkId: testNetwork.ID(),
CloudProvider: pulumi.Any(cloudProvider),
Region: pulumi.Any(region),
ClusterType: pulumi.String("dedicated"),
ConnectionType: pulumi.String("public"),
ThroughputTier: pulumi.Any(throughputTier),
Zones: pulumi.Any(zones),
AllowDeletion: pulumi.Any(clusterAllowDeletion),
ClusterConfiguration: &redpanda.ClusterClusterConfigurationArgs{
CustomPropertiesJson: pulumi.String(json0),
},
MaintenanceWindowConfig: &redpanda.ClusterMaintenanceWindowConfigArgs{
DayHour: &redpanda.ClusterMaintenanceWindowConfigDayHourArgs{
DayOfWeek: pulumi.Any(maintenanceDayOfWeek),
HourOfDay: pulumi.Any(maintenanceHourOfDay),
},
},
Tags: pulumi.Any(clusterTags),
Timeouts: &redpanda.ClusterTimeoutsArgs{
Create: pulumi.String("90m"),
},
})
if err != nil {
return err
}
testUser, err := redpanda.NewUser(ctx, "test", &redpanda.UserArgs{
Name: pulumi.Any(userName),
Password: pulumi.Any(userPw),
Mechanism: pulumi.Any(mechanism),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(userAllowDeletion),
})
if err != nil {
return err
}
var tmp0 pulumi.StringMap
if topicConfiguration != nil {
tmp0 = pulumi.Any(topicConfiguration)
} else {
tmp0 = pulumi.StringMap{
"cleanup.policy": pulumi.String("delete"),
"retention.ms": pulumi.Any(topicRetentionMs),
}
}
testTopic, err := redpanda.NewTopic(ctx, "test", &redpanda.TopicArgs{
Name: pulumi.Any(topicName),
PartitionCount: pulumi.Any(partitionCount),
ReplicationFactor: pulumi.Any(replicationFactor),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Bool(true),
Configuration: pulumi.StringMap(tmp0),
}, pulumi.DependsOn([]pulumi.Resource{
testUser,
}))
if err != nil {
return err
}
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// SUBJECT grant authorizes POST /subjects/<subj>/versions; REGISTRY grant
// authorizes the franz-go follow-up GET /schemas/ids/<id>/versions.
providerBootstrapSubject, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_subject", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Any(topicName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
providerBootstrapRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
clusterAdmin, err := redpanda.NewAcl(ctx, "cluster_admin", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
schemaRegistryAdmin, err := redpanda.NewAcl(ctx, "schema_registry_admin", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALTER"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
clusterAction, err := redpanda.NewAcl(ctx, "cluster_action", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("CLUSTER_ACTION"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
topicAccess, err := redpanda.NewAcl(ctx, "topic_access", &redpanda.AclArgs{
ResourceType: pulumi.String("TOPIC"),
ResourceName: testTopic.Name,
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
allTestTopic, err := redpanda.NewSchemaRegistryAcl(ctx, "all_test_topic", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Sprintf("%v-", topicName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
describeRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "describe_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("DESCRIBE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
alterConfigsRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "alter_configs_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALTER_CONFIGS"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
readRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "read_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
writeRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "write_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("WRITE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
userSchema, err := redpanda.NewSchema(ctx, "user_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(userSchemaDefinition),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
userEventSchema, err := redpanda.NewSchema(ctx, "user_event_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-events-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(userEventSchemaDefinition),
AllowDeletion: pulumi.Bool(true),
References: redpanda.SchemaReferenceArray{
&redpanda.SchemaReferenceArgs{
Name: pulumi.String("User"),
Subject: userSchema.Subject,
Version: userSchema.Version,
},
},
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
productSchema, err := redpanda.NewSchema(ctx, "product_schema", &redpanda.SchemaArgs{
ClusterId: testCluster.ID(),
Subject: pulumi.Sprintf("%v-product-value", topicName),
SchemaType: pulumi.Any(schemaType),
Schema: pulumi.Any(productSchemaDefinition),
Compatibility: pulumi.Any(compatibilityLevel),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry,
}))
if err != nil {
return err
}
developer, err := redpanda.NewRole(ctx, "developer", &redpanda.RoleArgs{
Name: pulumi.Any(roleName),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(roleAllowDeletion),
})
if err != nil {
return err
}
_, err = redpanda.NewAcl(ctx, "role_topic_read", &redpanda.AclArgs{
ResourceType: pulumi.String("TOPIC"),
ResourceName: testTopic.Name,
ResourcePatternType: pulumi.String("LITERAL"),
Principal: developer.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("RedpandaRole:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: testCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
_, err = redpanda.NewSchemaRegistryAcl(ctx, "read_product", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.String("product-"),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("READ"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Any(srAclAllowDeletion),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
_, err = redpanda.NewSchemaRegistryAcl(ctx, "write_orders", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.String("orders-value"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("WRITE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
_, err = redpanda.NewSchemaRegistryAcl(ctx, "describe_test_topic", &redpanda.SchemaRegistryAclArgs{
ClusterId: testCluster.ID(),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Sprintf("%v-", topicName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("DESCRIBE"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
}, pulumi.DependsOn([]pulumi.Resource{
clusterAdmin,
schemaRegistryAdmin,
}))
if err != nil {
return err
}
_, err = redpanda.NewRoleAssignment(ctx, "developer_assignment", &redpanda.RoleAssignmentArgs{
RoleName: developer.Name,
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
ClusterApiUrl: testCluster.ClusterApiUrl,
}, pulumi.DependsOn([]pulumi.Resource{
testUser,
}))
if err != nil {
return err
}
ctx.Export("userSchemaInfo", pulumi.Map{
"id": userSchema.SchemaId,
"subject": userSchema.Subject,
"version": userSchema.Version,
"type": userSchema.SchemaType,
})
ctx.Export("userEventSchemaInfo", pulumi.Map{
"id": userEventSchema.SchemaId,
"subject": userEventSchema.Subject,
"version": userEventSchema.Version,
"type": userEventSchema.SchemaType,
"references": userEventSchema.References,
})
ctx.Export("productSchemaInfo", pulumi.Map{
"id": productSchema.SchemaId,
"subject": productSchema.Subject,
"version": productSchema.Version,
"type": productSchema.SchemaType,
"compatibility": productSchema.Compatibility,
})
return nil
})
}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: yaml
Example currently unavailable in this language
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: java
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.redpanda.ResourceGroup;
import com.pulumi.redpanda.ResourceGroupArgs;
import com.pulumi.redpanda.Network;
import com.pulumi.redpanda.NetworkArgs;
import com.pulumi.redpanda.inputs.NetworkTimeoutsArgs;
import com.pulumi.redpanda.Cluster;
import com.pulumi.redpanda.ClusterArgs;
import com.pulumi.redpanda.inputs.ClusterClusterConfigurationArgs;
import com.pulumi.redpanda.inputs.ClusterMaintenanceWindowConfigArgs;
import com.pulumi.redpanda.inputs.ClusterMaintenanceWindowConfigDayHourArgs;
import com.pulumi.redpanda.inputs.ClusterTimeoutsArgs;
import com.pulumi.redpanda.User;
import com.pulumi.redpanda.UserArgs;
import com.pulumi.redpanda.Topic;
import com.pulumi.redpanda.TopicArgs;
import com.pulumi.redpanda.SchemaRegistryAcl;
import com.pulumi.redpanda.SchemaRegistryAclArgs;
import com.pulumi.redpanda.Acl;
import com.pulumi.redpanda.AclArgs;
import com.pulumi.redpanda.Schema;
import com.pulumi.redpanda.SchemaArgs;
import com.pulumi.redpanda.inputs.SchemaReferenceArgs;
import com.pulumi.redpanda.Role;
import com.pulumi.redpanda.RoleArgs;
import com.pulumi.redpanda.RoleAssignment;
import com.pulumi.redpanda.RoleAssignmentArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import com.pulumi.resources.CustomResourceOptions;
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 test = new ResourceGroup("test", ResourceGroupArgs.builder()
.name(resourceGroupName)
.build());
var testNetwork = new Network("testNetwork", NetworkArgs.builder()
.name(networkName)
.resourceGroupId(test.id())
.cloudProvider(cloudProvider)
.region(region)
.clusterType("dedicated")
.cidrBlock("10.0.0.0/20")
.timeouts(NetworkTimeoutsArgs.builder()
.create("20m")
.delete("20m")
.build())
.build());
var testCluster = new Cluster("testCluster", ClusterArgs.builder()
.name(clusterName)
.resourceGroupId(test.id())
.networkId(testNetwork.id())
.cloudProvider(cloudProvider)
.region(region)
.clusterType("dedicated")
.connectionType("public")
.throughputTier(throughputTier)
.zones(zones)
.allowDeletion(clusterAllowDeletion)
.clusterConfiguration(ClusterClusterConfigurationArgs.builder()
.customPropertiesJson(serializeJson(
jsonObject(
jsonProperty("enable_shadow_linking", clusterEnableShadowLinking),
jsonProperty("schema_registry_enable_authorization", true)
)))
.build())
.maintenanceWindowConfig(ClusterMaintenanceWindowConfigArgs.builder()
.dayHour(ClusterMaintenanceWindowConfigDayHourArgs.builder()
.dayOfWeek(maintenanceDayOfWeek)
.hourOfDay(maintenanceHourOfDay)
.build())
.build())
.tags(clusterTags)
.timeouts(ClusterTimeoutsArgs.builder()
.create("90m")
.build())
.build());
var testUser = new User("testUser", UserArgs.builder()
.name(userName)
.password(userPw)
.mechanism(mechanism)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(userAllowDeletion)
.build());
var testTopic = new Topic("testTopic", TopicArgs.builder()
.name(topicName)
.partitionCount(partitionCount)
.replicationFactor(replicationFactor)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(true)
.configuration(topicConfiguration != null ? topicConfiguration : Map.ofEntries(
Map.entry("cleanup.policy", "delete"),
Map.entry("retention.ms", topicRetentionMs)
))
.build(), CustomResourceOptions.builder()
.dependsOn(testUser)
.build());
// Bootstrap SR ACL grants for the provider's own Bearer-token principal.
// SUBJECT grant authorizes POST /subjects/<subj>/versions; REGISTRY grant
// authorizes the franz-go follow-up GET /schemas/ids/<id>/versions.
var providerBootstrapSubject = new SchemaRegistryAcl("providerBootstrapSubject", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal("User:*")
.resourceType("SUBJECT")
.resourceName(topicName)
.patternType("PREFIXED")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var providerBootstrapRegistry = new SchemaRegistryAcl("providerBootstrapRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal("User:*")
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var clusterAdmin = new Acl("clusterAdmin", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALL")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var schemaRegistryAdmin = new Acl("schemaRegistryAdmin", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALTER")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var clusterAction = new Acl("clusterAction", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("CLUSTER_ACTION")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var topicAccess = new Acl("topicAccess", AclArgs.builder()
.resourceType("TOPIC")
.resourceName(testTopic.name())
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALL")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var allTestTopic = new SchemaRegistryAcl("allTestTopic", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName(String.format("%s-", topicName))
.patternType("PREFIXED")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var describeRegistry = new SchemaRegistryAcl("describeRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("DESCRIBE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var alterConfigsRegistry = new SchemaRegistryAcl("alterConfigsRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("ALTER_CONFIGS")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var readRegistry = new SchemaRegistryAcl("readRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("READ")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var writeRegistry = new SchemaRegistryAcl("writeRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("WRITE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var userSchema = new Schema("userSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-value", topicName))
.schemaType(schemaType)
.schema(userSchemaDefinition)
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var userEventSchema = new Schema("userEventSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-events-value", topicName))
.schemaType(schemaType)
.schema(userEventSchemaDefinition)
.allowDeletion(true)
.references(SchemaReferenceArgs.builder()
.name("User")
.subject(userSchema.subject())
.version(userSchema.version())
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var productSchema = new Schema("productSchema", SchemaArgs.builder()
.clusterId(testCluster.id())
.subject(String.format("%s-product-value", topicName))
.schemaType(schemaType)
.schema(productSchemaDefinition)
.compatibility(compatibilityLevel)
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin,
clusterAction,
topicAccess,
providerBootstrapSubject,
providerBootstrapRegistry,
allTestTopic,
describeRegistry,
alterConfigsRegistry,
readRegistry,
writeRegistry)
.build());
var developer = new Role("developer", RoleArgs.builder()
.name(roleName)
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(roleAllowDeletion)
.build());
var roleTopicRead = new Acl("roleTopicRead", AclArgs.builder()
.resourceType("TOPIC")
.resourceName(testTopic.name())
.resourcePatternType("LITERAL")
.principal(developer.name().applyValue(_name -> String.format("RedpandaRole:%s", _name)))
.host("*")
.operation("READ")
.permissionType("ALLOW")
.clusterApiUrl(testCluster.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
var readProduct = new SchemaRegistryAcl("readProduct", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName("product-")
.patternType("PREFIXED")
.host("*")
.operation("READ")
.permission("ALLOW")
.allowDeletion(srAclAllowDeletion)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var writeOrders = new SchemaRegistryAcl("writeOrders", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName("orders-value")
.patternType("LITERAL")
.host("*")
.operation("WRITE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var describeTestTopic = new SchemaRegistryAcl("describeTestTopic", SchemaRegistryAclArgs.builder()
.clusterId(testCluster.id())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.resourceType("SUBJECT")
.resourceName(String.format("%s-", topicName))
.patternType("PREFIXED")
.host("*")
.operation("DESCRIBE")
.permission("ALLOW")
.allowDeletion(true)
.build(), CustomResourceOptions.builder()
.dependsOn(
clusterAdmin,
schemaRegistryAdmin)
.build());
var developerAssignment = new RoleAssignment("developerAssignment", RoleAssignmentArgs.builder()
.roleName(developer.name())
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.clusterApiUrl(testCluster.clusterApiUrl())
.build(), CustomResourceOptions.builder()
.dependsOn(testUser)
.build());
ctx.export("userSchemaInfo", Map.ofEntries(
Map.entry("id", userSchema.schemaId()),
Map.entry("subject", userSchema.subject()),
Map.entry("version", userSchema.version()),
Map.entry("type", userSchema.schemaType())
));
ctx.export("userEventSchemaInfo", Map.ofEntries(
Map.entry("id", userEventSchema.schemaId()),
Map.entry("subject", userEventSchema.subject()),
Map.entry("version", userEventSchema.version()),
Map.entry("type", userEventSchema.schemaType()),
Map.entry("references", userEventSchema.references())
));
ctx.export("productSchemaInfo", Map.ofEntries(
Map.entry("id", productSchema.schemaId()),
Map.entry("subject", productSchema.subject()),
Map.entry("version", productSchema.version()),
Map.entry("type", productSchema.schemaType()),
Map.entry("compatibility", productSchema.compatibility())
));
}
}
Example Usage of a function BYOC to manage users and ACLs
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: nodejs
import * as pulumi from "@pulumi/pulumi";
import * as redpanda from "@pulumi/redpanda";
const test = redpanda.getCluster({
id: clusterId,
});
const testTopic = new redpanda.Topic("test", {
name: topicName,
partitionCount: partitionCount,
replicationFactor: replicationFactor,
clusterApiUrl: test.then(test => test.clusterApiUrl),
allowDeletion: true,
configuration: topicConfig,
});
const testUser = new redpanda.User("test", {
name: userName,
password: userPw,
mechanism: mechanism,
clusterApiUrl: test.then(test => test.clusterApiUrl),
allowDeletion: userAllowDeletion,
});
const testAcl = new redpanda.Acl("test", {
resourceType: "CLUSTER",
resourceName: "kafka-cluster",
resourcePatternType: "LITERAL",
principal: pulumi.interpolate`User:${testUser.name}`,
host: "*",
operation: "ALTER",
permissionType: "ALLOW",
clusterApiUrl: test.then(test => test.clusterApiUrl),
allowDeletion: aclAllowDeletion,
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: python
import pulumi
import pulumi_redpanda as redpanda
test = redpanda.get_cluster(id=cluster_id)
test_topic = redpanda.Topic("test",
name=topic_name,
partition_count=partition_count,
replication_factor=replication_factor,
cluster_api_url=test.cluster_api_url,
allow_deletion=True,
configuration=topic_config)
test_user = redpanda.User("test",
name=user_name,
password=user_pw,
mechanism=mechanism,
cluster_api_url=test.cluster_api_url,
allow_deletion=user_allow_deletion)
test_acl = redpanda.Acl("test",
resource_type="CLUSTER",
resource_name_="kafka-cluster",
resource_pattern_type="LITERAL",
principal=test_user.name.apply(lambda name: f"User:{name}"),
host="*",
operation="ALTER",
permission_type="ALLOW",
cluster_api_url=test.cluster_api_url,
allow_deletion=acl_allow_deletion)
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: dotnet
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Redpanda = Pulumi.Redpanda;
return await Deployment.RunAsync(() =>
{
var test = Redpanda.GetCluster.Invoke(new()
{
Id = clusterId,
});
var testTopic = new Redpanda.Topic("test", new()
{
Name = topicName,
PartitionCount = partitionCount,
ReplicationFactor = replicationFactor,
ClusterApiUrl = test.Apply(getClusterResult => getClusterResult.ClusterApiUrl),
AllowDeletion = true,
Configuration = topicConfig,
});
var testUser = new Redpanda.User("test", new()
{
Name = userName,
Password = userPw,
Mechanism = mechanism,
ClusterApiUrl = test.Apply(getClusterResult => getClusterResult.ClusterApiUrl),
AllowDeletion = userAllowDeletion,
});
var testAcl = new Redpanda.Acl("test", new()
{
ResourceType = "CLUSTER",
ResourceName = "kafka-cluster",
ResourcePatternType = "LITERAL",
Principal = testUser.Name.Apply(name => $"User:{name}"),
Host = "*",
Operation = "ALTER",
PermissionType = "ALLOW",
ClusterApiUrl = test.Apply(getClusterResult => getClusterResult.ClusterApiUrl),
AllowDeletion = aclAllowDeletion,
});
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: go
package main
import (
"fmt"
"github.com/pulumi/pulumi-pulumi-provider/sdks/go/redpanda/v2/redpanda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := redpanda.LookupCluster(ctx, &redpanda.LookupClusterArgs{
Id: clusterId,
}, nil)
if err != nil {
return err
}
_, err = redpanda.NewTopic(ctx, "test", &redpanda.TopicArgs{
Name: pulumi.Any(topicName),
PartitionCount: pulumi.Any(partitionCount),
ReplicationFactor: pulumi.Any(replicationFactor),
ClusterApiUrl: pulumi.String(test.ClusterApiUrl),
AllowDeletion: pulumi.Bool(true),
Configuration: pulumi.Any(topicConfig),
})
if err != nil {
return err
}
testUser, err := redpanda.NewUser(ctx, "test", &redpanda.UserArgs{
Name: pulumi.Any(userName),
Password: pulumi.Any(userPw),
Mechanism: pulumi.Any(mechanism),
ClusterApiUrl: pulumi.String(test.ClusterApiUrl),
AllowDeletion: pulumi.Any(userAllowDeletion),
})
if err != nil {
return err
}
_, err = redpanda.NewAcl(ctx, "test", &redpanda.AclArgs{
ResourceType: pulumi.String("CLUSTER"),
ResourceName: pulumi.String("kafka-cluster"),
ResourcePatternType: pulumi.String("LITERAL"),
Principal: testUser.Name.ApplyT(func(name string) (string, error) {
return fmt.Sprintf("User:%v", name), nil
}).(pulumi.StringOutput),
Host: pulumi.String("*"),
Operation: pulumi.String("ALTER"),
PermissionType: pulumi.String("ALLOW"),
ClusterApiUrl: pulumi.String(test.ClusterApiUrl),
AllowDeletion: pulumi.Any(aclAllowDeletion),
})
if err != nil {
return err
}
return nil
})
}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: yaml
resources:
testTopic:
type: redpanda:Topic
name: test
properties:
name: ${topicName}
partitionCount: ${partitionCount}
replicationFactor: ${replicationFactor}
clusterApiUrl: ${test.clusterApiUrl}
allowDeletion: true
configuration: ${topicConfig}
testUser:
type: redpanda:User
name: test
properties:
name: ${userName}
password: ${userPw}
mechanism: ${mechanism}
clusterApiUrl: ${test.clusterApiUrl}
allowDeletion: ${userAllowDeletion}
testAcl:
type: redpanda:Acl
name: test
properties:
resourceType: CLUSTER
resourceName: kafka-cluster
resourcePatternType: LITERAL
principal: User:${testUser.name}
host: '*'
operation: ALTER
permissionType: ALLOW
clusterApiUrl: ${test.clusterApiUrl}
allowDeletion: ${aclAllowDeletion}
variables:
test:
fn::invoke:
function: redpanda:getCluster
arguments:
id: ${clusterId}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: java
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.redpanda.RedpandaFunctions;
import com.pulumi.redpanda.inputs.GetClusterArgs;
import com.pulumi.redpanda.Topic;
import com.pulumi.redpanda.TopicArgs;
import com.pulumi.redpanda.User;
import com.pulumi.redpanda.UserArgs;
import com.pulumi.redpanda.Acl;
import com.pulumi.redpanda.AclArgs;
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) {
final var test = RedpandaFunctions.getCluster(GetClusterArgs.builder()
.id(clusterId)
.build());
var testTopic = new Topic("testTopic", TopicArgs.builder()
.name(topicName)
.partitionCount(partitionCount)
.replicationFactor(replicationFactor)
.clusterApiUrl(test.clusterApiUrl())
.allowDeletion(true)
.configuration(topicConfig)
.build());
var testUser = new User("testUser", UserArgs.builder()
.name(userName)
.password(userPw)
.mechanism(mechanism)
.clusterApiUrl(test.clusterApiUrl())
.allowDeletion(userAllowDeletion)
.build());
var testAcl = new Acl("testAcl", AclArgs.builder()
.resourceType("CLUSTER")
.resourceName("kafka-cluster")
.resourcePatternType("LITERAL")
.principal(testUser.name().applyValue(_name -> String.format("User:%s", _name)))
.host("*")
.operation("ALTER")
.permissionType("ALLOW")
.clusterApiUrl(test.clusterApiUrl())
.allowDeletion(aclAllowDeletion)
.build());
}
}
Example Usage to create a serverless cluster
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: nodejs
import * as pulumi from "@pulumi/pulumi";
import * as redpanda from "@pulumi/redpanda";
const test = new redpanda.ResourceGroup("test", {name: resourceGroupName});
const testServerlessPrivateLink: redpanda.ServerlessPrivateLink[] = [];
for (const range = {value: 0}; range.value < (privateNetworking == "STATE_ENABLED" ? 1 : 0); range.value++) {
testServerlessPrivateLink.push(new redpanda.ServerlessPrivateLink(`test-${range.value}`, {
name: `${clusterName}-private-link`,
resourceGroupId: test.id,
cloudProvider: "aws",
serverlessRegion: region,
allowDeletion: allowPrivateLinkDeletion,
awsConfig: {
allowedPrincipals: allowedPrincipals,
},
}));
}
const testServerlessCluster = new redpanda.ServerlessCluster("test", {
name: clusterName,
resourceGroupId: test.id,
serverlessRegion: region,
allowDeletion: clusterAllowDeletion,
privateLinkId: privateNetworking == "STATE_ENABLED" ? testServerlessPrivateLink[0].id : null,
networkingConfig: {
"public": publicNetworking,
"private": privateNetworking,
},
});
const testTopic = new redpanda.Topic("test", {
name: topicName,
partitionCount: partitionCount,
replicationFactor: replicationFactor,
clusterApiUrl: testServerlessCluster.clusterApiUrl,
allowDeletion: true,
});
const testUser = new redpanda.User("test", {
name: userName,
password: userPw,
mechanism: mechanism,
clusterApiUrl: testServerlessCluster.clusterApiUrl,
allowDeletion: userAllowDeletion,
});
// Schema Registry against a serverless cluster keys off cluster_id (control
// plane), not cluster_api_url; cluster_id resolves the SR endpoint via the
// ServerlessClusterService fallback in GetSchemaRegistryClientForCluster.
// Both redpanda_schema_registry_acl and redpanda_schema route through it.
const providerBootstrapSubject = new redpanda.SchemaRegistryAcl("provider_bootstrap_subject", {
clusterId: testServerlessCluster.id,
principal: "User:*",
resourceType: "SUBJECT",
resourceName: resourceGroupName,
patternType: "PREFIXED",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const providerBootstrapRegistry = new redpanda.SchemaRegistryAcl("provider_bootstrap_registry", {
clusterId: testServerlessCluster.id,
principal: "User:*",
resourceType: "REGISTRY",
resourceName: "*",
patternType: "LITERAL",
host: "*",
operation: "ALL",
permission: "ALLOW",
allowDeletion: true,
});
const userSchema = new redpanda.Schema("user_schema", {
clusterId: testServerlessCluster.id,
subject: `${resourceGroupName}-value`,
schemaType: "AVRO",
compatibility: "BACKWARD",
allowDeletion: true,
schema: JSON.stringify({
type: "record",
name: "User",
fields: [
{
name: "id",
type: "long",
},
{
name: "name",
type: "string",
},
],
}),
}, {
dependsOn: [
providerBootstrapSubject,
providerBootstrapRegistry,
],
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: python
import pulumi
import json
import pulumi_redpanda as redpanda
test = redpanda.ResourceGroup("test", name=resource_group_name)
test_serverless_private_link = []
for range in [{"value": i} for i in range(0, 1 if private_networking == STATE_ENABLED else 0)]:
test_serverless_private_link.append(redpanda.ServerlessPrivateLink(f"test-{range['value']}",
name=f"{cluster_name}-private-link",
resource_group_id=test.id,
cloud_provider="aws",
serverless_region=region,
allow_deletion=allow_private_link_deletion,
aws_config={
"allowed_principals": allowed_principals,
}))
test_serverless_cluster = redpanda.ServerlessCluster("test",
name=cluster_name,
resource_group_id=test.id,
serverless_region=region,
allow_deletion=cluster_allow_deletion,
private_link_id=test_serverless_private_link[0].id if private_networking == "STATE_ENABLED" else None,
networking_config={
"public": public_networking,
"private": private_networking,
})
test_topic = redpanda.Topic("test",
name=topic_name,
partition_count=partition_count,
replication_factor=replication_factor,
cluster_api_url=test_serverless_cluster.cluster_api_url,
allow_deletion=True)
test_user = redpanda.User("test",
name=user_name,
password=user_pw,
mechanism=mechanism,
cluster_api_url=test_serverless_cluster.cluster_api_url,
allow_deletion=user_allow_deletion)
# Configuration Reference Registry against a serverless cluster keys off cluster_id (control
# plane), not cluster_api_url; cluster_id resolves the SR endpoint via the
# ServerlessClusterService fallback in GetSchemaRegistryClientForCluster.
# Both redpanda_schema_registry_acl and redpanda_schema route through it.
provider_bootstrap_subject = redpanda.SchemaRegistryAcl("provider_bootstrap_subject",
cluster_id=test_serverless_cluster.id,
principal="User:*",
resource_type="SUBJECT",
resource_name_=resource_group_name,
pattern_type="PREFIXED",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
provider_bootstrap_registry = redpanda.SchemaRegistryAcl("provider_bootstrap_registry",
cluster_id=test_serverless_cluster.id,
principal="User:*",
resource_type="REGISTRY",
resource_name_="*",
pattern_type="LITERAL",
host="*",
operation="ALL",
permission="ALLOW",
allow_deletion=True)
user_schema = redpanda.Schema("user_schema",
cluster_id=test_serverless_cluster.id,
subject=f"{resource_group_name}-value",
schema_type="AVRO",
compatibility="BACKWARD",
allow_deletion=True,
schema=json.dumps({
"type": "record",
"name": "User",
"fields": [
{
"name": "id",
"type": "long",
},
{
"name": "name",
"type": "string",
},
],
}),
opts = pulumi.ResourceOptions(depends_on=[
provider_bootstrap_subject,
provider_bootstrap_registry,
]))
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: dotnet
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Redpanda = Pulumi.Redpanda;
return await Deployment.RunAsync(() =>
{
var test = new Redpanda.ResourceGroup("test", new()
{
Name = resourceGroupName,
});
var testServerlessPrivateLink = new List<Redpanda.ServerlessPrivateLink>();
for (var rangeIndex = 0; rangeIndex < (privateNetworking == "STATE_ENABLED" ? 1 : 0); rangeIndex++)
{
var range = new { Value = rangeIndex };
testServerlessPrivateLink.Add(new Redpanda.ServerlessPrivateLink($"test-{range.Value}", new()
{
Name = $"{clusterName}-private-link",
ResourceGroupId = test.Id,
CloudProvider = "aws",
ServerlessRegion = region,
AllowDeletion = allowPrivateLinkDeletion,
AwsConfig = new Redpanda.Inputs.ServerlessPrivateLinkAwsConfigArgs
{
AllowedPrincipals = allowedPrincipals,
},
}));
}
var testServerlessCluster = new Redpanda.ServerlessCluster("test", new()
{
Name = clusterName,
ResourceGroupId = test.Id,
ServerlessRegion = region,
AllowDeletion = clusterAllowDeletion,
PrivateLinkId = privateNetworking == "STATE_ENABLED" ? testServerlessPrivateLink[0].Id : null,
NetworkingConfig = new Redpanda.Inputs.ServerlessClusterNetworkingConfigArgs
{
Public = publicNetworking,
Private = privateNetworking,
},
});
var testTopic = new Redpanda.Topic("test", new()
{
Name = topicName,
PartitionCount = partitionCount,
ReplicationFactor = replicationFactor,
ClusterApiUrl = testServerlessCluster.ClusterApiUrl,
AllowDeletion = true,
});
var testUser = new Redpanda.User("test", new()
{
Name = userName,
Password = userPw,
Mechanism = mechanism,
ClusterApiUrl = testServerlessCluster.ClusterApiUrl,
AllowDeletion = userAllowDeletion,
});
// Schema Registry against a serverless cluster keys off cluster_id (control
// plane), not cluster_api_url; cluster_id resolves the SR endpoint via the
// ServerlessClusterService fallback in GetSchemaRegistryClientForCluster.
// Both redpanda_schema_registry_acl and redpanda_schema route through it.
var providerBootstrapSubject = new Redpanda.SchemaRegistryAcl("provider_bootstrap_subject", new()
{
ClusterId = testServerlessCluster.Id,
Principal = "User:*",
ResourceType = "SUBJECT",
ResourceName = resourceGroupName,
PatternType = "PREFIXED",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var providerBootstrapRegistry = new Redpanda.SchemaRegistryAcl("provider_bootstrap_registry", new()
{
ClusterId = testServerlessCluster.Id,
Principal = "User:*",
ResourceType = "REGISTRY",
ResourceName = "*",
PatternType = "LITERAL",
Host = "*",
Operation = "ALL",
Permission = "ALLOW",
AllowDeletion = true,
});
var userSchema = new Redpanda.Schema("user_schema", new()
{
ClusterId = testServerlessCluster.Id,
Subject = $"{resourceGroupName}-value",
SchemaType = "AVRO",
Compatibility = "BACKWARD",
AllowDeletion = true,
Schema = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["type"] = "record",
["name"] = "User",
["fields"] = new[]
{
new Dictionary<string, object?>
{
["name"] = "id",
["type"] = "long",
},
new Dictionary<string, object?>
{
["name"] = "name",
["type"] = "string",
},
},
}),
}, new CustomResourceOptions
{
DependsOn =
{
providerBootstrapSubject,
providerBootstrapRegistry,
},
});
});
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: go
package main
import (
"encoding/json"
"fmt"
"github.com/pulumi/pulumi-pulumi-provider/sdks/go/redpanda/v2/redpanda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := redpanda.NewResourceGroup(ctx, "test", &redpanda.ResourceGroupArgs{
Name: pulumi.Any(resourceGroupName),
})
if err != nil {
return err
}
var tmp0 float64
if privateNetworking == "STATE_ENABLED" {
tmp0 = 1
} else {
tmp0 = 0
}
var testServerlessPrivateLink []*redpanda.ServerlessPrivateLink
for index := 0; index < tmp0; index++ {
key0 := index
_ := index
__res, err := redpanda.NewServerlessPrivateLink(ctx, fmt.Sprintf("test-%v", key0), &redpanda.ServerlessPrivateLinkArgs{
Name: pulumi.Sprintf("%v-private-link", clusterName),
ResourceGroupId: test.ID(),
CloudProvider: pulumi.String("aws"),
ServerlessRegion: pulumi.Any(region),
AllowDeletion: pulumi.Any(allowPrivateLinkDeletion),
AwsConfig: &redpanda.ServerlessPrivateLinkAwsConfigArgs{
AllowedPrincipals: pulumi.Any(allowedPrincipals),
},
})
if err != nil {
return err
}
testServerlessPrivateLink = append(testServerlessPrivateLink, __res)
}
var tmp1 pulumi.String
if privateNetworking == "STATE_ENABLED" {
tmp1 = testServerlessPrivateLink[0].ID()
} else {
tmp1 = nil
}
testServerlessCluster, err := redpanda.NewServerlessCluster(ctx, "test", &redpanda.ServerlessClusterArgs{
Name: pulumi.Any(clusterName),
ResourceGroupId: test.ID(),
ServerlessRegion: pulumi.Any(region),
AllowDeletion: pulumi.Any(clusterAllowDeletion),
PrivateLinkId: pulumi.String(tmp1),
NetworkingConfig: &redpanda.ServerlessClusterNetworkingConfigArgs{
Public: pulumi.Any(publicNetworking),
Private: pulumi.Any(privateNetworking),
},
})
if err != nil {
return err
}
_, err = redpanda.NewTopic(ctx, "test", &redpanda.TopicArgs{
Name: pulumi.Any(topicName),
PartitionCount: pulumi.Any(partitionCount),
ReplicationFactor: pulumi.Any(replicationFactor),
ClusterApiUrl: testServerlessCluster.ClusterApiUrl,
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
_, err = redpanda.NewUser(ctx, "test", &redpanda.UserArgs{
Name: pulumi.Any(userName),
Password: pulumi.Any(userPw),
Mechanism: pulumi.Any(mechanism),
ClusterApiUrl: testServerlessCluster.ClusterApiUrl,
AllowDeletion: pulumi.Any(userAllowDeletion),
})
if err != nil {
return err
}
// Schema Registry against a serverless cluster keys off cluster_id (control
// plane), not cluster_api_url; cluster_id resolves the SR endpoint via the
// ServerlessClusterService fallback in GetSchemaRegistryClientForCluster.
// Both redpanda_schema_registry_acl and redpanda_schema route through it.
providerBootstrapSubject, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_subject", &redpanda.SchemaRegistryAclArgs{
ClusterId: testServerlessCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("SUBJECT"),
ResourceName: pulumi.Any(resourceGroupName),
PatternType: pulumi.String("PREFIXED"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
providerBootstrapRegistry, err := redpanda.NewSchemaRegistryAcl(ctx, "provider_bootstrap_registry", &redpanda.SchemaRegistryAclArgs{
ClusterId: testServerlessCluster.ID(),
Principal: pulumi.String("User:*"),
ResourceType: pulumi.String("REGISTRY"),
ResourceName: pulumi.String("*"),
PatternType: pulumi.String("LITERAL"),
Host: pulumi.String("*"),
Operation: pulumi.String("ALL"),
Permission: pulumi.String("ALLOW"),
AllowDeletion: pulumi.Bool(true),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"type": "record",
"name": "User",
"fields": []map[string]interface{}{
map[string]interface{}{
"name": "id",
"type": "long",
},
map[string]interface{}{
"name": "name",
"type": "string",
},
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = redpanda.NewSchema(ctx, "user_schema", &redpanda.SchemaArgs{
ClusterId: testServerlessCluster.ID(),
Subject: pulumi.Sprintf("%v-value", resourceGroupName),
SchemaType: pulumi.String("AVRO"),
Compatibility: pulumi.String("BACKWARD"),
AllowDeletion: pulumi.Bool(true),
Schema: pulumi.String(json0),
}, pulumi.DependsOn([]pulumi.Resource{
providerBootstrapSubject,
providerBootstrapRegistry,
}))
if err != nil {
return err
}
return nil
})
}
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: yaml
Example currently unavailable in this language
# Pulumi.yaml provider configuration file
name: configuration-example
runtime: java
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.redpanda.ResourceGroup;
import com.pulumi.redpanda.ResourceGroupArgs;
import com.pulumi.redpanda.ServerlessPrivateLink;
import com.pulumi.redpanda.ServerlessPrivateLinkArgs;
import com.pulumi.redpanda.inputs.ServerlessPrivateLinkAwsConfigArgs;
import com.pulumi.redpanda.ServerlessCluster;
import com.pulumi.redpanda.ServerlessClusterArgs;
import com.pulumi.redpanda.inputs.ServerlessClusterNetworkingConfigArgs;
import com.pulumi.redpanda.Topic;
import com.pulumi.redpanda.TopicArgs;
import com.pulumi.redpanda.User;
import com.pulumi.redpanda.UserArgs;
import com.pulumi.redpanda.SchemaRegistryAcl;
import com.pulumi.redpanda.SchemaRegistryAclArgs;
import com.pulumi.redpanda.Schema;
import com.pulumi.redpanda.SchemaArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import com.pulumi.codegen.internal.KeyedValue;
import com.pulumi.resources.CustomResourceOptions;
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 test = new ResourceGroup("test", ResourceGroupArgs.builder()
.name(resourceGroupName)
.build());
for (var i = 0; i < (privateNetworking == "STATE_ENABLED" ? 1 : 0); i++) {
new ServerlessPrivateLink("testServerlessPrivateLink-" + i, ServerlessPrivateLinkArgs.builder()
.name(String.format("%s-private-link", clusterName))
.resourceGroupId(test.id())
.cloudProvider("aws")
.serverlessRegion(region)
.allowDeletion(allowPrivateLinkDeletion)
.awsConfig(ServerlessPrivateLinkAwsConfigArgs.builder()
.allowedPrincipals(allowedPrincipals)
.build())
.build());
}
var testServerlessCluster = new ServerlessCluster("testServerlessCluster", ServerlessClusterArgs.builder()
.name(clusterName)
.resourceGroupId(test.id())
.serverlessRegion(region)
.allowDeletion(clusterAllowDeletion)
.privateLinkId(privateNetworking == "STATE_ENABLED" ? testServerlessPrivateLink[0].id() : null)
.networkingConfig(ServerlessClusterNetworkingConfigArgs.builder()
.public_(publicNetworking)
.private_(privateNetworking)
.build())
.build());
var testTopic = new Topic("testTopic", TopicArgs.builder()
.name(topicName)
.partitionCount(partitionCount)
.replicationFactor(replicationFactor)
.clusterApiUrl(testServerlessCluster.clusterApiUrl())
.allowDeletion(true)
.build());
var testUser = new User("testUser", UserArgs.builder()
.name(userName)
.password(userPw)
.mechanism(mechanism)
.clusterApiUrl(testServerlessCluster.clusterApiUrl())
.allowDeletion(userAllowDeletion)
.build());
// Schema Registry against a serverless cluster keys off cluster_id (control
// plane), not cluster_api_url; cluster_id resolves the SR endpoint via the
// ServerlessClusterService fallback in GetSchemaRegistryClientForCluster.
// Both redpanda_schema_registry_acl and redpanda_schema route through it.
var providerBootstrapSubject = new SchemaRegistryAcl("providerBootstrapSubject", SchemaRegistryAclArgs.builder()
.clusterId(testServerlessCluster.id())
.principal("User:*")
.resourceType("SUBJECT")
.resourceName(resourceGroupName)
.patternType("PREFIXED")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var providerBootstrapRegistry = new SchemaRegistryAcl("providerBootstrapRegistry", SchemaRegistryAclArgs.builder()
.clusterId(testServerlessCluster.id())
.principal("User:*")
.resourceType("REGISTRY")
.resourceName("*")
.patternType("LITERAL")
.host("*")
.operation("ALL")
.permission("ALLOW")
.allowDeletion(true)
.build());
var userSchema = new Schema("userSchema", SchemaArgs.builder()
.clusterId(testServerlessCluster.id())
.subject(String.format("%s-value", resourceGroupName))
.schemaType("AVRO")
.compatibility("BACKWARD")
.allowDeletion(true)
.schema(serializeJson(
jsonObject(
jsonProperty("type", "record"),
jsonProperty("name", "User"),
jsonProperty("fields", jsonArray(
jsonObject(
jsonProperty("name", "id"),
jsonProperty("type", "long")
),
jsonObject(
jsonProperty("name", "name"),
jsonProperty("type", "string")
)
))
)))
.build(), CustomResourceOptions.builder()
.dependsOn(
providerBootstrapSubject,
providerBootstrapRegistry)
.build());
}
}
published on Wednesday, Jun 3, 2026 by redpanda-data