kurel CLI
kurel CLI Reference
kurel is an OAM-native package manager for Kubernetes. Packages are described with
a launcher Application document (app.yaml) and an optional parameter schema
(kurel.yaml); build-time parameter substitution produces static, GitOps-ready
Kubernetes manifests.
This package defines the kurel command tree (NewKurelCommand) and entry point
(Execute). The completion and version subcommands are provided by
pkg/cmd/shared.
Command tree
kurel build
Builds static manifests from an Application (a path to app.yaml, or a directory
containing app.yaml and optionally kurel.yaml) plus a platform ClusterProfile.
Output goes to stdout by default, or to a directory with --output.
All built-in component and trait handlers are registered automatically (via
builtinComponentHandlers() / builtinTraitHandlers(), which return the library’s
exported sets from pkg/oam/builtin/registry, unfiltered; testdata/builtin-registries.txt
pins the set, TestBuiltinRegistries_TypesUnchanged), alongside the built-in lowering rules: the trait-position ones
(builtinTraitLoweringRules() — currently just expose, registered via
RegisterBuiltinTraitLowering rather than RegisterBuiltinTrait) and the
component-position ones (builtinComponentLoweringRules() — worker,
webservice, postgresql, helm and oci, registered via RegisterComponentLowering).
worker lowers to a deployment component plus, unless topologySpread: false, a
synthesized topology-spread trait. webservice lowers to a same-name deployment
and service pair, deployed as one component, with the same topology-spread
treatment on the deployment. Unless serviceAccountName is authored, both also
emit a same-name serviceaccount member for the component’s ServiceAccount, and
turn each claim a pvc volume describes into a synthesized pvc trait on the
deployment member (go-kure/launcher#702), so builtinComponentHandlers() must
register serviceaccount and the pvc trait handler must be registered. postgresql lowers to a cnpg-cluster
(plus cnpg-objectstore, cnpg-pooler and one cnpg-database per database
when authored), with a post-policy step on the cnpg-cluster for the values
postgresql derives after the policy; nothing besides the rule needs registering
for it. helm lowers to a helmrelease (plus a generated
helmrepository, ocirepository, gitrepository or bucket for an inline
source, shared within the document)
or, under delivery: template, to a helmtemplate. oci lowers to an
ocirepository and a fluxcd-kustomization (go-kure/launcher#784): a same-name
pair deployed as one component, or, when several oci components in the document
use the same artifact at the same interval, one shared ocirepository they all
reference. So builtinComponentHandlers() must register ocirepository and
fluxcd-kustomization, the kind-named projection of the Flux Kustomization,
authorable on its own; the oci fixture under testdata/ builds the pair. The built-in application policy
handlers are registered too (builtinPolicyHandlers() — dependency and placement,
registered via RegisterPolicy). Every registered handler and rule
declares a PropertySchema for its user-facing properties, so every authored
component’s, trait’s and policy’s properties are validated against it before dispatch
(a misspelt policy key such as teir fails the build). A policy type with no built-in handler —
including app-dependency, which orders one application after others and has nothing to
order against in a single-application build — fails with no handler for policy type.
The reconciliation and health-checks policies and the fluxcd-patches and
fluxcd-postbuild traits configure how Flux delivers an application, which launcher leaves
to the consumer that delivers it (go-kure/launcher#781): build has no handler for them, and
the no handler for policy type or no handler for trait type error says so.
Policies shape the bundle tree, which kurel build’s manifest
output does not include; see
Policy Handlers.
See
Component Handlers
and Trait Handlers
for the full catalogue; the deployment component — the kind-named projection
of appsv1.Deployment, alongside the role-named webservice and worker —
the service component — the kind-named projection of corev1.Service,
emitting only a Service in front of pods another component owns —
the job component — a run-to-completion workload sharing the whole
JobSpec-level surface with cronjob’s job template — and the
security-context trait were added in this release. The topology-spread
trait (launcher’s default spread constraints on any typed Deployment a
component generates, from its post-policy replica count) is registered the
same way. The force-replace trait (opt-in: it lets the delivering engine
replace an object on an immutable-field change, e.g. so a job
can be updated in place) is registered in both builtinTraitHandlers() and
pkg/oam’s trait allowlist, and force_replace_build_test.go builds a job
with and without it. The kind-named Flux source components — helmrepository,
ocirepository, gitrepository and bucket (go-kure/launcher#347), and
helmchart (go-kure/launcher#351), each emitting exactly one source CR — are
registered in both builtinComponentHandlers() and pkg/oam’s component
allowlist; the flux-sources fixture under testdata/ builds all five. The cnpg-cluster component — the full-fidelity,
opinion-free projection of a CloudNativePG Cluster — is registered in
builtinComponentHandlers() and pkg/oam’s component allowlist; the
cnpg-cluster-minimal and cnpg-cluster-full fixtures build it. Its siblings
cnpg-pooler, cnpg-database and cnpg-objectstore (one CloudNativePG
Pooler, Database or Barman Cloud ObjectStore each) are registered the same
way; the cnpg-<kind>-minimal and cnpg-<kind>-full fixtures build each. The
kind components serviceaccount, persistentvolumeclaim and configmap
(go-kure/launcher#702) are registered the same way. The secret trait
(go-kure/launcher#786), which emits one Secret beside its component, is
registered in both builtinTraitHandlers() and pkg/oam’s trait allowlist;
helm_secret_values_test.go builds it authored and as the helm component’s
secretValues lowering. Fixtures with the same names
build each one, and the pvc-volume-claimname fixture mounts a
persistentvolumeclaim through a pvc volume’s claimName.
The kind components of go-kure/launcher#790 are registered the same way. Each
but secret is built by the fixture named after it, <type>-component. The
table has one row per type, in the order of the types; a new kind’s row goes
at its position.
type | What the fixture builds |
|---|---|
alertmanager | An Alertmanager in the build namespace, and nothing else, since the operator runs the pods. What its spec says of those pods is held to the environment policy; no capability is required to build it. |
apiservice | Two APIServices with no namespace, one named by the component, <version>.<group>, and one by objectName, each handing its group and version to a Service of the metrics namespace. Only the environment policy’s object kind rules apply to it. |
artifactgenerator | Two ArtifactGenerators in the build namespace, no Flux namespace being set for the build, one named by objectName, with a pathPattern and a source of another namespace. No capability is required to build it. |
backendtlspolicy | A BackendTLSPolicy in the build namespace. No capability is required of the cluster profile to build it. |
certificate | A Certificate in the build namespace. No capability is required of the cluster profile to build it; the certificate trait, which shares the kind’s name, still requires its own. |
cilium-bgpadvertisement | A CiliumBGPAdvertisement with no namespace. No capability is required to build it. |
cilium-bgpclusterconfig | A CiliumBGPClusterConfig with no namespace. No capability is required to build it. |
cilium-bgpnodeconfigoverride | A CiliumBGPNodeConfigOverride with no namespace. No capability is required to build it. |
cilium-bgppeerconfig | A CiliumBGPPeerConfig with no namespace. No capability is required to build it. |
cilium-cidrgroup | A CiliumCIDRGroup with no namespace. No capability is required to build it. |
cilium-clusterwidenetworkpolicy | Two CiliumClusterwideNetworkPolicy objects with no namespace, one with a rule for nodes under spec, one named by objectName with two rules for endpoints under specs. No capability is required to build it. |
cilium-egressgatewaypolicy | A CiliumEgressGatewayPolicy with no namespace. No capability is required to build it. |
cilium-loadbalancerippool | A CiliumLoadBalancerIPPool with no namespace. No capability is required to build it. |
cilium-localredirectpolicy | A CiliumLocalRedirectPolicy in the build namespace. No capability is required to build it. |
cilium-networkpolicy | The authored spec and specs. The kind refuses a policy Cilium would reject when it reads it. |
cilium-nodeconfig | A CiliumNodeConfig in the build namespace. No capability is required to build it. |
clusterexternalsecret | A ClusterExternalSecret with no namespace. No capability is required of the cluster profile to build it, and it does not read the profile’s external-secret capability, which gives the external-secret trait its store. |
clusterissuer | A ClusterIssuer with no namespace. No capability is required of the cluster profile to build it. |
clusterrole | A ClusterRole with a rule of non-resource URLs and an aggregated one. No capability is required to build it, and no environment policy restricts what it grants. TestObjectName_CollidesWithAGeneratedName holds that a component of this type and an rbac trait that names the same object are refused. |
clusterrolebinding | A ClusterRoleBinding with no namespace. No capability is required to build it, and no environment policy restricts what it grants. TestObjectName_CollidesWithAGeneratedName holds that a component of this type and an rbac trait that names the same object are refused. |
clustersecretstore | A ClusterSecretStore with no namespace. No capability is required of the cluster profile to build it, and it does not read the profile’s external-secret capability, which gives the external-secret trait its store. |
cnpg-backup | Two Backup objects in the build namespace, the second named by objectName. No capability is required to build it. |
cnpg-clusterimagecatalog | Two ClusterImageCatalog objects with no namespace, the second named by objectName. No capability is required to build it. |
cnpg-databaserole | Two DatabaseRole objects in the build namespace, the second named by objectName. The fixture authors a validUntil with an offset and expects it in UTC. No capability is required to build it. |
cnpg-imagecatalog | Two ImageCatalog objects in the build namespace, the second named by objectName. No capability is required to build it. |
cnpg-publication | Two Publication objects in the build namespace, the second named by objectName. No capability is required to build it. |
cnpg-scheduledbackup | Two ScheduledBackup objects in the build namespace, the second named by objectName. No capability is required to build it. |
cnpg-subscription | Two Subscription objects in the build namespace, the second named by objectName. No capability is required to build it. |
csidriver | Each component emits one object, named after the component unless objectName names it, with no namespace. |
endpointslice | A Service named by objectName, an EndpointSlice in the build namespace whose authored kubernetes.io/service-name label holds that name as a literal, and a slice that authors only its address type. |
externalsecret | An ExternalSecret in the build namespace. No capability is required of the cluster profile to build it, and it does not read the profile’s external-secret capability, which gives the external-secret trait its store. |
fluxcd-alert | Two Alerts in the build namespace, no Flux namespace being set for the build, one named by objectName and reading the events of another namespace’s Kustomizations. No capability is required to build it. |
fluxcd-provider | Two Providers in the build namespace, no Flux namespace being set for the build, a chat provider and a git provider named by objectName, with its three Secrets, an address, a commit status expression and a timeout of ninety minutes, written 90m0s. No capability is required to build it. |
fluxcd-receiver | Two Receivers in the build namespace, no Flux namespace being set for the build, a GitHub receiver with its Secret and a generic-oidc receiver named by objectName, reconciling every labelled OCIRepository of another namespace, with an OIDC provider and an interval of two hours, written 2h0m0s. No capability is required to build it. |
gateway | A Gateway in the build namespace. No capability is required of the cluster profile to build it. |
gatewayclass | A GatewayClass with no namespace. No capability is required of the cluster profile to build it. |
grpcroute | A GRPCRoute in the build namespace attaching to a Gateway of another namespace, one rule matching a method and one splitting its traffic over two backends. No capability is required of the cluster profile to build it. |
horizontalpodautoscaler | A HorizontalPodAutoscaler in the build namespace, holding what was authored. |
httproute | The authored object and, unlike the trait of the same name, no NetworkPolicy allow rule. |
imagepolicy | Two ImagePolicies in the build namespace, no Flux namespace being set for the build, one named by objectName and selecting from the ImageRepository of another namespace. No capability is required to build it. |
imagerepository | Two ImageRepositories in the build namespace, no Flux namespace being set for the build, one named by objectName, with its three Secrets, an ACL that opens it to the namespaces of one team and a timeout of ninety minutes, written 90m0s. No capability is required to build it. |
imageupdateautomation | Two ImageUpdateAutomations in the build namespace, no Flux namespace being set for the build, one named by objectName, committing through the GitRepository of another namespace with a signing key and pushing to a branch of its own. No capability is required to build it. |
ingress | The authored object and, unlike the trait of the same name, no NetworkPolicy allow rule. |
ingressclass | Each component emits one object, named after the component unless objectName names it, with no namespace. |
issuer | An Issuer in the build namespace. No capability is required of the cluster profile to build it. |
limitrange | |
listenerset | A ListenerSet in the build namespace. No capability is required of the cluster profile to build it. |
metallb-bfdprofile | Two BFDProfile objects in the build namespace, one with every field, an authored echoMode: false among them, and one that authors nothing but its objectName. No capability is required to build it. |
metallb-bgpadvertisement | Three BGPAdvertisement objects in the build namespace: one that rolls addresses up, one with a service selector alone, and one that authors nothing but its objectName. No capability is required to build it. |
metallb-bgppeer | Two BGPPeer objects in the build namespace, at metallb.io/v1beta2: one with its address, its timers and the Secret of its password, and an unnumbered one named by objectName, which is written with the passwordSecret: {} the upstream type always encodes. No capability is required to build it. |
metallb-community | Two Community objects in the build namespace, one with three aliases, one of them a value the writer quotes (64512:10, which YAML 1.1 reads as a base-60 number where it is not quoted), and one that authors nothing but its objectName. No capability is required to build it. |
metallb-ipaddresspool | Two IPAddressPool objects in the build namespace, one with every field, one named by objectName with its addresses alone. No capability is required to build it. |
metallb-l2advertisement | Two L2Advertisement objects in the build namespace, one with every field, one named by objectName that authors nothing else and is written with an empty spec. No capability is required to build it. |
mutatingwebhookconfiguration | Two MutatingWebhookConfigurations with no namespace: a pod-injecting webhook with every field the fixture authors, reinvocationPolicy among them, and one named by objectName that holds no webhook. Only the environment policy’s object kind rules apply to it. |
namespace | |
networkpolicy | The authored spec. Unlike the trait of the same name, the kind selects every pod of the namespace when no podSelector is written. |
persistentvolume | |
pod | The authored spec and the app label. Not one of the five pod kinds named below. |
poddisruptionbudget | A PodDisruptionBudget in the build namespace, holding what was authored. |
podmonitor | A PodMonitor in the build namespace. No capability is required of the cluster profile to build it. |
podtemplate | The authored template, with no app label. Not one of the five pod kinds named below. |
priorityclass | Each component emits one object, named after the component unless objectName names it, with no namespace. |
prometheus | A Prometheus in the build namespace, its externalLabels under the spec’s own name, a Thanos sidecar image, and an excluded-from-enforcement entry with no group written with the operator’s one group. Its pods, those of every shard, are held to the environment policy as the Alertmanager’s are; no capability is required to build it. |
prometheus-probe | A Probe in the build namespace. No capability is required of the cluster profile to build it. |
prometheusrule | A PrometheusRule in the build namespace. No capability is required of the cluster profile to build it. |
referencegrant | A ReferenceGrant in the build namespace. No capability is required of the cluster profile to build it. |
replicaset | The authored spec, with the app label on the pod template. Not one of the five pod kinds named below. |
replicationcontroller | The authored spec, with the app label on the pod template. Not one of the five pod kinds named below. |
replicationdestination | Two ReplicationDestination objects in the build namespace, a Restic restore and an rsync-over-TLS receiver. No capability is required of the cluster profile to build them. |
replicationsource | Two ReplicationSource objects in the build namespace, a Restic backup on a schedule and a Syncthing source. No capability is required of the cluster profile to build them. |
resourcequota | |
resourcesetinputprovider | Two ResourceSetInputProviders in the build namespace, no Flux namespace being set for the build, a GitHub pull-request provider with its Secret, a filter and a schedule whose window of ninety minutes is written 1h30m0s, and an ExternalArtifact provider named by objectName, listing the labelled ExternalArtifacts of every namespace. No capability is required to build it. |
role | A Role with two rules and one that authors none (rules: null). No capability is required to build it, and no environment policy restricts what it grants. TestObjectName_CollidesWithAGeneratedName holds that a component of this type and an rbac trait that names the same object are refused. |
rolebinding | Two RoleBindings in the build namespace, one of them without roleRef.apiGroup (written apiGroup: ""). No capability is required to build it, and no environment policy restricts what it grants. TestObjectName_CollidesWithAGeneratedName holds that a component of this type and an rbac trait that names the same object are refused. |
runtimeclass | Each component emits one object, named after the component unless objectName names it, with no namespace. |
secret | No fixture, which would be a Secret manifest with entries: secret_twin_test.go builds it through kurel build instead. The kind is the secret trait’s twin: it emits the same Secret from the same properties, under the component’s name, and is refused under a policy that forbids explicit secrets. |
secretstore | A SecretStore in the build namespace. No capability is required of the cluster profile to build it, and it does not read the profile’s external-secret capability, which gives the external-secret trait its store. |
servicecidr | A ServiceCIDR with no namespace, holding what was authored. |
servicemonitor | A ServiceMonitor in the build namespace. No capability is required of the cluster profile to build it. |
storageclass | Each component emits one object, named after the component unless objectName names it, with no namespace. |
tcproute | Two TCPRoutes in the build namespace, one with a single backend, one named by objectName that attaches to a Gateway of another namespace and splits its traffic over two backends, one of them in another namespace. No capability is required of the cluster profile to build them. |
thanosruler | A ThanosRuler in the build namespace, its Prometheus external labels authored as externalLabels and its own labels as labels, and an excluded-from-enforcement entry with no group written with the operator’s one group. Its pods are held to the environment policy as the Alertmanager’s are; no capability is required to build it. |
tlsroute | Two TLSRoutes as the tcproute fixture’s, each naming its host names, one of them a wildcard. No capability is required of the cluster profile to build them. |
udproute | Two UDPRoutes as the tcproute fixture’s. No capability is required of the cluster profile to build them. |
validatingwebhookconfiguration | Two ValidatingWebhookConfigurations with no namespace: one whose webhook a Service serves, with a rule, a selector and a match condition, and one named by objectName whose webhook a URL serves. Only the environment policy’s object kind rules apply to it. |
volumeattributesclass | Each component emits one object, named after the component unless objectName names it, with no namespace. |
The
webservice-pvc-volumes and worker-pvc-volumes fixtures pin the claims both
role components generate, byte-identical to before the serviceaccount member
and the synthesized pvc traits. The five pod kinds generate no ServiceAccount
and no claim: their fixtures emit the workload alone, with
automountServiceAccountToken: false on the pod when no account is authored.
TestLabelReach_EveryFieldIsHeldOrListed (label_reach_test.go) holds the kind
components to the component label and the reserved metadata keys of
go-kure/launcher#790. It walks the API type of the object each kind builds from its
fixture and finds every field through which labels and annotations reach what the
cluster creates from the object: one that holds labels and annotations, and a map
of strings named for labels or annotations. Each such field is either refused through
by both checks, which a passthrough object of the kind shows; or refused through by the
reserved keys alone, as metadata an operator copies onto objects that are no pods, and
listed in labelReachReservedOnly with what it reaches; or listed in
labelReachNotRead with its reason. A field a dependency bump adds fails the test until
it is one of them, and so does a listed field no kind has any more. A field whose name and type say neither is not found; the
test lists those by hand.
Because a lowering rule may claim types the parser would otherwise reject, build
constructs the transformer BEFORE parsing the Application: newBuiltinTransformer()
runs first, and its LowerableTypes() (the kinds/component-types/trait-types claimed
by its registered lowering rules — worker, webservice, postgresql, helm and
expose today) is passed into
oam.ParseWithExtraTypes alongside the --capability-def-supplied custom trait
types. See the OAM model’s
Parsing and Lowering sections for the general mechanism.
Once the application is parsed and the profile evaluated, build calls
ValidateAuthoredPropertiesWithCapabilities with the evaluated bindings, so a
component or trait property no handler declares is a build error naming the field
and the allowed set, rather than being silently dropped (go-kure/launcher#408). The
bindings are what let a trait leave a nested required key to the capability
rendering (go-kure/launcher#765):
The same check type-checks every declared property, so a value of the wrong YAML
type fails the build instead of being coerced. A handler that reads a string
property with a lenient type assertion turns a non-string into "" and then treats
it as absent, so on such a handler alone a wrongly typed value silently becomes the
default. Through build it is rejected (go-kure/launcher#325):
In package mode this runs after parameter resolution, because an authored ${...}
placeholder is a bare string until it is substituted — checking a typed property
before that point would reject a document that is correct. See the OAM model’s
Property schemas section for what the check does and does not cover.
Platform key domain
kurel derives its platform label/annotation keys under the launcher.gokure.dev
domain: the tier annotation is launcher.gokure.dev/tier, and synthesized
NetworkPolicies select pods via launcher.gokure.dev/component, valued at the
component’s label value (the name itself at 63 characters or fewer, a projection beyond —
ComponentLabelValue in the OAM model). Every object a component owns and each of its
pod templates carries that label in the build output, and a HelmRelease carries a
post-renderer that sets it on the chart’s pod templates, so a synthesized policy selects
its component’s pods as emitted (go-kure/launcher#788); a generated source shared by the
application carries none. This is kurel’s fixed
choice over the launcher library default (gokure.dev); other embedders set their own
domain through TransformContext.Domain. See the
OAM model for the derivation
and precedence rules.
| Flag | Description |
|---|---|
--profile | Path to the ClusterProfile YAML. Required unless --environment is set; the two are mutually exclusive. |
--environment | Named environment whose profile and values stand in for --profile/--values (see Named environments). Mutually exclusive with --profile and --values. |
--environments | EnvironmentSet file declaring the --environment names (default: environments.yaml next to app.yaml). Requires --environment. |
-o, --output | Output directory (default: stdout). |
-n, --namespace | Namespace override; must be a DNS-1123 label (at most 63 characters, no dots), like metadata.namespace. |
--cluster-id | Cluster identifier (default local). |
--values | Path to a values YAML file (requires a kurel.yaml package). The only flag that can supply an array or object parameter. |
--set key=value | Set a parameter value (repeatable; requires kurel.yaml). Scalars only: an array or object parameter set this way is refused; use --values or the parameter’s default. |
--capability-def | Additional CapabilityDefinition file (repeatable). |
--strict-capabilities | Error (instead of warn) on unvalidated custom capabilities. |
With --output, the written file is named <app.Metadata.Name>.yaml inside that
directory. Metadata.Name is safe to use unescaped here because parsing already
rejects any Application whose name fails validation.IsDNS1123Subdomain (see the
OAM model’s Parsing
section) before build ever reaches the write step, so the filename can’t carry a
/ or .. path-traversal segment.
Named environments
An environments file binds a name to a ClusterProfile and, optionally, a values
file, so kurel build --environment staging replaces a script that pairs
--profile with --values by hand (go-kure/launcher#291):
--environment <name> behaves exactly as if the bound --profile and --values had
been passed: the output is byte-identical to that invocation. profile and values
are relative to the environments file’s own directory, not the working directory, and
may not leave it: an absolute path, a .. element, or a symlink whose target lies
outside that directory is an error, because the file’s content (and, by default, its
location inside the package) is not the operator’s own command line. Pass --profile/--values directly for a file elsewhere. Each name
must be a unique DNS-1123 label; profile is required, values is optional (an
Application without a kurel.yaml can still be bound to a profile, and a binding
with values on such an Application fails the same way --values does). The file is
strict-decoded and holds exactly one YAML document, so an unknown field or a trailing
--- document is an error. An explicitly empty --environment= or --environments=
(an unset variable in a wrapper script) is also an error, never read as absent.
--profile or --values together with --environment is an error rather than an
override, so a build never silently mixes an environment’s half with an explicit
flag. --set stays available and overrides the environment’s values key by key, as
it overrides --values.
The file is a deployer input, deliberately separate from kurel.yaml: the package
descriptor is the package author’s public API, while the profile belongs to whoever
operates the target cluster. Bindings carry no policy, constraint or limit model —
they name a profile+values pair and nothing more.
build generates the manifests it outputs directly from the transform result
(oam.GenerateApplications), each application once, and refuses the document when two
of its applications generate the same object (API group, kind, namespace and name): a
component and another component’s trait, two components, or two traits, which would each
deploy that object, the last applied winning. The error names the object and both
producers, and nothing is written (go-kure/launcher#646). That generation never
constructs or walks a kure layout.ManifestLayout. A component whose config implements the optional
layout.LayoutAugmenter interface fails the build outright, naming the
component, unless it also implements oam.LayoutAugmentationCoverage and
its GenerateCoversAugmentLayout() returns true — meaning its plain
Generate output is already a complete superset of whatever AugmentLayout
would otherwise add, so skipping the layout walk loses nothing. The helmtemplate component (which
only repartitions Generate’s own flat output into hook-group child layouts,
adding no resources) opts in and builds normally, and so does a helm component
under delivery: template, which lowers to it — see the
Component Handlers
helmtemplate section. Any other LayoutAugmenter that doesn’t implement
oam.LayoutAugmentationCoverage at all still fails closed, the same as before
this opt-out existed. A helm component under valuesMode: configMap is not a
LayoutAugmenter either: its values ConfigMap comes from a configmap trait
on the helmrelease it lowers to, ordinary trait output, so build emits it
after the HelmRelease. The same holds for secretValues: its values Secret
comes from a secret trait and is written to the output in clear form (base64),
so a build’s output is as sensitive as the secretValues it was given.
Warnings
A build that renders no objects warns no resources generated on stderr and writes no
<app>.yaml (one an earlier build wrote stays). A build also warns, on stderr and with
unchanged output, once per PersistentVolume or PersistentVolumeClaim that carries the Flux
force annotation itself or that the force-replace trait covers. One that carries the
annotation is force-applied: Flux deletes and recreates it on an immutable-field change, and
the warning lists the trait’s intent as a second reason where both hold. One under the
trait’s intent alone gets a conditional warning: the output carries no mapping of that
intent, so the warning describes what a consumer’s delivery workflow would do where it maps
the intent, not what the output does (go-kure/launcher#720; force_warning_test.go).
No delivery output
build writes the application’s objects and nothing that delivers them. The
--oci-repository and --oci-tag flags are gone, with the per-bundle artifact directories
and the Flux OCIRepository and Kustomization objects they wrote
(go-kure/launcher#781): how an application is delivered belongs to the consumer that
delivers it, see docs/delivery-scope.md.
The prune-protection and force-replace traits state a delivery intent on the
application (Application.Delivery, go-kure/launcher#782), which this output has no
place for: the two traits no longer show in it. A consumer that applies the output
through a Kustomization of its own loses the effect; to keep it, it builds through the
library and reads Application.Delivery.
Global flags
Available on all commands (defined in pkg/cmd/shared/options):
| Flag | Description |
|---|---|
-c, --config | Config file (default $HOME/.kurel.yaml). |
-v, --verbose | Verbose output. |
--debug | Debug output (implies verbose). |
--strict | Treat warnings as errors. |
-o, --output | Output format: yaml|json|table|wide|name. |
-f, --output-file | Write output to a file instead of stdout. |
--no-headers, --show-labels, --wide | Table-output controls. |
--dry-run | Print generated resources without writing files. |
-n, --namespace | Target namespace. |