docs: document secrets, custom_runtime_options, and remaining source/sink arguments in README - #204
Conversation
The README's `pulsar_source` and `pulsar_sink` property tables lagged the actual schema: `secrets` (and, for sources, `custom_runtime_options` and `schema_type`) have been supported since v0.2.0 (PRs streamnative#96/streamnative#97) but were never added to the README, leading users to believe credentials could only be passed via the plaintext `configs` field. - Add the missing `secrets`, `custom_runtime_options`, and `schema_type` rows to the source/sink property tables. - Add `secrets` usage to the README examples and the runnable examples under examples/sources and examples/sinks, demonstrating how to keep credentials (GSA keys, DB passwords) out of `configs` — which is persisted in plaintext in the function metadata topic, `pulsar-admin ... get` output, and state. - Add a credential-handling note explaining the SecretsProvider contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@david-streamlio:Thanks for your contribution. For this PR, do we need to update docs? |
Follow-up to the secrets/custom_runtime_options docs fix. The README property tables were still missing several supported arguments, leaving users unaware of producer/crypto tuning and dead-letter handling. - pulsar_source: add producer config (max_pending_messages, max_pending_messages_across_partitions, use_thread_local_producers, batch_builder, compression_type) and crypto config (crypto_key_reader_classname, crypto_key_reader_config, encryption_keys, producer_crypto_failure_action, consumer_crypto_failure_action) rows. - pulsar_sink: add classname, dead_letter_topic, max_redeliver_count, negative_ack_redelivery_delay_ms, retain_key_ordering, and sink_type rows. Descriptions match the schema descriptions in the resource Go files. Every top-level argument in resource_pulsar_source.go / resource_pulsar_sink.go is now represented in the README tables. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@david-streamlio:Thanks for providing doc info! |
freeznet
left a comment
There was a problem hiding this comment.
Thanks for this — the table gaps were real and the secrets-over-plaintext-configs guidance is the right thing to document.
I verified the PR's central claim mechanically rather than by eye, and it holds:
- Completeness ✅ — extracted every
resourceSource*Key/resourceSink*Keyconstant frompulsar/resource_pulsar_source.goandpulsar/resource_pulsar_sink.goand diffed against the two README tables on this branch: zero missing, zero extra top-level arguments in either (after excluding the 5 nestedinput_specssub-keys). - Descriptions ✅ — all new rows match the schema
Descriptionstrings verbatim, so README and generateddocs/resources/*.mdagree. Agreed notfplugindocsrun needed. Requiredcolumn ✅ — every new row is correctlyFalse. The onlyRequired: trueattributes are tenant/namespace/name/archive/destination_topic_name (source) and tenant/namespace/name/cleanup_subscription/archive/auto_ack (sink).- Secret shape ✅ — the documented
{ "path": ..., "key": ... }object matches what the acceptance tests already exercise (resource_pulsar_source_test.go:254,resource_pulsar_sink_test.go:237). - No perpetual-diff risk ✅ — I ran the snippets through
terraform validate/apply:jsonencodeemits compact key-sorted JSON, which matches what the read path writes back viajson.Marshal(map[string]interface{}). Both the README (:) and examples (=) forms parse fine.
Two things I'd like changed before merge, both in the examples rather than the tables:
- The
gsaKeysecret in the source example doesn't correspond to anything the connector reads. Both source examples usepulsar-io-filewithconfigs = {"inputDirectory":"opt"}— a filesystem source with no credentials at all. There was no plaintext credential to move, and the file connector never reads agsaKey. Details inline. examples/should stay runnable against the repo's own local cluster.hack/pulsar-docker.shstarts a plain Pulsar standalone (defaultDefaultSecretsProviderConfigurator→ClearTextSecretsProvider, process/thread runtime). The{path, key}indirection isKubernetesSecretsProviderConfigurator-specific — as your README note says.terraform applystill succeeds (Pulsar stores the map without resolving it at submit time), so this fails silently: the JDBC sink just gets no password at runtime. Details inline.
The rest are nits — take or leave.
One follow-up worth a separate issue, since this PR raises the security framing: configs isn't marked Sensitive: true in either schema, so its value is echoed in plan output and stored readably in state regardless of the secrets guidance. Closing that is a code change, and I'd rather not widen a docs PR into it — but the note here would be strictly stronger once it lands.
| // Reference the database password through the secrets provider rather than | ||
| // embedding it in `configs` (stored in plaintext). The sink reads it under | ||
| // the `password` secret name. | ||
| secrets = jsonencode({ |
There was a problem hiding this comment.
Nit — style drift from the convention already in the tree. examples/functions/main.tf:61 writes this as:
secrets = jsonencode(
{
"SECRET1": {
"path": "sectest"
"key": "hello"
}
})i.e. the paren on its own line and : separators — which is what your README snippets use. The two new blocks in examples/sinks/main.tf and examples/sources/main.tf use inline jsonencode({ with = instead. Both parse (I checked with terraform validate), so purely cosmetic, but worth matching the functions example so all three read the same.
| | `custom_runtime_options` | A string that encodes options to customize the runtime, see docs for configured runtime for details | False | | ||
| | `secrets` | The map of secretName to an object that encapsulates how the secret is fetched by the underlying secrets provider | False | | ||
| | `max_pending_messages` | The maximum size of a queue holding pending messages | False | | ||
| | `max_pending_messages_across_partitions` | The maximum number of pending messages across partitions | False | |
There was a problem hiding this comment.
Nit, purely cosmetic: the long new keys (max_pending_messages_across_partitions, use_thread_local_producers, crypto_key_reader_classname, and negative_ack_redelivery_delay_ms in the sink table) overflow the padded column widths the rest of the table uses, so the raw source goes ragged. Renders identically on GitHub — only worth a reflow if you want future diffs to stay clean.
- Drop the secrets block from the pulsar-io-file source examples: the file
connector reads no credentials, so a gsaKey secret would never be looked up
- Restore the working plaintext password in the sink examples so they stay
runnable against the local standalone cluster (ClearTextSecretsProvider
does not resolve {path, key} references), and show the secrets form as a
commented-out alternative for Kubernetes runtimes
- Strengthen the credential-handling note: secrets references require a
resolving SecretsProvider; the default silently provides no value
- Add type hints to custom_runtime_options, crypto_key_reader_config, and
encryption_keys table entries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N2X6fAf38zF7wtKT6qjqyL
|
Thanks for the thorough review! Addressed in 068acd5: dropped the Agreed |
|
Filed #213 to track marking |
What
The README's
pulsar_sourceandpulsar_sinkProperties tables lag the actual resource schema, so readers relying on the README believe connector credentials can only be supplied through the plaintextconfigsfield — and miss a number of other supported arguments entirely.This is a documentation gap, not a code gap: the fields are present in
pulsar/resource_pulsar_source.go/pulsar/resource_pulsar_sink.goand in the generateddocs/resources/*.md; only the README was stale.Changes (README + examples)
Credential handling (the motivating fix):
secretsrow to both source and sink property tables, pluscustom_runtime_optionsandschema_typeto the source table.secretsusage to the README examples and the runnable examples underexamples/sources/examples/sinks, moving credentials (a GSA key / DB password) out ofconfigs.configsis persisted in plaintext (function metadata topic,pulsar-admin ... getoutput, Terraform state);secretsreferences are resolved at runtime by the worker's configuredSecretsProvider(e.g.KubernetesSecretsProviderConfigurator), so only the reference is persisted.Remaining undocumented arguments:
pulsar_source— producer config (max_pending_messages,max_pending_messages_across_partitions,use_thread_local_producers,batch_builder,compression_type) and crypto config (crypto_key_reader_classname,crypto_key_reader_config,encryption_keys,producer_crypto_failure_action,consumer_crypto_failure_action).pulsar_sink—classname,dead_letter_topic,max_redeliver_count,negative_ack_redelivery_delay_ms,retain_key_ordering,sink_type.Why it matters
Embedding API keys / service-account keys / passwords in
configsexposes them in the function metadata topic,pulsar-admin sources|sinks getoutput, audit logs, and Terraform state. Documentingsecretsgives users the secure, already-supported path.secretshas been supported since v0.2.0 (PRs #96 / #97).Notes
Descriptionstrings, so README and the generateddocs/resources/*.mdagree. Notfplugindocsregeneration required.Documentation
docdoc-requireddoc-not-neededdoc-complete🤖 Generated with Claude Code