diff --git a/.gitignore b/.gitignore index 3cea691091..ac25255d7d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ *.tgz *.vbox *.zst +*.zim assets/ build bundle/ diff --git a/Makefile b/Makefile index 39b722244e..267af39f17 100644 --- a/Makefile +++ b/Makefile @@ -130,7 +130,7 @@ build-examples: ## Build all of the example packages @test -s ./build/zarf-package-variables-$(ARCH).tar.zst || $(ZARF_BIN) package create examples/variables --set NGINX_VERSION=1.23.3 -o build -a $(ARCH) --confirm - @test -s ./build/zarf-package-data-injection-$(ARCH).tar || $(ZARF_BIN) package create examples/data-injection -o build -a $(ARCH) --confirm + @test -s ./build/zarf-package-kiwix-$(ARCH)-3.5.0.tar || $(ZARF_BIN) package create examples/kiwix -o build -a $(ARCH) --confirm @test -s ./build/zarf-package-git-data-$(ARCH)-0.0.1.tar.zst || $(ZARF_BIN) package create examples/git-data -o build -a $(ARCH) --confirm diff --git a/docs/0-zarf-overview.md b/docs/0-zarf-overview.md index 354f7f0e48..7d9d8c13b7 100644 --- a/docs/0-zarf-overview.md +++ b/docs/0-zarf-overview.md @@ -67,7 +67,7 @@ Given Zarf's being a "K8s cluster to serve _other_ K8s clusters", the following - Pre-compiled binaries: to provide the software necessary to start and support the Zarf cluster. - [Component actions](3-create-a-zarf-package/7-component-actions.md): to support scripts and commands that run at various stages of the Zarf [package create lifecycle](./3-create-a-zarf-package/5-package-create-lifecycle.md), and [package deploy lifecycle](./4-deploy-a-zarf-package/1-package-deploy-lifecycle.md). - Helm charts, kustomizations, and other K8s manifests: to apply in a Kubernetes cluster. -- [Data injections](../examples/data-injection/README.md): to declaratively inject data into running containers in a Kubernetes cluster. +- [Data injections](../examples/kiwix/README.md): to declaratively inject data into running containers in a Kubernetes cluster. ## How To Use Zarf diff --git a/docs/3-create-a-zarf-package/2-zarf-components.md b/docs/3-create-a-zarf-package/2-zarf-components.md index 28ebfad75d..31db494afe 100644 --- a/docs/3-create-a-zarf-package/2-zarf-components.md +++ b/docs/3-create-a-zarf-package/2-zarf-components.md @@ -160,7 +160,7 @@ The [`podinfo-flux`](/examples/podinfo-flux/) example showcases a simple GitOps - + ### Component Imports diff --git a/docs/3-create-a-zarf-package/7-component-actions.md b/docs/3-create-a-zarf-package/7-component-actions.md index a286f6925b..39162a6b1f 100644 --- a/docs/3-create-a-zarf-package/7-component-actions.md +++ b/docs/3-create-a-zarf-package/7-component-actions.md @@ -1,6 +1,10 @@ +import ExampleYAML from '@site/src/components/ExampleYAML'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Component Actions -Component Actions offer several exec entrypoints that allow a component to perform additional logic at key stages of its lifecycle. These actions are executed within the same context as the Zarf binary. For a detailed overview of the execution sequence of component actions, please refer to the Zarf [package create lifecycle documentation](./5-package-create-lifecycle.md), [package deploy lifecycle documentation](../4-deploy-a-zarf-package/1-package-deploy-lifecycle.md). Additionally, you can experiment with the component actions example located in the [Component Actions](../../examples/component-actions/README.md) example page. +Component Actions offer several exec entrypoints that allow a component to perform additional logic at key stages of its lifecycle. These actions are executed within a shell with the same context as the Zarf binary. For a detailed overview of the execution sequence of component actions, please refer to the Zarf [package create lifecycle documentation](./5-package-create-lifecycle.md) and [package deploy lifecycle documentation](../4-deploy-a-zarf-package/1-package-deploy-lifecycle.md). Additionally, you can experiment with the component actions example located in the [Component Actions](../../examples/component-actions/README.md) example page. ## Action Sets @@ -10,112 +14,33 @@ The `component.actions` field includes the following optional keys, also known a - `onDeploy` - Runs during `zarf package deploy`. - `onRemove` - Runs during `zarf package remove`. -## Action Lists +### Action Set Lists -These `action sets` contain optional `action` lists. The `onSuccess` and `onFailure` action lists are conditional and rely on the success or failure of previous actions within the same component, as well as the component's lifecycle stages. +These `action sets` contain optional `action lists`. The `onSuccess` and `onFailure` action lists are conditional and rely on the success or failure of previous actions within the same component, as well as the component's lifecycle stages. - `before` - sequential list of actions that will run before this component is processed for `create`, `deploy`, or `remove`. - `after` - sequential list of actions that will run after this component is successfully processed for `create`, `deploy`, or `remove`. - `onSuccess` - sequential list of actions that will run after **ALL** `after` actions have successfully completed. - `onFailure` - sequential list of actions that will run after **ANY** error during the above actions or component operations. -Below are some examples of `action` lists and their usages: - -```yaml -components: - - name: on-create - actions: - # runs during "zarf package create" - onCreate: - # runs before the component is created - before: - # on Windows, touch is replaced with New-Item - - cmd: touch test-create-before.txt - # dir is the directory to run the command in - dir: '' - # this environment variable will be set for this action only - env: - - 'thing=stuff' - # the number of times to retry the action if it fails - maxRetries: 0 - # the maximum amount of times the action can run before it is killed, including retries - maxTotalSeconds: 30 - # determine if actions output should be printed to the console - mute: false - # runs after the component is deployed - after: - - cmd: touch test-create-after.txt - - - name: on-deploy-with-dynamic-variable - actions: - # runs during "zarf package deploy" - onDeploy: - # runs before the component is deployed - before: - # setVariables can be used to set variables for use in other actions or components (only onDeploy) - - cmd: echo "meow" - setVariables: - - name: CAT_SOUND - # these variables can also (optionally) be marked as sensitive to sanitize them in the Zarf log - sensitive: true - # NOTE: when including a variable in a command output this will be written to the log regardless of the sensitive setting - # - use `mute` to silence the command output for sensitive variables - - cmd: echo "the cat says ${ZARF_VAR_CAT_SOUND}" - mute: true - - - name: on-deploy-with-timeout - description: This component will fail after 1 second - actions: - # runs during "zarf package deploy" - onDeploy: - # defaults allow you to specify default values for the actions in that acitonSet - defaults: - # maxTotalSeconds is the maximum amount of time the action can run before it is killed, including retries - maxTotalSeconds: 1 - # maxRetries is the maximum number of times the action will be retried on failure - maxRetries: 3 - before: - # this action will fail after 1 second - - cmd: sleep 30 - onFailure: - - cmd: echo "😭😭😭 this action failed because it took too long to run 😭😭😭" -``` - -## Action Set Defaults - -In addition to the `action` lists above, an `action set` also contains a `defaults` section that will be applied to all actions in the set. The `defaults` section contains all of the same elements as an action configuration, with the exception of the `cmd` element, which is not allowed in the `defaults` section. Below is an example of `action set` defaults: - -```yaml -actions: - onCreate: - defaults: - # Set the default directory for all actions in this action set (onCreate) - dir: dir-1 - before: - # dir-1 will be used for these action - - cmd: echo "before" - # dir-2 will be used for this action - - cmd: echo "before" - dir: dir-2 - after: - # dir-1 will be used for these actions - - cmd: echo "after" - onDeploy: - before: - # this action will use the current working directory - - cmd: echo "before" -``` - -## Common Action Configuration Keys - -The following keys are common to all action configurations (wait or command): +### Action Set Defaults + +In addition to `action lists`, `action sets` can also specify a `defaults` section that will be applied to all actions in the set. The `defaults` section contains all of the same elements as an action configuration, with the exception of the action specific keys like `cmd`, `description` or `wait`, which are not allowed in the `defaults` section. + +## Action Configurations + +An `action list` contains an ordered set of `action configurations` that specify what a particular action will do. In Zarf there are two action types (`cmd` and `wait`), the configuration of which is described below. + +### Common Action Configuration Keys + +Between all action configurations, there are a few common keys that are common to all of them which are described below: - `description` - a description of the action that will replace the default text displayed to the user when the action is running. For example: `description: "File to be created"` would display `Waiting for "File to be created"` instead of `Waiting for "touch test-create-before.txt"`. - `maxTotalSeconds` - the maximum total time to allow the command to run (default: `0` - no limit for command actions, `300` - 5 minutes for wait actions). -## Command Action Configuration +### `cmd` Action Configuration -A command action executes arbitrary commands or scripts within a shell wrapper. You can use the `cmd` key to define the command(s) to run. This can also be a multi-line script. _You cannot use `cmd` and `wait` in the same action_. +A `cmd` action executes arbitrary commands or scripts within a shell wrapper. You can use the `cmd` key to define the command(s) to run. This can also be a multi-line script. _You cannot use `cmd` and `wait` in the same action_. Within each of the `action` lists (`before`, `after`, `onSuccess`, and `onFailure`), the following action configurations are available: @@ -125,8 +50,15 @@ Within each of the `action` lists (`before`, `after`, `onSuccess`, and `onFailur - `maxRetries` - the maximum number of times to retry the command if it fails (default: `0` - no retries). - `env` - an array of environment variables to set for the command in the form of `name=value`. - `setVariables` - set the standard output of the command to a list of variables that can be used in other actions or components (onDeploy only). +- `shell` - set a preferred shell for the command to run in for a particular operating system (default is `sh` for macOS/Linux and `powershell` for Windows). + +:::note + +Any binaries you execute in your `cmd` actions must exist on the machine they are executed on. You can bring binaries with a Zarf Package as `files` with the `executable` key set, or take advantage of the `./zarf ` transformation as described in [action transformations](#action-transformations). -## Wait Action Configuration +::: + +### `wait` Action Configuration The `wait` action temporarily halts the component stage it's initiated in, either until the specified condition is satisfied or until the maxTotalSeconds time limit is exceeded (which, by default, is set to 5 minutes). To define `wait` parameters, execute the `wait` key; it's essential to note that _you cannot use `cmd` and `wait` in the same action_. Essentially, a `wait` action is _yaml sugar_ for a call to `./zarf tools wait-for`. @@ -143,61 +75,101 @@ Within each of the `action` lists (`before`, `after`, `onSuccess`, and `onFailur - `address` - the address/port to wait for (required). - `code` - the HTTP status code to wait for if using `http` or `https`, or `success` to check for any 2xx response code (default: `success`). ---- +## Action Examples -## Creating Dynamic Variables from Actions +Below are some examples of putting together simple actions at various points in the Zarf lifecycle: -You can use the `setVariables` action configuration to set a list of variables that can be used in other actions or components during `zarf package deploy`. The variable will be assigned values in two environment variables: `ZARF_VAR_{NAME}` and `TF_VAR_{name}`. These values will be accessible in subsequent actions and can be used for templating in files or manifests in other components as `###ZARF_VAR_{NAME}###`. This feature allows package authors to define dynamic runtime variables for consumption by other components or actions. _Unlike normal variables, these do not need to be defined at the top of the `zarf.yaml`._ + + -## Additional Action Examples +Below is a simple example of an `onCreate` action set that declares `defaults` as well as `before` and `after` action lists: -### `onCreate` + + + -The `onCreate` action runs during `zarf package create` and allows a package creator to run commands during package creation. For instance, if a large data file must be included in your package, the following example (with the URL updated accordingly) can be used: +Below is an example of an `onDeploy` action set that demonstrates how you can use `onFailure` actions to perform cleanup tasks or user messaging when an action of component lifecycle step fails: -```yaml -components: - - name: on-create-example - actions: - onCreate: - before: - - cmd: 'wget https://download.kiwix.org/zim/wikipedia_en_100.zim' -``` + + + -### `onDeploy.before` +Below are examples of waiting for resources to exist or be available within an action using `wait` actions: -The `onDeploy` action runs during `zarf package deploy` and allow a package to execute commands during component deployment. + + + + -You can use `onDeploy.before` to execute a command _before_ the component is deployed. The following example uses the `eksctl` binary to create an EKS cluster. The package includes the `eks.yaml` file, which contains the cluster configuration: +## Action Transformations -```yaml -components: - - name: before-example - actions: - onDeploy: - before: - - cmd:"./eksctl create cluster -f eks.yaml" -``` +As you may have noticed mentioned in the `before` action list of the above `Simple onCreate` example, Zarf provides some helpful transformations that help enhance cross-platform compatibility and allow you to better orchestrate Zarf and its components. -### `onDeploy.after` +Below are the transformations that Zarf will make on an action before it is ran: -The `onDeploy.after` can be used to execute a command _after_ the component is deployed. This can be useful for resource cleanup of any temporary resources created during the deployment process: +- Replace `./zarf ` with the path to the currently running Zarf executable. + - This allows you to run Zarf in Zarf and is designed to help you use `zarf tools` commands in the air gap. +- Replace common Unix commands and shell syntax with `powershell` / `pwsh` alternatives on Windows. + - This allows commands like `touch` to work on Windows and while not perfect enhances cross-platform capabilities. +- Add `env` entries for all previously declared Zarf `variables`. + - This allows you to use variables in actions and when combined with `setVariables` allows you to chain `variables` from an action for use in later actions or templates. -```yaml -components: - - name: prepare-example - actions: - onDeploy: - after: - - cmd: 'rm my-temp-file.txt' -``` + -### `onRemove` + -The `onRemove` action runs during `zarf package remove` and allows a package to execute commands during component removal. +Within `onDeploy` action lists, you can use the `setVariables` action configuration to set a list of variables that can be used in other actions or components during `zarf package deploy`. The variable value will be assigned in two environment variables: `ZARF_VAR_{NAME}` and `TF_VAR_{name}`. These values will be accessible in subsequent actions and can be used for templating in `files` or `manifests` in other components as `###ZARF_VAR_{NAME}###`. This feature allows package authors to define dynamic runtime variables for consumption by other components or actions. :::note -Any binaries you execute in your actions must exist on the machine they are executed on. +Unlike normal variables, `setVariables` do not need to be defined with the `variables` key at the top of the `zarf.yaml`. ::: + + + + + + +Below is an example of an `onRemove` action set that demonstrates how you can use `./zarf ` to use Zarf commands like `zarf tools kubectl` to perform actions on systems that might not have the pre-requisite software (like `kubectl`) installed onto them: + + + + + + +--- + +## Additional Action Use Cases + +Below are a few more use cases from other `examples` and `packages` for how actions can be used: + + + + + +The below example shows the `kiwix-serve` component from the data injections example which downloads a `.zim` file with an `onCreate.before` action for inclusion into the Zarf package. + + + + + + + + +The below example includes the `eksctl` binary and `eks.yaml` file in one component, setting it up in an `onDeploy.after` action and then uses the `eksctl` binary in a second component to create an EKS cluster in an `onDeploy.before` action. + + + + + + + + +The below example shows using a `wait` command to wait for a GitOps deployment to happen after Zarf configures the initial `GitRepository` manifest. By default Zarf will only track the resources it directly deploys, but adding a `wait` action allows you to control the lifecycle more directly. + + + + + + diff --git a/examples/component-actions/README.md b/examples/component-actions/README.md index 71fbe8c2ba..1d8d12652a 100644 --- a/examples/component-actions/README.md +++ b/examples/component-actions/README.md @@ -4,7 +4,7 @@ import ExampleYAML from '@site/src/components/ExampleYAML'; :::note -Component Actions have replaced Component Scripts. Zarf will still read scripts entries, but will convert them to actions. Component Scripts will be removed in a future release. Please update your package configurations to use Component Actions instead. +Component Actions have replaced Component Scripts. Zarf will still read `scripts` entries, but will convert them to `actions`. Component Scripts will be removed in a future release. Please update your package configurations to use Component Actions instead. ::: diff --git a/examples/component-actions/zarf.yaml b/examples/component-actions/zarf.yaml index 5873ea9e96..8670cd1440 100644 --- a/examples/component-actions/zarf.yaml +++ b/examples/component-actions/zarf.yaml @@ -13,47 +13,54 @@ components: actions: # runs during "zarf package create" onCreate: - # defaults are applied to all actions in this actionSet + # defaults are applied to all actions in this action set - below are the default defaults defaults: dir: "" env: [] maxRetries: 0 - maxTotalSeconds: 30 + maxTotalSeconds: 300 + mute: false + shell: + darwin: sh + linux: sh + windows: powershell # runs before the component is created before: - # on Windows, touch is replaced with New-Item + # on Windows with `pwsh` or `powershell`, `touch` is replaced with New-Item - cmd: touch test-create-before.txt + # description shows a more user friendly message when waiting for the command + description: Create a test file # dir is the directory to run the command in dir: "" - # this environment variable will be set for this action only + # env sets environment variables for this action only env: - thing=stuff - # the number of times to retry the action if it fails + # maxRetries is the number of times to retry the action if it fails maxRetries: 0 - # the maximum amount of times the action can run before it is killed, including retries + # maxTotalSeconds is the maximum amount of times the action can run before it is killed, including retries maxTotalSeconds: 30 - # determine if actions output should be printed to the console + # mute determine if actions output should be printed to the console mute: false - # runs after the component is deployed + # shell sets the preferred shell across operating systems, in this case "pwsh" instead of "powershell" on Windows + shell: + windows: pwsh + # runs after the component is created after: + # actions in a list run in order - cmd: touch test-create-after.txt - - cmd: sleep 1 + - cmd: sleep 0.5 - cmd: echo "I can print!" - # prefer to run the above command in "cmd" instead of "powershell" on Windows - shell: - windows: cmd - - cmd: sleep 1 + - cmd: sleep 0.5 + # cmd actions can also specify a multiline string to run like a script - cmd: | echo "multiline!" - sleep 1 + sleep 0.5 echo "updates!" - sleep 3 - echo "in!" sleep 1 + echo "in!" + sleep 0.5 echo "realtime!" - sleep 1 - description: multiline & description demo - - cmd: sleep 1 + sleep 0.5 - name: on-deploy-and-remove actions: @@ -105,18 +112,21 @@ components: # setting this variable will allow it to be used in other actions with additional variables # set in other actions or components - cmd: echo "hiss" + # setVariables defines a list of variables to set from the `cmd` standard out. setVariables: - name: SNAKE_SOUND - # You can also mark variables as sensitive to prevent them from being output in the Zarf log + # marks this variable as sensitive to prevent it from being output in the Zarf log sensitive: true + # autoIndent tells Zarf to maintain spacing for any newlines when templating into a yaml file + autoIndent: true # onSuccess will only run if steps in this component are successful onSuccess: - # this action will have access to the variables set in a previous component + # this action will print the CAT_SOUND variable that was set in a previous component - cmd: echo "the cat says ${ZARF_VAR_CAT_SOUND}" - # this action will have access to the variables set at the top of the zarf.yaml file + # this action will print the DOG_SOUND variable set at the top of the zarf.yaml file - cmd: echo "the dog says ${ZARF_VAR_DOG_SOUND}" - # this action will have access to the variables set within this component - # NOTE: when including a variable in a command output this will be written to the log regardless of the sensitive setting + # this action will print the SNAKE_SOUND variable set within this component + # > NOTE: when including a variable in a command output this will be written to the log regardless of the sensitive setting # - use `mute` if you want to silence the command output for sensitive variables - cmd: echo "the snake says ${ZARF_VAR_SNAKE_SOUND}" # variables are also exposed as TF_VAR_name for terraform, note the lowercase variable name @@ -147,7 +157,7 @@ components: - cmd: echo "😭😭😭 this action failed because it took too long to run 😭😭😭" - name: on-remove - # A manifest so we can test the onRemove action + # A manifest that we expect to be removed by Zarf manifests: - name: test-configmap files: @@ -156,10 +166,10 @@ components: # runs during "zarf package remove" onRemove: before: - # because this runs before remove this should be found + # because this runs before the manifest is removed this should return our manifest - cmd: ./zarf tools kubectl get configmap -n zarf remove-test-configmap || echo "Not Found" after: - # because this runs after remove this should no longer be found + # because this runs after the manifest is removed this should no longer be found - cmd: ./zarf tools kubectl get configmap -n zarf remove-test-configmap || echo "Not Found" - name: on-deploy-with-env-var @@ -179,6 +189,7 @@ components: - description: Cloudflare 1.1.1.1 site to be available maxTotalSeconds: 15 wait: + # wait for a network address to return a 200 OK response network: protocol: https address: 1.1.1.1 @@ -196,6 +207,7 @@ components: - description: The simple-configmap to exist maxTotalSeconds: 5 wait: + # wait for the configmap to be available in the cluster cluster: kind: configmap name: simple-configmap diff --git a/examples/data-injection/README.md b/examples/data-injection/README.md deleted file mode 100644 index ea6f286c69..0000000000 --- a/examples/data-injection/README.md +++ /dev/null @@ -1,25 +0,0 @@ -import ExampleYAML from "@site/src/components/ExampleYAML"; - -# Data Injection - -This example shows Zarf's ability to inject data into a container running in a pod. This allows for data that is not included in the container image to be injected at deploy time. - -Data injections are declared using the `dataInjections` key within a component, and once the specified container is started, Zarf will copy the files and folders from the specified source into the specified container and path. - -:::caution - -This feature depends on the `tar` (and for `compress`, `gzip`) executables and their implementation across operating systems. Between macOS and Linux there is general agreement on how these utilities should function, however on Windows you may see issues enabling compression. - -To resolve this you can either disable compression or use the GNU core-utils version of `tar` and `gzip`. - -::: - -## `zarf.yaml` {#zarf.yaml} - -:::info - -To view the example in its entirety, select the `Edit this page` link below the article and select the parent folder. - -::: - - diff --git a/examples/data-injection/manifest.yaml b/examples/data-injection/manifest.yaml deleted file mode 100644 index 5a1764fbd3..0000000000 --- a/examples/data-injection/manifest.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: data-injection - namespace: demo - labels: - app: data-injection -spec: - selector: - matchLabels: - app: data-injection - template: - metadata: - labels: - app: data-injection - spec: - initContainers: - - name: data-loader - image: alpine:3.15 - command: - [ - "sh", - "-c", - 'while [ ! -f /test/###ZARF_DATA_INJECTION_MARKER### ]; do echo "waiting for zarf data sync" && sleep 1; done; echo "we are done waiting!"', - ] - resources: - requests: - memory: "16Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "100m" - volumeMounts: - - mountPath: /test - name: test - containers: - - name: data-injection - image: alpine:3.15 - command: - ["/bin/sh", "-ec", "while :; do ls -lah /test ; sleep 2 ; done"] - resources: - requests: - memory: "16Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "100m" - volumeMounts: - - mountPath: /test - name: test - readinessProbe: - exec: - command: - - "cat" - - "/test/###ZARF_DATA_INJECTION_MARKER###" - initialDelaySeconds: 1 - periodSeconds: 1 - - volumes: - - name: test - emptyDir: {} diff --git a/examples/data-injection/sample-data/requirements.txt b/examples/data-injection/sample-data/requirements.txt deleted file mode 100644 index 4ae9d753ba..0000000000 --- a/examples/data-injection/sample-data/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pytz==2022.5 diff --git a/examples/data-injection/sample-data/this-is-an-example-file.txt b/examples/data-injection/sample-data/this-is-an-example-file.txt deleted file mode 100644 index 698c758654..0000000000 --- a/examples/data-injection/sample-data/this-is-an-example-file.txt +++ /dev/null @@ -1 +0,0 @@ -This is a sample file to be injected into the cluster. Normal flow would keep this data gitignored as it would likely be large. diff --git a/examples/data-injection/zarf.yaml b/examples/data-injection/zarf.yaml deleted file mode 100644 index 645d3966f9..0000000000 --- a/examples/data-injection/zarf.yaml +++ /dev/null @@ -1,27 +0,0 @@ -kind: ZarfPackageConfig -metadata: - name: data-injection - description: Demo Zarf local data injection into a pod - # (optional) Some large datasets may already be compressed making zarf compression less efficient - uncompressed: true - -components: - - name: with-init-container - required: true - manifests: - - name: example-data-injection - namespace: demo - files: - - manifest.yaml - images: - - alpine:3.15 - # Add new data into the cluster, these will keep trying up until their timeout - dataInjections: - # Injection in the root directory using data-loader init container - - source: sample-data - target: - namespace: demo - selector: app=data-injection - container: data-loader - path: /test - compress: true diff --git a/examples/dos-games/README.md b/examples/dos-games/README.md index ae7d3d1b8c..ac63efb759 100644 --- a/examples/dos-games/README.md +++ b/examples/dos-games/README.md @@ -1,6 +1,6 @@ import ExampleYAML from "@site/src/components/ExampleYAML"; -# DOS Games in the Cluster! +# Retro Arcade This example provides the basis for Zarf's [Retro Arcade](../../docs/5-zarf-tutorials/3-deploy-a-retro-arcade.md) tutorial. It deploys a Dos Games arcade into the cluster and provides an easy way to connect and play games. diff --git a/examples/git-data/README.md b/examples/git-data/README.md index 1418ff75a6..c74549d727 100644 --- a/examples/git-data/README.md +++ b/examples/git-data/README.md @@ -1,6 +1,6 @@ import ExampleYAML from "@site/src/components/ExampleYAML"; -# Git Data +# Git Repositories This example shows how to package `git` repositories within a Zarf package. This package does not deploy anything itself but pushes assets to the specified `git` service to be consumed as desired. Within Zarf, there are a few ways to include `git` repositories (as described below). diff --git a/examples/kiwix/README.md b/examples/kiwix/README.md new file mode 100644 index 0000000000..c58ce26451 --- /dev/null +++ b/examples/kiwix/README.md @@ -0,0 +1,26 @@ +import ExampleYAML from "@site/src/components/ExampleYAML"; + +# Data Injections (Kiwix) + +This example shows Zarf's ability to inject data into a container running in a pod, in this case to initialize a [Kiwix server](https://www.kiwix.org/en/) to allow offline viewing of documentation and wiki pages. + + +Data injections allow for data that is not included in the container image to be injected at deploy time and are declared using the `dataInjections` key within a component. Once the specified container is started, Zarf will copy the files and folders from the specified source into the specified container and path. + +:::caution + +Data injections depend on the `tar` (and for `compress`, `gzip`) executables and their implementation across operating systems. Between macOS and Linux there is general agreement on how these utilities should function, however on Windows you may see issues enabling compression. + +To resolve this you can either disable compression or use the GNU core-utils version of `tar` and `gzip`. + +::: + +## `zarf.yaml` {#zarf.yaml} + +:::info + +To view the example in its entirety, select the `Edit this page` link below the article and select the parent folder. + +::: + + diff --git a/examples/kiwix/manifests/deployment.yaml b/examples/kiwix/manifests/deployment.yaml new file mode 100644 index 0000000000..95d2f3b2d4 --- /dev/null +++ b/examples/kiwix/manifests/deployment.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kiwix-serve + namespace: kiwix + labels: + app: kiwix-serve +spec: + selector: + matchLabels: + app: kiwix-serve + template: + metadata: + labels: + app: kiwix-serve + spec: + # Kiwix can hot-load files from the filesystem, but if your application cannot, this example shows how you can use an initContainer to bootstrap the injected files. + initContainers: + - name: data-loader + image: alpine:3.18 + command: + [ + "sh", + "-c", + # This command looks for the Zarf "data injection marker" which is a timestamped file that is injected after everything else and marks the injection as complete. + 'while [ ! -f /data/###ZARF_DATA_INJECTION_MARKER### ]; do echo "waiting for zarf data sync" && sleep 1; done; echo "we are done waiting!"', + ] + resources: + requests: + memory: "16Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "100m" + volumeMounts: + - mountPath: /data + name: data + containers: + - name: kiwix-serve + image: "ghcr.io/kiwix/kiwix-serve:3.5.0" + command: + [ + "sh", + "-c", + "ls -la /data && kiwix-serve -v /data/*.zim", + ] + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + volumeMounts: + - name: data + mountPath: /data + readinessProbe: + httpGet: + path: / + port: 80 + volumes: + - name: data + persistentVolumeClaim: + claimName: kiwix-data diff --git a/examples/kiwix/manifests/persistence.yaml b/examples/kiwix/manifests/persistence.yaml new file mode 100644 index 0000000000..c3bf15bca2 --- /dev/null +++ b/examples/kiwix/manifests/persistence.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: kiwix-data +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi diff --git a/examples/kiwix/manifests/service.yaml b/examples/kiwix/manifests/service.yaml new file mode 100644 index 0000000000..1395536648 --- /dev/null +++ b/examples/kiwix/manifests/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: kiwix + annotations: + zarf.dev/connect-description: "View the Kiwix web interface" + labels: + zarf.dev/connect-name: kiwix +spec: + selector: + app: kiwix-serve + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 80 diff --git a/examples/kiwix/zarf.yaml b/examples/kiwix/zarf.yaml new file mode 100644 index 0000000000..73bdb48710 --- /dev/null +++ b/examples/kiwix/zarf.yaml @@ -0,0 +1,39 @@ +kind: ZarfPackageConfig +metadata: + name: kiwix + description: Demo Zarf data injection with Kiwix (https://www.kiwix.org/en/) + # (optional) Some large datasets may already be compressed making Zarf compression less efficient + uncompressed: true + version: 3.5.0 + +components: + - name: kiwix-serve + required: true + manifests: + - name: kiwix-serve + namespace: kiwix + files: + - manifests/persistence.yaml + - manifests/deployment.yaml + - manifests/service.yaml + images: + - ghcr.io/kiwix/kiwix-serve:3.5.0 + - alpine:3.18 + # Add new data into the cluster, these will keep trying up until their timeout + dataInjections: + # Injection in the data directory using the data-loader init container + - source: zim-data + target: + namespace: kiwix + selector: app=kiwix-serve + container: data-loader + path: /data + compress: true + actions: + onCreate: + before: + # Download a .zim file of a DevOps Stack Exchange snapshot into the data directory for use with Kiwix + - cmd: curl https://zarf-examples.s3.amazonaws.com/devops.stackexchange.com_en_all_2023-05.zim -o zim-data/devops.stackexchange.com_en_all_2023-05.zim + # Below are some more examples of *.zim files of available content: + # https://library.kiwix.org/?lang=eng + # NOTE: If `zarf package create`ing regularly you should mirror content to a web host you control to be a friendly neighbor diff --git a/examples/kiwix/zim-data/.gitkeep b/examples/kiwix/zim-data/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/podinfo-flux/README.md b/examples/podinfo-flux/README.md index f6bd2cc7fb..6c58f4be54 100644 --- a/examples/podinfo-flux/README.md +++ b/examples/podinfo-flux/README.md @@ -1,6 +1,6 @@ import ExampleYAML from "@site/src/components/ExampleYAML"; -# Podinfo via Flux +# Flux (with Podinfo) This example demonstrates how to use flux with Zarf to deploy the `stefanprodan/podinfo` app using GitOps. diff --git a/examples/podinfo-flux/zarf.yaml b/examples/podinfo-flux/zarf.yaml index fbe171b344..0f0e4b3336 100644 --- a/examples/podinfo-flux/zarf.yaml +++ b/examples/podinfo-flux/zarf.yaml @@ -32,7 +32,7 @@ components: actions: onDeploy: after: - # This will use a wait action to wait for the podinfo pods to be ready + # This will use a wait action to wait for the podinfo pod to be ready - description: Podinfo pods to be ready via wait action wait: cluster: diff --git a/packages/distros/eks/zarf.yaml b/packages/distros/eks/zarf.yaml index 990a2da7a4..007f8fd211 100644 --- a/packages/distros/eks/zarf.yaml +++ b/packages/distros/eks/zarf.yaml @@ -52,7 +52,6 @@ components: - cmd: ./eksctl create cluster --dry-run -f eks.yaml - cmd: sleep 15 - cmd: ./eksctl create cluster -f eks.yaml - after: - cmd: ./eksctl utils write-kubeconfig -c ${ZARF_VAR_CLUSTER_NAME} - cmd: ./zarf tools kubectl create namespace zarf - cmd: ./zarf tools kubectl create secret generic zarf-eks-yaml -n zarf --from-file=eks.yaml diff --git a/src/test/e2e/02_component_actions_test.go b/src/test/e2e/02_component_actions_test.go index 75c09e5e15..5d9206cdb3 100644 --- a/src/test/e2e/02_component_actions_test.go +++ b/src/test/e2e/02_component_actions_test.go @@ -33,11 +33,11 @@ func TestComponentActions(t *testing.T) { // Try creating the package to test the onCreate actions. stdOut, stdErr, err := e2e.Zarf("package", "create", "examples/component-actions", "--confirm") require.NoError(t, err, stdOut, stdErr) - require.Contains(t, stdErr, "Completed \"touch test-create-before.txt\"") + require.Contains(t, stdErr, "Completed \"Create a test file\"") + require.Contains(t, stdErr, "Completed \"touch test-create-after.txt\"") require.Contains(t, stdErr, "multiline!") require.Contains(t, stdErr, "updates!") require.Contains(t, stdErr, "realtime!") - require.Contains(t, stdErr, "Completed \"multiline & description demo\"") // Test for package create prepare artifacts. for _, artifact := range createArtifacts { diff --git a/src/test/e2e/23_data_injection_test.go b/src/test/e2e/23_data_injection_test.go index 5fcdbc4e39..9d3281e916 100644 --- a/src/test/e2e/23_data_injection_test.go +++ b/src/test/e2e/23_data_injection_test.go @@ -7,7 +7,6 @@ package test import ( "context" "fmt" - "os" "path/filepath" "testing" "time" @@ -20,7 +19,7 @@ func TestDataInjection(t *testing.T) { t.Log("E2E: Data injection") e2e.SetupWithCluster(t) - path := fmt.Sprintf("build/zarf-package-data-injection-%s.tar", e2e.Arch) + path := fmt.Sprintf("build/zarf-package-kiwix-%s-3.5.0.tar", e2e.Arch) tmpdir := t.TempDir() sbomPath := filepath.Join(tmpdir, ".sbom-location") @@ -31,9 +30,9 @@ func TestDataInjection(t *testing.T) { } // Verify the file and injection marker were created - stdOut, stdErr, err := e2e.Kubectl("--namespace=demo", "logs", "--tail=5", "--selector=app=data-injection", "-c=data-injection") + stdOut, stdErr, err := e2e.Kubectl("--namespace=kiwix", "logs", "--tail=5", "--selector=app=kiwix-serve", "-c=kiwix-serve") require.NoError(t, err, stdOut, stdErr) - require.Contains(t, stdOut, "this-is-an-example-file.txt") + require.Contains(t, stdOut, "devops.stackexchange.com_en_all_2023-05.zim") require.Contains(t, stdOut, ".zarf-injection-") // Remove the data injection example @@ -43,13 +42,10 @@ func TestDataInjection(t *testing.T) { // Ensure that the `requirements.txt` file is discovered correctly stdOut, stdErr, err = e2e.Zarf("package", "inspect", path, "--sbom-out", sbomPath) require.NoError(t, err, stdOut, stdErr) - _, err = os.ReadFile(filepath.Join(sbomPath, "data-injection", "compare.html")) - require.NoError(t, err) - _, err = os.ReadFile(filepath.Join(sbomPath, "data-injection", "sbom-viewer-zarf-component-with-init-container.html")) - require.NoError(t, err) - withInitContainerJSON, err := os.ReadFile(filepath.Join(sbomPath, "data-injection", "zarf-component-with-init-container.json")) - require.NoError(t, err) - require.Contains(t, string(withInitContainerJSON), "pytz") + require.FileExists(t, filepath.Join(sbomPath, "kiwix", "compare.html"), "A compare.html file should have been made") + + require.FileExists(t, filepath.Join(sbomPath, "kiwix", "sbom-viewer-zarf-component-kiwix-serve.html"), "The data-injection component should have an SBOM viewer") + require.FileExists(t, filepath.Join(sbomPath, "kiwix", "zarf-component-kiwix-serve.json"), "The data-injection component should have an SBOM json") } func runDataInjection(t *testing.T, path string) { @@ -58,6 +54,6 @@ func runDataInjection(t *testing.T, path string) { defer cancel() // Deploy the data injection example - stdOut, stdErr, err := exec.CmdWithContext(ctx, exec.PrintCfg(), e2e.ZarfBinPath, "package", "deploy", path, "--confirm") + stdOut, stdErr, err := exec.CmdWithContext(ctx, exec.PrintCfg(), e2e.ZarfBinPath, "package", "deploy", path, "-l", "trace", "--confirm") require.NoError(t, err, stdOut, stdErr) }