Merge development docs into the manual
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
# Container Images
|
||||
|
||||
These [container images](https://github.com/truecharts/containers) are tailored for Kubernetes.
|
||||
|
||||
## Purpose
|
||||
|
||||
The goal of this project and the container images are to support [Semantic Versioning](https://semver.org/), security and native K8S support.
|
||||
We try to keep a [KISS principle](https://en.wikipedia.org/wiki/KISS_principle) when building these images, which means no [s6-overlay](https://github.com/just-containers/s6-overlay) and all images are built on top of [ubuntu:focal](https://hub.docker.com/_/ubuntu).
|
||||
|
||||
## Configuration
|
||||
|
||||
In order to get the Container images repository and tags see [here](https://github.com/orgs/truecharts/packages?ecosystem=container&visibility=public).
|
||||
|
||||
For configuration and documentation see [here](https://truecharts/containers/getting-started/).
|
||||
|
||||
## Support
|
||||
|
||||
We have several different methods for getting support.
|
||||
|
||||
- [GitHub Discussions](https://github.com/truecharts/apps/discussions)
|
||||
@@ -0,0 +1,46 @@
|
||||
# License Header Format
|
||||
|
||||
Within TrueCharts we sometimes use code thats has a different license from the rest of the project.
|
||||
When there is not already a license header present, we use these standard license headers.
|
||||
|
||||
##### TPL
|
||||
```
|
||||
{{/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
`SPDX-License-Identifier: Apache-2.0`
|
||||
|
||||
This file is considered to be modified by the TrueCharts Project.
|
||||
*/}}
|
||||
```
|
||||
|
||||
##### YAML
|
||||
```
|
||||
##
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# `SPDX-License-Identifier: Apache-2.0`
|
||||
#
|
||||
# This file is considered to be modified by the TrueCharts Project.
|
||||
##
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# App Addition Guidelines
|
||||
|
||||
Though we aim to be as open to contributions, at TrueCharts we still sometimes have to decide which Apps we do and do not add to our catalog. This document aims to give some guidelines in how we are going to make such decisions.
|
||||
|
||||
### Guidelines
|
||||
|
||||
##### Target Audience
|
||||
|
||||
- Our target audience is Home and SMB users
|
||||
- While we currently support only one node, due to TrueNAS SCALE constraints, we aim for a maximum adviced deployment size of 10 Nodes and/or 50 Drives. This is in line with what we expect our target audience to be
|
||||
|
||||
|
||||
##### Commercial vs non-commercial
|
||||
|
||||
- Apps that are only useable for paying customers are a no-go
|
||||
- Apps that are trial-ware to non-paying customers are a no-go. Apps that have an enterprise option, that doesn't obstruct the open-core version are generally allowed
|
||||
- Apps that are open-source are prefered over closed-source Apps. If opensource alternatives are available we might not approve a closed-source App.
|
||||
- If a company or official maintainer submits an App, we expect them to maintain it themselves. We do not have the resources to work for external projects.
|
||||
|
||||
##### Update Policies and stability
|
||||
|
||||
- We expect Apps to have decent security (options) in place
|
||||
- We expect Apps not to contain higher-level CVE's
|
||||
- We prefer Apps that are actively maintained. Expect Apps that are abandoned (or barely maintained) for a year or more to even be removed, as we do not expect those to be secure.
|
||||
|
||||
##### App design
|
||||
|
||||
- Apps charts are expected to be kept as simple as possible, preferably using the common-chart where-ever possible.
|
||||
- It's adviced to only deploy HA versions of apps if they are relatively simple. Complicated Apps (with addon operators and load balancers for example), should only be used in key area's because they are harder to maintain.
|
||||
- We aim for a "1 App - 1 DB - 1 DB Instance" solution, because small single DB instances can be easily spread over multiple nodes in the future.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Apps GUI Suggestions
|
||||
|
||||
The goal is to gather some suggestions and forward them to iX-Systems.
|
||||
|
||||
##### Visual suggestions
|
||||
|
||||
- Use all screen on install / edit app, not just a sidebar. [NAS-110183](https://jira.ixsystems.com/browse/NAS-110183)
|
||||
- Add more bulk options, like bulk upgrade and restart.
|
||||
- Add sorting options in app catalog.
|
||||
- Default tab should be "Installed Apps" or have an option to set the default.
|
||||
- Make timezone searchable and sorted in Scale Apps installation [NAS-109524](https://jira.ixsystems.com/browse/NAS-109524)
|
||||
- Add service information (Service name and ports) to the App Overview (In the card displayed when clicking an installed app).
|
||||
- The "Application Events" in the App Overview should be shown in a similar UI widget as the container logs. This would improve the readability.
|
||||
- Application Events should be auto-updated, instead of having to re-open the app card to see the new events. [NAS-111626](https://jira.ixsystems.com/browse/NAS-111626)
|
||||
- The App overview card should be resizable, right now viewing application events is very limiting.
|
||||
- Fix some of the themes to work with apps section. Light color themes like paper make it very hard to see if an app is up to date or requiring upgrade
|
||||
- Add ability to set which app will start on boot (Auto start)
|
||||
- Add ability to set a delay before an app starts on boot (Delayed auto start)
|
||||
- Add ability to group apps (for better organization) (e.g. Media apps, Production apps, Dev Apps etc)
|
||||
- Show statistics per app (cpu / network / ram)
|
||||
|
||||
- :white_check_mark: Make timezone default to timezone set in TN System [NAS-110373](https://jira.ixsystems.com/browse/NAS-110373)
|
||||
- :white_check_mark: Show all config options on "Confirm options" when installing an App
|
||||
- :white_check_mark: Installed apps status should be updated without the need to change view and come back. e.g After installing/updating an app, you will always see "Deploying" until you go to manage catalogs and come back to installed apps.
|
||||
|
||||
##### Technical suggestions
|
||||
|
||||
- Allow `show_if` and `show_subquestions_if` to to use values for evaluation from parent variables [NAS-110751](https://jira.ixsystems.com/browse/NAS-110751)
|
||||
- Add option for separators and whitespace in questions.yaml [NAS-110750](https://jira.ixsystems.com/browse/NAS-110750)
|
||||
- Validate regex defined in questions.yaml when focus leaves input field.
|
||||
- Set custom message to display when `valid_chars` is not matched.
|
||||
- Add ability to save a PVC backup even on app delete
|
||||
- Add ability to restore a PVC backup from a deleted app
|
||||
|
||||
Join our [discord](https://truecharts.org/discord) to make a new suggestion.
|
||||
@@ -0,0 +1,88 @@
|
||||
# TrueNAS SCALE Chart Structure
|
||||
|
||||
A TrueNAS SCALE chart repository differs slightly in directory structure from upstream repos in that it includes an `app version` directory.
|
||||
|
||||
A TrueNAS SCALE chart also has three additional files an `app-readme.md` file that provides a high level overview display in the TrueNAS SCALE UI and a `questions.yaml` file defining questions to prompt the user with and an `item.yaml` file outlining item specific details.
|
||||
|
||||
There are 2 directories `charts` and `test`, each representing a train. Chart releases created from catalog items in a specific train cannot be moved to another train. Currently only the `charts` train can be used inside the UI.
|
||||
|
||||
```
|
||||
charts/<train>/<chart name>/
|
||||
charts/ # Directory containing dependency charts
|
||||
Chart.yaml # Required Helm chart information file
|
||||
README.md # Optional: Helm Readme file (will be rendered in TrueNAS SCALE UI as well)
|
||||
templates/ # A directory of templates that, when combined with values.yml will generate K8s YAML
|
||||
values.yaml # The default configuration values for this chart
|
||||
```
|
||||
|
||||
```
|
||||
charts/<train>/<chart name>/
|
||||
app-readme.md # TrueNAS SCALE Specific: Readme file for display in TrueNAS SCALE UI
|
||||
questions.yaml # TrueNAS SCALE Specific: File containing questions for TrueNAS SCALE UI
|
||||
ix_values.yaml # Hidden configuration values when installing using TrueNAS SCALE
|
||||
```
|
||||
|
||||
*See the upstream Helm chart [developer reference](https://helm.sh/docs/chart_template_guide/) for a complete walk through of developing charts.*
|
||||
|
||||
To convert an upstream chart to take advantage of TrueNAS SCALE enhanced UX, first create an `item.yaml` file.
|
||||
This file among other catalog item information provides a list of categories that this chart fits into. This helps users navigate and filtering when browsing the catalog UI.
|
||||
|
||||
```
|
||||
$ cat charts/<train>/<chart name>/SCALE/item.yaml
|
||||
categories:
|
||||
- generic
|
||||
icon_url: "http://ix_url"
|
||||
```
|
||||
|
||||
After that create `app-readme.md` file.
|
||||
|
||||
```
|
||||
$ cat charts/<train>/<chart name>/SCALE/app-readme.md
|
||||
|
||||
iX-chart is a chart designed to let user deploy a docker image in a TrueNAS SCALE kubernetes cluster.
|
||||
It provides a mechanism to specify workload type, add external host interfaces in the pods, configure volumes and allocate host resources to the workload.
|
||||
```
|
||||
|
||||
Then add a `questions.yaml` file to prompt the user for something.
|
||||
|
||||
```
|
||||
groups:
|
||||
- name: "Container Images"
|
||||
description: "Image to be used for container"
|
||||
questions:
|
||||
- variable: image
|
||||
description: "Docker Image Details"
|
||||
group: "Container Images"
|
||||
schema:
|
||||
type: dict
|
||||
required: true
|
||||
attrs:
|
||||
- variable: repository
|
||||
description: "Docker image repository"
|
||||
label: "Image repository"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
- variable: tag
|
||||
description: "Tag to use for specified image"
|
||||
label: "Image Tag"
|
||||
schema:
|
||||
type: string
|
||||
default: "latest"
|
||||
- variable: pullPolicy
|
||||
description: "Docker Image Pull Policy"
|
||||
label: "Image Pull Policy"
|
||||
schema:
|
||||
type: string
|
||||
default: "IfNotPresent"
|
||||
enum:
|
||||
- value: "IfNotPresent"
|
||||
description: "Only pull image if not present on host"
|
||||
- value: "Always"
|
||||
description: "Always pull image even if present on host"
|
||||
- value: "Never"
|
||||
description: "Never pull image even if it's not present on host"
|
||||
```
|
||||
|
||||
The above will prompt the user with 2 text fields and a dropdown in the UI getting details for image configuration in a helm chart.
|
||||
_More information about questions.yaml is available [here](https://wiki.truecharts.org/development/questions-yaml/)_
|
||||
@@ -0,0 +1,61 @@
|
||||
# Chart.yaml layout
|
||||
|
||||
At TrueCharts we try to keep some files standardised, this enables us to make changes to these charts in bulk with less risk of mistakes. Chart.yaml is one of these files.
|
||||
In this documentation we will explain the standardised layout options. For an example layout, please see our standard Chart.yaml [template](https://github.com/truecharts/apps/tree/master/tools/templates/chart/Chart.yaml)
|
||||
|
||||
|
||||
### Layout Explained
|
||||
|
||||
```
|
||||
apiVersion: The chart API version (required)
|
||||
kubeVersion: A SemVer range of compatible Kubernetes versions (optional)
|
||||
name: The name of the chart (required)
|
||||
version: A SemVer 2 version (required)
|
||||
upstream_version: A SemVer 2 version, as used by an upstream Helm Chart source (optional)
|
||||
appVersion: The version of the app that this contains (optional). Needn't be SemVer. Quotes recommended.
|
||||
description: A single-sentence description of this project (optional)
|
||||
type: The type of the chart (optional)
|
||||
deprecated: Whether this chart is deprecated (optional, boolean)
|
||||
home: The URL of this projects home page (optional)
|
||||
icon: A URL to an SVG or PNG image to be used as an icon (optional).
|
||||
keywords:
|
||||
- A list of keywords about this project (optional)
|
||||
sources:
|
||||
- A list of URLs to source code for this project (optional)
|
||||
dependencies:
|
||||
- name: The name of the chart (nginx)
|
||||
repository: The repository URL ("https://example.com/charts") or alias ("@repo-name")
|
||||
version: The version of the chart ("1.2.3")
|
||||
condition: (optional) A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled )
|
||||
tags: # (optional)
|
||||
- Tags can be used to group charts for enabling/disabling together
|
||||
import-values: # (optional)
|
||||
- ImportValues holds the mapping of source values to parent key to be imported. Each item can be a string or pair of child/parent sublist items.
|
||||
alias: (optional) Alias to be used for the chart. Useful when you have to add the same chart multiple times
|
||||
maintainers: # (optional)
|
||||
- name: The maintainers name (required for each maintainer)
|
||||
email: The maintainers email (optional for each maintainer)
|
||||
url: A URL for the maintainer (optional for each maintainer)
|
||||
annotations:
|
||||
example: A list of annotations keyed by name (optional).
|
||||
```
|
||||
|
||||
##### Commenting
|
||||
|
||||
In the above description there are a lot of values that are not actually used. Some of those, like `deprecated`, we just set to false. While others, like `annotations` get commented out.
|
||||
|
||||
Please refer to our standard Chart.yaml [template](https://github.com/truecharts/apps/tree/master/tools/templates/chart/Chart.yaml) to see which unused values needs which treatment.
|
||||
|
||||
##### Dependencies
|
||||
|
||||
We expect each chart to use our Common-Chart in some capacity, inless it's absolutely impossible to do so. This also means we expect the Common-Chart to always be the first dependency in the list. This enables us to easily update all common-chart references in bulk.
|
||||
|
||||
All other dependencies are expected to be listed in alphabetical order.
|
||||
|
||||
##### Maintainers
|
||||
|
||||
The first maintainer should always be TrueCharts, as the TrueCharts core team is expected to step in if the other maintainers fail to maintain their work.
|
||||
An example of how to list TrueCharts as a maintainer is available in our standard Chart.yaml [template](https://github.com/truecharts/apps/tree/master/tools/templates/chart/Chart.yaml).
|
||||
|
||||
While currently we primarily use the CODEOWNERS file to define maintainers. We might in the future either automate keeping track of maintainers, completely rely on the maintainers or do both. For this reason it's important to add yourself as a maintainer if you expect to maintain your work.
|
||||
All other maintainers are, ofcoarse, expected to be entered in importance. With the primary maintainer under "truecharts" and secondary maintainers thereunder.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Common Library Chart
|
||||
|
||||
In Helm 3, their team introduced the concept of a [Library chart](https://helm.sh/docs/topics/library_charts/).
|
||||
|
||||
> A library chart is a type of Helm chart that defines chart primitives or definitions which can be shared by Helm templates in other charts. This allows users to share snippets of code that can be re-used across charts, avoiding repetition and keeping charts DRY.
|
||||
|
||||
The first version of our Common library was ported from k8s-at-home, which they introduced because they saw many charts requiring only a few select configuration options in their Helm charts.
|
||||
|
||||
Let's take for example, Sonarr, Sabnzbd, Overseerr. Each of these charts only require setting `service`, `port`, `persistence`, `ingress` and `image` since state and app configuration is handled by the application itself. In order to stay somewhat DRY (Don't Repeat Yourself) and keeping with Helm 3 usage for a Library chart, we saw this pattern and decided it was worth it for us to create a library. This means each one of these app charts has a dependency on what we call the `common` library.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
This project welcomes any and all input, but we need to have a few quality guidelines. These guidelines will be examplained here, in this document.
|
||||
|
||||
### GIT Guidelines
|
||||
***
|
||||
#### New to GIT
|
||||
|
||||
If you have never used git before, you can look up our general reference on our wiki.
|
||||
|
||||
#### Git and You
|
||||
|
||||
GIT is a fantastic system, but while using it we have a few guidelines to keep it fantastic for everyone.
|
||||
|
||||
* Submit complete PR's.
|
||||
* Add [DNM] if you do not want your PR merged yet.
|
||||
* Always try and fill in the whole form, even for small PR's.
|
||||
* Don't close when a reviewer requests changes (just push the changes or ask for help).
|
||||
* Explain what you did in your PR.
|
||||
* Be thorough.
|
||||
* If you can add screenshots to clarify.
|
||||
* Always try to add "Fixes #000" (where 000 is the Issue your PR fixes)
|
||||
* found something you want to fix yourself? Please do make an issue too.
|
||||
|
||||
### Structure Guidelines
|
||||
***
|
||||
|
||||
#### Inclusion of files and folders
|
||||
|
||||
Although GIT is quite friendly in what it accepts in terms of files and folder changes in a commit, a reviewer's or bugfixer's time is not unlimited. For that reason, we have a few specific guidelines in regards to the inclusion of files and folders in your PR.
|
||||
|
||||
* Only include files you actually changed.
|
||||
* Try not to include multiple changes in one PR
|
||||
* Want to change the formatting of multiple files too? Make a separate PR.
|
||||
|
||||
|
||||
### Code Guidelines
|
||||
***
|
||||
#### Your code, your style, my review
|
||||
|
||||
Here at TrueCharts, we value people having their own style. But your code needs to be reviewable and editable by others too. For that reason, we have a few basic coding guidelines
|
||||
|
||||
* **Always** explain regex in a comment within your code.
|
||||
* Write simple code and don't try to impress.
|
||||
* We will run (Basic) automated reformating of code once in a while.
|
||||
* Document your changes in your code and if need be, on the wiki.
|
||||
* All PR's should be able to pass our automated tests.
|
||||
|
||||
#### Apps requirements
|
||||
|
||||
- Apps should always save user-specific data in a persistant location. That can be connected by both IXVolume or Hostpath
|
||||
- Apps should not require the user to edit any config file themselves. All config changes should be either automated or using the UI
|
||||
- Apps should not use default passwords, the user should always be forced(!) to put credentials in manually
|
||||
|
||||
|
||||
### Review Guidelines
|
||||
***
|
||||
Even us review gods need some guidelines once in a while.
|
||||
|
||||
* Let people learn from their mistakes
|
||||
* Review instead of merging without comments
|
||||
* Abide by these guidelines in your review
|
||||
* Tests exist for a reason. Don't merge with test-failures
|
||||
|
||||
|
||||
|
||||
### Todo vs Feature vs bug:
|
||||
***
|
||||
Please take note of the difference between a TODO and Feature
|
||||
|
||||
* Bug: An unexpected behavior of the script or a crash. Including, but not limited to, errors and warnings.
|
||||
* Todo: When you come across something that needs tweaking/adding during development, is not an unexpected behavior
|
||||
* Feature: When you, out of personal preference, want something added or changed.
|
||||
|
||||
### That's it!
|
||||
***
|
||||
Someone will come along and review the changes. If everything looks good then they will merge it with the main repo. If you need any help don't be afraid to ask in the discord channel: [https://discord.gg/tFcTpBp](https://discord.gg/tFcTpBp)
|
||||
@@ -0,0 +1,202 @@
|
||||
# Getting Started
|
||||
|
||||
This is a step by step guide for people who want to contribute but have no idea how to get started.
|
||||
|
||||
If you get lost at any point in this guide, don't be afraid to ask. There are tons of friendly dudes and dudettes who will answer all your questions.
|
||||
|
||||
***
|
||||
|
||||
|
||||
|
||||
### First thing first
|
||||
|
||||
You will need these to start your journey:
|
||||
|
||||
- A [GitHub account](https://github.com/).
|
||||
|
||||
- You'll also need to download Git from this link https://git-scm.com/, this is different from GitHub and will allow you to download and upload TrueCharts and your personal changes
|
||||
|
||||
|
||||
|
||||
### Setting up your dev environment
|
||||
|
||||
If you already know what you're doing, go to our [GitHub](https://github.com/truecharts/apps) and fork. Otherwise, look at this picture, from now on this will be the **contribution cycle**. This is how our workflow will look at the end of the tutorial.
|
||||
|
||||
<img src="https://i.imgur.com/qPg9XmQ.png" alt="Contribution cycle" style="zoom:120%;" />
|
||||
|
||||
|
||||
|
||||
What's that? You have no idea what any of that means? Worry not, my fellow contributor! I will guide you step by step.
|
||||
|
||||
First, you did your [GitHub account](https://github.com/) account as suggested, right? Good. We will now visit the [TrueCharts Repository in GitHub](https://github.com/truecharts/apps) and click this little button located at the top right corner of the page:
|
||||
|
||||

|
||||
|
||||
As the hint suggests, this will create your very own copy of TrueCharts under your account. This copy is yours and you can do whatever you want with it, but in order to contribute, you will need to comply with some good practices I'll tell you in a second.
|
||||
|
||||
Good, now we just need GIT. You don't know what a GIT is? Well, GIT is a [Version Control Software](https://en.wikipedia.org/wiki/Version_control) designed to deal with the problem of having multiple people modifying the same files at the same time. In other words, we need it. If we don't use it, the project would descend into chaos.
|
||||
|
||||
At this point, you have a very important decision to make. It is like the type of Pokémon you choose to start your adventure... You want [GIT with GUI](https://desktop.github.com/) or [CLI](https://gitforwindows.org/)? I will describe the starting steps for both now, so you can make your mind. (OSX and Linux come with GIT CLI installed!)
|
||||
|
||||
At a later stage you might also want to pick your own GUI, like [GitKraken](https://www.gitkraken.com/) or [SourceTree](https://www.sourcetreeapp.com/)
|
||||
|
||||
|
||||
##### Downloading GIT and Dependencies
|
||||
First of all, you need to download Git from this link https://git-scm.com/, this is also a great stage to install [GIT with GUI](https://desktop.github.com/) or your own GIT GUI.
|
||||
|
||||
**Optionally**
|
||||
_With TrueCharts we use some custom tools to make sure you have the least amount of work possible when working on the project._
|
||||
_However, this means you need some custom tools before you can start working on TrueCharts:_
|
||||
|
||||
- _Git (git client optional)_
|
||||
- _Python (including Pip, added to path on windows)_
|
||||
- _Pre-Commit (prefered)_
|
||||
|
||||
_When on Windows install Python3 with the installer available here: (https://www.python.org/downloads/), Be sure to check "Add to Path" during installation._
|
||||
|
||||
After that's finished installing, restart your computer then you can continue with setting up the project.
|
||||
|
||||
##### Cloning from your GitHub
|
||||
|
||||
**You are here**: <img src="https://i.imgur.com/jLPqKL9.png" alt="cloning" style="zoom: 80%;" />
|
||||
|
||||
After **Forking** from TrueCharts central repo (**upstream**), we need to **clone** from our fork so we get the files into your computer (**Local repo**).
|
||||
|
||||
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <br /><img src="https://i.imgur.com/mVoz1Kp.pnghttps://i.imgur.com/QYUSgJQ.png" alt="desk2" style="zoom:80%;" /> | Navigate to the folder where you want to save the files<br />``git clone https://github.com/YourUser/YourRepo.git`` |
|
||||
|
||||
|
||||
|
||||
##### Adding the central repo as a remote
|
||||
|
||||
Are you done downloading? Awesome! Now your local repo is automagically soul-linked with your remote repo in GitHub (remember we call this **origin**). We're going to also link the central repo and name it **upstream**
|
||||
|
||||
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :------------------------: | :----------------------------------------------------------: |
|
||||
| This is automagically done | Navigate to the folder where your local repo is<br />``git remote add upstream https://github.com/truecharts/apps.git``<br />Now to make sure everything is in order, we do<br />``git remote -v``<br />and it should show both repos, yours in **origin** and central in **upstream** |
|
||||
|
||||
|
||||
##### Setting up Pre-Commit
|
||||
|
||||
Pre-Commit makes sure to fix small warnings that might prevent us from merging your changes into our repo. For now it isn't really important why, how and what. But realise it does so in each step called "commit" in the future.
|
||||
|
||||
To setup Pre-Commit on windows, simply double click `tools/pre-commit-install.bat`, on Linux you can install pre-commit by using `pip install pre-commit` and `pre-commit install` from the project top-most directory
|
||||
|
||||
|
||||
### Opening the project and editing the project
|
||||
|
||||
|
||||
By now you would have a complete copy of TrueCharts to play with.
|
||||
Use your favorite editor to edit them and/or follow other guides to make the changes you want!
|
||||
|
||||
What follows in this guide is how to get your changes into the TrueCharts official catalog
|
||||
|
||||
|
||||
### Final step in your setup!
|
||||
|
||||
After some playing around you might notice it created changes you don't want to keep. Said files **should not be committed** when you request your other changes to be integrated into the TrueCharts. Let's go and discard all of them...
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| Go to the **changes** tab. In my case, I have 2 changes<br /><br /> Now right-click in the amount of changes and discard all | ``git status`` will show you all the unstaged changes you currently have.<br />``git checkout .`` and ``git clean -f`` to get rid of all of them. |
|
||||
|
||||
You will be doing this **a lot** so make sure to learn it!
|
||||
|
||||
Now that our **master** branch is completely clean we will create a new branch from it. Try to always have a **feature branch** you can play with and keep **master** pristine.
|
||||
|
||||
What's a branch? Well, let's say it is like having a multiverse in your folder. In **branch A** you have a file called "greeting.txt" and its content is "hello world", while in **branch B** you have the same file but now its content is "hello universe". You can see how this is useful for us, so we have a version of the game that is common to everyone and you have your own version with the feature you're adding. We can later **merge** both branches and GIT will try its best to do it smoothly.
|
||||
|
||||
So how do I create a new branch?
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| Click the current branch button<br /><br />![create new branch 2]()<br />All that's missing is to publish the new branch so your remote in GitHub (**origin**) is up to date<br /> | <br />``git branch mybranch``<br />Where "mybranch" is the name you chose for your branch (be more creative than this, please).<br />Then we do ``git checkout mybranch`` to change the current branch to **mybranch** instead of **master**<br />Finally we publish our new branch doing ``git push`` |
|
||||
|
||||
|
||||
### Contribute to the central repo
|
||||
|
||||
|
||||
#### Committing and pushing your changes
|
||||
|
||||
You are here: 
|
||||
|
||||
|
||||
I strongly suggest you handle your changes in your IDE or GitHub Desktop. Remember to only commit those files you intended to change.
|
||||
|
||||
In the case of GitHub Desktop, all you got to do is to select the files you wish to commit and click the commit button
|
||||
|
||||

|
||||
|
||||
Now all that is missing is publishing your commits to your remote (**origin**)
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :------------------------------------------------: | :-----------------: |
|
||||
|  | ``git push origin`` |
|
||||
|
||||
|
||||
|
||||
#### Making a PR
|
||||
|
||||
A **P**ull **R**equest is the only way to get your changes into the central version of the game. You do a PR by **committing** your changes and **pushing them** to your remote repo (**origin**). Then, visit the [TrueCharts Repository in GitHub](https://github.com/truecharts/apps) and click this green button:
|
||||
|
||||

|
||||
|
||||
You will see a page where you can name your PR and fill a little form with the relevant information. Your PR will be tested and reviewed and once you answered all questions and processed all feedback, it will be accepted into TrueCharts!
|
||||
|
||||
#### Updating your repo
|
||||
|
||||
This is a chaotic project and stuff happens almost **every day** so it is very important that you keep your repo up-to-date, especially when mapping.
|
||||
|
||||
|
||||
|
||||
| GitHub Desktop | Git Bash |
|
||||
| :------------------------------------------------: | :-----------------------------------------------------: |
|
||||
| Click the current branch tab<br /><br />In the list find ``upstream/master``<br /><img src="https://i.imgur.com/7ifC4MQ.png" /> | ``git fetch --all``<br />``git merge upstream/master`` |
|
||||
|
||||
|
||||
|
||||
You did it, you completed the tutorial! Now go back to the first time I showed you the **Contribution cycle** picture and see how you understand it a little better now!
|
||||
|
||||
Here is a little resume of what we just saw:
|
||||
|
||||
**Set up**
|
||||
|
||||
1. Fork from the central repo (upstream)
|
||||
2. Clone from your remote repo (origin) to your local
|
||||
3. Create a feature branch
|
||||
|
||||
**Working**
|
||||
|
||||
0. Update your repo from the central (upstream)
|
||||
|
||||
1. Start working in your feature
|
||||
2. Commit to your local repo
|
||||
3. Push from your local to your remote (origin)
|
||||
4. Make a PR
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## Now what?
|
||||
Well, feeling confused after messing around with the scenes and all? well, it's now time to actually learn to work on TrueCharts and TrueNAS SCALE Apps!
|
||||
|
||||
##### Reading other TrueCharts wikis
|
||||
Take a look at [other wiki pages we have](https://wiki.truecharts.org)
|
||||
|
||||
|
||||
##### Downloading a code editor
|
||||
There is a lot you can accomplish through simple text editors like notepad and notepad++, but if you plan on contributing seriously to the code/scripts, you'll do better if you have a good coding environment set-up.
|
||||
|
||||
##### Getting help
|
||||
There is no shame in asking questions.
|
||||
Anyone would be glad to answer your questions, just ask!
|
||||
|
||||
##### License
|
||||
This specific file is licensed under GNU AGPL v3
|
||||
`SPDX-License-Identifier: AGPL-3.0-only`
|
||||
@@ -0,0 +1,356 @@
|
||||
# Ingress
|
||||
|
||||
Ingress is what we call "Reverse Proxy" in the UI and in the user side of the documentation. Please be aware that those refer to the same system. An Ingress is, simply put, just Kubernetes way of connecting outsides to Apps running in containers.
|
||||
|
||||
### Ingress Types
|
||||
|
||||
We currently support:
|
||||
- HTTP via Ingres
|
||||
- HTTP via Traefik IngressRoute (HTTP-IR)
|
||||
- TCP via Traefik IngressRouteTCP
|
||||
- UDP via Traefik IngressRouteUDP
|
||||
|
||||
From questions.yaml and the UI, these can be changed with selecting another "Type". However: Under the hood IngressRoutes and Ingress are totally different beasts and have a seperate creation process. Errors for Plain HTTP do NOT have to be present in HTTP-IR.
|
||||
|
||||
It's also important to note that TCP (and even more so: UDP) have less options available. The example configurations below contain a mostly complete overview of what is currently available and reasonable.
|
||||
|
||||
##### Ingress and Services
|
||||
|
||||
It's important to know what Ingress does, before you start creating ingresses in questions.yaml. Ingresses send outside Traffic, to a kubernetes Service, which in turn forwards traffic to the actual containers.
|
||||
|
||||
This means that every container needs to know how to reach their Service. If they do not, things go wrong.
|
||||
|
||||
To ensure this, it's adviced to keep the names of your Ingresses the same as the names of your services. We made sure the ingress would automatically detect (and connect to) the main port of a Service with the same name.
|
||||
|
||||
However: In case you need to do this differently, need to connect to additionalServices and/or need to connect to a secondary port, you can manually set both the serviceName and servicePort in questions.yaml. We advice however, to only do so if absolutely necessary!
|
||||
|
||||
##### The Main Ingress
|
||||
|
||||
The main Ingress and Main service take an important role in our standardisation. Where the main Service is used for healthchecks and the "portal" button, the main Ingress is just used for the portal button.
|
||||
|
||||
However: As the maintainers expect new features to be connecting to the main service and main ingress, it will cause problems if you decide to bypass/ignore these.
|
||||
|
||||
### Standards/Examples
|
||||
|
||||
We try to maintain as much of a standardised questions.yaml format as possible, to ensure (bulk) editing stays as easy as possible.
|
||||
|
||||
##### HTTP Ingress
|
||||
|
||||
```
|
||||
- variable: ingress
|
||||
label: "Ingress Configuration"
|
||||
group: "Ingress Configuration"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: main
|
||||
label: "Main Ingress"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable Ingress"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
show_subquestions_if: true
|
||||
subquestions:
|
||||
- variable: hosts
|
||||
label: "Hosts"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: host
|
||||
label: "Host"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: host
|
||||
label: "HostName"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
required: true
|
||||
- variable: paths
|
||||
label: "Hosts"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: path
|
||||
label: "path"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
hidden: false
|
||||
default: "/"
|
||||
- variable: pathType
|
||||
label: "pathType"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
hidden: false
|
||||
default: "Prefix"
|
||||
- variable: tls
|
||||
label: "TLS-Settings"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: hosts
|
||||
label: "Certificate Hosts"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: host
|
||||
label: "Host"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
required: true
|
||||
- variable: scaleCERT
|
||||
label: "Select TrueNAS SCALE Certificate"
|
||||
schema:
|
||||
type: int
|
||||
$ref:
|
||||
- "definitions/certificate"
|
||||
|
||||
```
|
||||
|
||||
##### TCP Ingress
|
||||
|
||||
```
|
||||
- variable: tcp
|
||||
label: "TCP Reverse Proxy Configuration"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable TCP Reverse Proxy"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
show_subquestions_if: true
|
||||
subquestions:
|
||||
- variable: type
|
||||
label: "Select Reverse Proxy Type"
|
||||
schema:
|
||||
type: string
|
||||
default: "TCP"
|
||||
required: true
|
||||
editable: false
|
||||
hidden: true
|
||||
- variable: serviceName
|
||||
label: "Service name to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: ""
|
||||
- variable: entrypoint
|
||||
label: "Select Entrypoint"
|
||||
schema:
|
||||
type: string
|
||||
default: "torrent-tcp"
|
||||
required: true
|
||||
enum:
|
||||
- value: "torrent-tcp"
|
||||
description: "Torrent-TCP: port 51413"
|
||||
```
|
||||
|
||||
##### UDP Ingress
|
||||
|
||||
```
|
||||
- variable: udp
|
||||
label: "UDP Reverse Proxy Configuration"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable UDP Reverse Proxy"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
show_subquestions_if: true
|
||||
subquestions:
|
||||
- variable: type
|
||||
label: "Select Reverse Proxy Type"
|
||||
schema:
|
||||
type: string
|
||||
default: "UDP"
|
||||
required: true
|
||||
editable: false
|
||||
hidden: true
|
||||
- variable: serviceName
|
||||
label: "Service name to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: ""
|
||||
- variable: entrypoint
|
||||
label: "Select Entrypoint"
|
||||
schema:
|
||||
type: string
|
||||
default: "torrent-udp"
|
||||
required: true
|
||||
enum:
|
||||
- value: "torrent-udp"
|
||||
description: "Torrent-UDP: port 51413"
|
||||
```
|
||||
|
||||
### Other Ingress options
|
||||
|
||||
There are a few other options that are rarely (if ever) used.
|
||||
|
||||
##### servicePort
|
||||
|
||||
```
|
||||
- variable: servicePort
|
||||
label: "Service Port to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: int
|
||||
default: 80
|
||||
```
|
||||
|
||||
|
||||
##### serviceKind
|
||||
|
||||
```
|
||||
- variable: serviceKind
|
||||
label: "Service Kind to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: ""
|
||||
```
|
||||
|
||||
|
||||
### External Services
|
||||
|
||||
The externalServices option, is actually mostly an Ingress "under the hood" which just creates a very small (minimal) service.
|
||||
|
||||
```
|
||||
- variable: externalServices
|
||||
label: "(Advanced) Add External Services"
|
||||
group: "Advanced"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: externalService
|
||||
label: "External Service"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable Web Reverse Proxy"
|
||||
schema:
|
||||
type: boolean
|
||||
hidden: true
|
||||
editable: false
|
||||
default: true
|
||||
- variable: type
|
||||
label: "Reverse Proxy Type"
|
||||
schema:
|
||||
type: string
|
||||
default: "HTTP"
|
||||
hidden: true
|
||||
editable: false
|
||||
required: true
|
||||
- variable: serviceName
|
||||
label: "Service name to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: ""
|
||||
- variable: serviceTarget
|
||||
label: "IP Adress of the external service"
|
||||
schema:
|
||||
hidden: false
|
||||
editable: true
|
||||
required: true
|
||||
type: string
|
||||
default: "192.168.0.0"
|
||||
- variable: servicePort
|
||||
label: "External Service Port"
|
||||
description: "The port on the external service you want to proxy"
|
||||
schema:
|
||||
hidden: false
|
||||
required: true
|
||||
editable: true
|
||||
type: int
|
||||
default: 80
|
||||
- variable: serviceType
|
||||
label: "Connection Type"
|
||||
description: "Connection Type between Traefik and the external service"
|
||||
schema:
|
||||
hidden: false
|
||||
editable: true
|
||||
required: true
|
||||
default: "HTTP"
|
||||
type: string
|
||||
enum:
|
||||
- value: "HTTP"
|
||||
description: "HTTP"
|
||||
- value: "HTTPS"
|
||||
description: "HTTPS"
|
||||
- variable: serviceKind
|
||||
label: "Service Kind to proxy to"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: ""
|
||||
- variable: entrypoint
|
||||
label: "Select Entrypoint"
|
||||
schema:
|
||||
type: string
|
||||
default: "websecure"
|
||||
required: true
|
||||
enum:
|
||||
- value: "websecure"
|
||||
description: "Websecure: HTTPS/TLS port 443"
|
||||
- variable: host
|
||||
label: "Domain Name"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- variable: path
|
||||
label: "path"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
hidden: false
|
||||
default: "/"
|
||||
- variable: certType
|
||||
label: "Select Certificate Type"
|
||||
schema:
|
||||
type: string
|
||||
default: "selfsigned"
|
||||
enum:
|
||||
- value: ""
|
||||
description: "No Encryption/TLS/Certificates"
|
||||
- value: "selfsigned"
|
||||
description: "Self-Signed Certificate"
|
||||
- value: "ixcert"
|
||||
description: "TrueNAS SCALE Certificate"
|
||||
- variable: certificate
|
||||
label: "Select TrueNAS SCALE Certificate"
|
||||
schema:
|
||||
type: int
|
||||
show_if: [["certType", "=", "ixcert"]]
|
||||
$ref:
|
||||
- "definitions/certificate"
|
||||
- variable: authForwardURL
|
||||
label: "Forward Authentication URL"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
# Portal Button
|
||||
|
||||
After installation almost every app should have a "portal" button. This button is an easy and streamlined way of entering the Applications after installation. However, one should be aware that it does not magically follow changes inside the application (for example: from http to https).
|
||||
|
||||
##### questions.yaml example
|
||||
|
||||
Every questions.yaml file should contain the following snippets to enable the portal button. Please be aware to change `"http"` to `"https"` in services.main.port.protocol if your application uses http instead of https when running using "NodePort".
|
||||
|
||||
Also please be aware that the portal only(!) points towards the main service, main service port and main ingress.
|
||||
|
||||
```
|
||||
portals:
|
||||
web_portal:
|
||||
protocols:
|
||||
- "$kubernetes-resource_configmap_portal_protocol"
|
||||
host:
|
||||
- "$kubernetes-resource_configmap_portal_host"
|
||||
ports:
|
||||
- "$kubernetes-resource_configmap_portal_port"
|
||||
path: "/"
|
||||
|
||||
questions:
|
||||
|
||||
- variable: portal
|
||||
group: "Container Image"
|
||||
label: "Configure Portal Button"
|
||||
schema:
|
||||
type: dict
|
||||
hidden: true
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable"
|
||||
description: "enable the portal button"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
```
|
||||
|
||||
There are also some additional (advanced) options availale, these can be added below the above required portion as required:
|
||||
|
||||
**ingressPort:**
|
||||
```
|
||||
- variable: ingressPort
|
||||
label: "Port when ingress is not using 443"
|
||||
description: "Advanced setting, please enter a different port to use if Ingress uses something other than port 443"
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: int
|
||||
default: 8443
|
||||
```
|
||||
|
||||
**host:**
|
||||
```
|
||||
- variable: host
|
||||
label: "override Host when using NodePort"
|
||||
description: "Overrides the host setting when using NodePort. Example usecase would be loadbalanced NodePorts."
|
||||
schema:
|
||||
hidden: true
|
||||
editable: false
|
||||
type: string
|
||||
default: "test.com"
|
||||
```
|
||||
|
||||
|
||||
##### Known issues
|
||||
|
||||
- Portal currently doesn't work (yet) when setting the servicetype to "Loadbalancer"
|
||||
@@ -0,0 +1,223 @@
|
||||
# Questions.yaml
|
||||
Questions.yaml is the file which get rendered by TrueNAS to create the UI. When not creating new charts, most of what this project does is stitching together questions.yaml files to turn existing Helm Charts into Apps.
|
||||
|
||||
### Syntax
|
||||
In this document we give you a short reference guide (ported from IX Official) which lays out the settings available in questions.yaml.
|
||||
|
||||
#### Question Variable Reference
|
||||
| Variable | Type | Required | Description |
|
||||
| ------------- | ------------- | --- |------------- |
|
||||
| variable | string | true | define the variable name specified in the `values.yaml`file. |
|
||||
| label | string | true | define the UI label. |
|
||||
| description | string | false | specify the description of the variable. |
|
||||
| group | string | false | group questions by input value. |
|
||||
| schema | dictionary | true | specify schema details for the `variable` |
|
||||
| schema.type | string | true | specify type of value for `variable` (current supported types are string, int, boolean, path, hostpath, list, dict, ipaddr, and cron).|
|
||||
| schema.required | bool | false | define if the variable is required or not (true \ false), defaults to false |
|
||||
| schema.default | object | false | specify the default value. |
|
||||
| schema.min_length | int | false | min character length for string type variable.|
|
||||
| schema.max_length | int | false | max character length for string type variable.|
|
||||
| schema.min | int | false | min integer length. |
|
||||
| schema.max | int | false | max integer length. |
|
||||
| schema.enum | []dictionary | false | specify the options when the variable type is `string`, for example, <br><br>enum:<br> - value: "RollingUpdate" <br> description: "Create new pods and then kill old ones"<br> - value: "Recreate"<br> description: "Kill existing pods before creating new ones"|
|
||||
| schema.valid_chars | string | false | regular expression for input chars validation. |
|
||||
| schema.subquestions | []subquestion | false | add an array of subquestions.|
|
||||
| schema.show_if | string | false | show current variable if condition specified is true, for example `show_if: [["workloadType", "=", "CronJob"]]` |
|
||||
| schema.show_subquestions_if | string | false | show subquestions if is true or equal to one of the options. for example `show_subquestion_if: "static"`. system will convert this to the filters format specifid for `shcema.show_if` automatically.|
|
||||
| schema.attrs | []variables | false | specified when `schema.type` is dictionary to declare attributes allowed in the dictionary. |
|
||||
| schema.items | []variables | false | specified when `schema.type` is list to declare attributes allowed in the list. |
|
||||
| schema.private | bool | false | specified for declaring information sensitive fields. |
|
||||
| schema.null | bool | false | specifies if the value for the variable can be null. defaults to false. |
|
||||
|
||||
##### Subquestions
|
||||
`subquestions[]` cannot contain `subquestions` or `show_subquestions_if` keys, but all other keys in the above table are supported. Also variables having `schema.type` list do not support `subquestions`.
|
||||
##### Special Questions
|
||||
There are some novel cases where we would like to provide ability to configure / manage resources for workloads with getting some data from system dynamically.
|
||||
So a chart can specify certain actions to be performed by the system for a variable by defining a reference. An example better illustrates this concept:
|
||||
```
|
||||
- variable: volume
|
||||
label: "Volume"
|
||||
schema:
|
||||
type: dict
|
||||
$ref:
|
||||
- "normalize/ixVolume"
|
||||
attrs:
|
||||
- variable: mountPath
|
||||
label: "Mount Path"
|
||||
description: "Path where the volume will be mounted inside the pod"
|
||||
schema:
|
||||
type: path
|
||||
required: true
|
||||
- variable: datasetName
|
||||
label: "Dataset Name"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
```
|
||||
In the above variable we define a `$ref` in schema which specifies that the system should take some action for normalising the value specified for the variable.
|
||||
In this specific case, `ix_volume` is a concept introduced where we recommend using a volume which we are able to rollback automatically on chart release rollback. In essence,
|
||||
it is just a `hostPath` volume for which the system automatically creates the dataset specified.
|
||||
We have following types of actions supported in `$ref` right now:
|
||||
1) definitions
|
||||
2) normalize
|
||||
For (1), system will automatically update schema for a particular definition. For example,
|
||||
```
|
||||
- variable: hostInterface
|
||||
description: "Please specify host interface"
|
||||
label: "Host Interface"
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
$ref:
|
||||
- "definitions/interface"
|
||||
```
|
||||
System will automatically populate available interfaces for the user based on what interfaces are available on the system.
|
||||
For (2), system will normalize values or perform some actions as discussed above.
|
||||
|
||||
### Standardised questions.yaml sections
|
||||
To minimise the maintenance load of our App collection, we always aim to standardise as much as possible. The same goes for questions.yaml. Included here are some code standardised code-snippets that are expected to be included in every App.
|
||||
Be aware that sometimes specific functions might or might not completely function. Leaving them out would, however, everely increase the maintenance load and often said functionality will be added in the common-chart later on anyway.
|
||||
##### Groups
|
||||
To make sure all apps stay somewhat the same, we use a list of standardised groups for the groups section. Please make sure to use these groups in your Apps:
|
||||
```
|
||||
groups:
|
||||
- name: "Container Image"
|
||||
description: "Image to be used for container"
|
||||
- name: "Workload Configuration"
|
||||
description: "Configure workload deployment"
|
||||
- name: "Configuration"
|
||||
description: "additional container configuration"
|
||||
- name: "Networking"
|
||||
description: "Configure Network and Services for container"
|
||||
- name: "Storage"
|
||||
description: "Persist and share data that is separate from the lifecycle of the container"
|
||||
- name: "Resources and Devices"
|
||||
description: "Specify resources/devices to be allocated to workload"
|
||||
- name: "Ingress Configuration"
|
||||
description: "Ingress Configuration"
|
||||
- name: "Security"
|
||||
description: "Configure security context"
|
||||
- name: "Advanced"
|
||||
description: "Advanced Configuration"
|
||||
- name: "WARNING"
|
||||
description: "WARNING"
|
||||
```
|
||||
|
||||
##### General Configuration options
|
||||
These options are always* included because almost every chart (eventually) has a use for them and/or other parts of the common chart depend on them.
|
||||
They are called general options, because they affect the basic functionalities of a chart. For example: Custom User environment variables, permissions and timezones.
|
||||
|
||||
*`PUID`, `PGID`, `UMASK` are only included when they are needed.
|
||||
|
||||
```
|
||||
- variable: env
|
||||
group: "Configuration"
|
||||
label: "Image Environment"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: TZ
|
||||
label: "Timezone"
|
||||
schema:
|
||||
type: string
|
||||
default: "Etc/UTC"
|
||||
$ref:
|
||||
- "definitions/timezone"
|
||||
- variable: PUID
|
||||
label: "PUID"
|
||||
description: "Sets the PUID env var for LinuxServer.io (compatible) containers"
|
||||
schema:
|
||||
type: int
|
||||
default: 568
|
||||
- variable: PGID
|
||||
label: "PGID"
|
||||
description: "Sets the PGID env var for LinuxServer.io (compatible) containers"
|
||||
schema:
|
||||
type: int
|
||||
default: 568
|
||||
- variable: UMASK
|
||||
label: "UMASK"
|
||||
description: "Sets the UMASK env var for LinuxServer.io (compatible) containers"
|
||||
schema:
|
||||
type: string
|
||||
default: "002"
|
||||
|
||||
# Configure Custom Enviroment Variables
|
||||
- variable: environmentVariables
|
||||
label: "Image environment"
|
||||
group: "Configuration"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: environmentVariable
|
||||
label: "Environment Variable"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: name
|
||||
label: "Name"
|
||||
schema:
|
||||
type: string
|
||||
- variable: value
|
||||
label: "Value"
|
||||
schema:
|
||||
type: string
|
||||
```
|
||||
|
||||
##### Security Context Configuration options
|
||||
|
||||
```
|
||||
# Enable privileged
|
||||
- variable: securityContext
|
||||
group: "Security"
|
||||
label: "Security Context"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: privileged
|
||||
label: "Enable privileged mode for Common-Chart based charts"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
# Set Pod Security Policy
|
||||
- variable: podSecurityContext
|
||||
group: "Security"
|
||||
label: "Pod Security Context"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: runAsNonRoot
|
||||
label: "runAsNonRoot"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
- variable: runAsUser
|
||||
label: "runAsUser"
|
||||
description: "The UserID of the user running the application"
|
||||
schema:
|
||||
type: int
|
||||
default: 568
|
||||
- variable: runAsGroup
|
||||
label: "runAsGroup"
|
||||
description: The groupID this App of the user running the application"
|
||||
schema:
|
||||
type: int
|
||||
default: 568
|
||||
- variable: fsGroup
|
||||
label: "fsGroup"
|
||||
description: "The group that should own ALL storage."
|
||||
schema:
|
||||
type: int
|
||||
default: 568
|
||||
- variable: fsGroupChangePolicy
|
||||
label: "When should we take ownership?"
|
||||
schema:
|
||||
type: string
|
||||
default: "OnRootMismatch"
|
||||
enum:
|
||||
- value: "OnRootMismatch"
|
||||
description: "OnRootMismatch"
|
||||
- value: "Always"
|
||||
description: "Always"
|
||||
```
|
||||
@@ -0,0 +1,137 @@
|
||||
# Services
|
||||
|
||||
Every App needs to be exposed to something, either an UI, API or other containers.However with Kubernetes we don't directly connect to the containers running the App, because those might be on another node or there might be multiple "high available" containers for the App. Instead we use what is called `Services`. Services are simply put "Internal Load-Balancers", they also guaranteed to be reachable by (internal!) DNS name and (in some cases) prevent traffic from reaching your App when the healthcheck isn't finished yet (or is failing).
|
||||
|
||||
### Two kinds of services
|
||||
|
||||
##### First: hostNetwork
|
||||
|
||||
Always add the hostNetwork option above the "services" section.
|
||||
This is to try and keep things clear for the user.
|
||||
|
||||
```
|
||||
# Enable Host Networking
|
||||
- variable: hostNetwork
|
||||
group: "Networking"
|
||||
label: "Enable Host Networking"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
```
|
||||
|
||||
##### Main Service
|
||||
|
||||
Every App is required to have a main service, the primary thing that users (or other Apps!) connect with. No mater if it's a webUI, an API, a database connection or something totally else, A service is always required.
|
||||
|
||||
Please keep in mind that every App is different, some just have one service (which *ALWAYS* has to be called `main`) and others need more (which each has to have an unique name). Every App also uses different ports, so please alter accordingly.
|
||||
|
||||
```
|
||||
- variable: service
|
||||
group: "Networking"
|
||||
label: "Configure Service(s)"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: main
|
||||
label: "Main Service"
|
||||
description: "The Primary service on which the healthcheck runs, often the webUI"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable the service"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
hidden: true
|
||||
- variable: type
|
||||
label: "Service Type"
|
||||
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
|
||||
schema:
|
||||
type: string
|
||||
default: "NodePort"
|
||||
enum:
|
||||
- value: "NodePort"
|
||||
description: "NodePort"
|
||||
- value: "ClusterIP"
|
||||
description: "ClusterIP"
|
||||
- value: "LoadBalancer"
|
||||
description: "LoadBalancer"
|
||||
- variable: loadBalancerIP
|
||||
label: "LoadBalancer IP"
|
||||
description: "LoadBalancerIP"
|
||||
schema:
|
||||
show_if: [["type", "=", "LoadBalancer"]]
|
||||
type: string
|
||||
default: ""
|
||||
required: true
|
||||
- variable: exetrnalIPs
|
||||
label: "External IP's"
|
||||
description: "External IP's"
|
||||
schema:
|
||||
show_if: [["type", "=", "LoadBalancer"]]
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: externalIP
|
||||
label: "External IP"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- variable: ports
|
||||
label: "Service's Port(s) Configuration"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: main
|
||||
label: "Main Service Port Configuration"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable the port"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
hidden: true
|
||||
- variable: protocol
|
||||
label: "Port Type"
|
||||
schema:
|
||||
type: string
|
||||
default: "HTTP"
|
||||
hidden: false
|
||||
enum:
|
||||
- value: HTTP
|
||||
description: "HTTP"
|
||||
- value: "HTTPS"
|
||||
description: "HTTPS"
|
||||
- value: TCP
|
||||
description: "TCP"
|
||||
- value: "UDP"
|
||||
description: "UDP"
|
||||
- variable: port
|
||||
label: "Container Port"
|
||||
schema:
|
||||
type: int
|
||||
default: 5076
|
||||
editable: false
|
||||
hidden: true
|
||||
- variable: targetport
|
||||
label: "Target Port"
|
||||
description: "This port exposes the container port on the service"
|
||||
schema:
|
||||
type: int
|
||||
default: 5076
|
||||
editable: true
|
||||
hidden: false
|
||||
required: true
|
||||
- variable: nodePort
|
||||
label: "Node Port (Optional)"
|
||||
description: "This port gets exposed to the node. Only considered when service type is NodePort"
|
||||
schema:
|
||||
type: int
|
||||
min: 9000
|
||||
max: 65535
|
||||
default: 36041
|
||||
required: true
|
||||
```
|
||||
@@ -0,0 +1,180 @@
|
||||
# Storage
|
||||
|
||||
This article serves as a development extention to the storage article available [here](https://wiki.truecharts.org/general/storage/)
|
||||
|
||||
##### Storage and Common-Chart
|
||||
|
||||
For all these storage solutions we require the commonchart to be added to the App.
|
||||
The Common-Chart handles both the connection/addition of storage to the container and spinning up special k8s jobs to fix the permissions if requested for the Custom storage.
|
||||
|
||||
### Integrated Persistent Storage
|
||||
|
||||
When adding an App, there are almost always certain folders that are required for solid Apps performance. For example config files that should be persistent across restarts.
|
||||
|
||||
For these storages we can easily add fixes values in the UI, these settings can not be disabled or removed and would, by default and preferably, be limited to the "internal" storage class
|
||||
Preventing the user to disable them, ensures that users don't (by mistake) remove the storage.
|
||||
|
||||
#####
|
||||
|
||||
```
|
||||
- variable: persistence
|
||||
label: "Integrated Persistent Storage"
|
||||
description: "Websocket Service"
|
||||
group: "Storage"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: data
|
||||
label: "App Config Storage"
|
||||
description: "Stores the Application Configuration."
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enable the storage"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
hidden: false
|
||||
- variable: storageClass
|
||||
label: "Type of Storage"
|
||||
description: " Warning: Anything other than SCALE-ZFS will break rollback!"
|
||||
schema:
|
||||
type: string
|
||||
default: "SCALE-ZFS"
|
||||
- variable: mountPath
|
||||
label: "mountPath"
|
||||
description: "Path inside the container the storage is mounted"
|
||||
schema:
|
||||
type: string
|
||||
default: "/config"
|
||||
hidden: true
|
||||
- variable: emptyDir
|
||||
label: "EmptyDir Volume"
|
||||
schema:
|
||||
type: dict
|
||||
hidden: false
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Use emptyDir volume"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
hidden: false
|
||||
show_subquestions_if: true
|
||||
subquestions:
|
||||
- variable: medium
|
||||
label: "EmptyDir Medium"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
enum:
|
||||
- value: ""
|
||||
description: "Default"
|
||||
- value: "Memory"
|
||||
description: "Memory"
|
||||
- variable: accessMode
|
||||
label: "Access Mode (Advanced)"
|
||||
description: "Allow or disallow multiple PVC's writhing to the same PVC"
|
||||
schema:
|
||||
type: string
|
||||
default: "ReadWriteOnce"
|
||||
enum:
|
||||
- value: "ReadWriteOnce"
|
||||
description: "ReadWriteOnce"
|
||||
- value: "ReadOnlyMany"
|
||||
description: "ReadOnlyMany"
|
||||
- value: "ReadWriteMany"
|
||||
description: "ReadWriteMany"
|
||||
- variable: size
|
||||
label: "Size quotum of storage"
|
||||
schema:
|
||||
type: string
|
||||
default: "100Gi"
|
||||
```
|
||||
|
||||
### Unlimited Custom Storage Mounts
|
||||
|
||||
We support presenting the user with a "Do it yourself" style list, in which the user can add unlimited paths on the host system to mount.
|
||||
It should always be included in any App, to give users the option to customise things however they like.
|
||||
|
||||
##### Example
|
||||
|
||||
```
|
||||
- variable: hostPathMounts
|
||||
label: "Custom app storage"
|
||||
group: "Storage and Devices"
|
||||
schema:
|
||||
type: list
|
||||
default: []
|
||||
items:
|
||||
- variable: volumeMount
|
||||
label: "Custom Storage"
|
||||
schema:
|
||||
type: dict
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Enabled"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
required: true
|
||||
hidden: true
|
||||
editable: false
|
||||
- variable: setPermissions
|
||||
label: "Automatic Permissions"
|
||||
description: "Automatically set permissions on install"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
hidden: false
|
||||
- variable: name
|
||||
label: "Mountpoint Name"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
required: true
|
||||
editable: true
|
||||
- variable: emptyDir
|
||||
label: "EmptyDir Volume"
|
||||
schema:
|
||||
type: dict
|
||||
hidden: false
|
||||
attrs:
|
||||
- variable: enabled
|
||||
label: "Use emptyDir volume"
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
hidden: false
|
||||
- variable: medium
|
||||
label: "EmptyDir Medium"
|
||||
schema:
|
||||
type: string
|
||||
default: ""
|
||||
enum:
|
||||
- value: ""
|
||||
description: "Default"
|
||||
- value: "Memory"
|
||||
description: "Memory"
|
||||
- variable: mountPath
|
||||
label: "Mount Path"
|
||||
description: "Path to mount inside the pod"
|
||||
schema:
|
||||
type: path
|
||||
required: true
|
||||
default: ""
|
||||
editable: true
|
||||
- variable: hostPathEnabled
|
||||
label: "host Path Enabled"
|
||||
schema:
|
||||
type: boolean
|
||||
default: true
|
||||
hidden: true
|
||||
- variable: hostPath
|
||||
label: "Host Path"
|
||||
description: "Path on the host to mount inside the container, ignored when emptyDir is enabled"
|
||||
schema:
|
||||
type: hostpath
|
||||
required: true
|
||||
```
|
||||
@@ -0,0 +1,129 @@
|
||||
# Unit tests
|
||||
|
||||
We unit test our common library, while it isn't near complete coverage but it does offer some basic checks.
|
||||
|
||||
## Running the tests
|
||||
|
||||
Running these tests can be done any way you like. In this document we describe a number of approaches:
|
||||
|
||||
* [Directly on your development machine](#directly-on-your-development-machine)
|
||||
* [Through a development container in Visual Studio Code](#using-visual-studio-code)
|
||||
* [Using a local Docker container](#using-a-local-docker-container)
|
||||
|
||||
### Directly on your development machine
|
||||
|
||||
First set up the environment:
|
||||
|
||||
```console
|
||||
$ export RUBYJQ_USE_SYSTEM_LIBRARIES=1
|
||||
$ bundle install
|
||||
```
|
||||
|
||||
Run the tests:
|
||||
|
||||
```console
|
||||
$ bundle exec m -r test/charts
|
||||
```
|
||||
|
||||
### Using Visual Studio Code
|
||||
|
||||
Our repo comes with a Visual Studio Code [development container](https://code.visualstudio.com/docs/remote/containers) definition and `launch.json` that allow you to quickly set up an environment in which you can run the tests.
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
- Visual Studio Code is installed.
|
||||
- Docker is installed and running.
|
||||
- The "Remote - Containers" extension is installed and enabled in Visual Studio Code.
|
||||
|
||||
For more details, please refer to the [official documentation](https://code.visualstudio.com/docs/remote/containers#_system-requirements).
|
||||
|
||||
##### Running tests
|
||||
|
||||
Once Visual Studio Code is set up, and you open the `charts` workspace, you will see a popup asking if you wish to re-open the workspace in a development container:
|
||||
|
||||

|
||||
|
||||
Select the option that you prefer. The workspace will be reopened and a Dockerized workspace will be built. You can now use Visual Studio Code as normal.
|
||||
|
||||
To run or debug the unit tests, click the "Run" button on the left sidebar and select the desired configuration:
|
||||
|
||||

|
||||
|
||||
* _UnitTest - active spec file only_: This configuration will try to run the currently opened test file.
|
||||
|
||||
**Note:** Make sure that you have opened a valid test file (`.rb` files in the `test/charts` folder), or this will not work.
|
||||
|
||||
* _UnitTest - all spec files_: This configuration will run the all test files in the `test/charts` folder.
|
||||
|
||||
Next, press the green "Play" icon. This will start the tests show the outcome in a terminal window.
|
||||
|
||||
### Using a local Docker container
|
||||
|
||||
The [Visual Studio Code development container](#using-visual-studio-code) can also be leveraged without using Visual Studio Code.
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
- Docker is installed and running.
|
||||
- You have the charts repo root folder opened in your shell of choice. The commands in this article assume you are running a Bash-compatible shell.
|
||||
|
||||
##### Running tests
|
||||
|
||||
The first step is to build the development container image containing the required tools. This step only needs to be done once.
|
||||
To build the container, run this command in your shell:
|
||||
|
||||
```console
|
||||
$ docker build -t k8s-at-home/charts-unit-test -f .devcontainer/Dockerfile .
|
||||
```
|
||||
|
||||
When you wish to run the tests, run this command in your shell:
|
||||
|
||||
```console
|
||||
$ docker run --rm -it -v $(pwd):/charts --entrypoint "/bin/bash" -w /charts k8s-at-home/charts-unit-test -l -c "bundle exec m -r ./test/charts"
|
||||
```
|
||||
|
||||
This will create a container with the charts repo root folder mounted to `/charts` and execute all the test files in the `test/charts` folder.
|
||||
|
||||
## Output
|
||||
|
||||
A successful test will output something like the following...
|
||||
|
||||
```text
|
||||
Started with run options --seed 52955
|
||||
|
||||
common-test::statefulset volumeClaimTemplates
|
||||
can set values for volumeClaimTemplates PASS (0.16s)
|
||||
volumeClaimTemplates should be empty by default PASS (0.06s)
|
||||
|
||||
common-test::ports settings
|
||||
targetPort can be overridden PASS (0.17s)
|
||||
port name can be overridden PASS (0.17s)
|
||||
defaults to name "http" on port 8080 PASS (0.16s)
|
||||
targetPort cannot be a named port PASS (0.05s)
|
||||
|
||||
common-test::pod replicas
|
||||
defaults to 1 PASS (0.08s)
|
||||
accepts integer as value PASS (0.08s)
|
||||
|
||||
common-test::Environment settings
|
||||
Check no environment variables PASS (0.05s)
|
||||
set "valueFrom" environment variables PASS (0.11s)
|
||||
set "static" and "Dynamic/Tpl" environment variables PASS (0.15s)
|
||||
set "Dynamic/Tpl" environment variables PASS (0.11s)
|
||||
set "static" environment variables PASS (0.10s)
|
||||
|
||||
common-test::ingress
|
||||
ingress with hosts PASS (0.10s)
|
||||
should be disabled when ingress.enabled: false PASS (0.06s)
|
||||
ingress with hosts template is evaluated PASS (0.11s)
|
||||
ingress with hosts and tls PASS (0.15s)
|
||||
ingress with hosts and tls templates is evaluated PASS (0.16s)
|
||||
should be enabled when ingress.enabled: true PASS (0.06s)
|
||||
|
||||
common-test::controller type
|
||||
accepts "daemonset" PASS (0.06s)
|
||||
accepts "statefulset" PASS (0.06s)
|
||||
defaults to "Deployment" PASS (0.06s)
|
||||
|
||||
Finished in 2.26077s
|
||||
22 tests, 59 assertions, 0 failures, 0 errors, 0 skips
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
# Values.yaml Files
|
||||
|
||||
Values.yaml files generally always contain configuration setting for Helm charts, TrueCharts is no different.
|
||||
However, we have multiple different values.yaml files, with different goals. Because TrueNAS SCALE just works slightly differently from standard Helm Charts
|
||||
|
||||
### The Files
|
||||
|
||||
##### values.yaml
|
||||
|
||||
This file contains the default config when running the App using stock helm (not SCALE). It also gets used for the testingsuite.
|
||||
|
||||
##### ix_values.yaml
|
||||
|
||||
This file contains config values that are not included in questions.yaml, but should be copied into the resulting configuration anyway. It's mostly used to ensure setting can be changed by the maintainer with every update, such as versions, which is not possible when setting things as defaults inside questions.yaml
|
||||
|
||||
This file is, however, not very well checked by validation and CI. Use it when you absolutely have to.
|
||||
|
||||
One important setting in ix_values.yaml is the optional setting: `startAsRoot: true`
|
||||
This setting is a compatibility toggle for containers that need to be started by root, often these containers use PUID and PGID to descalate (lower) away from root but require it to start.
|
||||
|
||||
A minimal example ix_values.yaml would be:
|
||||
|
||||
```
|
||||
##
|
||||
# This file contains Values.yaml content that gets added to the output of questions.yaml
|
||||
# It's ONLY meant for content that the user is NOT expected to change.
|
||||
# Example: Everything under "image" is not included in questions.yaml but is included here.
|
||||
##
|
||||
|
||||
image:
|
||||
repository: jacobalberty/unifi
|
||||
tag: 6.0.45
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
|
||||
##
|
||||
# Most other defaults are set in questions.yaml
|
||||
# For other options please refer to the wiki, default_values.yaml or the common library chart
|
||||
##
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user