-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zarf Component Chart Values/Outputs #1137
Comments
Love this for passing information from one component to the next within a single Zarf package. Zarf's build-time constants and deploy-time variables are great but lacking when a component produces something dynamic that needs to be consumed by a downstream component. The first option described feels too brittle. The second option with saved outputs is a better / more generic solution. Take, for bad example, Zarf component graph TD;
terraform-->needs-db;
on-prem-->needs-db;
I would be interested in expanding this capability. Has there been thought/debate on adding a simple Using the bad example above, upgrading the This |
I think the second option - name: foobar
description: "Sample terraform that creates things that we'll need later"
required: true
terraform:
module: ./terraform/
output:
baz: number
- name: script
description: "This is a zebra and they have ###ZARF_PKG_VAR_BAZ###"
would work well for the exact reasons you mentioned. it allows for better flexibility in HOW those variables get set and allow for better component composibility. For implementation details, would the ZarfComponent's each need to implement their own // ZarfChart defines a helm chart to be deployed.
type ZarfChart struct {
Name string `json:"name" jsonschema:"description=The name of the chart to deploy; this should be the name of the chart as it is installed in the helm repo"`
ReleaseName string `json:"releaseName,omitempty" jsonschema:"description=The name of the release to create; defaults to the name of the chart"`
Url string `json:"url,omitempty" jsonschema:"oneof_required=url,description=The URL of the chart repository or git url if the chart is using a git repo instead of helm repo"`
Version string `json:"version" jsonschema:"description=The version of the chart to deploy; for git-based charts this is also the tag of the git repo"`
Namespace string `json:"namespace" jsonschema:"description=The namespace to deploy the chart to"`
ValuesFiles []string `json:"valuesFiles,omitempty" jsonschema:"description=List of values files to include in the package; these will be merged together"`
GitPath string `json:"gitPath,omitempty" jsonschema:"description=The path to the chart in the repo if using a git repo instead of a helm repo"`
LocalPath string `json:"localPath,omitempty" jsonschema:"oneof_required=localPath,description=The path to the chart folder"`
NoWait bool `json:"noWait,omitempty" jsonschema:"description=Wait for chart resources to be ready before continuing"`
+ Outputs map[string]string `json:"outputs,omitempty" jsonschema:"description=outputs from the component to be saved as variables"`
}
// ZarfManifest defines raw manifests Zarf will deploy as a helm chart
type ZarfManifest struct {
Name string `json:"name" jsonschema:"description=A name to give this collection of manifests; this will become the name of the dynamically-created helm chart"`
Namespace string `json:"namespace,omitempty" jsonschema:"description=The namespace to deploy the manifests to"`
Files []string `json:"files,omitempty" jsonschema:"description=List of individual K8s YAML files to deploy (in order)"`
KustomizeAllowAnyDirectory bool `json:"kustomizeAllowAnyDirectory,omitempty" jsonschema:"description=Allow traversing directory above the current directory if needed for kustomization"`
Kustomizations []string `json:"kustomizations,omitempty" jsonschema:"description=List of kustomization paths to include in the package"`
NoWait bool `json:"noWait,omitempty" jsonschema:"description=Wait for manifest resources to be ready before continuing"`
+ Outputs map[string]string `json:"outputs,omitempty" jsonschema:"description=outputs from the component to be saved as variables"`
} so that the Zarf.yaml could be components:
- name: component-name
charts:
- name: chart-name
localPath: path/to/chart
output:
baz: ".Release.Name" // not sure I love the chart templating engine here, but it seems powerful
istio: ".Values.istio.enabled" |
I think the output sub block of option 2 could work well, but I would argue that we shouldn't re-template the zarf.yaml file if we can avoid it. IMO these would become component variables (template-able with |
Agree with @Racer159 variables would be saner than package variables because of how they work under the hood. Also thinking about how you actually map outputs, what would that look like? How would we know to map things say given a helm chart install or script run, how would we know how to handle multiple outputs? Would there be some |
I think we could just handle them globally for now (requiring people to name them appropriately for now) such that any downstream component that used a ZARF_VAR_ with that name would just get templated with it. To me picking up the correct string (which I think this should be limited to for now) would be the tougher part across all of the various technologies Zarf uses. For helm charts something like this could make sense: components:
- name: component-name
charts:
- name: chart-name
localPath: path/to/chart
outputs:
- name: BAZ
file: Chart.yaml
key: ".Release.Name"
- name: ISTIO
file: values.yaml
key: ".Values.istio.enabled" Don't love them under each and every type of thing though since you would also need it for files, manifests and more potentially... |
I was picturing something more crafted to each type of component rather than making outputs generic/consistent across all the components. This would obvious require a lot of documentation and nuance, but each type of ZarfComponent has its own type of data that would be useful to export, and it might be easier/more flexible to allow each component to define how to define that... but that does create some frustrations when trying to get exports from different types of components TerraformAny of the outputs available from the terraform module Chart
Files
Scripts
Manifests
Plugins
In my head this is the back and forth between Zarf (global) and the components: graph
subgraph zarfcomponent[Zarf Component1]
Template[Template Component] --> ComponentDeploy[Deploy Component]
ComponentDeploy --> CheckStatus[Check Deploy Result]
CheckStatus --> CreateOutputs[Create Outputs Map]
end
subgraph zarfcomponent2[Zarf Component2]
Template2[Template Component] --> ComponentDeploy2[Deploy Component]
ComponentDeploy2 --> CheckStatus2[Check Deploy Result]
CheckStatus2 --> CreateOutputs2[Create Outputs Map]
end
subgraph zarf
load[Load Zarf.yaml] --> LoadVariables
LoadVariables --> Compose
Compose[Compose Components] --> Deploy
Deploy --Pass Global Variables --> Template
CreateOutputs --Pass Outputs Back --> CheckResults
CheckResults[Check Result] --> UpdateVariables
UpdateVariables[Update Global Vars] --> Deploy2
Deploy2[Deploy] --Pass Global Variables --> Template2
CreateOutputs2 --Pass Outputs Back --> CheckResults2
CheckResults2[Check Result] --> UpdateVariables2[Update Global Vars]
end
|
Instead of placing outputs at each type of thing, does it make sense for the component to have an outputs block and implement different ways to populate the outputs? The example below could work for Terraform outputs and a Helm value.
Tangentially, has there been any consideration for component upgrades? Assume component |
This PR is also looking to provide the ability to create new variables inside of @jeff-mccoy will this capability be able to be used for non-action components by chaining them together as separate components: - name: helm
chart:
...
- name: export-variable
actions:
onDeploy:
before:
- cmd: "helm get values -n bigbang bigbang | jq .istio.enabled"
setVariable: ISTIO_ENABLED or will the action command have a known running order (before or after) that would let things like: - name: helm
chart:
...
actions:
onDeploy:
before:
- cmd: "helm get values -n bigbang bigbang | jq .istio.enabled"
setVariable: ISTIO_ENABLED
|
@runyontr that's correct, as soon as you set the value in an action, the very next action and any future component can access the value. I was actually wondering how best to grab the data from something like helm and this answer that question. I would like to explore handling multiple variables at once, something like - name: helm
chart:
...
actions:
onDeploy:
before:
- cmd: "helm get values -n bigbang bigbang -o json"
setJSONValues: BIGBANG |
We don't need that to be in this PR, I just wanted to establish basic structure for the actions conversion in this first PR. |
After we settle on this implementation, I think we can reasonably talk about KV persistence from a package deployment. We would have to ensure uniqueness, so that will be a challenge, but I imagine something along the lines of kind: ZarfPackageConfig
metadata:
name: component-actions
description: "Component actions examples"
peristVariables: true We could use the package name, but it's not a very strong guarantee of uniqueness. Alternatively, we could require something like "package name + some provided unique key" or a hash of the package metadata, etc. |
This would actually be pretty cool. Something like this would be really powerful:
|
that's probably a smarter way to do it tbh 😆 |
I bet we have enough helm code in the codebase to actually make that more native too...pull that out of actions even. |
This kinda goes back to the conversation we were having around: Does each noun have its own "output" ability that's coded (e.g. the values, or helm name), or is there a generic way to make outputs that's implemented globally. I like this structure, but it could be something like:
where the string that's provided to the It would also localize implementation detail for that capability once plugins become a thing and we can provide each plugin its own ability to export values |
Yeah I feel pretty strongly we should be consistent with the verb here. We did |
For example, instead of |
We already internally use just
|
Yeah though I still think |
I actually think there is room for both |
## Related Issues Related to #939 Fixes #1137, #1022 ### Backwards compatible replacement of simple `scripts` with complex `actions` - [x] Define types - [x] `package create` transparent migration - [x] `package deploy` transparent migration - [x] Introduce deprecation pattern into `src/pkg/packager` - [x] Package`Create` actions: `Before`, `After`, `Success`, `Failure` - [x] Package`Deploy` actions: `Before`, `After`, `Success`, `Failure` - [x] Package`Remove` actions: `Before`, `After`, `Success`, `Failure` ### Other refactors - [x] Expand exec to support env variables, add config struct - [x] Add common cmd defaults - [x] Add set working dir support - [x] Inject deploy-time variables as env variables for `onDeploy` - [x] Expand sha256sum function to support any generic crypto hash type Co-authored-by: Wayne Starr <[email protected]> Co-authored-by: Jon Perry <[email protected]>
As a package developer, I would like to be able to reference objects that were created by previous components.
For example, as part of #939, the ability to define a terraform component that creates cloud resources for an application, e.g. an RDS database and then inject the credentials for that database correctly into the application as one component, would provide the ability for a Zarf package creator to declare how the application should be run in production.
Explicitly, when deploying a terraform module like this,
I would like to be able to use the outputs from the terraform module.
In this example, the component named
foobar
has terraform outputs available that get templated like variables. This could be done via a new type of variable outlined by###ZARF_COMPONENT_<NAME>_<TYPE>_OUTPUT_<OUTPUTNAME>###
.Another option could be to add definitions to have the outputs be saved as a variable with a definition like:
Where the variable
baz
is assigned the output of thenumber
output from the terraform module and then treated like a variable.The text was updated successfully, but these errors were encountered: