diff --git a/content/docs/04.workflow-components/01.flow.md b/content/docs/04.workflow-components/01.flow.md index 85590cc578..cd98eeceb8 100644 --- a/content/docs/04.workflow-components/01.flow.md +++ b/content/docs/04.workflow-components/01.flow.md @@ -29,7 +29,7 @@ Optionally, a flow can also have: - [pluginDefaults](./09.plugin-defaults.md) - [errors](./11.errors.md) - [retries](./12.retries.md) -- [timeout](./13.timeout.md) +- [sla](./18.sla.md) - [concurrency](./14.concurrency.md) - [descriptions](./15.descriptions.md) - [disabled](./16.disabled.md) diff --git a/content/docs/04.workflow-components/07.triggers/02.flow-trigger.md b/content/docs/04.workflow-components/07.triggers/02.flow-trigger.md index 4dd8ecec04..25e6c34447 100644 --- a/content/docs/04.workflow-components/07.triggers/02.flow-trigger.md +++ b/content/docs/04.workflow-components/07.triggers/02.flow-trigger.md @@ -11,141 +11,218 @@ Flow triggers allows you to trigger a flow after another flow execution, enablin type: "io.kestra.plugin.core.trigger.Flow" ``` -Kestra is able to trigger one flow after another one. This allows the chaining of flows without the need to update the base flows. With this capacity, you can break responsibility between different flows to different teams. +Kestra is able to trigger a flow as soon as another flow ends. This allows to add implicit dependencies between multiple flows, which can often be managed by different teams. Check the [Flow trigger](/plugins/core/triggers/io.kestra.plugin.core.trigger.Flow) documentation for the list of all properties. -## Conditions +## Preconditions -You can provide conditions to determine when your Flow should be executed. Along with the [core trigger conditions](./index.md#conditions), you can use the following: +A flow trigger must have preconditions which filter on other flow executions on a time window. -- [ExecutionFlowCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.ExecutionFlowCondition) -- [ExecutionNamespaceCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.ExecutionNamespaceCondition) -- [ExecutionLabelsCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.executionlabelscondition) -- [ExecutionStatusCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.ExecutionStatusCondition) -- [ExecutionOutputsCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.executionoutputscondition) -- [ExpressionCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.ExpressionCondition) -## Example +### Filters -This flow will be triggered after each successful execution of the flow `io.kestra.tests.trigger-flow` and forward the `uri` output of the `my-task` task. -```yaml -id: trigger_flow_listener -namespace: company.team -inputs: - - id: fromParent - type: STRING +- `flows` +A list of preconditions to met, in the form of upstream flows. + +For example, the following flow will trigger as soon as `flow_a` finish in SUCCESS state. + +```yaml +id: flow_b +namespace: kestra.sandbox tasks: - - id: onlyNoInput - type: io.kestra.plugin.core.debug.Return - format: "v1: {{ trigger.executionId }}" + - id: hello + type: io.kestra.plugin.core.log.Log + message: "Hello World!" triggers: - - id: listenFlow + - id: upstream_dependancy type: io.kestra.plugin.core.trigger.Flow - inputs: - fromParent: '{{ outputs.myTask.uri }}' - conditions: - - type: io.kestra.plugin.core.condition.ExecutionFlowCondition - namespace: company.team - flowId: trigger_flow - - type: io.kestra.plugin.core.condition.ExecutionStatusCondition - in: - - SUCCESS + preconditions: + id: flow_trigger + flows: + - namespace: kestra.sandbox + flowId: flow_a + states: [SUCCESS] ``` -Parent flow: -```yaml -id: trigger_flow -namespace: company.team -tasks: - - id: myTask - type: io.kestra.plugin.core.http.Download - uri: https://dummyjson.com/products +- `where` + +You can also add execution filters on fields `FLOW_ID`, `NAMESPACE`, `STATE` and `EXPRESSION`. + +For example, the following Flow Trigger will trigger on for execution from flows in FAILED or WARNING state in namespaces starting with "company": + +```yaml +triggers: + - id: alert_on_failure + type: io.kestra.plugin.core.trigger.Flow + states: + - FAILED + - WARNING + preconditions: + id: company_namespace + where: + - id: company + filters: + - field: NAMESPACE + type: STARTS_WITH + value: company ``` +### Time Window & SLA + +You can set the `timeWindow` property in different ways: +`DURATION_WINDOW`: this is the default type. It uses a start time (windowAdvance) and end time (window) that are moving forward to the next interval whenever the evaluation time reaches the end time, based on the defined duration window. -This flow will be triggered after the successful execution of both flows `flow-a` and `flow-b` during the current day. When the conditions are met, the counter is reset and can be re-triggered during the same day. See [MultipleCondition](/plugins/core/conditions/io.kestra.plugin.core.condition.MultipleCondition) for more details +For example, with a 1-day window (the default option: window: PT1D), the SLA conditions are always evaluated during 24h starting at midnight (i.e. at time 00:00:00) each day. If you set windowAdvance: PT6H, the window will start at 6 AM each day. If you set windowAdvance: PT6H and you also override the window property to PT6H, the window will start at 6 AM and last for 6 hours — as a result, Kestra will check the SLA conditions during the following time periods: 06:00 to 12:00, 12:00 to 18:00, 18:00 to 00:00, and 00:00 to 06:00, and so on. + + +`SLIDING_WINDOW`: this option also evaluates SLA conditions over a fixed time window, but it always goes backward from the current time. For example, a sliding window of 1 hour (window: PT1H) will evaluate executions for the past hour (so between now and one hour before now). It uses a default window of 1 day. + +For example, the flow below will evaluate every hour if the flow `flow_a` is in SUCCESS state. If so it will trigger the `flow_b` passing corresponding inputs (reading `flow_a` outputs). ```yaml -id: trigger-multiplecondition-listener -namespace: company.team +id: flow_b +namespace: kestra.sandbox + +inputs: + - id: value_from_a + type: STRING tasks: - - id: onlyListener - type: io.kestra.plugin.core.debug.Return - format: "let's go " + - id: hello + type: io.kestra.plugin.core.log.Log + message: "{{ inputs.value_from_a }}" triggers: - - id: multipleListenFlow + - id: upstream_dep type: io.kestra.plugin.core.trigger.Flow - conditions: - - id: multiple - type: io.kestra.plugin.core.condition.MultipleCondition - window: P1D - windowAdvance: P0D - conditions: - flow-a: - type: io.kestra.plugin.core.condition.ExecutionFlowCondition - namespace: company.team - flowId: trigger-multiplecondition-flow-a - flow-b: - type: io.kestra.plugin.core.condition.ExecutionFlowCondition - namespace: company.team - flowId: trigger-multiplecondition-flow-b + inputs: + value_from_a: "{{ trigger.outputs.return_value }}" + preconditions: + id: test + flows: + - namespace: kestra.sandbox + flowId: flow_a + states: [SUCCESS] + timeWindow: + type: SLIDING_WINDOW + window: PT1H ``` -Simply execute the two flows below to trigger `trigger-multiplecondition-listener`: +Here is for reference the `flow_a`: + ```yaml -id: trigger-multiplecondition-flow-a -namespace: company.team +id: flow_a +namespace: kestra.sandbox tasks: - id: hello type: io.kestra.plugin.core.log.Log - message: Trigger A + message: Hello World! 🚀 + +outputs: + - id: return_value + type: STRING + value: "Flow A run succesfully" ``` + +`DAILY_TIME_DEADLINE`: this option declares that some SLA conditions should be met “before a specific time in a day”. With the string property deadline, you can configure a daily cutoff for checking conditions. For example, deadline: "09:00:00.00Z" means that the defined SLA conditions should be met from midnight until 9 AM each day; otherwise, the flow will not be triggered. + +For the example, this trigger definition will only trigger the flow if `flow_a` is in SUCCESS state before 9:00 AM every day. + ```yaml -id: trigger-multiplecondition-flow-b -namespace: company.team +triggers: + - id: upstream_dep + type: io.kestra.plugin.core.trigger.Flow + preconditions: + id: should_be_success_by_nine + flows: + - namespace: kestra.sandbox + flowId: flow_a + states: [SUCCESS] + timeWindow: + type: DAILY_TIME_DEADLINE + deadline: "09:00:00.00Z" +``` + + +`DAILY_TIME_WINDOW`: this option declares that some SLA conditions should be met “within a given time range in a day”. For example, a window from startTime: "06:00:00" to endTime: "09:00:00" evaluates executions within that interval each day. This option is particularly useful for declarative definition of freshness conditions when building data pipelines. For example, if you only need one successful execution within a given time range to guarantee that some data has been successfully refreshed in order for you to proceed with the next steps of your pipeline, this option can be more useful than a strict DAG-based approach. Usually, each failure in your flow would block the entire pipeline, whereas with this option, you can proceed with the next steps of the pipeline as soon as the data is successfully refreshed at least once within the given time range. + +```yaml +triggers: + - id: upstream_dep + type: io.kestra.plugin.core.trigger.Flow + inputs: + value_from_a: "{{ trigger.outputs.return_value }}" + preconditions: + id: test + flows: + - namespace: kestra.sandbox + flowId: flow_a + states: [SUCCESS] + timeWindow: + type: DAILY_TIME_WINDOW + startTime: "06:00:00" + endTime: "12:00:00" +``` + + + +## Example + +Trigger the `silver_layer` flow once the `bronze_layer` flow finishes successfully by 9 AM. The deadline time string must include the timezone offset. This ensures that no new executions are triggered past the deadline. Here is the `silver_layer` flow: +```yaml +id: silver_layer +namespace: company.team tasks: - - id: hello + - id: transform_data type: io.kestra.plugin.core.log.Log - message: Trigger B + message: deduplication, cleaning, and minor aggregations +triggers: + - id: flow_trigger + type: io.kestra.plugin.core.trigger.Flow + preconditions: + id: bronze_layer + timeWindow: + type: DAILY_TIME_DEADLINE + deadline: "09:00:00+01:00" + flows: + - namespace: company.team + flowId: bronze_layer + states: [SUCCESS] ``` ## Example: Alerting -In this example, the Flow Trigger conditions are set to execute the flow when any workflow execution has a warning or failed status. We can configure this flow to send a notification to Slack (or any other platform) with information around the failure. Using this pattern, you can manage alerts on failure all in one place. +Create a `System Flow` to send a Slack alert on any failure or warning state within the `company` namespace. This example uses the Slack webhook secret to notify the `#general` channel about the failed flow. ```yaml -id: failure_alert_slack +id: alert namespace: system - tasks: - id: send_alert type: io.kestra.plugin.notifications.slack.SlackExecution - url: "{{ secret('SLACK_WEBHOOK') }}" + url: "{{secret('SLACK_WEBHOOK')}}" # format: https://hooks.slack.com/services/xzy/xyz/xyz channel: "#general" - executionId: "{{ trigger.executionId }}" - + executionId: "{{trigger.executionId}}" triggers: - - id: on_failure + - id: alert_on_failure type: io.kestra.plugin.core.trigger.Flow - conditions: - - type: io.kestra.plugin.core.condition.ExecutionStatusCondition - in: - - FAILED - - WARNING -``` - -Check out the Blueprint [here](https://kestra.io/blueprints/failure-alert-slack). - -
- -
+ states: + - FAILED + - WARNING + preconditions: + id: company_namespace + where: + - id: company + filters: + - field: NAMESPACE + type: STARTS_WITH + value: company +``` \ No newline at end of file diff --git a/content/docs/04.workflow-components/13.timeout.md b/content/docs/04.workflow-components/13.timeout.md index 8a0aa49f84..456d81ab88 100644 --- a/content/docs/04.workflow-components/13.timeout.md +++ b/content/docs/04.workflow-components/13.timeout.md @@ -1,5 +1,5 @@ --- -title: Timeout +title: Task timeout icon: /docs/icons/flow.svg --- @@ -45,3 +45,7 @@ tasks: - sleep 10 timeout: PT5S ``` + +## Flow-level timeout + +There is no flow-level timeout. If you want to cancel a workflow execution if it exceeds a certain duration, you can leverage `MAX_DURATION`-type [SLA](./18.sla.md). \ No newline at end of file diff --git a/content/docs/04.workflow-components/18.sla.md b/content/docs/04.workflow-components/18.sla.md new file mode 100644 index 0000000000..76ca0b9c31 --- /dev/null +++ b/content/docs/04.workflow-components/18.sla.md @@ -0,0 +1,121 @@ +--- +title: SLA +icon: /docs/icons/flow.svg +version: ">= 0.20.0" +editions: ["Beta"] +--- + +Assert that your workflows meet SLAs. + +## What is an SLA + +An SLA (Service Level Agreement) is a core property of a flow that defines a `behavior` that should be triggered if the flow runs for too long or doesn't satisfy the assertion defined in the SLA. + +::alert{type="warning"} +Note that SLA is in Beta so some properties might change in the next release or two. Please be aware that its API could change in ways that are not compatible with earlier versions in future releases, or it might become unsupported. If you have any questions or suggestions, please let us know via [Slack](/slack) or [GitHub](https://github.com/kestra-io/kestra/issues/new/choose). +:: + +## SLA types + +Currently, Kestra supports the following SLA types: +1. **MAX_DURATION** — the maximum allowed execution duration before the SLA is breached +2. **EXECUTION_ASSERTION** — an assertion defined by a Pebble expression that must be met during the execution. If the assertion doesn't hold true, the SLA is breached. + +## How to use SLAs + +SLAs are defined usig the `sla` property at the root of a flow and they declare the desired state that must be met during executions of the flow. + +### MAX_DURATION + +If a workflow execution exceeds the expected duration, an SLA can trigger corrective actions e.g. cancelling such execution. + +The following SLA cancels an execution if it takes more than 8 hours: + +```yaml +id: sla_example +namespace: company.team + +sla: + - id: maxDuration + type: MAX_DURATION + duration: PT8H + behavior: CANCEL + labels: + sla: miss + reason: durationExceeded + +tasks: + - id: punctual + type: io.kestra.plugin.core.log.Log + message: Workflow started, monitoring SLA compliance + + - id: sleepyhead + type: io.kestra.plugin.core.flow.Sleep + duration: PT9H + + - id: never_executed_task + type: io.kestra.plugin.core.log.Log + message: This task will never start because the SLA was breached +``` + +### EXECUTION_ASSERTION + +An SLA can also be defined by an assertion that must be met during the execution. If the assertion doesn't hold true, the SLA is breached. + +The following SLA fails if the output of `mytask` is not equal to `expected output`: + +```yaml +id: sla_demo +namespace: company.team + +sla: + - id: assert_output + type: EXECUTION_ASSERTION + assert: "{{ outputs.mytask.value == 'expected output' }}" + behavior: FAIL + labels: + sla: miss + reason: outputMismatch + +tasks: + - id: mytask + type: io.kestra.plugin.core.debug.Return + format: expected output +``` + +## SLA behavior + +The `behavior` property of an SLA defines the action to take when the SLA is breached. The following behaviors are supported: +1. **CANCEL** — cancels the execution +2. **FAIL** — fails the execution +3. **NONE** — logs a message. + +On top of that behavior, each breached SLA can set labels that can be used to filter executions or to trigger specific actions. + +## Alerts on SLA breaches + +Let's say that you want to receive a Slack alert anytime an SLA is breached. Using the Flow trigger, you can react to cancelled or failed Executions that were marked with the `sla: miss` label: + +```yaml +id: sla_miss_alert +namespace: system + +tasks: + - id: send_alert + type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook + url: "{{secret('SLACK_WEBHOOK')}}" + payload: | + { + "text": "SLA breached for flow `{{trigger.namespace}}.{{trigger.flowId}}` with ID `{{trigger.executionId}}`" + } + +triggers: + - id: alert_on_failure + type: io.kestra.plugin.core.trigger.Flow + labels: + sla: miss + states: + - FAILED + - WARNING + - CANCELLED +``` diff --git a/content/docs/05.concepts/readOnly.png b/content/docs/05.concepts/readOnly.png new file mode 100644 index 0000000000..2fd99ab334 Binary files /dev/null and b/content/docs/05.concepts/readOnly.png differ diff --git a/content/docs/05.concepts/system-labels.md b/content/docs/05.concepts/system-labels.md new file mode 100644 index 0000000000..674f0fbbe8 --- /dev/null +++ b/content/docs/05.concepts/system-labels.md @@ -0,0 +1,83 @@ +--- +title: System Labels & Hidden Labels +icon: /docs/icons/admin.svg +editions: ["OSS", "EE"] +version: ">= 0.20.0" +--- + +Special labels for system use only. + +## Overview + +System Labels and Hidden Labels are reserved for storing metadata used by administrators to manage and monitor Kestra. These labels are hidden in the UI by default. To view executions with a specific Hidden Label, you must explicitly filter for it using the `Labels` filter, such as `system.correlationId: 4DhfCBCDznBqipTAnd7zfm`. + +![correlationId](/docs/concepts/correlationId.png) + +--- + +## Hidden Labels + +Hidden Labels are labels excluded from the UI by default. You can configure which prefixes should be hidden via the `kestra.hidden-labels.prefixes` configuration. For example, to hide labels starting with `admin.`, `internal.`, and `system.`, you can use the following configuration in your `application.yaml`: + +```yaml +kestra: + hidden-labels: + prefixes: + - system. + - internal. + - admin. +``` + +By default, System Labels (prefixed with `system.`) are hidden. To display them, simply remove the `system.` prefix from the list of hidden prefixes. + +--- + +## System Labels + +System Labels are labels prefixed with `system.` that serve specific purposes. Below are the available System Labels. + +### `system.correlationId` + +- Automatically set for every execution and propagated to downstream executions created by `Subflow` or `ForEachItem` tasks. +- Represents the ID of the first execution in a chain of executions, enabling tracking of execution lineage. +- Use this label to filter all executions originating from a specific parent execution. + +For example, if a parent flow triggers multiple subflows, filtering by the parent's `system.correlationId` will display all related executions. + +**Note:** The Execution API supports setting this label at execution creation but not modification. + +--- + +### `system.username` + +- Automatically set for every execution and contains the username of the user who triggered the execution. +- Useful for auditing and identifying who initiated specific executions. + +--- + +### `system.readOnly` + +- Used to mark a flow as read-only, disabling the flow editor in the UI. +- Helps prevent modifications to critical workflows, such as production flows managed through CI/CD pipelines. + +**Example:** + +```yaml +id: read_only_flow +namespace: company.team + +labels: + system.readOnly: "true" + +tasks: + - id: log + type: io.kestra.plugin.core.log.Log + message: Hello from a read-only flow! +``` + +Once this label is set, the editor for this flow will be disabled in the UI. + +![readOnly](/docs/concepts/system-labels/readOnly.png) + +**Note:** In the Enterprise Edition, updating a read-only flow server-side is restricted to service accounts or API keys. + diff --git a/content/docs/06.enterprise/03.tenants.md b/content/docs/06.enterprise/03.tenants.md index 6336c9e3f2..954dd5e6d1 100644 --- a/content/docs/06.enterprise/03.tenants.md +++ b/content/docs/06.enterprise/03.tenants.md @@ -155,3 +155,18 @@ resource "kestra_tenant" "stage" { Regardless of which of the above methods you use to create a tenant, the User who creates the tenant will automatically get the Admin Role assigned. That role grants admin rights to that user on that tenant. Note that there is an exception to this rule if tenant is created by a Super Admin. In that case, the Super Admin will have to explicitly assign the Admin Role for that tenant to themselves or any other User, Service Account or Group. + +### Dedicated Storage and Secrets backend per Tenant + +By default, each tenant uses the same [internal storage](../configuration/index.md#internal-storage) and [secrets backend](./secrets-manager.md) configured for your Kestra instance. If you need more isolation, you can configure a dedicated storage and secrets backend per tenant. This can be useful if each of your tenants serves different customers and you need to ensure complete data isolation between them. + +To configure a dedicated storage and secrets backend per tenant, navigate to the respective tenant in the UI and click on the **Edit** button. Then, select the storage and secrets backend you want to use for that tenant: + +![tenants-dedicated-internal-storage](/docs/enterprise/tenants-dedicated-internal-storage.png) + + +::alert{type="warning"} +Note that this feature has been introduced in Kestra 0.20.0. If you are using an older version, you will need to upgrade to set up dedicated storage and secrets backend per tenant. + +Also, make sure to use `camelCase` notation. For example, if you want to use the `GCS` storage backend, you should use `projectId` as the value rather than `project-id`. +:: diff --git a/content/docs/06.enterprise/announcements.md b/content/docs/06.enterprise/announcements.md new file mode 100644 index 0000000000..7b4f4625b5 --- /dev/null +++ b/content/docs/06.enterprise/announcements.md @@ -0,0 +1,29 @@ +--- +title: Announcements +icon: /docs/icons/admin.svg +editions: ["EE"] +version: ">= 0.20.0" +--- + +Communicate planned maintenance or incidents with in-app banners + +## Overview + +Announcements allow you to notify your users about any important events such as planned maintenance downtime. + +## How to create an announcement + +To add a custom in-app banner, go to the Administration → Cluster → Announcements tab. + +![announcement panel](/docs/enterprise/announcement/main_announcement.png) + +As a user with an Admin role, you can configure the following within each announcement: + +- `Message`: the text to display in the banner +- `Type`: the type of banner to display (`info`, `warning`, `error`) +- The `start` and `end` date during which the announcement should be displayed. + +![setup announcement](/docs/enterprise/announcement/setup_announcement.png) + +![display announcement](/docs/enterprise/announcement/display_announcement.png) + diff --git a/content/docs/06.enterprise/apps.md b/content/docs/06.enterprise/apps.md new file mode 100644 index 0000000000..e7a5912655 --- /dev/null +++ b/content/docs/06.enterprise/apps.md @@ -0,0 +1,163 @@ +--- +title: Apps +icon: /docs/icons/kestra.svg +editions: ["EE"] +version: ">= 0.20.0" +--- + +Build custom UIs to interact with Kestra from the outside world. + +## Overview + +Apps let you use your Kestra workflows as the backend for custom applications. Within each app, you can specify custom frontend blocks, such as forms for data entry, output displays, approval buttons, or markdown blocks. **Flows** act as the **backend**, processing data and executing tasks, while Apps serve as frontend, allowing anyone to interact with your workflows regardless of their technical background. Business users can trigger new workflow executions, manually approve workflows that are paused, submit data to automated processes using simple forms, and view the execution results. + +You can think of Apps as **custom UIs for flows**, allowing your users to interact with Kestra from the outside world. + +You can build custom applications that resume paused workflows waiting for approval, or interact with Kestra’s API. In short, Apps allow you and your users to interact with Kestra from the outside world. + +--- + +## App Types + +Currently, Kestra offers two types of Apps: +- **Form Apps**: these apps allow you to create forms that can trigger workflows with input parameters. For example, a form might allow users to specify resources that need to be provisioned, and their inputs will feed directly into a workflow that automatically provisions those resources. +- **Approval Apps**: these apps enable forms for approving or rejecting paused workflows. Using the same example, an approval app could be used to either approve or reject a request for provisioning resources. Depending on the decision, the workflow will either resume and provision the resources, or stop. + +--- + +## How Apps Help + +Apps offer custom UIs on top of your Kestra workflows. Often, workflows are designed for non-technical users, and creating custom frontends for each of these workflows can be a lot of work. Imagine having to build and serve a frontend, connect it to Kestra’s API, validate user inputs, handle responses, manage workflow outputs, and deal with authentication and authorization — all from scratch. **With Apps, you can generate a custom UI for any flow in seconds, and let Kestra handle the heavy lifting.** + +Here are some common scenarios where a custom UI is useful: + +- **Manual Approval**: workflows that need manual approval, such as provisioning resources, granting access to services, deploying apps, validating data results, or reviewing AI-generated outputs. +- **Report Generation**: workflows where business users request data and receive a downloadable CSV or Excel file. +- **IT Helpdesk**: workflows that accept bug reports, feature requests, or other tickets, and automatically forward the ticket to the relevant team. +- **User Feedback & Signups**: workflows that collect feedback or allow users to sign up for events or email lists. +- **Data Entry**: workflows where business users enter data that is processed and either sent back to them or stored in a database. + +In short, Apps make it easy to turn your Kestra workflows into simple applications that anyone can use. + +--- + +## Creating Apps in Code + +To create a new app, go to the `Apps` page in the main UI and click the `+ Create` button. Add your app configuration as code and click on `Save`. + +### App to run a Hello World flow + +Apps serve as custom UIs for workflows, so you need to first create a flow. Here is a simple configuration for a paremtrized flow that logs a message when triggered: + +```yaml +id: myflow +namespace: company.team + +inputs: + - id: user + type: STRING + defaults: World + +tasks: + - id: hello + type: io.kestra.plugin.core.log.Log + message: Hello {{ inputs.user }} +``` + +Add a form app that triggers a new workflow execution when submitted: [app source code](https://github.com/kestra-io/enterprise-edition-examples/blob/main/apps/06_hello_world_app.yaml). + +This app is `PUBLIC`, so anyone with the URL can access it without requiring login. Alternatively, you can set the `access` type to `PRIVATE` to restrict the app only to specific users. +This app is perfect for building **public forms** that anyone in the world can access. + +### App to request and download data + +Let's create a flow that fetches the relevant dataset based on user input: [flow source code](https://github.com/kestra-io/enterprise-edition-examples/blob/main/flows/company.team.get_data.yaml). + +Now, from the Apps page, you can create a new app that allows users to select the data they want to download: [app source code](https://github.com/kestra-io/enterprise-edition-examples/blob/main/apps/05_request_data_form.yaml). + +This app is perfect for reporting and analytics use cases where users can request data and download the results. + +### App to request compute resources and get them approved + +Add a flow simulating a request for resources that needs manual approval: [flow source code](https://github.com/kestra-io/enterprise-edition-examples/blob/main/flows/company.team.request_resources.yaml). + +Then, add your app configuration to create a form that requests compute resources and gets them approved: [app source code](https://github.com/kestra-io/enterprise-edition-examples/blob/main/apps/03_compute_resources_approval.yaml). + + +--- + +## App Catalog + +The App Catalog is where users can find available apps. You can filter apps by name, type, namespace, or tags. From this page, you can also create new apps, edit existing ones, and temporarily disable or delete apps. + +![apps_catalog](/docs/enterprise/apps/apps_catalog.png) + +--- + +## App Tags + +You can add custom tags to organize and filter apps in the App Catalog. For example, you might tag apps with `DevOps`, `data-team`, `project-x`. You can then filter apps by tags to quickly find the apps you are looking for. + +--- + +## App URL + +Each app has a unique URL that you can share with others. When someone opens the URL, they will see the app and can submit requests. You can share the URL with team members, customers, or partners to let them interact with your Kestra workflows. + +The base URL of an app URL is: `https://yourHost/ui/tenantId/apps/appId` e.g. `http://localhost:8080/ui/release/apps/5CS8qsm7YTif4PWuAUWHQ5`. + +You can copy the URL from the Apps catalog page in the Kestra UI. + +--- + +## App Access and RBAC Permissions + +For each app, you can set the access level to either `PUBLIC` or `PRIVATE`. + +### Public Access + +When an app is set to `PUBLIC`, anyone with the URL can access the form and submit requests. This is ideal for situations where the app needs to be widely available to collect user feedback or conduct a survey. You can share the app URL on social media, embed it within your website, or send it via email. + + +### Private Access for Using Apps + +When an app is set to `PRIVATE`, only users with the `APPEXECUTION` RBAC permission can submit requests. This setup works well when you want to allow a specific group (such as business stakeholders or external partners) to use the app without giving them direct access to the Kestra UI. You can invite these users to a specific Kestra tenant, where they’ll only see the App Catalog, optionally restricted to apps in a specific namespace. This fine-grained access control ensures that only authorized users can access and use the apps. + +### Private Access for Building Apps + +The `APP` RBAC permission controls who can create, read, update, or delete apps within a tenant. This permission can also be restricted to specific namespaces. Unlike the `APPEXECUTION` permission which governs the ability to submit requests using apps, the `APP` permission manages the ability to build, modify, and delete apps. + +--- + +## App Executions + +Each time a user creates an execution by submitting a form in the app, a new execution is generated with the system label `system.app` and a value of `yourAppId`. For example, to filter all executions created by the `computeResourcesForm` app, you can search for `system.app:computeResourcesForm` in the label filter. + +For every execution, you can track the user inputs, see the current state, view logs, and check the outputs — all from the Kestra UI. This lets you observe, troubleshoot and manage issues with your apps just as you would with any other workflow execution in Kestra. + +--- + +## App Layout Blocks + +Each app is made up of blocks that define the layout and content of the app. You can add blocks for markdown text, forms, buttons, logs, inputs, outputs, and more. The blocks are displayed in a specific order based on the app’s state (e.g. on `OPEN`, `RUNNING`, `SUCCESS`, `FAILURE`, `PAUSE`, `RESUME`). + +By combining different blocks, you can create a custom UI that guides users through the app’s workflow. For example, you could start with a markdown block that explains the purpose of the app, followed by a form block for users to enter their inputs, and a button block to submit the request. You can also add blocks to display execution logs, outputs, and buttons for approving or rejecting paused workflows. + +| Block type | Available on | Properties | Example | +|--------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Markdown` | OPEN, CREATED, RUNNING, PAUSE, RESUME, SUCCESS, FAILURE, FALLBACK | - `content` | `- type: io.kestra.plugin.ee.apps.core.blocks.Markdown`
    `content: "## Please validate the request. Inspect the logs and outputs below. Then, approve or reject the request."` | +| `RedirectTo` | OPEN, CREATED, RUNNING, PAUSE, RESUME, SUCCESS, FAILURE, ERROR, FALLBACK | - `uri`: redirect URL
- `delay`: delay in seconds | `- type: io.kestra.plugin.ee.apps.blocks.RedirectTo`
    `uri: "https://kestra.io/docs"`
    `delay: "PT60S"` | +| `CreateExecutionForm` | OPEN | None | `- type: io.kestra.plugin.ee.apps.execution.blocks.CreateExecutionForm` | +| `ResumeExecutionForm` | PAUSE | None | `- type: io.kestra.plugin.ee.apps.execution.blocks.ResumeExecutionForm` | +| `CreateExecutionButton` | OPEN | - `text`
- `style`: DEFAULT, SUCCESS, DANGER, INFO
- `size`: SMALL, MEDIUM, LARGE | `- type: io.kestra.plugin.ee.apps.execution.blocks.CreateExecutionButton`
    `text: "Submit"`
    `style: "SUCCESS"`
    `size: "MEDIUM"` | +| `CancelExecutionButton` | CREATED, RUNNING, PAUSE | - `text`
- `style`: DEFAULT, SUCCESS, DANGER, INFO
- `size`: SMALL, MEDIUM, LARGE | `- type: io.kestra.plugin.ee.apps.execution.blocks.CancelExecutionButton`
    `text: "Reject"`
    `style: "DANGER"`
    `size: "SMALL"` | +| `ResumeExecutionButton` | PAUSE | - `text`
- `style`: DEFAULT, SUCCESS, DANGER, INFO
- `size`: SMALL, MEDIUM, LARGE | `- type: io.kestra.plugin.ee.apps.execution.blocks.ResumeExecutionButton`
    `text: "Approve"`
    `style: "SUCCESS"`
    `size: "LARGE"` | +| `ExecutionInputs` | PAUSE, RESUME, SUCCESS, FAILURE | - `filter`: include, exclude | `- type: io.kestra.plugin.ee.apps.execution.blocks.Inputs`
    `filter:`
        `include: []`
        `exclude: []` | +| `ExecutionOutputs` | PAUSE, RESUME, SUCCESS, FAILURE | - `filter`: include, exclude | `- type: io.kestra.plugin.ee.apps.execution.blocks.Outputs`
    `filter:`
        `include: []`
        `exclude: []` | +| `ExecutionLogs` | PAUSE, RESUME, SUCCESS, FAILURE, FALLBACK | - `filter`: logLevel, taskIds | `- type: io.kestra.plugin.ee.apps.execution.blocks.Logs`
    `filter:`
        `logLevel: "INFO"`
        `taskIds: []` | +| `Loading` | RUNNING | None | `- type: io.kestra.plugin.ee.apps.core.blocks.Loading` | +| `Alert` | FAILURE | - `style`: SUCCESS, WARNING, ERROR, INFO
- `showIcon`: true, false | `- type: io.kestra.plugin.ee.apps.core.blocks.Alert`
    `style: "WARNING"`
    `showIcon: true`
    `content: "An error occurred!"` | +| `Button` | SUCCESS, FAILURE | - `text`
- `url`
- `style`: DEFAULT, SUCCESS, DANGER, INFO | `- type: io.kestra.plugin.ee.apps.core.blocks.Button`
    `text: "More examples"`
    `url: "https://github.com/kestra-io/examples"`
    `style: "INFO"` | +| `TaskOutputs` | RUNNING, PAUSE, RESUME, SUCCESS | - `outputs`: list of outputs with `displayName`, `value`, and `type` | `- type: io.kestra.plugin.ee.apps.execution.blocks.TaskOutputs`
    `outputs:`
        `- displayName: My Task Output`
        `value: "{{ outputs.test.value }}"`
        `type: FILE` | + +Everything is customizable, from the text and style of buttons to the messages displayed before and after submissions. diff --git a/content/docs/06.enterprise/custom-dashboards.md b/content/docs/06.enterprise/custom-dashboards.md new file mode 100644 index 0000000000..c1e7487a99 --- /dev/null +++ b/content/docs/06.enterprise/custom-dashboards.md @@ -0,0 +1,146 @@ +--- +title: Custom Dashboards +icon: /docs/icons/kestra.svg +editions: ["EE", "Beta"] +version: ">= 0.20.0" +--- + +Build custom dashboards to visualize your executions, logs and metrics. + +## Overview + +Dashboards let you define custom queries and charts to visualize data on your executions, logs, and metrics. Rather than relying only on the default dashboard on Kestra’s home screen, you can create charts that answer specific questions and track key metrics. + +## The Dashboard Page + +The Dashboard page displays both the **default dashboard** and any **custom dashboards** you’ve created. To switch between dashboards, use the hamburger menu. If you have over 10 dashboards, simply type the dashboard name in the search bar to quickly find it. The same menu also lets you edit or delete existing dashboards. + +![main_page](/docs/enterprise/dashboards/main_page.png) + +The `+ Create a new dashboard` button lets you set up a new dashboard defined directly as code. + +## Create a new Dashboard as Code + +Clicking on the `+ Create a new dashboard` button opens a Code Editor where you can define the dashboard layout and data sources in code. + +Here's an example of a dashboard definition that displays executions over time and a pie chart of execution states: + +```yaml +title: Getting Started +description: First custom dashboard +timeWindow: + default: P7D + max: P365D +charts: + - id: executions_timeseries + type: io.kestra.plugin.core.dashboard.chart.TimeSeries + chartOptions: + displayName: Executions + description: Executions last week + legend: + enabled: true + column: date + colorByColumn: state + data: + type: io.kestra.plugin.core.dashboard.data.Executions + columns: + date: + field: START_DATE + displayName: Date + state: + field: STATE + total: + displayName: Executions + agg: COUNT + graphStyle: BARS + duration: + displayName: Duration + field: DURATION + agg: SUM + graphStyle: LINES + + - id: executions_pie + type: io.kestra.plugin.core.dashboard.chart.Pie + chartOptions: + graphStyle: DONUT + displayName: Total Executions + description: Total executions per state + legend: + enabled: true + colorByColumn: state + data: + type: io.kestra.plugin.core.dashboard.data.Executions + columns: + state: + field: STATE + total: + agg: COUNT +``` + +To see all available properties to configure a custom dashboard as code, see examples provided in the [Enterprise Edition Examples](https://github.com/kestra-io/enterprise-edition-examples) repository. + +## Querying Data + +The `data` property of a chart defines the type of data that will be queried and displayed. The `type` determines which columns are available for display. + +Dashboards can query data from these source `types`: +- `type: io.kestra.plugin.core.dashboard.data.Executions`: data related to your workflow executions +- `type: io.kestra.plugin.core.dashboard.data.Logs`: logs produced by your workflows +- `type: io.kestra.plugin.core.dashboard.data.Metrics`: metrics emitted by your plugins + +After defining the data source, specify the columns to display in the chart. Each column is defined by the `field` and may include additional optional properties. + + +| Property | Description | +| --- |----------------------------------------------------------------------------------------------------------------| +| `field` | The name of the column in the data source. This is the only required field. | +| `displayName` | The label that will be displayed in the chart | +| `agg` | The aggregation function to apply to the column. Supported aggregations include `AVG`, `COUNT`, `MAX`, `MIN`, `SUM` | +| `graphStyle` | The style of the graph to display. Supported styles include `LINES`, `BARS`, `POINTS` | +| `columnAlignment` | The alignment of the column in the table. Supported alignments include `LEFT`, `RIGHT`, `CENTER` | + + +You can also use the `where` property to set conditions that filter the result set before displaying it in the chart. Filters can apply to any column in the data source, with all conditions in the `where` property combined using the `AND` operator. If multiple conditions are needed with different logic, you can use the `type: OR` property. + +Available filter types include: +- `CONTAINS` +- `ENDS_WITH` +- `EQUAL_TO` +- `GREATER_THAN` +- `GREATER_THAN_OR_EQUAL_TO` +- `IN` +- `IS_FALSE` +- `IS_NOT_NULL` +- `IS_NULL` +- `IS_TRUE` +- `LESS_THAN` +- `LESS_THAN_OR_EQUAL_TO` +- `NOT_EQUAL_TO` +- `NOT_IN` +- `OR` +- `REGEX` +- `STARTS_WITH`. + +Available field types include the following columns: +- `ATTEMPT_NUMBER` +- `DATE` +- `DURATION` +- `END_DATE` +- `EXECUTION_ID` +- `FLOW_ID` +- `FLOW_REVISION` +- `ID` +- `LABELS` +- `LEVEL` +- `MESSAGE` +- `NAME` +- `NAMESPACE` +- `START_DATE` +- `STATE` +- `TASK_ID` +- `TASK_RUN_ID` +- `TRIGGER_ID` +- `TYPE` +- `VALUE`. + +Note that some of the above are reserved only for specific types of `data` e.g. the `LEVEL` column is only available for `type: io.kestra.plugin.core.dashboard.data.Logs`. diff --git a/content/docs/06.enterprise/invitations.md b/content/docs/06.enterprise/invitations.md new file mode 100644 index 0000000000..7b4bba429e --- /dev/null +++ b/content/docs/06.enterprise/invitations.md @@ -0,0 +1,43 @@ +--- +title: Invitations +icon: /docs/icons/admin.svg +editions: ["EE"] +version: ">= 0.20.0" +--- + +Add new users to your tenant or instance by using the invitation process. + +## Overview + +Administrators can invite users with pre-configured RBAC permissions. Invitations can be emailed directly, and users can set up their accounts upon acceptance. + +By default, if the email server is configured in Kestra EE, we send an email with an invitation link. If the email server isn’t configured, you can manually share the link with invited users. + +## How to Invite Users + +1. Navigate to the `IAM` page in the Administration section +2. Click on the `Users` tab +3. Click on the `Invite` button +4. Fill in the user's email address and select the desired Group or attach the role directly, optionally restricting the permission to one or more namespaces +5. Click on the `Invite` button — this will send an email to the user with an invitation link, or display the link you can share with the user manually. + +![invite1](/docs/enterprise/invitations/invite1.png) + +![invite2](/docs/enterprise/invitations/invite2.png) + +## Accepting Invitations + +When a user receives an invitation, they can click on the link in the email to accept it. The user will be redirected to the Kestra login page, where they can set up their account (i.e. create a password), or login using SSO if it's enabled. + +## Invite Expiration Time + +The user has 7 days to accept the invitation. After this period, the invitation will expire, and the user will need to be re-invited. + +If you want to change the default expiration time, you can do so by setting the `expireAfter` property in the `kestra.security.invitation` section of your `application.yaml` file. For example, to set the expiration time to 30 days, add the following configuration: + +```yaml +kestra: + security: + invitations: + expireAfter: P30D +``` \ No newline at end of file diff --git a/content/docs/06.enterprise/rbac.md b/content/docs/06.enterprise/rbac.md index 310eb53394..6c08209c2d 100644 --- a/content/docs/06.enterprise/rbac.md +++ b/content/docs/06.enterprise/rbac.md @@ -244,6 +244,11 @@ information attached to it, such as the first name or last name. They can change their own password, and adjust other settings such as theme, editor preferences, timezone, and a default namespace. +To add users to your Kestra instance, you can do one of the following: +- [Invite users](./invitations.md) to your instance or tenant from the UI +- Sync users from an external identity provider using SCIM +- Create users directly using Terraform + #### Change password If a user wants to change their password, they can do it on their profile. This page can be accessed through the top right corner of the UI. diff --git a/content/docs/08.ui/09.bookmarks.md b/content/docs/08.ui/09.bookmarks.md new file mode 100644 index 0000000000..65c91e67bc --- /dev/null +++ b/content/docs/08.ui/09.bookmarks.md @@ -0,0 +1,13 @@ +--- +title: Bookmarks +icon: /docs/icons/ui.svg +version: ">= 0.20.0" +--- + +Quickly save and access your favorite pages by starring them for instant retrieval. + +The bookmark feature allows you to star any page, instantly adding it to the Starred tab located in the left panel. + +You can easily customize your bookmarks by renaming or removing them directly from the left panel, ensuring a personalized and simple browsing experience. + +![bookmark](/docs/user-interface-guide/bookmarks.png) \ No newline at end of file diff --git a/content/docs/09.administrator-guide/03.monitoring.md b/content/docs/09.administrator-guide/03.monitoring.md index 30fafa7b1b..8ff62b1b52 100644 --- a/content/docs/09.administrator-guide/03.monitoring.md +++ b/content/docs/09.administrator-guide/03.monitoring.md @@ -29,8 +29,7 @@ errors: url: "{{ secret('SLACK_WEBHOOK') }}" payload: | { - "channel": "#alerts", - "text": "Failure alert for flow {{ flow.namespace }}.{{ flow.id }} with ID {{ execution.id }}" + "text": "Failure alert for flow `{{ flow.namespace }}.{{ flow.id }}` with ID `{{ execution.id }}`. Here is a bit more context about why the execution failed: `{{ errorLogs() }}`" } ``` diff --git a/content/docs/15.how-to-guides/local-file-sync.md b/content/docs/15.how-to-guides/local-file-sync.md new file mode 100644 index 0000000000..9f4b5bb16d --- /dev/null +++ b/content/docs/15.how-to-guides/local-file-sync.md @@ -0,0 +1,66 @@ +--- +title: Local Flow Synchronization +icon: /docs/icons/admin.svg +--- + +Sync Flows from a local directory. + +How to synchronize flows from a local directory on a local development instance. + +
+ +
+ +## Configure your instance + +::alert{type="warning"} +This feature is only for local development, that is why you can not connect to a distant Kestra instance. +:: + +When developing on a local Kestra instance, it can be more convenient to have your flows in a local directory, maybe synchronize with a GitHub repository, and have Kestra automatically load them. + +Below is the minimal configuration to enable local flow synchronization: + +```yaml +micronaut: + io: + watch: + enabled: true + paths: + - /path/to/your/flows +``` + +Multiple paths can be provided, and nested files will also be watched. +Files have to end with `.yml` or `.yaml` to be considered as a flow. And only valid flows will be loaded, invalid flows will be ignored. + +File created locally should use `..yml` or `_.yml` syntax to be loaded properly. + +Flow created inside the UI will be created at the root of the first path supplied in the configuration. + + +::alert{type="note"} +If you are using the docker-compose installation, you will need to mount a volume so Kestra container can access your local folder. + +```yaml + volumes: + # ... other volumes + - ./local_folder:/local_folder + environment: + KESTRA_CONFIGURATION: | + micronaut: + io: + watch: + enabled: true + paths: + - /local_folder +``` +:: + +## Details + +At startup, every file in the watched directory will be loaded into the database. Then every flow not existing in the watched directory will be created in the first path supplied in the configuration. + +When a file is created, updated, or deleted in the watched directory, Kestra will automatically load the flow into the database or remove it if the file is deleted. +If a flow is created, updated or deleted in the UI, the file will be created, updated or deleted in the watched directory. + +In the Kestra UI, you cannot change an ID nor a namespace, but in a file you can, in this case, the previous flow will be deleted, and a new one created. diff --git a/content/docs/15.how-to-guides/pause-resume.md b/content/docs/15.how-to-guides/pause-resume.md index 8e59850dcf..b6d10eda1b 100644 --- a/content/docs/15.how-to-guides/pause-resume.md +++ b/content/docs/15.how-to-guides/pause-resume.md @@ -34,7 +34,7 @@ The `Pause` task will pause the execution and the `Log` task will run only once ## Pausing and resuming a workflow from the UI -Create and execute the above workflow. Once the execution is paused, you can inspect the current logs and outputs. Then, you can resume it from the UI by clicking on the `Resume` button in the `Overview` tab: +You can either use the Pause task or manually Pause from the Execution overview page. Once the execution is paused, you can inspect the current logs and outputs. Then, you can resume it from the UI by clicking on the `Resume` button in the `Overview` tab: ![pause_resume](/docs/how-to-guides/pause-resume/pause_resume.png) diff --git a/content/docs/configuration/index.md b/content/docs/configuration/index.md index cad61f853c..a40c501515 100644 --- a/content/docs/configuration/index.md +++ b/content/docs/configuration/index.md @@ -1043,6 +1043,21 @@ micronaut: For more detailed changes like allowing only specific origins or specific methods, you can refer [this guide](https://docs.micronaut.io/latest/guide/index.html#corsConfiguration). +### Configure Local Flow Syncronization + +Below is the minimal configuration to enable local flow synchronization: + +```yaml +micronaut: + io: + watch: + enabled: true + paths: + - /path/to/your/flows +``` + +For more information, check out the [dedicated guide](../15.how-to-guides/local-file-sync.md). + ## Plugins Maven repositories used by the command `kestra plugins install` can be configured using the `kestra.plugins` configuration. @@ -1408,6 +1423,19 @@ kestra: Make sure that you attach the `defaultRole` configuration under `kestra.security`rather than under `micronaut.security` — it's easy to confuse the two so make sure you enter that configuration in the right place. :: +### Invitation Expiration + +When you invite a new user to Kestra, the invitation will expire after a certain amount of time. By default, invitations expire after 7 days. + +If you want to change the default expiration time, you can do so by setting the `expireAfter` property in the `kestra.security.invitation` section. For example, to set the expiration time to 30 days, add the following configuration: + +```yaml +kestra: + security: + invitations: + expireAfter: P30D +``` + ## Server Using the `kestra.server` configuration, you can set up multiple server-specific functionalities. diff --git a/content/docs/expressions/index.md b/content/docs/expressions/index.md index be174271ac..dd1d8200e7 100644 --- a/content/docs/expressions/index.md +++ b/content/docs/expressions/index.md @@ -1380,6 +1380,27 @@ Functions in Kestra allow you to dynamically generate or manipulate content. The --- +### errorLogs + +The `errorLogs()` function retrieves a list of error logs from the failed task run. This is useful when sending alerts on failure. When using this function e.g. in a Slack alert message, you'll have a context about why the execution failed. + +```yaml +id: error_logs_demo +namespace: company.team + +tasks: + - id: fail + type: io.kestra.plugin.core.execution.Fail + errorMessage: Something went wrong, make sure to fix it asap ⚠️ + +errors: + - id: alert + type: io.kestra.plugin.core.log.Log + message: list of error logs — {{ errorLogs() }}> +``` + +--- + ### block The `block` function renders the contents of a block multiple times. It is distinct from the `block` tag used to declare blocks. diff --git a/public/docs/concepts/correlationId.png b/public/docs/concepts/correlationId.png new file mode 100644 index 0000000000..76c0f0f747 Binary files /dev/null and b/public/docs/concepts/correlationId.png differ diff --git a/public/docs/enterprise/announcement/display_announcement.png b/public/docs/enterprise/announcement/display_announcement.png new file mode 100644 index 0000000000..ae652acac9 Binary files /dev/null and b/public/docs/enterprise/announcement/display_announcement.png differ diff --git a/public/docs/enterprise/announcement/main_announcement.png b/public/docs/enterprise/announcement/main_announcement.png new file mode 100644 index 0000000000..d25b697d06 Binary files /dev/null and b/public/docs/enterprise/announcement/main_announcement.png differ diff --git a/public/docs/enterprise/announcement/setup_announcement.png b/public/docs/enterprise/announcement/setup_announcement.png new file mode 100644 index 0000000000..a6b9397925 Binary files /dev/null and b/public/docs/enterprise/announcement/setup_announcement.png differ diff --git a/public/docs/enterprise/apps/apps_catalog.png b/public/docs/enterprise/apps/apps_catalog.png new file mode 100644 index 0000000000..9b4ef72e42 Binary files /dev/null and b/public/docs/enterprise/apps/apps_catalog.png differ diff --git a/public/docs/enterprise/dashboards/main_page.png b/public/docs/enterprise/dashboards/main_page.png new file mode 100644 index 0000000000..d549404d74 Binary files /dev/null and b/public/docs/enterprise/dashboards/main_page.png differ diff --git a/public/docs/enterprise/invitations/invite1.png b/public/docs/enterprise/invitations/invite1.png new file mode 100644 index 0000000000..2f13410fa9 Binary files /dev/null and b/public/docs/enterprise/invitations/invite1.png differ diff --git a/public/docs/enterprise/invitations/invite2.png b/public/docs/enterprise/invitations/invite2.png new file mode 100644 index 0000000000..879b2c9259 Binary files /dev/null and b/public/docs/enterprise/invitations/invite2.png differ diff --git a/public/docs/enterprise/tenants-dedicated-internal-storage.png b/public/docs/enterprise/tenants-dedicated-internal-storage.png new file mode 100644 index 0000000000..14d2b71d9c Binary files /dev/null and b/public/docs/enterprise/tenants-dedicated-internal-storage.png differ diff --git a/public/docs/user-interface-guide/bookmarks.png b/public/docs/user-interface-guide/bookmarks.png new file mode 100644 index 0000000000..63c5e099a3 Binary files /dev/null and b/public/docs/user-interface-guide/bookmarks.png differ