Skip to content

docs: document secrets, custom_runtime_options, and remaining source/sink arguments in README - #204

Open
david-streamlio wants to merge 4 commits into
streamnative:masterfrom
david-streamlio:docs/source-sink-secrets
Open

docs: document secrets, custom_runtime_options, and remaining source/sink arguments in README#204
david-streamlio wants to merge 4 commits into
streamnative:masterfrom
david-streamlio:docs/source-sink-secrets

Conversation

@david-streamlio

@david-streamlio david-streamlio commented Jun 5, 2026

Copy link
Copy Markdown

What

The README's pulsar_source and pulsar_sink Properties tables lag the actual resource schema, so readers relying on the README believe connector credentials can only be supplied through the plaintext configs field — 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.go and in the generated docs/resources/*.md; only the README was stale.

Changes (README + examples)

Credential handling (the motivating fix):

  • Add the secrets row to both source and sink property tables, plus custom_runtime_options and schema_type to the source table.
  • Add secrets usage to the README examples and the runnable examples under examples/sources / examples/sinks, moving credentials (a GSA key / DB password) out of configs.
  • Add a credential-handling note: configs is persisted in plaintext (function metadata topic, pulsar-admin ... get output, Terraform state); secrets references are resolved at runtime by the worker's configured SecretsProvider (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_sinkclassname, 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 configs exposes them in the function metadata topic, pulsar-admin sources|sinks get output, audit logs, and Terraform state. Documenting secrets gives users the secure, already-supported path. secrets has been supported since v0.2.0 (PRs #96 / #97).

Notes

  • Documentation only; descriptions are copied verbatim from the schema Description strings, so README and the generated docs/resources/*.md agree. No tfplugindocs regeneration required.
  • Verified with a schema-key-vs-README cross-check: every top-level argument in both resources is now represented in the README.
  • Supersedes docs: document remaining pulsar_source / pulsar_sink arguments in README #205 (consolidated here).

Documentation

  • doc
  • doc-required
  • doc-not-needed
  • doc-complete

🤖 Generated with Claude Code

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
david-streamlio requested a review from a team as a code owner June 5, 2026 17:31
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

@david-streamlio:Thanks for your contribution. For this PR, do we need to update docs?
(The PR template contains info about doc, which helps others know more about the changes. Can you provide doc-related info in this and future PR descriptions? Thanks)

@github-actions github-actions Bot added the doc-info-missing This pr needs to mark a document option in description label Jun 5, 2026
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 david-streamlio changed the title docs: document secrets and custom_runtime_options on pulsar_source / pulsar_sink docs: document secrets, custom_runtime_options, and remaining source/sink arguments in README Jun 6, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

@david-streamlio:Thanks for providing doc info!

@github-actions github-actions Bot added doc This pr contains a document and removed doc-info-missing This pr needs to mark a document option in description labels Jul 8, 2026
@david-streamlio

Copy link
Copy Markdown
Author

@maxsxu @freeznet Friendly ping when you have a moment — this is a docs-only PR (README + examples) documenting secrets and the other already-supported source/sink arguments. All checks are green and the doc label is set. Happy to adjust anything.

@freeznet freeznet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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*Key constant from pulsar/resource_pulsar_source.go and pulsar/resource_pulsar_sink.go and diffed against the two README tables on this branch: zero missing, zero extra top-level arguments in either (after excluding the 5 nested input_specs sub-keys).
  • Descriptions ✅ — all new rows match the schema Description strings verbatim, so README and generated docs/resources/*.md agree. Agreed no tfplugindocs run needed.
  • Required column ✅ — every new row is correctly False. The only Required: true attributes 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: jsonencode emits compact key-sorted JSON, which matches what the read path writes back via json.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:

  1. The gsaKey secret in the source example doesn't correspond to anything the connector reads. Both source examples use pulsar-io-file with configs = {"inputDirectory":"opt"} — a filesystem source with no credentials at all. There was no plaintext credential to move, and the file connector never reads a gsaKey. Details inline.
  2. examples/ should stay runnable against the repo's own local cluster. hack/pulsar-docker.sh starts a plain Pulsar standalone (default DefaultSecretsProviderConfiguratorClearTextSecretsProvider, process/thread runtime). The {path, key} indirection is KubernetesSecretsProviderConfigurator-specific — as your README note says. terraform apply still 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.

Comment thread examples/sources/main.tf Outdated
Comment thread examples/sinks/main.tf Outdated
Comment thread examples/sinks/main.tf Outdated
// 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({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md
| `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 |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
@david-streamlio

Copy link
Copy Markdown
Author

Thanks for the thorough review! Addressed in 068acd5: dropped the gsaKey secrets block from the source examples (the file connector reads no credentials), restored the working password in both sink examples so they run against the local standalone cluster, and moved the secrets form to a commented-out alternative with a note that {path, key} references require a resolving SecretsProvider (Kubernetes runtime). Also picked up the type-hint nits and strengthened the credentials note. Skipped the table-padding reflow to keep this diff clean — happy to do it as a follow-up.

Agreed Sensitive: true on configs deserves its own issue.

@david-streamlio
david-streamlio requested a review from freeznet July 31, 2026 16:06
@david-streamlio

Copy link
Copy Markdown
Author

Filed #213 to track marking configs as Sensitive: true, per the review discussion above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc This pr contains a document

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants