diff --git a/README.md b/README.md
index 688e4083..c003321a 100644
--- a/README.md
+++ b/README.md
@@ -77,3 +77,11 @@ hooks are:
[pre-commit]: https://pre-commit.com/
[web-readme]: ./web/README.md
[lib-readme]: ./rust/stackable-cockpit/README.md
+
+### Templating variables
+
+| Variable | Availability | Content |
+| ----------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
+| `NAMESPACE` | Always | The namespace where the stack and demo (not the operators!) are deployed into |
+| `STACK` | Always (both in stack and demo manifests) | The name of the stack |
+| `DEMO` | In demos manifests: Always
In stack manifests: Only when deployed as part of a demo! | The name of the demo |
diff --git a/rust/stackable-cockpit/src/platform/demo/params.rs b/rust/stackable-cockpit/src/platform/demo/params.rs
index 84f54d2b..3f1486ac 100644
--- a/rust/stackable-cockpit/src/platform/demo/params.rs
+++ b/rust/stackable-cockpit/src/platform/demo/params.rs
@@ -4,6 +4,12 @@ use stackable_operator::kvp::Labels;
use crate::platform::operator::ChartSourceType;
pub struct DemoInstallParameters {
+ /// Name of the stack, which is always present, as a demo builds on top of a stack
+ pub stack_name: String,
+
+ /// Name of the demo, which is always present
+ pub demo_name: String,
+
pub operator_namespace: String,
pub demo_namespace: String,
diff --git a/rust/stackable-cockpit/src/platform/demo/spec.rs b/rust/stackable-cockpit/src/platform/demo/spec.rs
index 96107d49..bce047dc 100644
--- a/rust/stackable-cockpit/src/platform/demo/spec.rs
+++ b/rust/stackable-cockpit/src/platform/demo/spec.rs
@@ -153,13 +153,13 @@ impl DemoSpec {
.await?;
let stack_install_parameters = StackInstallParameters {
+ stack_name: self.stack.clone(),
+ demo_name: Some(install_parameters.demo_name.clone()),
operator_namespace: install_parameters.operator_namespace.clone(),
stack_namespace: install_parameters.demo_namespace.clone(),
parameters: install_parameters.stack_parameters.clone(),
labels: install_parameters.stack_labels.clone(),
skip_release: install_parameters.skip_release,
- stack_name: self.stack.clone(),
- demo_name: None,
chart_source: install_parameters.chart_source.clone(),
operator_values: install_parameters.operator_values.clone(),
};
@@ -204,6 +204,8 @@ impl DemoSpec {
&self.manifests,
¶ms,
&install_params.demo_namespace,
+ &install_params.stack_name,
+ Some(&install_params.demo_name),
install_params.labels,
client,
transfer_client,
diff --git a/rust/stackable-cockpit/src/platform/manifests.rs b/rust/stackable-cockpit/src/platform/manifests.rs
index 15fcf306..56181dde 100644
--- a/rust/stackable-cockpit/src/platform/manifests.rs
+++ b/rust/stackable-cockpit/src/platform/manifests.rs
@@ -65,11 +65,13 @@ pub enum Error {
pub trait InstallManifestsExt {
// TODO (Techassi): This step shouldn't care about templating the manifests nor fetching them from remote
#[instrument(skip_all, fields(%namespace, indicatif.pb_show = true))]
- #[allow(async_fn_in_trait)]
+ #[allow(clippy::too_many_arguments, async_fn_in_trait)]
async fn install_manifests(
manifests: &[ManifestSpec],
parameters: &HashMap,
namespace: &str,
+ stack_name: &str,
+ demo_name: Option<&str>,
labels: Labels,
client: &Client,
transfer_client: &xfer::Client,
@@ -80,9 +82,13 @@ pub trait InstallManifestsExt {
Span::current().pb_set_length(manifests.len() as u64);
let mut parameters = parameters.clone();
- // We add the NAMESPACE parameter, so that stacks/demos can use that to render e.g. the
- // fqdn service names [which contain the namespace].
+ // We need some additional templating capabilities, e.g. the namespace, so that stacks/demos
+ // can use that to render e.g. the fqdn service names [which contain the namespace].
parameters.insert("NAMESPACE".to_owned(), namespace.to_owned());
+ parameters.insert("STACK".to_owned(), stack_name.into());
+ if let Some(demo_name) = demo_name {
+ parameters.insert("DEMO".to_owned(), demo_name.into());
+ }
for manifest in manifests {
let parameters = parameters.clone();
diff --git a/rust/stackable-cockpit/src/platform/stack/params.rs b/rust/stackable-cockpit/src/platform/stack/params.rs
index 0688eba2..b3cf9717 100644
--- a/rust/stackable-cockpit/src/platform/stack/params.rs
+++ b/rust/stackable-cockpit/src/platform/stack/params.rs
@@ -5,9 +5,13 @@ use crate::platform::operator::ChartSourceType;
#[derive(Debug)]
pub struct StackInstallParameters {
- pub demo_name: Option,
+ /// Name of the stack, which is always present
pub stack_name: String,
+ /// Optional name of the demo, which is only present in case this stack is installed as part of
+ /// a demo. This is unset in case a stack is installed directly.
+ pub demo_name: Option,
+
pub operator_namespace: String,
pub stack_namespace: String,
diff --git a/rust/stackable-cockpit/src/platform/stack/spec.rs b/rust/stackable-cockpit/src/platform/stack/spec.rs
index 2bb39d62..58ace389 100644
--- a/rust/stackable-cockpit/src/platform/stack/spec.rs
+++ b/rust/stackable-cockpit/src/platform/stack/spec.rs
@@ -249,6 +249,8 @@ impl StackSpec {
&self.manifests,
¶meters,
&install_params.stack_namespace,
+ &install_params.stack_name,
+ install_params.demo_name.as_deref(),
install_params.labels,
client,
transfer_client,
diff --git a/rust/stackablectl/CHANGELOG.md b/rust/stackablectl/CHANGELOG.md
index a1e2ad53..2ff5a338 100644
--- a/rust/stackablectl/CHANGELOG.md
+++ b/rust/stackablectl/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+### Added
+
+- Add `STACK` and `DEMO` templating parameters. Have a look at the README for details ([#432]).
+
+[#432]: https://github.com/stackabletech/stackable-cockpit/pull/432
+
## [1.3.0] - 2026-03-16
### Added
diff --git a/rust/stackablectl/src/cmds/demo.rs b/rust/stackablectl/src/cmds/demo.rs
index 251a94fe..4980ff30 100644
--- a/rust/stackablectl/src/cmds/demo.rs
+++ b/rust/stackablectl/src/cmds/demo.rs
@@ -388,6 +388,8 @@ async fn install_cmd(
.context(LoadOperatorValuesSnafu)?;
let install_parameters = DemoInstallParameters {
+ stack_name: demo.stack.clone(),
+ demo_name: args.demo_name.clone(),
operator_namespace: args.namespaces.operator_namespace.clone(),
demo_namespace: args.namespaces.namespace.clone(),
stack_parameters: args.stack_parameters.clone(),
diff --git a/rust/stackablectl/src/cmds/stack.rs b/rust/stackablectl/src/cmds/stack.rs
index f4045f9a..490d74e0 100644
--- a/rust/stackablectl/src/cmds/stack.rs
+++ b/rust/stackablectl/src/cmds/stack.rs
@@ -359,12 +359,13 @@ async fn install_cmd(
.context(LoadOperatorValuesSnafu)?;
let install_parameters = StackInstallParameters {
+ stack_name: args.stack_name.clone(),
+ // There is no demo when installing only a stack
+ demo_name: None,
operator_namespace: args.namespaces.operator_namespace.clone(),
stack_namespace: args.namespaces.namespace.clone(),
- stack_name: args.stack_name.clone(),
parameters: args.parameters.clone(),
skip_release: args.skip_release,
- demo_name: None,
labels,
chart_source: ChartSourceType::from(cli.chart_type()),
operator_values,