Develop #131

Merged
metal3d merged 9 commits from develop into master 2025-07-07 21:02:13 +00:00
10 changed files with 563 additions and 406 deletions

4
.gitignore vendored
View File

@@ -18,3 +18,7 @@ cover*
# will be treated later # will be treated later
/examples/* /examples/*
# nsis
nsis/*.dll
nsis/*.exe

144
Makefile
View File

@@ -1,28 +1,44 @@
CUR_SHA=$(shell git log -n1 --pretty='%h') CUR_SHA=$(shell git log -n1 --pretty='%h')
CUR_BRANCH=$(shell git branch --show-current) CUR_BRANCH=$(shell git branch --show-current)
VERSION=$(shell git describe --exact-match --tags $(CUR_SHA) 2>/dev/null || echo $(CUR_BRANCH)-$(CUR_SHA)) VERSION=$(shell git describe --exact-match --tags $(CUR_SHA) 2>/dev/null || echo $(CUR_BRANCH)-$(CUR_SHA))
# get the container (podman is preferred, but docker is also supported)
# TODO: prpose nerdctl
CTN:=$(shell which podman 2>&1 1>/dev/null && echo "podman" || echo "docker") CTN:=$(shell which podman 2>&1 1>/dev/null && echo "podman" || echo "docker")
PREFIX=~/.local PREFIX=~/.local
GOVERSION=1.24 GOVERSION=1.24
GO=container GO=container
OUT=katenary OUT=katenary
MODE=default
RELEASE="" RELEASE=""
BLD_CMD=go build -ldflags="-X 'katenary/generator.Version=$(RELEASE)$(VERSION)'" -o $(OUT) ./cmd/katenary # if release mode
ifeq ($(MODE),release)
VERSION:=release-$(VERSION)
endif
BLD_CMD=go build -ldflags="-X 'katenary/generator.Version=$(VERSION)'" -o $(OUT) ./cmd/katenary
GOOS=linux GOOS=linux
GOARCH=amd64 GOARCH=amd64
CGO_ENABLED=0 CGO_ENABLED=0
# GPG signer
SIGNER=metal3d@gmail.com SIGNER=metal3d@gmail.com
UPX_OPTS =
# upx compression
UPX_OPTS =
UPX ?= upx $(UPX_OPTS) UPX ?= upx $(UPX_OPTS)
BUILD_IMAGE=docker.io/golang:$(GOVERSION)-alpine BUILD_IMAGE=docker.io/golang:$(GOVERSION)
# SHELL=/bin/bash # SHELL=/bin/bash
# List of source files # List of source files
SOURCES=$(wildcard ./*.go ./*/*.go ./*/*/*.go) SOURCES=$(wildcard ./*.go ./*/*.go ./*/*/*.go)
# List of binaries to build and sign # List of binaries to build and sign
BINARIES=dist/katenary-linux-amd64 dist/katenary-linux-arm64 dist/katenary.exe dist/katenary-darwin-amd64 dist/katenary-freebsd-amd64 dist/katenary-freebsd-arm64 BINARIES=dist/katenary-linux-amd64 dist/katenary-linux-arm64 dist/katenary.exe dist/katenary-darwin-amd64 dist/katenary-freebsd-amd64 dist/katenary-freebsd-arm64
BINARIES += dist/katenary-windows-setup.exe
# installer
# List of signatures to build # List of signatures to build
ASC_BINARIES=$(patsubst %,%.asc,$(BINARIES)) ASC_BINARIES=$(patsubst %,%.asc,$(BINARIES))
@@ -36,11 +52,10 @@ SHELL := bash
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-builtin-rules
.PHONY: help clean build install tests test doc .PHONY: help dist-clean build install tests test doc nsis
all: build all: build
help: help:
@cat <<EOF | fold -s -w 80 @cat <<EOF | fold -s -w 80
=== HELP === === HELP ===
@@ -78,7 +93,8 @@ help:
EOF EOF
## Standard build ## BUILD
build: pull katenary build: pull katenary
pull: pull:
@@ -93,8 +109,7 @@ ifeq ($(GO),local)
$(BLD_CMD) $(BLD_CMD)
else ifeq ($(CTN),podman) else ifeq ($(CTN),podman)
@echo "=> Build in container using" $(CTN) @echo "=> Build in container using" $(CTN)
echo $(GOOS) $(GOARCH) @podman run -e CGO_ENABLED=$(CGO_ENABLED) -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) \
podman run -e CGO_ENABLED=$(CGO_ENABLED) -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) -e CC=$(CC) \
--rm -v $(PWD):/go/src/katenary:z -w /go/src/katenary --userns keep-id $(BUILD_IMAGE) $(BLD_CMD) --rm -v $(PWD):/go/src/katenary:z -w /go/src/katenary --userns keep-id $(BUILD_IMAGE) $(BLD_CMD)
else else
@echo "=> Build in container using" $(CTN) @echo "=> Build in container using" $(CTN)
@@ -103,8 +118,9 @@ else
endif endif
## Release build # Make dist, build executables for all platforms, sign them, and compress them with upx if possible.
dist: prepare $(BINARIES) upx $(ASC_BINARIES) # Also generate the windows installer.
dist: prepare $(BINARIES) upx gpg-sign check-sign
prepare: pull prepare: pull
mkdir -p dist mkdir -p dist
@@ -141,13 +157,16 @@ dist/katenary-freebsd-arm64:
@echo -e "\033[1;32mBuilding katenary $(VERSION) for freebsd-arm64...\033[0m" @echo -e "\033[1;32mBuilding katenary $(VERSION) for freebsd-arm64...\033[0m"
$(MAKE) katenary GOOS=freebsd GOARCH=arm64 OUT=$@ $(MAKE) katenary GOOS=freebsd GOARCH=arm64 OUT=$@
gpg-sign: dist/katenary-windows-setup.exe: nsis/EnVar.dll dist/katenary.exe
rm -f dist/*.asc makensis -DAPP_VERSION=$(VERSION) nsis/katenary.nsi
$(MAKE) $(ASC_BINARIES) mv nsis/katenary-windows-setup.exe dist/katenary-windows-setup.exe
dist/%.asc: dist/%
gpg --armor --detach-sign --default-key $(SIGNER) $< &>/dev/null || exit 1
nsis/EnVar.dll:
curl https://nsis.sourceforge.io/mediawiki/images/7/7f/EnVar_plugin.zip -o nsis/EnVar_plugin.zip
cd nsis
unzip -o EnVar_plugin.zip Plugins/x86-unicode/EnVar.dll
mv Plugins/x86-unicode/EnVar.dll EnVar.dll
rm -rf EnVar_plugin.zip Plugins
upx: upx:
$(UPX) dist/katenary-linux-amd64 $(UPX) dist/katenary-linux-amd64
@@ -155,15 +174,35 @@ upx:
#$(UPX) dist/katenary.exe #$(UPX) dist/katenary.exe
$(UPX) dist/katenary-darwin-amd64 --force-macos $(UPX) dist/katenary-darwin-amd64 --force-macos
## GPG signing
gpg-sign:
rm -f dist/*.asc
$(MAKE) $(ASC_BINARIES)
check-sign:
@echo "=> Checking signatures..."
@for f in $(ASC_BINARIES); do \
if gpg --verify $$f &>/dev/null; then \
echo "Signature for $$f is valid"; \
else \
echo "Signature for $$f is invalid"; \
exit 1; \
fi; \
done
dist/%.asc: dist/%
gpg --armor --detach-sign --default-key $(SIGNER) $< &>/dev/null || exit 1
## installation and uninstallation
install: build install: build
install -Dm755 katenary $(PREFIX)/bin/katenary install -Dm755 katenary $(PREFIX)/bin/katenary
uninstall: uninstall:
rm -f $(PREFIX)/bin/katenary rm -f $(PREFIX)/bin/katenary
clean:
rm -rf katenary dist/* release.id
serve-doc: __label_doc serve-doc: __label_doc
@cd doc && \ @cd doc && \
@@ -174,52 +213,19 @@ serve-doc: __label_doc
echo "==> Serving doc with mkdocs..." && \ echo "==> Serving doc with mkdocs..." && \
mkdocs serve mkdocs serve
tests: test ## Documentation generation
test:
@echo -e "\033[1;33mTesting katenary $(VERSION)...\033[0m"
go test -coverprofile=cover.out ./...
$(MAKE) cover
cover:
go tool cover -func=cover.out | grep "total:"
go tool cover -html=cover.out -o cover.html
if [ "$(BROWSER)" = "xdg-open" ]; then
xdg-open cover.html
else
$(BROWSER) -i --new-window cover.html
fi
push-release: build-all
@rm -f release.id
# read personal access token from .git-credentials
TOKEN=$(shell cat .credentials)
# create a new release based on current tag and get the release id
@curl -sSL -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $$TOKEN" \
-d "{\"tag_name\": \"$(VERSION)\", \"target_commitish\": \"\", \"name\": \"$(VERSION)\", \"draft\": true, \"prerelease\": true}" \
https://api.github.com/repos/metal3d/katenary/releases | jq -r '.id' > release.id
@echo "Release id: $$(cat release.id) created"
@echo "Uploading assets..."
# push all dist binary as assets to the release
@for i in $$(find dist -type f -name "katenary*"); do
curl -sSL -H "Authorization: token $$TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/octet-stream" \
--data-binary @$$i \
https://uploads.github.com/repos/metal3d/katenary/releases/$$(cat release.id)/assets?name=$$(basename $$i)
done
@rm -f release.id
doc: doc:
@echo "=> Generating documentation..." @echo "=> Generating documentation..."
# generate the labels doc and code doc # generate the labels doc and code doc
$(MAKE) __label_doc $(MAKE) __label_doc
install-gomarkdoc:
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest
__label_doc: __label_doc:
@command -v gomarkdoc || (echo "==> We need to install gomarkdoc..." && \ @command -v gomarkdoc || (echo "==> We need to install gomarkdoc..." && \
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest) $(MAKE) install-gomarkdoc)
@echo "=> Generating labels doc..." @echo "=> Generating labels doc..."
# short label doc # short label doc
go run ./cmd/katenary help-labels -m | \ go run ./cmd/katenary help-labels -m | \
@@ -243,6 +249,8 @@ __label_doc:
done done
## TESTS, security analysis, and code quality
# Scan the source code. # Scan the source code.
# - we don't need detection of text/template as it's not a web application, and # - we don't need detection of text/template as it's not a web application, and
# - we don't need sha1 detection as it is not used for cryptographic purposes. # - we don't need sha1 detection as it is not used for cryptographic purposes.
@@ -254,3 +262,25 @@ sast:
--exclude-rule go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1 \ --exclude-rule go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1 \
--metrics=on \ --metrics=on \
. .
tests: test
test:
@echo -e "\033[1;33mTesting katenary $(VERSION)...\033[0m"
go test -coverprofile=cover.out ./...
$(MAKE) cover
cover:
go tool cover -func=cover.out | grep "total:"
go tool cover -html=cover.out -o cover.html
if [ "$(BROWSER)" = "xdg-open" ]; then
xdg-open cover.html
else
$(BROWSER) -i --new-window cover.html
fi
## Miscellaneous
dist-clean:
rm -rf dist
rm -f katenary

View File

@@ -1,19 +1,28 @@
# Labels documentation # Labels documentation
Katenary proposes labels to set in `compose.yaml` files (or override files) to configure the Helm Chart generation. Because it is sometimes needed to have structured values, it is necessary to use the Yaml syntax. While compose labels are string, we can use `|` to use Yaml multilines as value. Katenary proposes labels to set in `compose.yaml` files (or override files) to configure the Helm Chart generation.
Because it is sometimes needed to have structured values, it is necessary to use the YAML syntax.
While compose labels are string, we can use _here-doc_ syntax using `|` to use YAML multiline as value.
Katenary will try to Unmarshal these labels. ```yaml
label-name: |-
# this is actually a multiline string here
key1: value1
key2: value2
```
Katenary will try to _Unmarshal_ these labels.
## Label list and types ## Label list and types
<!-- START_LABEL_DOC : do not remove this tag !--> <!-- START_LABEL_DOC : do not remove this tag !-->
| Label name | Description | Type | | Label name | Description | Type |
| ------------------------------ | ---------------------------------------------------------------- | -------------------------------- | | ------------------------------ | ---------------------------------------------------------------- | -------------------------------- |
| `katenary.v3/configmap-files` | Add files to the configmap. | `[]string` | | `katenary.v3/configmap-files` | Inject files as Configmap. | `[]string` |
| `katenary.v3/cronjob` | Create a cronjob from the service. | `object` | | `katenary.v3/cronjob` | Create a cronjob from the service. | `object` |
| `katenary.v3/dependencies` | Add Helm dependencies to the service. | `[]object` | | `katenary.v3/dependencies` | Add Helm dependencies to the service. | `[]object` |
| `katenary.v3/description` | Description of the service | `string` | | `katenary.v3/description` | Description of the service | `string` |
| `katenary.v3/env-from` | Add environment variables from antoher service. | `[]string` | | `katenary.v3/env-from` | Add environment variables from another service. | `[]string` |
| `katenary.v3/exchange-volumes` | Add exchange volumes (empty directory on the node) to share data | `[]object` | | `katenary.v3/exchange-volumes` | Add exchange volumes (empty directory on the node) to share data | `[]object` |
| `katenary.v3/health-check` | Health check to be added to the deployment. | `object` | | `katenary.v3/health-check` | Health check to be added to the deployment. | `object` |
| `katenary.v3/ignore` | Ignore the service | `bool` | | `katenary.v3/ignore` | Ignore the service | `bool` |
@@ -33,7 +42,7 @@ Katenary will try to Unmarshal these labels.
<!-- START_DETAILED_DOC : do not remove this tag !--> <!-- START_DETAILED_DOC : do not remove this tag !-->
### katenary.v3/configmap-files ### katenary.v3/configmap-files
Add files to the configmap. Inject files as Configmap.
**Type**: `[]string` **Type**: `[]string`
@@ -157,7 +166,7 @@ labels:
### katenary.v3/env-from ### katenary.v3/env-from
Add environment variables from antoher service. Add environment variables from another service.
**Type**: `[]string` **Type**: `[]string`

View File

@@ -1,246 +0,0 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# labelStructs
```go
import "katenary/generator/labels/labelStructs"
```
labelStructs is a package that contains the structs used to represent the labels in the yaml files.
## type [ConfigMapFile](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/configMap.go#L5>)
```go
type ConfigMapFile []string
```
<a name="ConfigMapFileFrom"></a>
### func [ConfigMapFileFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/configMap.go#L7>)
```go
func ConfigMapFileFrom(data string) (ConfigMapFile, error)
```
<a name="CronJob"></a>
## type [CronJob](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/cronJob.go#L5-L10>)
```go
type CronJob struct {
Image string `yaml:"image,omitempty" json:"image,omitempty"`
Command string `yaml:"command" json:"command,omitempty"`
Schedule string `yaml:"schedule" json:"schedule,omitempty"`
Rbac bool `yaml:"rbac" json:"rbac,omitempty"`
}
```
<a name="CronJobFrom"></a>
### func [CronJobFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/cronJob.go#L12>)
```go
func CronJobFrom(data string) (*CronJob, error)
```
<a name="Dependency"></a>
## type [Dependency](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/dependencies.go#L6-L12>)
Dependency is a dependency of a chart to other charts.
```go
type Dependency struct {
Values map[string]any `yaml:"-" json:"values,omitempty"`
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Repository string `yaml:"repository" json:"repository"`
Alias string `yaml:"alias,omitempty" json:"alias,omitempty"`
}
```
<a name="DependenciesFrom"></a>
### func [DependenciesFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/dependencies.go#L15>)
```go
func DependenciesFrom(data string) ([]Dependency, error)
```
DependenciesFrom returns a slice of dependencies from the given string.
<a name="EnvFrom"></a>
## type [EnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/envFrom.go#L5>)
```go
type EnvFrom []string
```
<a name="EnvFromFrom"></a>
### func [EnvFromFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/envFrom.go#L8>)
```go
func EnvFromFrom(data string) (EnvFrom, error)
```
EnvFromFrom returns a EnvFrom from the given string.
<a name="ExchangeVolume"></a>
## type [ExchangeVolume](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/exchangeVolume.go#L5-L10>)
```go
type ExchangeVolume struct {
Name string `yaml:"name" json:"name"`
MountPath string `yaml:"mountPath" json:"mountPath"`
Type string `yaml:"type,omitempty" json:"type,omitempty"`
Init string `yaml:"init,omitempty" json:"init,omitempty"`
}
```
<a name="NewExchangeVolumes"></a>
### func [NewExchangeVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/exchangeVolume.go#L12>)
```go
func NewExchangeVolumes(data string) ([]*ExchangeVolume, error)
```
<a name="HealthCheck"></a>
## type [HealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/probes.go#L11-L14>)
```go
type HealthCheck struct {
LivenessProbe *corev1.Probe `yaml:"livenessProbe,omitempty" json:"livenessProbe,omitempty"`
ReadinessProbe *corev1.Probe `yaml:"readinessProbe,omitempty" json:"readinessProbe,omitempty"`
}
```
<a name="ProbeFrom"></a>
### func [ProbeFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/probes.go#L16>)
```go
func ProbeFrom(data string) (*HealthCheck, error)
```
<a name="Ingress"></a>
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L14-L22>)
```go
type Ingress struct {
Port *int32 `yaml:"port,omitempty" json:"port,omitempty"`
Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,omitempty"`
Hostname string `yaml:"hostname" json:"hostname,omitempty"`
Path *string `yaml:"path,omitempty" json:"path,omitempty"`
Class *string `yaml:"class,omitempty" json:"class,omitempty" jsonschema:"default:-"`
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
}
```
<a name="IngressFrom"></a>
### func [IngressFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L25>)
```go
func IngressFrom(data string) (*Ingress, error)
```
IngressFrom creates a new Ingress from a compose service.
<a name="MapEnv"></a>
## type [MapEnv](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/mapenv.go#L5>)
```go
type MapEnv map[string]string
```
<a name="MapEnvFrom"></a>
### func [MapEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/mapenv.go#L8>)
```go
func MapEnvFrom(data string) (MapEnv, error)
```
MapEnvFrom returns a MapEnv from the given string.
<a name="Ports"></a>
## type [Ports](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ports.go#L5>)
```go
type Ports []uint32
```
<a name="PortsFrom"></a>
### func [PortsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ports.go#L8>)
```go
func PortsFrom(data string) (Ports, error)
```
PortsFrom returns a Ports from the given string.
<a name="Secrets"></a>
## type [Secrets](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/secrets.go#L5>)
```go
type Secrets []string
```
<a name="SecretsFrom"></a>
### func [SecretsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/secrets.go#L7>)
```go
func SecretsFrom(data string) (Secrets, error)
```
<a name="TLS"></a>
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L10-L12>)
```go
type TLS struct {
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
}
```
<a name="ValueFrom"></a>
## type [ValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/valueFrom.go#L5>)
```go
type ValueFrom map[string]string
```
<a name="GetValueFrom"></a>
### func [GetValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/valueFrom.go#L7>)
```go
func GetValueFrom(data string) (*ValueFrom, error)
```
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -13,7 +13,7 @@ katenary convert
This will create a `chart` directory with the helm chart inside. This will create a `chart` directory with the helm chart inside.
But, in general, you will need to add a few configuration to help Katenary to transpose the compose file to a working But, in general, you will need to add a few configurations to help Katenary to transpose the compose file to a working
helm chart. helm chart.
There are two ways to configure Katenary: There are two ways to configure Katenary:
@@ -25,7 +25,7 @@ The Katenary file `katenary.yaml` has benefits over the labels in the compose fi
- you can validate the configuration with a schema, and use completion in your editor - you can validate the configuration with a schema, and use completion in your editor
- you separate the configuration and leave the compose file "intact" - you separate the configuration and leave the compose file "intact"
- the syntax is a bit simpler, instead of using `katenary.v3/xxx: |-" you can use`xxx: ...` - the syntax is a bit simpler, instead of using `katenary.v3/xxx: |-` you can use `xxx: ...`
But: **this implies that you have to maintain two files if the compose file changes.** But: **this implies that you have to maintain two files if the compose file changes.**
@@ -34,19 +34,18 @@ For example. With "labels", you should do:
```yaml ```yaml
# in compose file # in compose file
services: services:
webapp: webapp:
image: php:7-apache image: php:7-apache
ports: ports:
- 8080:80 - 8080:80
environment: environment:
DB_HOST: database DB_HOST: database
labels: labels:
katenary.v3/ingress: |- katenary.v3/ingress: |-
hostname: myapp.example.com hostname: myapp.example.com
port: 8080 port: 8080
katenary.v3/map-env: |- katenary.v3/map-env: |-
DB_HOST: "{{ .Release.Name }}-database" DB_HOST: "{{ .Release.Name }}-database"
``` ```
Using a Katenary file, you can do: Using a Katenary file, you can do:
@@ -54,26 +53,26 @@ Using a Katenary file, you can do:
```yaml ```yaml
# in compose file, no need to add labels # in compose file, no need to add labels
services: services:
webapp: webapp:
image: php:7-apache image: php:7-apache
ports: ports:
- 8080:80 - 8080:80
environment: environment:
DB_HOST: database DB_HOST: database
# in katenary.yaml # in katenary.yaml
webapp: webapp:
ingress: ingress:
hostname: myapp.example.com hostname: myapp.example.com
port: 8080 port: 8080
map-env: map-env:
DB_HOST: "{{ .Release.Name }}-database" DB_HOST: "{{ .Release.Name }}-database"
``` ```
!!! Warning "YAML in multiline label" !!! Warning "YAML in multiline label"
Compose only accept text label. So, to put a complete YAML content in the target label, Compose only accept text label. So, to put a complete YAML content in the target label,
you need to use a pipe char (`|` or `|-`) and to **indent** your content. you need to use a pipe char (`|` or `|-`) and to **indent** your content.
For example : For example :
@@ -130,8 +129,8 @@ After having installed `katenary`, the standard usage is to call:
It will search standard compose files in the current directory and try to create a helm chart in "chart" directory. It will search standard compose files in the current directory and try to create a helm chart in "chart" directory.
!!! Info !!! Info
Katenary uses the compose-go library which respects the Docker and Docker-Compose specification. Keep in mind that Katenary uses the compose-go library which respects the Docker and Docker-Compose specification. Keep in mind that
it will find files exactly the same way as `docker-compose` and `podman-compose` do it. it will find files exactly the same way as `docker-compose` and `podman-compose` do it.
Of course, you can provide others files than the default with (cumulative) `-c` options: Of course, you can provide others files than the default with (cumulative) `-c` options:
@@ -142,7 +141,7 @@ Of course, you can provide others files than the default with (cumulative) `-c`
Katenary proposes a lot of labels to configure the helm chart generation, but some are very important. Katenary proposes a lot of labels to configure the helm chart generation, but some are very important.
!!! Info !!! Info
For more complete label usage, see [the labels page](labels.md). For more complete label usage, see [the labels page](labels.md).
### Work with Depends On? ### Work with Depends On?
@@ -155,15 +154,15 @@ See this compose file:
version: "3" version: "3"
services: services:
webapp: webapp:
image: php:8-apache image: php:8-apache
depends_on: depends_on:
- database - database
database: database:
image: mariadb image: mariadb
environment: environment:
MYSQL_ROOT_PASSWORD: foobar MYSQL_ROOT_PASSWORD: foobar
``` ```
In this case, `webapp` needs to know the `database` port because the `depends_on` points on it and Kubernetes has not In this case, `webapp` needs to know the `database` port because the `depends_on` points on it and Kubernetes has not
@@ -174,18 +173,18 @@ So, instead of exposing the port in the compose definition, let's declare this t
version: "3" version: "3"
services: services:
webapp: webapp:
image: php:8-apache image: php:8-apache
depends_on: depends_on:
- database - database
database: database:
image: mariadb image: mariadb
environment: environment:
MYSQL_ROOT_PASSWORD: foobar MYSQL_ROOT_PASSWORD: foobar
labels: labels:
katenary.v3/ports: |- katenary.v3/ports: |-
- 3306 - 3306
``` ```
### Declare ingresses ### Declare ingresses
@@ -197,14 +196,14 @@ Katenary can create this resource for you. You just need to declare the hostname
```yaml ```yaml
services: services:
webapp: webapp:
image: ... image: ...
ports: 8080:5050 ports: 8080:5050
labels: labels:
katenary.v3/ingress: |- katenary.v3/ingress: |-
# the target port is 5050 wich is the "service" port # the target port is 5050 wich is the "service" port
port: 5050 port: 5050
hostname: myapp.example.com hostname: myapp.example.com
``` ```
Note that the port to bind is the one used by the container, not the used locally. This is because Katenary create a Note that the port to bind is the one used by the container, not the used locally. This is because Katenary create a
@@ -219,13 +218,13 @@ With a compose file, there is no problem as Docker/Podman allows resolving the n
```yaml ```yaml
services: services:
webapp: webapp:
image: php:7-apache image: php:7-apache
environment: environment:
DB_HOST: database DB_HOST: database
database: database:
image: mariadb image: mariadb
``` ```
Katenary prefixes the services with `{{ .Release.Name }}` (to make it possible to install the application several times Katenary prefixes the services with `{{ .Release.Name }}` (to make it possible to install the application several times
@@ -233,16 +232,16 @@ in a namespace), so you need to "remap" the environment variable to the right on
```yaml ```yaml
services: services:
webapp: webapp:
image: php:7-apache image: php:7-apache
environment: environment:
DB_HOST: database DB_HOST: database
labels: labels:
katenary.v3/mapenv: |- katenary.v3/mapenv: |-
DB_HOST: "{{ .Release.Name }}-database" DB_HOST: "{{ .Release.Name }}-database"
database: database:
image: mariadb image: mariadb
``` ```
This label can be used to map others environment for any others reason. E.g. to change an informational environment This label can be used to map others environment for any others reason. E.g. to change an informational environment
@@ -250,13 +249,13 @@ variable.
```yaml ```yaml
services: services:
webapp: webapp:
#... #...
environment: environment:
RUNNING: docker RUNNING: docker
labels: labels:
katenary.v3/mapenv: |- katenary.v3/mapenv: |-
RUNNING: kubernetes RUNNING: kubernetes
``` ```
In the above example, `RUNNING` will be set to `kubernetes` when you'll deploy the application with helm, and it's In the above example, `RUNNING` will be set to `kubernetes` when you'll deploy the application with helm, and it's

View File

@@ -1,6 +1,6 @@
site_name: Katenary documentation site_name: Katenary documentation
docs_dir: ./docs docs_dir: ./docs
plugins: plugins:
- search - search
- inline-svg - inline-svg
theme: theme:
@@ -48,18 +48,17 @@ nav:
- usage.md - usage.md
- labels.md - labels.md
- Behind the scene: - Behind the scene:
- coding.md - coding.md
- dependencies.md - dependencies.md
- FAQ: faq.md - FAQ: faq.md
- Go Packages: - Go Packages:
- packages/cmd/katenary.md - packages/cmd/katenary.md
- packages/parser.md - packages/parser.md
- packages/utils.md - packages/utils.md
- Generator: - Generator:
- Index: packages/generator.md - Index: packages/generator.md
- ExtraFiles: packages/generator/extrafiles.md - ExtraFiles: packages/generator/extrafiles.md
- labels: - labels:
- packages/generator/labels.md - packages/generator/labels.md
- LabelStructs: packages/generator/labels/labelStructs.md - Labelstructs: packages/generator/labels/labelstructs.md
- KatenaryFile: packages/generator/katenaryfile.md - KatenaryFile: packages/generator/katenaryfile.md

View File

@@ -224,7 +224,7 @@
type: "[]object" type: "[]object"
"configmap-files": "configmap-files":
short: "Add files to the configmap." short: "Inject files as Configmap."
long: |- long: |-
It makes a file or directory to be converted to one or more ConfigMaps It makes a file or directory to be converted to one or more ConfigMaps
and mounted in the pod. The file or directory is relative to the and mounted in the pod. The file or directory is relative to the
@@ -266,7 +266,7 @@
type: "object" type: "object"
"env-from": "env-from":
short: "Add environment variables from antoher service." short: "Add environment variables from another service."
type: "[]string" type: "[]string"
long: |- long: |-
It adds environment variables from another service to the current service. It adds environment variables from another service to the current service.

117
nsis/katenary.nsi Normal file
View File

@@ -0,0 +1,117 @@
!define APP_NAME "Katenary"
!define COMPANY_NAME "Katenary"
OutFile "katenary-windows-setup.exe"
InstallDir "$LOCALAPPDATA\Katenary"
RequestExecutionLevel user
!include "MUI2.nsh"
!addplugindir "."
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English" ; The first language is the default language
!insertmacro MUI_LANGUAGE "Afrikaans"
!insertmacro MUI_LANGUAGE "Albanian"
!insertmacro MUI_LANGUAGE "Arabic"
!insertmacro MUI_LANGUAGE "Armenian"
!insertmacro MUI_LANGUAGE "Asturian"
!insertmacro MUI_LANGUAGE "Basque"
!insertmacro MUI_LANGUAGE "Belarusian"
!insertmacro MUI_LANGUAGE "Bosnian"
!insertmacro MUI_LANGUAGE "Breton"
!insertmacro MUI_LANGUAGE "Bulgarian"
!insertmacro MUI_LANGUAGE "Catalan"
!insertmacro MUI_LANGUAGE "Corsican"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Czech"
!insertmacro MUI_LANGUAGE "Danish"
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "Esperanto"
!insertmacro MUI_LANGUAGE "Estonian"
!insertmacro MUI_LANGUAGE "Farsi"
!insertmacro MUI_LANGUAGE "Finnish"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "Galician"
!insertmacro MUI_LANGUAGE "Georgian"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Greek"
!insertmacro MUI_LANGUAGE "Hebrew"
!insertmacro MUI_LANGUAGE "Hindi"
!insertmacro MUI_LANGUAGE "Hungarian"
!insertmacro MUI_LANGUAGE "Icelandic"
!insertmacro MUI_LANGUAGE "Indonesian"
!insertmacro MUI_LANGUAGE "Irish"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Japanese"
!insertmacro MUI_LANGUAGE "Korean"
!insertmacro MUI_LANGUAGE "Kurdish"
!insertmacro MUI_LANGUAGE "Latvian"
!insertmacro MUI_LANGUAGE "Lithuanian"
!insertmacro MUI_LANGUAGE "Luxembourgish"
!insertmacro MUI_LANGUAGE "Macedonian"
!insertmacro MUI_LANGUAGE "Malay"
!insertmacro MUI_LANGUAGE "Mongolian"
!insertmacro MUI_LANGUAGE "Norwegian"
!insertmacro MUI_LANGUAGE "NorwegianNynorsk"
!insertmacro MUI_LANGUAGE "Pashto"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "PortugueseBR"
!insertmacro MUI_LANGUAGE "Romanian"
!insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "ScotsGaelic"
!insertmacro MUI_LANGUAGE "Serbian"
!insertmacro MUI_LANGUAGE "SerbianLatin"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "Slovak"
!insertmacro MUI_LANGUAGE "Slovenian"
!insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "SpanishInternational"
!insertmacro MUI_LANGUAGE "Swedish"
!insertmacro MUI_LANGUAGE "Tatar"
!insertmacro MUI_LANGUAGE "Thai"
!insertmacro MUI_LANGUAGE "TradChinese"
!insertmacro MUI_LANGUAGE "Turkish"
!insertmacro MUI_LANGUAGE "Ukrainian"
!insertmacro MUI_LANGUAGE "Uzbek"
!insertmacro MUI_LANGUAGE "Vietnamese"
!insertmacro MUI_LANGUAGE "Welsh"
Name "${APP_NAME} ${APP_VERSION}"
Section "Install"
SetOutPath "$INSTDIR"
File "..\dist\katenary.exe"
File "..\LICENSE"
File "..\README.md"
WriteUninstaller "$INSTDIR\uninstall-katenary.exe"
EnVar::SetHKCU
Pop $0
EnVar::AddValue "Path" "$INSTDIR"
Pop $0
SectionEnd
Section "Uninstall"
EnVar::SetHKCU
Pop $0
EnVar::DeleteValue "Path" "$INSTDIR"
Pop $0
Delete "$INSTDIR\katenary.exe"
Delete "$INSTDIR\uninstall-katenary.exe"
Delete "$INSTDIR\LICENSE"
Delete "$INSTDIR\README.md"
RMDir "$INSTDIR"
SectionEnd

View File

@@ -93,7 +93,7 @@ func GetContainerByName(name string, containers []corev1.Container) (*corev1.Con
return nil, -1 return nil, -1
} }
// TplValue returns a container by name and its index in the array. // TplValue returns a string that can be used in a template to access a value from the values file.
func TplValue(serviceName, variable string, pipes ...string) string { func TplValue(serviceName, variable string, pipes ...string) string {
if len(pipes) == 0 { if len(pipes) == 0 {
return `{{ tpl .Values.` + serviceName + `.` + variable + ` $ }}` return `{{ tpl .Values.` + serviceName + `.` + variable + ` $ }}`

245
utils/utils_test.go Normal file
View File

@@ -0,0 +1,245 @@
package utils
import (
"testing"
corev1 "k8s.io/api/core/v1"
)
func TestTplName(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
serviceName string
appname string
suffix []string
want string
}{
{"simple test without suffix", "foosvc", "myapp", nil, `{{ include "myapp.fullname" . }}-foosvc`},
{"simple test with suffix", "foosvc", "myapp", []string{"bar"}, `{{ include "myapp.fullname" . }}-foosvc-bar`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := TplName(tt.serviceName, tt.appname, tt.suffix...)
if got != tt.want {
t.Errorf("TplName() = %v, want %v", got, tt.want)
}
})
}
}
func TestCountStartingSpaces(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
line string
want int
}{
{
"test no spaces",
"the line is here",
0,
},
{
"test with 4 spaces",
" line with 4 spaces",
4,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CountStartingSpaces(tt.line)
if got != tt.want {
t.Errorf("CountStartingSpaces() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetKind(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
path string
want string
}{
{
"test get kind from file path",
"my.deployment.yaml",
"deployment",
},
{
"test with 2 parts",
"service.yaml",
"service",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetKind(tt.path)
if got != tt.want {
t.Errorf("GetKind() = %v, want %v", got, tt.want)
}
})
}
}
func TestWrap(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
src string
above string
below string
want string
}{
{
"test a simple wrap",
" - foo: bar",
"line above",
"line below",
" line above\n - foo: bar\n line below",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Wrap(tt.src, tt.above, tt.below)
if got != tt.want {
t.Errorf("Wrap() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetServiceNameByPort(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
port int
want string
}{
{
"test http port by service number 80",
80,
"http",
},
{
"test with a port that has no service name",
8745,
"",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetServiceNameByPort(tt.port)
if got != tt.want {
t.Errorf("GetServiceNameByPort() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetContainerByName(t *testing.T) {
httpContainer := &corev1.Container{
Name: "http",
}
mariadbContainer := &corev1.Container{
Name: "mariadb",
}
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
containerName string
containers []corev1.Container
want *corev1.Container
want2 int
}{
{
"get container from by name",
"http",
[]corev1.Container{
*httpContainer,
*mariadbContainer,
},
httpContainer, 0,
},
{
"get container from by name",
"mariadb",
[]corev1.Container{
*httpContainer,
*mariadbContainer,
},
mariadbContainer, 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got2 := GetContainerByName(tt.containerName, tt.containers)
if got.Name != tt.want.Name {
t.Errorf("GetContainerByName() = %v, want %v", got.Name, tt.want.Name)
}
if got2 != tt.want2 {
t.Errorf("GetContainerByName() = %v, want %v", got2, tt.want2)
}
})
}
}
func TestTplValue(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
serviceName string
variable string
pipes []string
want string
}{
{
"check simple template value",
"foosvc",
"variableFoo",
nil,
"{{ tpl .Values.foosvc.variableFoo $ }}",
},
{
"check with pipes",
"foosvc",
"bar",
[]string{"toYaml", "nindent 2"},
"{{ tpl .Values.foosvc.bar $ | toYaml | nindent 2 }}",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := TplValue(tt.serviceName, tt.variable, tt.pipes...)
if got != tt.want {
t.Errorf("TplValue() = %v, want %v", got, tt.want)
}
})
}
}
func TestPathToName(t *testing.T) {
tests := []struct {
name string // description of this test case
// Named input parameters for target function.
path string
want string
}{
{
"check complete path with various characters",
"./foo/bar.test/and_bad_name",
"foo-bar-test-and-bad-name",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := PathToName(tt.path)
if got != tt.want {
t.Errorf("PathToName() = %v, want %v", got, tt.want)
}
})
}
}