New to Kestra?
Use blueprints to kickstart your first workflows.
Audit a Quickwit index's attached sources against an approved type, alert Slack on drift, and optionally pause one named source.
A Quickwit source can only be set to kafka, kinesis, or pulsar once, that choice
cannot be changed after creation, only replaced by deleting and recreating the source.
That makes source type an easy thing to standardize on for a given environment, and an
easy thing to drift from silently, someone attaches a pulsar source to an index that is
supposed to be kafka-only, and nothing in Quickwit itself flags it. This blueprint reads
an index's real attached sources on a schedule, alerts Slack the moment one does not match
the approved type, or the index has no sources at all, and can pause one specifically
named non-compliant source without deleting it or its indexing checkpoint.
probe_index_metadata (io.kestra.plugin.quickwit.index.Get) reads the index's
configuration and the list of sources attached to it, with allowFailure: true so a
bad URL or a renamed index does not stop the flow before it can be classified as
PROBE_FAILED below.classify_index_source_compliance (io.kestra.plugin.core.debug.Return) returns
PROBE_FAILED when the probe did not return at all, NO_SOURCES when the index has
zero attached sources, NON_COMPLIANT_SOURCE_TYPE when any attached source's real
source_type does not match approved_source_type, HEALTHY otherwise.route_by_index_source_compliance (io.kestra.plugin.core.flow.Switch) branches on
that status: HEALTHY logs it, the other three each alert Slack, the
NON_COMPLIANT_SOURCE_TYPE alert lists the real source types actually found, never an
invented list. An unexpected value falls through to a defaults branch that logs it
rather than being silently dropped.remediate_gate (io.kestra.plugin.core.flow.If) runs only when the status was
NON_COMPLIANT_SOURCE_TYPE, target_source_id is set, auto_remediate is true, and
dry_run is false. It calls io.kestra.plugin.quickwit.source.Toggle with
enable: false on that one source, then re-reads the index to confirm the source is
still attached, failing the flow with io.kestra.plugin.core.execution.Fail if it is
not, rather than silently reporting success.log_audit_summary always runs last and logs the final classification.errors block posts to Slack if the flow itself fails outside the gate logic
above.Toggle stops a non-compliant source from indexing further while
keeping its checkpoint, so re-enabling it later resumes exactly where it left off.index.Get and
source.Toggle.Quickwit's own REST API will happily accept a source of any supported type on any index, it has no concept of an organization's own approved-type policy. Kestra adds that policy as a scheduled, declarative check: the probe, the classification against your approved type, the Slack alert naming the real sources found, and the optional scoped pause are all one auditable execution history.
For local testing, the official Quickwit Docker image:
mkdir qwdata
docker run --rm -v $(pwd)/qwdata:/quickwit/qwdata -p 127.0.0.1:7280:7280 \\
quickwit/quickwit:0.9.0 run
Quickwit has no authentication layer of its own, so no credentials are needed against a local node. Only add one in front of a shared or production cluster, typically a reverse proxy or API gateway, not something this blueprint configures.
An index to audit. Create one from the stackoverflow tutorial config, or any index
config of your own, via POST /api/v1/indexes or Kestra's own
io.kestra.plugin.quickwit.index.Create.
At least one source attached, to see NON_COMPLIANT_SOURCE_TYPE rather than
NO_SOURCES. io.kestra.plugin.quickwit.source.Create can attach one without a live
broker behind it, this blueprint only reads source configuration metadata, it does not
check whether the source is actually receiving data.
A Slack incoming webhook for alerts.
SLACK_WEBHOOK: Slack incoming webhook URL used by the alert tasks and the errors
block.
In Kestra OSS, set this as a base64-encoded environment variable, for example
SECRET_SLACK_WEBHOOK.
| Input | Type | Default | Allowed values |
|---|---|---|---|
quickwit_url |
STRING | http://localhost:7280 |
any reachable Quickwit base URL |
index_id |
STRING | app-logs |
any existing index ID |
approved_source_type |
SELECT | kafka |
kafka, kinesis, pulsar |
target_source_id |
STRING | `` (empty) | empty, or an existing source ID |
auto_remediate |
BOOL | false |
true, false |
dry_run |
BOOL | true |
true, false |
| Task | Output path | Description |
|---|---|---|
probe_index_metadata |
{{ outputs.probe_index_metadata.metadata.sources }} |
Sources attached to the index, each with source_id and source_type. |
classify_index_source_compliance |
{{ outputs.classify_index_source_compliance.value }} |
One of HEALTHY, NO_SOURCES, NON_COMPLIANT_SOURCE_TYPE, PROBE_FAILED. |
toggle_disable_source |
{{ outputs.toggle_disable_source.enable }} |
false once the remediation toggle call completes. |
verify_source_still_exists |
{{ outputs.verify_source_still_exists.metadata.sources }} |
Source list re-read after the toggle, used to confirm target_source_id is still attached. |
source_type: pulsar (or any type other
than your approved_source_type) using io.kestra.plugin.quickwit.source.Create.SLACK_WEBHOOK secret.NON_COMPLIANT_SOURCE_TYPE
and list pulsar as the source type found.target_source_id to that source's ID, auto_remediate: true, and dry_run: false, then run it again, it should pause the source and log the verified result.every_15_minutes trigger.io.kestra.plugin.core.flow.Loop to audit
every index in a cluster from one flow.num_pipelines against an approved maximum, a source with far more
pipelines than expected can be a sign of a misconfigured deployment.io.kestra.plugin.quickwit.source.Toggle with enable: true in a separate,
explicitly triggered flow once an operator has reviewed and approved the non-compliant
source, rather than auto-re-enabling here.index.Get response exposes no enabled or disabled flag for a source, only
its configuration. report_remediation_result can confirm the toggled source still
exists after the call, it cannot independently confirm from this plugin that indexing
actually paused.source_type cannot be changed after a source is created, only replaced by deleting and
recreating it. This gate flags a non-compliant type, it cannot fix it by changing the
type in place.NO_SOURCES and NON_COMPLIANT_SOURCE_TYPE are mutually exclusive in this
classification, an index with zero sources is always reported NO_SOURCES even if that
is itself the intended, static-ingestion state for that index.kafka source that stopped actually consuming from its topic reports HEALTHY here.