Compare commits
76 Commits
Author | SHA1 | Date | |
---|---|---|---|
1f406dc558 | |||
0c0b50b0df | |||
6efee2fbae | |||
47e149e20b | |||
d163700147 | |||
fa3befaa88 | |||
e5b7c0d550 | |||
9e4663cc6e | |||
1a5c95d240 | |||
21845c5de1 | |||
4a91d458fd | |||
a52b20efab | |||
02c4c5168b | |||
7b875454cb | |||
2da5d9df08 | |||
a0eb3c0bb6 | |||
7e76543c48 | |||
09c2c86d59 | |||
e58948bb44 | |||
a00b03b2aa | |||
b47b956798 | |||
a409a1347e | |||
8999aabc21 | |||
14e8907437 | |||
740c400b9a | |||
7cd38bbd23 | |||
8c509b5bff | |||
28b22a0b30 | |||
748d0bf1ea | |||
130e6d4e24 | |||
a66fec07e1 | |||
a3d1e9342f | |||
72bc88661a | |||
e2b897eb9d | |||
9fcce059e5 | |||
36f6413917 | |||
8c729f3c57 | |||
063cc9d439 | |||
ac5317e600 | |||
bc0b65006d | |||
933f04bf5e | |||
7d46435ba2 | |||
d94bb8ac32 | |||
b143f743ef | |||
a8341a9b44 | |||
def5d097a4 | |||
ba0ae1bc60 | |||
d77029b597 | |||
b5f62d43af | |||
9220dc3278 | |||
36c72fb665 | |||
|
c90504f4f1 | ||
9ef961ae7c | |||
fe6663f9f4 | |||
1190b316bb | |||
7068dc229c | |||
|
61ce6fb25b | ||
116ef658d8 | |||
d7b354de8c | |||
|
d06c0574fb | ||
|
bcd7894e3b | ||
80aba05f66 | |||
41a4292939 | |||
131ea5d569 | |||
e36bbf41f4 | |||
c97b398914 | |||
d27ed76cf4 | |||
17b6ea51af | |||
0986f73f06 | |||
dcd282779f | |||
b93a3df98c | |||
4768330c1a | |||
23d0afd85f | |||
5c939383be | |||
72ddb8aa74 | |||
4d0e5b2e6a |
40
.github/workflows/go-test.yaml
vendored
40
.github/workflows/go-test.yaml
vendored
@@ -2,31 +2,47 @@ name: Go-Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- develop
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- develop
|
||||
- 'releases/**'
|
||||
jobs:
|
||||
test:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
- name: Install Helm
|
||||
run: |
|
||||
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
|
||||
chmod 700 get_helm.sh
|
||||
./get_helm.sh
|
||||
go-version: 1.24
|
||||
- name: Launch Test
|
||||
run: |
|
||||
go mod tidy
|
||||
go vet ./... && go test -coverprofile=coverprofile.out -json -v ./... > gotest.json
|
||||
- name: SonarCloud Scan
|
||||
uses: SonarSource/sonarcloud-github-action@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tests-results
|
||||
path: |
|
||||
coverprofile.out
|
||||
gotest.json
|
||||
sonar:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
runs-on: ubuntu-latest
|
||||
needs: tests
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tests-results
|
||||
- name: SonarQube Scan
|
||||
uses: SonarSource/sonarqube-scan-action@v5.2.0
|
||||
env:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}
|
||||
|
26
.golangci.yml
Normal file
26
.golangci.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
version: "2"
|
||||
run:
|
||||
issues-exit-code: 1
|
||||
linters:
|
||||
enabled:
|
||||
- unused
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- "(.+)_test.go"
|
||||
formatters:
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- "(.+)_test.go"
|
56
Makefile
56
Makefile
@@ -4,14 +4,17 @@ VERSION=$(shell git describe --exact-match --tags $(CUR_SHA) 2>/dev/null || echo
|
||||
CTN:=$(shell which podman 2>&1 1>/dev/null && echo "podman" || echo "docker")
|
||||
PREFIX=~/.local
|
||||
|
||||
GOVERSION=1.23
|
||||
GOVERSION=1.24
|
||||
GO=container
|
||||
OUT=katenary
|
||||
RELEASE=""
|
||||
BLD_CMD=go build -ldflags="-X 'katenary/generator.Version=$(RELEASE)$(VERSION)'" -o $(OUT) ./cmd/katenary
|
||||
GOOS=linux
|
||||
GOARCH=amd64
|
||||
CGO_ENABLED=0
|
||||
SIGNER=metal3d@gmail.com
|
||||
UPX_OPTS =
|
||||
UPX ?= upx $(UPX_OPTS)
|
||||
|
||||
BUILD_IMAGE=docker.io/golang:$(GOVERSION)-alpine
|
||||
# SHELL=/bin/bash
|
||||
@@ -33,7 +36,7 @@ SHELL := bash
|
||||
.DELETE_ON_ERROR:
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
.PHONY: help clean build install tests test
|
||||
.PHONY: help clean build install tests test doc
|
||||
|
||||
all: build
|
||||
|
||||
@@ -87,25 +90,21 @@ endif
|
||||
katenary: $(SOURCES) Makefile go.mod go.sum
|
||||
ifeq ($(GO),local)
|
||||
@echo "=> Build on host using go"
|
||||
else
|
||||
@echo "=> Build in container using" $(CTN)
|
||||
endif
|
||||
echo $(BLD_CMD)
|
||||
ifeq ($(GO),local)
|
||||
$(BLD_CMD)
|
||||
else ifeq ($(CTN),podman)
|
||||
@podman run -e CGO_ENABLED=0 -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) \
|
||||
--rm -v $(PWD):/go/src/katenary:z -w /go/src/katenary --userns keep-id -it $(BUILD_IMAGE) $(BLD_CMD)
|
||||
@echo "=> Build in container using" $(CTN)
|
||||
echo $(GOOS) $(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)
|
||||
else
|
||||
@docker run -e CGO_ENABLED=0 -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) \
|
||||
--rm -v $(PWD):/go/src/katenary:z -w /go/src/katenary --user $(shell id -u):$(shell id -g) -e HOME=/tmp -it $(BUILD_IMAGE) $(BLD_CMD)
|
||||
@echo "=> Build in container using" $(CTN)
|
||||
@docker run -e CGO_ENABLED=$(CGO_ENABLED) -e GOOS=$(GOOS) -e GOARCH=$(GOARCH) \
|
||||
--rm -v $(PWD):/go/src/katenary:z -w /go/src/katenary --user $(shell id -u):$(shell id -g) -e HOME=/tmp $(BUILD_IMAGE) $(BLD_CMD)
|
||||
endif
|
||||
echo "=> Stripping if possible"
|
||||
strip $(OUT) 2>/dev/null || echo "=> No strip available"
|
||||
|
||||
|
||||
## Release build
|
||||
dist: prepare $(BINARIES) $(ASC_BINARIES)
|
||||
dist: prepare $(BINARIES) upx $(ASC_BINARIES)
|
||||
|
||||
prepare: pull
|
||||
mkdir -p dist
|
||||
@@ -114,6 +113,7 @@ dist/katenary-linux-amd64:
|
||||
@echo
|
||||
@echo -e "\033[1;32mBuilding katenary $(VERSION) for linux-amd64...\033[0m"
|
||||
$(MAKE) katenary GOOS=linux GOARCH=amd64 OUT=$@
|
||||
strip $@
|
||||
|
||||
dist/katenary-linux-arm64:
|
||||
@echo
|
||||
@@ -134,12 +134,13 @@ dist/katenary-freebsd-amd64:
|
||||
@echo
|
||||
@echo -e "\033[1;32mBuilding katenary $(VERSION) for freebsd...\033[0m"
|
||||
$(MAKE) katenary GOOS=freebsd GOARCH=amd64 OUT=$@
|
||||
strip $@
|
||||
|
||||
dist/katenary-freebsd-arm64:
|
||||
@echo
|
||||
@echo -e "\033[1;32mBuilding katenary $(VERSION) for freebsd-arm64...\033[0m"
|
||||
$(MAKE) katenary GOOS=freebsd GOARCH=arm64 OUT=$@
|
||||
|
||||
|
||||
gpg-sign:
|
||||
rm -f dist/*.asc
|
||||
$(MAKE) $(ASC_BINARIES)
|
||||
@@ -147,6 +148,13 @@ gpg-sign:
|
||||
dist/%.asc: dist/%
|
||||
gpg --armor --detach-sign --default-key $(SIGNER) $< &>/dev/null || exit 1
|
||||
|
||||
|
||||
upx:
|
||||
$(UPX) dist/katenary-linux-amd64
|
||||
$(UPX) dist/katenary-linux-arm64
|
||||
#$(UPX) dist/katenary.exe
|
||||
$(UPX) dist/katenary-darwin-amd64 --force-macos
|
||||
|
||||
install: build
|
||||
install -Dm755 katenary $(PREFIX)/bin/katenary
|
||||
|
||||
@@ -204,6 +212,11 @@ push-release: build-all
|
||||
@rm -f release.id
|
||||
|
||||
|
||||
doc:
|
||||
@echo "=> Generating documentation..."
|
||||
# generate the labels doc and code doc
|
||||
$(MAKE) __label_doc
|
||||
|
||||
__label_doc:
|
||||
@command -v gomarkdoc || (echo "==> We need to install gomarkdoc..." && \
|
||||
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest)
|
||||
@@ -228,3 +241,16 @@ __label_doc:
|
||||
gomarkdoc --repository.default-branch $(shell git branch --show-current) -o doc/docs/packages/$$pack.md $$pack
|
||||
sed -i '/^## Index/,/^##/ { /## Index/d; /^##/! d }' doc/docs/packages/$$pack.md
|
||||
done
|
||||
|
||||
|
||||
# Scan the source code.
|
||||
# - 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.
|
||||
# Note: metrics are actually not sent to anyone - it's a thing that is removed from the code in the future.
|
||||
sast:
|
||||
opengrep \
|
||||
--config auto \
|
||||
--exclude-rule go.lang.security.audit.xss.import-text-template.import-text-template \
|
||||
--exclude-rule go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1 \
|
||||
--metrics=on \
|
||||
.
|
||||
|
58
README.md
58
README.md
@@ -2,11 +2,22 @@
|
||||
<img src="./doc/docs/statics/logo-vertical.svg" alt="Katenary Logo" style="max-width: 90%" align="center"/>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; margin: auto 0 4em 0" align="center">
|
||||
|
||||
[](https://katenary.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://goreportcard.com/report/github.com/metal3d/katenary)
|
||||
[](https://github.com/metal3d/katenary/releases)
|
||||
[](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
|
||||
[](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
|
||||
[](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
|
||||
|
||||
🚀 Unleash Productivity with Katenary! 🚀
|
||||
[](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
|
||||
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; margin: auto 0 4em 0" align="center">
|
||||
<h3>🚀 Unleash Productivity with Katenary! 🚀</h3>
|
||||
</div>
|
||||
|
||||
Tired of manual conversions? Katenary harnesses the labels from your "`compose`" file to craft complete Helm Charts
|
||||
effortlessly, saving you time and energy.
|
||||
@@ -161,33 +172,34 @@ services:
|
||||
katenary.v3/ingress: |-
|
||||
hostname: myapp.example.com
|
||||
port: 80
|
||||
# make adaptations, DB_HOST environment is actually the service name
|
||||
katenary.v3/map-env: |-
|
||||
# make adaptations, DB_HOST environment is actually the service name
|
||||
DB_HOST: '{{ .Release.Name }}-database'
|
||||
# get the values from the "database" service
|
||||
# this will use the database secrets and environment,
|
||||
# see the "database" service to see the values
|
||||
katenary.v3/values-from: |-
|
||||
# get the values from the "database" service
|
||||
# this will use the databas secret, see below
|
||||
DB_USER: databse.MARIADB_USER
|
||||
DB_USER: database.MARIADB_USER
|
||||
DB_PASSWORD: database.MARIADB_PASSWORD
|
||||
|
||||
database:
|
||||
image: mariadb:10
|
||||
env_file:
|
||||
# this valuse will be added in a configMap
|
||||
- my_env.env
|
||||
environment:
|
||||
MARIADB_USER: foo
|
||||
MARIADB_ROOT_PASSWORD: foobar
|
||||
MARIADB_PASSWORD: bar
|
||||
labels:
|
||||
# no need to declare this port in docker-compose
|
||||
# but katenary will need it
|
||||
katenary.v3/ports: |-
|
||||
- 3306
|
||||
# these variables are secrets
|
||||
katenary.v3/secrets: |-
|
||||
- MARIADB_ROOT_PASSWORD
|
||||
- MARIADB_PASSWORD
|
||||
database:
|
||||
image: mariadb:10
|
||||
env_file:
|
||||
# this valuse will be added in a configMap
|
||||
- my_env.env
|
||||
environment:
|
||||
MARIADB_USER: foo
|
||||
MARIADB_ROOT_PASSWORD: foobar
|
||||
MARIADB_PASSWORD: bar
|
||||
labels:
|
||||
# no need to declare this port in docker-compose
|
||||
# but katenary will need it
|
||||
katenary.v3/ports: |-
|
||||
- 3306
|
||||
# these variables are secrets
|
||||
katenary.v3/secrets: |-
|
||||
- MARIADB_ROOT_PASSWORD
|
||||
- MARIADB_PASSWORD
|
||||
```
|
||||
|
||||
## Labels
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"katenary/generator/katenaryfile"
|
||||
"katenary/generator/labels"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -24,7 +25,10 @@ Each [command] and subcommand has got an "help" and "--help" flag to show more i
|
||||
|
||||
func main() {
|
||||
rootCmd := buildRootCmd()
|
||||
rootCmd.Execute()
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildRootCmd() *cobra.Command {
|
||||
@@ -97,26 +101,26 @@ func generateCompletionCommand(name string) *cobra.Command {
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
Short: "Generates completion scripts",
|
||||
Long: fmt.Sprintf(completionHelp, name),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
cmd.Help()
|
||||
return
|
||||
return cmd.Help()
|
||||
}
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
// get the bash version
|
||||
if cmd.Flags().Changed("bash-v1") {
|
||||
cmd.Root().GenBashCompletion(os.Stdout)
|
||||
return
|
||||
return cmd.Root().GenBashCompletion(os.Stdout)
|
||||
}
|
||||
cmd.Root().GenBashCompletionV2(os.Stdout, true)
|
||||
return cmd.Root().GenBashCompletionV2(os.Stdout, true)
|
||||
case "zsh":
|
||||
cmd.Root().GenZshCompletion(os.Stdout)
|
||||
return cmd.Root().GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||
return cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
cmd.Root().GenPowerShellCompletion(os.Stdout)
|
||||
return cmd.Root().GenPowerShellCompletion(os.Stdout)
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown completion type: %s", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
@@ -142,7 +146,7 @@ func generateConvertCommand() *cobra.Command {
|
||||
Use: "convert",
|
||||
Short: "Converts a docker-compose file to a Helm Chart",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if givenAppVersion != "" {
|
||||
if len(strings.TrimSpace(givenAppVersion)) > 0 {
|
||||
appVersion = &givenAppVersion
|
||||
}
|
||||
return generator.Convert(generator.ConvertOptions{
|
||||
|
5
doc/docs/.markdownlint.yaml
Normal file
5
doc/docs/.markdownlint.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
MD012: false
|
||||
MD013: false
|
||||
MD022: false
|
||||
MD033: false
|
||||
MD046: false
|
@@ -460,9 +460,9 @@ database:
|
||||
MARIADB_USER: myuser
|
||||
MARIADB_PASSWORD: mypassword
|
||||
labels:
|
||||
# it can be a secret
|
||||
# we can declare secrets
|
||||
katenary.v3/secrets: |-
|
||||
- DB_PASSWORD
|
||||
- MARIADB_PASSWORD
|
||||
php:
|
||||
image: php:7.4-fpm
|
||||
environment:
|
||||
|
@@ -6,7 +6,7 @@
|
||||
import "katenary/generator"
|
||||
```
|
||||
|
||||
The generator package generates kubernetes objects from a "compose" file and transforms them into a helm chart.
|
||||
Package generator generates kubernetes objects from a "compose" file and transforms them into a helm chart.
|
||||
|
||||
The generator package is the core of katenary. It is responsible for generating kubernetes objects from a compose file and transforming them into a helm chart. Conversion manipulates Yaml representation of kubernetes object to add conditions, labels, annotations, etc. to the objects. It also create the values to be set to the values.yaml file.
|
||||
|
||||
@@ -35,7 +35,7 @@ var Version = "master" // changed at compile time
|
||||
```
|
||||
|
||||
<a name="Convert"></a>
|
||||
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L93>)
|
||||
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L99>)
|
||||
|
||||
```go
|
||||
func Convert(config ConvertOptions, dockerComposeFile ...string) error
|
||||
@@ -92,7 +92,7 @@ NewCronJob creates a new CronJob from a compose service. The appName is the name
|
||||
## func [ToK8SYaml](<https://github.com/metal3d/katenary/blob/develop/generator/utils.go#L90>)
|
||||
|
||||
```go
|
||||
func ToK8SYaml(obj interface{}) ([]byte, error)
|
||||
func ToK8SYaml(obj any) ([]byte, error)
|
||||
```
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ func UnWrapTPL(in []byte) []byte
|
||||
UnWrapTPL removes the line wrapping from a template.
|
||||
|
||||
<a name="ChartTemplate"></a>
|
||||
## type [ChartTemplate](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L19-L22>)
|
||||
## type [ChartTemplate](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L21-L24>)
|
||||
|
||||
ChartTemplate is a template of a chart. It contains the content of the template and the name of the service. This is used internally to generate the templates.
|
||||
|
||||
@@ -149,7 +149,7 @@ func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string
|
||||
NewConfigMapFromDirectory creates a new ConfigMap from a compose service. This path is the path to the file or directory. If the path is a directory, all files in the directory are added to the ConfigMap. Each subdirectory are ignored. Note that the Generate\(\) function will create the subdirectories ConfigMaps.
|
||||
|
||||
<a name="ConfigMap.AddBinaryData"></a>
|
||||
### func \(\*ConfigMap\) [AddBinaryData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L155>)
|
||||
### func \(\*ConfigMap\) [AddBinaryData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L157>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AddBinaryData(key string, value []byte)
|
||||
@@ -158,7 +158,7 @@ func (c *ConfigMap) AddBinaryData(key string, value []byte)
|
||||
AddBinaryData adds binary data to the configmap. Append or overwrite the value if the key already exists.
|
||||
|
||||
<a name="ConfigMap.AddData"></a>
|
||||
### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L150>)
|
||||
### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L152>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AddData(key, value string)
|
||||
@@ -167,16 +167,16 @@ func (c *ConfigMap) AddData(key, value string)
|
||||
AddData adds a key value pair to the configmap. Append or overwrite the value if the key already exists.
|
||||
|
||||
<a name="ConfigMap.AppendDir"></a>
|
||||
### func \(\*ConfigMap\) [AppendDir](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L164>)
|
||||
### func \(\*ConfigMap\) [AppendDir](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L166>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AppendDir(path string) error
|
||||
```
|
||||
|
||||
AddFile adds files from given path to the configmap. It is not recursive, to add all files in a directory, you need to call this function for each subdirectory.
|
||||
AppendDir adds files from given path to the configmap. It is not recursive, to add all files in a directory, you need to call this function for each subdirectory.
|
||||
|
||||
<a name="ConfigMap.AppendFile"></a>
|
||||
### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L211>)
|
||||
### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L213>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AppendFile(path string) error
|
||||
@@ -185,7 +185,7 @@ func (c *ConfigMap) AppendFile(path string) error
|
||||
|
||||
|
||||
<a name="ConfigMap.Filename"></a>
|
||||
### func \(\*ConfigMap\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L235>)
|
||||
### func \(\*ConfigMap\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L237>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) Filename() string
|
||||
@@ -194,7 +194,7 @@ func (c *ConfigMap) Filename() string
|
||||
Filename returns the filename of the configmap. If the configmap is used for files, the filename contains the path.
|
||||
|
||||
<a name="ConfigMap.SetData"></a>
|
||||
### func \(\*ConfigMap\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L245>)
|
||||
### func \(\*ConfigMap\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L247>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) SetData(data map[string]string)
|
||||
@@ -203,7 +203,7 @@ func (c *ConfigMap) SetData(data map[string]string)
|
||||
SetData sets the data of the configmap. It replaces the entire data.
|
||||
|
||||
<a name="ConfigMap.Yaml"></a>
|
||||
### func \(\*ConfigMap\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L250>)
|
||||
### func \(\*ConfigMap\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L252>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) Yaml() ([]byte, error)
|
||||
@@ -223,7 +223,7 @@ type ConfigMapMount struct {
|
||||
```
|
||||
|
||||
<a name="ConvertOptions"></a>
|
||||
## type [ConvertOptions](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L25-L34>)
|
||||
## type [ConvertOptions](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L27-L36>)
|
||||
|
||||
ConvertOptions are the options to convert a compose project to a helm chart.
|
||||
|
||||
@@ -275,7 +275,7 @@ Yaml returns the yaml representation of the cronjob.
|
||||
Implements the Yaml interface.
|
||||
|
||||
<a name="CronJobValue"></a>
|
||||
## type [CronJobValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L113-L118>)
|
||||
## type [CronJobValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L118-L123>)
|
||||
|
||||
CronJobValue is a cronjob configuration that will be saved in values.yaml.
|
||||
|
||||
@@ -376,7 +376,7 @@ func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment)
|
||||
|
||||
|
||||
<a name="Deployment.BindMapFilesToContainer"></a>
|
||||
### func \(\*Deployment\) [BindMapFilesToContainer](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L377>)
|
||||
### func \(\*Deployment\) [BindMapFilesToContainer](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L374>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secrets []string, appName string) (*corev1.Container, int)
|
||||
@@ -403,7 +403,7 @@ func (d *Deployment) Filename() string
|
||||
Filename returns the filename of the deployment.
|
||||
|
||||
<a name="Deployment.MountExchangeVolumes"></a>
|
||||
### func \(\*Deployment\) [MountExchangeVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L428>)
|
||||
### func \(\*Deployment\) [MountExchangeVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L425>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) MountExchangeVolumes()
|
||||
@@ -421,7 +421,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
SetEnvFrom sets the environment variables to a configmap. The configmap is created.
|
||||
|
||||
<a name="Deployment.Yaml"></a>
|
||||
### func \(\*Deployment\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L452>)
|
||||
### func \(\*Deployment\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L449>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) Yaml() ([]byte, error)
|
||||
@@ -448,7 +448,7 @@ const (
|
||||
```
|
||||
|
||||
<a name="HelmChart"></a>
|
||||
## type [HelmChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L38-L51>)
|
||||
## type [HelmChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L40-L53>)
|
||||
|
||||
HelmChart is a Helm Chart representation. It contains all the templates, values, versions, helpers...
|
||||
|
||||
@@ -460,18 +460,18 @@ type HelmChart struct {
|
||||
|
||||
Name string `yaml:"name"`
|
||||
Icon string `yaml:"icon,omitempty"`
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
APIVersion string `yaml:"apiVersion"`
|
||||
Version string `yaml:"version"`
|
||||
AppVersion string `yaml:"appVersion"`
|
||||
Description string `yaml:"description"`
|
||||
Helper string `yaml:"-"`
|
||||
Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Generate"></a>
|
||||
### func [Generate](<https://github.com/metal3d/katenary/blob/develop/generator/generator.go#L29>)
|
||||
### func [Generate](<https://github.com/metal3d/katenary/blob/develop/generator/generator.go#L31>)
|
||||
|
||||
```go
|
||||
func Generate(project *types.Project) (*HelmChart, error)
|
||||
@@ -491,7 +491,7 @@ The Generate function will create the HelmChart object this way:
|
||||
- Merge the same\-pod services.
|
||||
|
||||
<a name="NewChart"></a>
|
||||
### func [NewChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L54>)
|
||||
### func [NewChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L56>)
|
||||
|
||||
```go
|
||||
func NewChart(name string) *HelmChart
|
||||
@@ -500,7 +500,7 @@ func NewChart(name string) *HelmChart
|
||||
NewChart creates a new empty chart with the given name.
|
||||
|
||||
<a name="HelmChart.SaveTemplates"></a>
|
||||
### func \(\*HelmChart\) [SaveTemplates](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L69>)
|
||||
### func \(\*HelmChart\) [SaveTemplates](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L71>)
|
||||
|
||||
```go
|
||||
func (chart *HelmChart) SaveTemplates(templateDir string)
|
||||
@@ -509,7 +509,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string)
|
||||
SaveTemplates the templates of the chart to the given directory.
|
||||
|
||||
<a name="Ingress"></a>
|
||||
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L17-L20>)
|
||||
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L17-L21>)
|
||||
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ type Ingress struct {
|
||||
```
|
||||
|
||||
<a name="NewIngress"></a>
|
||||
### func [NewIngress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L23>)
|
||||
### func [NewIngress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L24>)
|
||||
|
||||
```go
|
||||
func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress
|
||||
@@ -530,7 +530,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress
|
||||
NewIngress creates a new Ingress from a compose service.
|
||||
|
||||
<a name="Ingress.Filename"></a>
|
||||
### func \(\*Ingress\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L122>)
|
||||
### func \(\*Ingress\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L128>)
|
||||
|
||||
```go
|
||||
func (ingress *Ingress) Filename() string
|
||||
@@ -539,7 +539,7 @@ func (ingress *Ingress) Filename() string
|
||||
|
||||
|
||||
<a name="Ingress.Yaml"></a>
|
||||
### func \(\*Ingress\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L126>)
|
||||
### func \(\*Ingress\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L132>)
|
||||
|
||||
```go
|
||||
func (ingress *Ingress) Yaml() ([]byte, error)
|
||||
@@ -548,7 +548,7 @@ func (ingress *Ingress) Yaml() ([]byte, error)
|
||||
|
||||
|
||||
<a name="IngressValue"></a>
|
||||
## type [IngressValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L28-L35>)
|
||||
## type [IngressValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L29-L36>)
|
||||
|
||||
IngressValue is a ingress configuration that will be saved in values.yaml.
|
||||
|
||||
@@ -809,18 +809,19 @@ func (r *ServiceAccount) Yaml() ([]byte, error)
|
||||
|
||||
|
||||
<a name="TLS"></a>
|
||||
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L23-L25>)
|
||||
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L23-L26>)
|
||||
|
||||
|
||||
|
||||
```go
|
||||
type TLS struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
SecretName string `yaml:"secretName"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Value"></a>
|
||||
## type [Value](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L38-L49>)
|
||||
## type [Value](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L39-L50>)
|
||||
|
||||
Value will be saved in values.yaml. It contains configuration for all deployment and services.
|
||||
|
||||
@@ -840,7 +841,7 @@ type Value struct {
|
||||
```
|
||||
|
||||
<a name="NewValue"></a>
|
||||
### func [NewValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L56>)
|
||||
### func [NewValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L57>)
|
||||
|
||||
```go
|
||||
func NewValue(service types.ServiceConfig, main ...bool) *Value
|
||||
@@ -851,7 +852,7 @@ NewValue creates a new Value from a compose service. The value contains the nece
|
||||
If \`main\` is true, the tag will be empty because it will be set in the helm chart appVersion.
|
||||
|
||||
<a name="Value.AddIngress"></a>
|
||||
### func \(\*Value\) [AddIngress](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L89>)
|
||||
### func \(\*Value\) [AddIngress](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L90>)
|
||||
|
||||
```go
|
||||
func (v *Value) AddIngress(host, path string)
|
||||
@@ -860,7 +861,7 @@ func (v *Value) AddIngress(host, path string)
|
||||
|
||||
|
||||
<a name="Value.AddPersistence"></a>
|
||||
### func \(\*Value\) [AddPersistence](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L99>)
|
||||
### func \(\*Value\) [AddPersistence](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L104>)
|
||||
|
||||
```go
|
||||
func (v *Value) AddPersistence(volumeName string)
|
||||
|
@@ -6,7 +6,7 @@
|
||||
import "katenary/generator/extrafiles"
|
||||
```
|
||||
|
||||
extrafiles package provides function to generate the Chart files that are not objects. Like README.md and notes.txt...
|
||||
Package extrafiles provides function to generate the Chart files that are not objects. Like README.md and notes.txt...
|
||||
|
||||
## func [NotesFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/notes.go#L13>)
|
||||
|
||||
@@ -17,7 +17,7 @@ func NotesFile(services []string) string
|
||||
NotesFile returns the content of the note.txt file.
|
||||
|
||||
<a name="ReadMeFile"></a>
|
||||
## func [ReadMeFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/readme.go#L45>)
|
||||
## func [ReadMeFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/readme.go#L46>)
|
||||
|
||||
```go
|
||||
func ReadMeFile(charname, description string, values map[string]any) string
|
||||
|
@@ -12,7 +12,7 @@ A katenary file, named "katenary.yml" or "katenary.yaml", is a file where you ca
|
||||
|
||||
Formely, the file describe the same structure as in labels, and so that can be validated and completed by LSP. It also ease the use of katenary.
|
||||
|
||||
## func [GenerateSchema](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryfile/main.go#L131>)
|
||||
## func [GenerateSchema](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryfile/main.go#L137>)
|
||||
|
||||
```go
|
||||
func GenerateSchema() string
|
||||
@@ -38,20 +38,20 @@ Service is a struct that contains the service configuration for katenary
|
||||
type Service struct {
|
||||
MainApp *bool `json:"main-app,omitempty" jsonschema:"title=Is this service the main application"`
|
||||
Values []StringOrMap `json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"`
|
||||
Secrets *labelStructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
|
||||
Ports *labelStructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
|
||||
Ingress *labelStructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
|
||||
HealthCheck *labelStructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
|
||||
Secrets *labelstructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
|
||||
Ports *labelstructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
|
||||
Ingress *labelstructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
|
||||
HealthCheck *labelstructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
|
||||
SamePod *string `json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"`
|
||||
Description *string `json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"`
|
||||
Ignore *bool `json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"`
|
||||
Dependencies []labelStructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
|
||||
ConfigMapFile *labelStructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
|
||||
MapEnv *labelStructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
|
||||
CronJob *labelStructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
|
||||
EnvFrom *labelStructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
|
||||
ExchangeVolumes []*labelStructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
|
||||
ValuesFrom *labelStructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
|
||||
Dependencies []labelstructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
|
||||
ConfigMapFile *labelstructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
|
||||
MapEnv *labelstructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
|
||||
CronJob *labelstructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
|
||||
EnvFrom *labelstructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
|
||||
ExchangeVolumes []*labelstructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
|
||||
ValuesFrom *labelstructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -6,6 +6,8 @@
|
||||
import "katenary/generator/labels"
|
||||
```
|
||||
|
||||
Package labels provides functionality to parse and manipulate labels.
|
||||
|
||||
## Constants
|
||||
|
||||
<a name="KatenaryLabelPrefix"></a>
|
||||
@@ -15,16 +17,16 @@ const KatenaryLabelPrefix = "katenary.v3"
|
||||
```
|
||||
|
||||
<a name="GetLabelHelp"></a>
|
||||
## func [GetLabelHelp](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L87>)
|
||||
## func [GetLabelHelp](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L88>)
|
||||
|
||||
```go
|
||||
func GetLabelHelp(asMarkdown bool) string
|
||||
```
|
||||
|
||||
Generate the help for the labels.
|
||||
GetLabelHelp return the help for the labels.
|
||||
|
||||
<a name="GetLabelHelpFor"></a>
|
||||
## func [GetLabelHelpFor](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L96>)
|
||||
## func [GetLabelHelpFor](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L97>)
|
||||
|
||||
```go
|
||||
func GetLabelHelpFor(labelname string, asMarkdown bool) string
|
||||
@@ -33,7 +35,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string
|
||||
GetLabelHelpFor returns the help for a specific label.
|
||||
|
||||
<a name="GetLabelNames"></a>
|
||||
## func [GetLabelNames](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L71>)
|
||||
## func [GetLabelNames](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L72>)
|
||||
|
||||
```go
|
||||
func GetLabelNames() []string
|
||||
@@ -42,7 +44,7 @@ func GetLabelNames() []string
|
||||
GetLabelNames returns a sorted list of all katenary label names.
|
||||
|
||||
<a name="Prefix"></a>
|
||||
## func [Prefix](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L224>)
|
||||
## func [Prefix](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L235>)
|
||||
|
||||
```go
|
||||
func Prefix() string
|
||||
@@ -51,7 +53,7 @@ func Prefix() string
|
||||
|
||||
|
||||
<a name="Help"></a>
|
||||
## type [Help](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L63-L68>)
|
||||
## type [Help](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L64-L69>)
|
||||
|
||||
Help is the documentation of a label.
|
||||
|
||||
@@ -65,7 +67,7 @@ type Help struct {
|
||||
```
|
||||
|
||||
<a name="Label"></a>
|
||||
## type [Label](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L56>)
|
||||
## type [Label](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L57>)
|
||||
|
||||
Label is a katenary label to find in compose files.
|
||||
|
||||
@@ -97,7 +99,7 @@ const (
|
||||
```
|
||||
|
||||
<a name="LabelName"></a>
|
||||
### func [LabelName](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L58>)
|
||||
### func [LabelName](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L59>)
|
||||
|
||||
```go
|
||||
func LabelName(name string) Label
|
||||
|
246
doc/docs/packages/generator/labels/labelstructs.md
Normal file
246
doc/docs/packages/generator/labels/labelstructs.md
Normal file
@@ -0,0 +1,246 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# labelstructs
|
||||
|
||||
```go
|
||||
import "katenary/generator/labels/labelstructs"
|
||||
```
|
||||
|
||||
Package 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,omitempty" 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,omitempty" 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>)
|
@@ -6,7 +6,7 @@
|
||||
import "katenary/parser"
|
||||
```
|
||||
|
||||
Parser package is a wrapper around compose\-go to parse compose files.
|
||||
Package parser is a wrapper around compose\-go to parse compose files.
|
||||
|
||||
## func [Parse](<https://github.com/metal3d/katenary/blob/develop/parser/main.go#L29>)
|
||||
|
||||
|
@@ -1,60 +0,0 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# update
|
||||
|
||||
```go
|
||||
import "katenary/update"
|
||||
```
|
||||
|
||||
Update package is used to check if a new version of katenary is available.
|
||||
|
||||
## Variables
|
||||
|
||||
<a name="Version"></a>
|
||||
|
||||
```go
|
||||
var (
|
||||
Version = "master" // reset by cmd/main.go
|
||||
)
|
||||
```
|
||||
|
||||
<a name="DownloadFile"></a>
|
||||
## func [DownloadFile](<https://github.com/metal3d/katenary/blob/develop/update/main.go#L134>)
|
||||
|
||||
```go
|
||||
func DownloadFile(url, exe string) error
|
||||
```
|
||||
|
||||
DownloadFile will download a url to a local file. It also ensure that the file is executable.
|
||||
|
||||
<a name="DownloadLatestVersion"></a>
|
||||
## func [DownloadLatestVersion](<https://github.com/metal3d/katenary/blob/develop/update/main.go#L80>)
|
||||
|
||||
```go
|
||||
func DownloadLatestVersion(assets []Asset) error
|
||||
```
|
||||
|
||||
DownloadLatestVersion will download the latest version of katenary.
|
||||
|
||||
<a name="Asset"></a>
|
||||
## type [Asset](<https://github.com/metal3d/katenary/blob/develop/update/main.go#L23-L26>)
|
||||
|
||||
Asset is a github asset from release url.
|
||||
|
||||
```go
|
||||
type Asset struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"browser_download_url"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="CheckLatestVersion"></a>
|
||||
### func [CheckLatestVersion](<https://github.com/metal3d/katenary/blob/develop/update/main.go#L29>)
|
||||
|
||||
```go
|
||||
func CheckLatestVersion() (string, []Asset, error)
|
||||
```
|
||||
|
||||
CheckLatestVersion check katenary latest version from release and propose to download it
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
@@ -6,9 +6,18 @@
|
||||
import "katenary/utils"
|
||||
```
|
||||
|
||||
Utils package provides some utility functions used in katenary. It defines some constants and functions used in the whole project.
|
||||
Package utils provides some utility functions used in katenary. It defines some constants and functions used in the whole project.
|
||||
|
||||
## func [AsResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L191>)
|
||||
## Constants
|
||||
|
||||
<a name="DirectoryPermission"></a>DirectoryPermission is the default values for permissions apply to created directories.
|
||||
|
||||
```go
|
||||
const DirectoryPermission = 0o755
|
||||
```
|
||||
|
||||
<a name="AsResourceName"></a>
|
||||
## func [AsResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L196>)
|
||||
|
||||
```go
|
||||
func AsResourceName(name string) string
|
||||
@@ -17,7 +26,7 @@ func AsResourceName(name string) string
|
||||
AsResourceName returns a resource name with underscores to respect the kubernetes naming convention. It's the opposite of FixedResourceName.
|
||||
|
||||
<a name="Confirm"></a>
|
||||
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L161>)
|
||||
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L164>)
|
||||
|
||||
```go
|
||||
func Confirm(question string, icon ...Icon) bool
|
||||
@@ -26,7 +35,7 @@ func Confirm(question string, icon ...Icon) bool
|
||||
Confirm asks a question and returns true if the answer is y.
|
||||
|
||||
<a name="CountStartingSpaces"></a>
|
||||
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L38>)
|
||||
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L41>)
|
||||
|
||||
```go
|
||||
func CountStartingSpaces(line string) int
|
||||
@@ -35,7 +44,7 @@ func CountStartingSpaces(line string) int
|
||||
CountStartingSpaces counts the number of spaces at the beginning of a string.
|
||||
|
||||
<a name="EncodeBasicYaml"></a>
|
||||
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L173>)
|
||||
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L178>)
|
||||
|
||||
```go
|
||||
func EncodeBasicYaml(data any) ([]byte, error)
|
||||
@@ -44,7 +53,7 @@ func EncodeBasicYaml(data any) ([]byte, error)
|
||||
EncodeBasicYaml encodes a basic yaml from an interface.
|
||||
|
||||
<a name="FixedResourceName"></a>
|
||||
## func [FixedResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L185>)
|
||||
## func [FixedResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L190>)
|
||||
|
||||
```go
|
||||
func FixedResourceName(name string) string
|
||||
@@ -53,7 +62,7 @@ func FixedResourceName(name string) string
|
||||
FixedResourceName returns a resource name without underscores to respect the kubernetes naming convention.
|
||||
|
||||
<a name="GetContainerByName"></a>
|
||||
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L84>)
|
||||
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L87>)
|
||||
|
||||
```go
|
||||
func GetContainerByName(name string, containers []corev1.Container) (*corev1.Container, int)
|
||||
@@ -62,7 +71,7 @@ func GetContainerByName(name string, containers []corev1.Container) (*corev1.Con
|
||||
GetContainerByName returns a container by name and its index in the array. It returns nil, \-1 if not found.
|
||||
|
||||
<a name="GetKind"></a>
|
||||
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L51>)
|
||||
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L54>)
|
||||
|
||||
```go
|
||||
func GetKind(path string) (kind string)
|
||||
@@ -71,7 +80,7 @@ func GetKind(path string) (kind string)
|
||||
GetKind returns the kind of the resource from the file path.
|
||||
|
||||
<a name="GetServiceNameByPort"></a>
|
||||
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L74>)
|
||||
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L77>)
|
||||
|
||||
```go
|
||||
func GetServiceNameByPort(port int) string
|
||||
@@ -80,7 +89,7 @@ func GetServiceNameByPort(port int) string
|
||||
GetServiceNameByPort returns the service name for a port. It the service name is not found, it returns an empty string.
|
||||
|
||||
<a name="GetValuesFromLabel"></a>
|
||||
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L126>)
|
||||
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L129>)
|
||||
|
||||
```go
|
||||
func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[string]*EnvConfig
|
||||
@@ -98,7 +107,7 @@ func HashComposefiles(files []string) (string, error)
|
||||
HashComposefiles returns a hash of the compose files.
|
||||
|
||||
<a name="Int32Ptr"></a>
|
||||
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L32>)
|
||||
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L35>)
|
||||
|
||||
```go
|
||||
func Int32Ptr(i int32) *int32
|
||||
@@ -107,7 +116,7 @@ func Int32Ptr(i int32) *int32
|
||||
Int32Ptr returns a pointer to an int32.
|
||||
|
||||
<a name="PathToName"></a>
|
||||
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L103>)
|
||||
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L106>)
|
||||
|
||||
```go
|
||||
func PathToName(path string) string
|
||||
@@ -116,7 +125,7 @@ func PathToName(path string) string
|
||||
PathToName converts a path to a kubernetes complient name.
|
||||
|
||||
<a name="StrPtr"></a>
|
||||
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L35>)
|
||||
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L38>)
|
||||
|
||||
```go
|
||||
func StrPtr(s string) *string
|
||||
@@ -125,7 +134,7 @@ func StrPtr(s string) *string
|
||||
StrPtr returns a pointer to a string.
|
||||
|
||||
<a name="TplName"></a>
|
||||
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L19>)
|
||||
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L22>)
|
||||
|
||||
```go
|
||||
func TplName(serviceName, appname string, suffix ...string) string
|
||||
@@ -134,25 +143,25 @@ func TplName(serviceName, appname string, suffix ...string) string
|
||||
TplName returns the name of the kubernetes resource as a template string. It is used in the templates and defined in \_helper.tpl file.
|
||||
|
||||
<a name="TplValue"></a>
|
||||
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L94>)
|
||||
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L97>)
|
||||
|
||||
```go
|
||||
func TplValue(serviceName, variable string, pipes ...string) string
|
||||
```
|
||||
|
||||
GetContainerByName returns a container by name and its index in the array.
|
||||
TplValue returns a container by name and its index in the array.
|
||||
|
||||
<a name="Warn"></a>
|
||||
## func [Warn](<https://github.com/metal3d/katenary/blob/develop/utils/icons.go#L25>)
|
||||
|
||||
```go
|
||||
func Warn(msg ...interface{})
|
||||
func Warn(msg ...any)
|
||||
```
|
||||
|
||||
Warn prints a warning message
|
||||
|
||||
<a name="WordWrap"></a>
|
||||
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L156>)
|
||||
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L159>)
|
||||
|
||||
```go
|
||||
func WordWrap(text string, lineWidth int) string
|
||||
@@ -161,7 +170,7 @@ func WordWrap(text string, lineWidth int) string
|
||||
WordWrap wraps a string to a given line width. Warning: it may break the string. You need to check the result.
|
||||
|
||||
<a name="Wrap"></a>
|
||||
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L68>)
|
||||
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L71>)
|
||||
|
||||
```go
|
||||
func Wrap(src, above, below string) string
|
||||
@@ -170,7 +179,7 @@ func Wrap(src, above, below string) string
|
||||
Wrap wraps a string with a string above and below. It will respect the indentation of the src string.
|
||||
|
||||
<a name="EnvConfig"></a>
|
||||
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L120-L123>)
|
||||
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L123-L126>)
|
||||
|
||||
EnvConfig is a struct to hold the description of an environment variable.
|
||||
|
||||
|
@@ -54,7 +54,6 @@ nav:
|
||||
- Go Packages:
|
||||
- packages/cmd/katenary.md
|
||||
- packages/parser.md
|
||||
- packages/update.md
|
||||
- packages/utils.md
|
||||
- Generator:
|
||||
- Index: packages/generator.md
|
||||
|
@@ -3,11 +3,13 @@ package generator
|
||||
import (
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
@@ -42,12 +44,12 @@ type HelmChart struct {
|
||||
composeHash *string `yaml:"-"`
|
||||
Name string `yaml:"name"`
|
||||
Icon string `yaml:"icon,omitempty"`
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
APIVersion string `yaml:"apiVersion"`
|
||||
Version string `yaml:"version"`
|
||||
AppVersion string `yaml:"appVersion"`
|
||||
Description string `yaml:"description"`
|
||||
Helper string `yaml:"-"`
|
||||
Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
}
|
||||
|
||||
// NewChart creates a new empty chart with the given name.
|
||||
@@ -56,7 +58,7 @@ func NewChart(name string) *HelmChart {
|
||||
Name: name,
|
||||
Templates: make(map[string]*ChartTemplate, 0),
|
||||
Description: "A Helm chart for " + name,
|
||||
ApiVersion: "v2",
|
||||
APIVersion: "v2",
|
||||
Version: "",
|
||||
AppVersion: "", // set to 0.1.0 by default if no "main-app" label is found
|
||||
Values: map[string]any{
|
||||
@@ -93,7 +95,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
|
||||
}
|
||||
|
||||
servicename := template.Servicename
|
||||
if err := os.MkdirAll(filepath.Join(templateDir, servicename), 0o755); err != nil {
|
||||
if err := os.MkdirAll(filepath.Join(templateDir, servicename), utils.DirectoryPermission); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -101,7 +103,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
|
||||
// if the name is a path, create the directory
|
||||
if strings.Contains(name, string(filepath.Separator)) {
|
||||
name = filepath.Join(templateDir, name)
|
||||
err := os.MkdirAll(filepath.Dir(name), 0o755)
|
||||
err := os.MkdirAll(filepath.Dir(name), utils.DirectoryPermission)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
@@ -116,9 +118,11 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := f.Write(t); err != nil {
|
||||
log.Fatal("error writing template file:", err)
|
||||
}
|
||||
|
||||
f.Write(t)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +130,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
|
||||
func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) error {
|
||||
appName := chart.Name
|
||||
for _, s := range project.Services {
|
||||
if s.Environment == nil || len(s.Environment) == 0 {
|
||||
if len(s.Environment) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -134,12 +138,10 @@ func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) err
|
||||
secretsVar := types.MappingWithEquals{}
|
||||
|
||||
// copy env to originalEnv
|
||||
for k, v := range s.Environment {
|
||||
originalEnv[k] = v
|
||||
}
|
||||
maps.Copy(originalEnv, s.Environment)
|
||||
|
||||
if v, ok := s.Labels[labels.LabelSecrets]; ok {
|
||||
list, err := labelStructs.SecretsFrom(v)
|
||||
list, err := labelstructs.SecretsFrom(v)
|
||||
if err != nil {
|
||||
log.Fatal("error unmarshaling secrets label:", err)
|
||||
}
|
||||
@@ -212,7 +214,7 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme
|
||||
|
||||
if exchange, ok := service.Labels[labels.LabelExchangeVolume]; ok {
|
||||
// we need to add a volume and a mount point
|
||||
ex, err := labelStructs.NewExchangeVolumes(exchange)
|
||||
ex, err := labelstructs.NewExchangeVolumes(exchange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -296,7 +298,7 @@ func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string)
|
||||
func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) {
|
||||
// helm dependency
|
||||
if v, ok := service.Labels[labels.LabelDependencies]; ok {
|
||||
d, err := labelStructs.DependenciesFrom(v)
|
||||
d, err := labelstructs.DependenciesFrom(v)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -324,7 +326,7 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m
|
||||
if _, ok := service.Labels[labels.LabelEnvFrom]; !ok {
|
||||
return
|
||||
}
|
||||
fromservices, err := labelStructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
|
||||
fromservices, err := labelstructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
|
||||
if err != nil {
|
||||
log.Fatal("error unmarshaling env-from label:", err)
|
||||
}
|
||||
@@ -349,7 +351,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
|
||||
if _, ok := service.Labels[labels.LabelValueFrom]; !ok {
|
||||
return
|
||||
}
|
||||
mapping, err := labelStructs.GetValueFrom(service.Labels[labels.LabelValueFrom])
|
||||
mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValueFrom])
|
||||
if err != nil {
|
||||
log.Fatal("error unmarshaling values-from label:", err)
|
||||
}
|
||||
@@ -372,7 +374,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
|
||||
if dep == nil || target == nil {
|
||||
log.Fatalf("deployment %s or %s not found", depName[0], service.Name)
|
||||
}
|
||||
container, index := utils.GetContainerByName(target.service.Name, target.Spec.Template.Spec.Containers)
|
||||
container, index := utils.GetContainerByName(target.service.ContainerName, target.Spec.Template.Spec.Containers)
|
||||
if container == nil {
|
||||
log.Fatalf("Container %s not found", target.GetName())
|
||||
}
|
||||
@@ -381,13 +383,10 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
|
||||
|
||||
// is it a secret?
|
||||
isSecret := false
|
||||
secrets, err := labelStructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets])
|
||||
secrets, err := labelstructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets])
|
||||
if err == nil {
|
||||
for _, secret := range secrets {
|
||||
if secret == depName[1] {
|
||||
isSecret = true
|
||||
break
|
||||
}
|
||||
if slices.Contains(secrets, depName[1]) {
|
||||
isSecret = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ package generator
|
||||
import (
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"os"
|
||||
@@ -65,7 +65,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
||||
}
|
||||
|
||||
// get the secrets from the labels
|
||||
secrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
secrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
||||
// do not bind env variables to the configmap
|
||||
// remove the variables that are already defined in the environment
|
||||
if l, ok := service.Labels[labels.LabelMapEnv]; ok {
|
||||
envmap, err := labelStructs.MapEnvFrom(l)
|
||||
envmap, err := labelstructs.MapEnvFrom(l)
|
||||
if err != nil {
|
||||
log.Fatal("Error parsing map-env", err)
|
||||
}
|
||||
@@ -142,7 +142,9 @@ func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string
|
||||
// cumulate the path to the WorkingDir
|
||||
path = filepath.Join(service.WorkingDir, path)
|
||||
path = filepath.Clean(path)
|
||||
cm.AppendDir(path)
|
||||
if err := cm.AppendDir(path); err != nil {
|
||||
log.Fatal("Error adding files to configmap:", err)
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
@@ -159,13 +161,13 @@ func (c *ConfigMap) AddBinaryData(key string, value []byte) {
|
||||
c.BinaryData[key] = value
|
||||
}
|
||||
|
||||
// AddFile adds files from given path to the configmap. It is not recursive, to add all files in a directory,
|
||||
// AppendDir adds files from given path to the configmap. It is not recursive, to add all files in a directory,
|
||||
// you need to call this function for each subdirectory.
|
||||
func (c *ConfigMap) AppendDir(path string) error {
|
||||
// read all files in the path and add them to the configmap
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Path %s does not exist, %w\n", path, err)
|
||||
return fmt.Errorf("path %s does not exist, %w", path, err)
|
||||
}
|
||||
// recursively read all files in the path and add them to the configmap
|
||||
if stat.IsDir() {
|
||||
@@ -212,7 +214,7 @@ func (c *ConfigMap) AppendFile(path string) error {
|
||||
// read all files in the path and add them to the configmap
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Path %s doesn not exists, %w", path, err)
|
||||
return fmt.Errorf("path %s doesn not exists, %w", path, err)
|
||||
}
|
||||
// recursively read all files in the path and add them to the configmap
|
||||
if !stat.IsDir() {
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"katenary/generator/extrafiles"
|
||||
"katenary/generator/katenaryfile"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/parser"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
@@ -85,6 +85,12 @@ var unwantedLines = []string{
|
||||
"status:",
|
||||
}
|
||||
|
||||
var ingressTLSHelp = `# Ingress TLS configuration
|
||||
# If enabled, a secret containing the certificate and the key should be
|
||||
# created by the ingress controller. If the name if emtpy, so the secret
|
||||
# name is generated. You can specify the secret name to use your own secret.
|
||||
`
|
||||
|
||||
// keyRegExp checks if the line starts by a #
|
||||
var keyRegExp = regexp.MustCompile(`^\s*[^#]+:.*`)
|
||||
|
||||
@@ -107,7 +113,11 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
return err
|
||||
}
|
||||
defer os.Chdir(currentDir) // after the generation, go back to the original directory
|
||||
defer func() {
|
||||
if err := os.Chdir(currentDir); err != nil { // after the generation, go back to the original directory
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// repove the directory part of the docker-compose files
|
||||
for i, f := range dockerComposeFile {
|
||||
@@ -163,9 +173,8 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
|
||||
os.RemoveAll(config.OutputDir)
|
||||
|
||||
// create the chart directory
|
||||
if err := os.MkdirAll(templateDir, 0o755); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
if err := os.MkdirAll(templateDir, utils.DirectoryPermission); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add icon from the command line
|
||||
@@ -249,7 +258,7 @@ func addCommentsToValues(values []byte) []byte {
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func addDependencyDescription(values []byte, dependencies []labelStructs.Dependency) []byte {
|
||||
func addDependencyDescription(values []byte, dependencies []labelstructs.Dependency) []byte {
|
||||
for _, d := range dependencies {
|
||||
name := d.Name
|
||||
if d.Alias != "" {
|
||||
@@ -486,6 +495,24 @@ func addYAMLSelectorPath(values []byte) []byte {
|
||||
return []byte(strings.Join(toReturn, "\n"))
|
||||
}
|
||||
|
||||
// addTLSHelp adds a comment to the values.yaml file to explain how to
|
||||
// use the tls option.
|
||||
func addTLSHelp(values []byte) []byte {
|
||||
lines := strings.Split(string(values), "\n")
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, "tls:") {
|
||||
spaces := utils.CountStartingSpaces(line)
|
||||
spacesString := strings.Repeat(" ", spaces)
|
||||
// indent ingressClassHelper comment
|
||||
ingressTLSHelp := strings.ReplaceAll(ingressTLSHelp, "\n", "\n"+spacesString)
|
||||
ingressTLSHelp = strings.TrimRight(ingressTLSHelp, " ")
|
||||
ingressTLSHelp = spacesString + ingressTLSHelp
|
||||
lines[i] = ingressTLSHelp + line
|
||||
}
|
||||
}
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func buildCharYamlFile(chart *HelmChart, project *types.Project, chartPath string) {
|
||||
// calculate the sha1 hash of the services
|
||||
yamlChart, err := utils.EncodeBasicYaml(chart)
|
||||
@@ -494,16 +521,16 @@ func buildCharYamlFile(chart *HelmChart, project *types.Project, chartPath strin
|
||||
os.Exit(1)
|
||||
}
|
||||
// concat chart adding a comment with hash of services on top
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose hash (sha1): %s\n", *chart.composeHash)), yamlChart...)
|
||||
yamlChart = append(fmt.Appendf(nil, "# compose hash (sha1): %s\n", *chart.composeHash), yamlChart...)
|
||||
// add the list of compose files
|
||||
files := []string{}
|
||||
for _, file := range project.ComposeFiles {
|
||||
base := filepath.Base(file)
|
||||
files = append(files, base)
|
||||
}
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose files: %s\n", strings.Join(files, ", "))), yamlChart...)
|
||||
yamlChart = append(fmt.Appendf(nil, "# compose files: %s\n", strings.Join(files, ", ")), yamlChart...)
|
||||
// add generated date
|
||||
yamlChart = append([]byte(fmt.Sprintf("# generated at: %s\n", time.Now().Format(time.RFC3339))), yamlChart...)
|
||||
yamlChart = append(fmt.Appendf(nil, "# generated at: %s\n", time.Now().Format(time.RFC3339)), yamlChart...)
|
||||
|
||||
// document Chart.yaml file
|
||||
yamlChart = addChartDoc(yamlChart, project)
|
||||
@@ -537,6 +564,7 @@ func buildValues(chart *HelmChart, project *types.Project, valuesPath string) {
|
||||
values = addVariablesDoc(values, project)
|
||||
values = addMainTagAppDoc(values, project)
|
||||
values = addResourceHelp(values)
|
||||
values = addTLSHelp(values)
|
||||
values = addYAMLSelectorPath(values)
|
||||
values = append([]byte(headerHelp), values...)
|
||||
|
||||
@@ -602,7 +630,11 @@ func writeContent(path string, content []byte) {
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(content)
|
||||
defer func() {
|
||||
if _, err := f.Write(content); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// helmLint runs "helm lint" on the output directory.
|
||||
|
@@ -2,7 +2,7 @@ package generator
|
||||
|
||||
import (
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"strings"
|
||||
@@ -30,7 +30,7 @@ func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
mapping, err := labelStructs.CronJobFrom(labels)
|
||||
mapping, err := labelstructs.CronJobFrom(labels)
|
||||
if err != nil {
|
||||
log.Fatalf("Error parsing cronjob labels: %s", err)
|
||||
return nil, nil
|
||||
|
@@ -3,7 +3,7 @@ package generator
|
||||
import (
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"os"
|
||||
@@ -39,7 +39,7 @@ type Deployment struct {
|
||||
service *types.ServiceConfig `yaml:"-"`
|
||||
defaultTag string `yaml:"-"`
|
||||
isMainApp bool `yaml:"-"`
|
||||
exchangesVolumes map[string]*labelStructs.ExchangeVolume `yaml:"-"`
|
||||
exchangesVolumes map[string]*labelstructs.ExchangeVolume `yaml:"-"`
|
||||
boundEnvVar []string `yaml:"-"` // environement to remove
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
|
||||
},
|
||||
configMaps: make(map[string]*ConfigMapMount),
|
||||
volumeMap: make(map[string]string),
|
||||
exchangesVolumes: map[string]*labelStructs.ExchangeVolume{},
|
||||
exchangesVolumes: map[string]*labelstructs.ExchangeVolume{},
|
||||
boundEnvVar: []string{},
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
|
||||
Image: utils.TplValue(service.Name, "repository.image") + ":" +
|
||||
utils.TplValue(service.Name, "repository.tag", d.defaultTag),
|
||||
Ports: ports,
|
||||
Name: service.Name,
|
||||
Name: service.ContainerName,
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{},
|
||||
@@ -160,7 +160,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
|
||||
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
|
||||
// get the label for healthcheck
|
||||
if v, ok := service.Labels[labels.LabelHealthCheck]; ok {
|
||||
probes, err := labelStructs.ProbeFrom(v)
|
||||
probes, err := labelstructs.ProbeFrom(v)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *In
|
||||
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
||||
tobind := map[string]bool{}
|
||||
if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok {
|
||||
binds, err := labelStructs.ConfigMapFileFrom(v)
|
||||
binds, err := labelstructs.ConfigMapFileFrom(v)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -253,8 +253,8 @@ func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) {
|
||||
// get the container
|
||||
}
|
||||
// add volume mount to the container
|
||||
targetContainer, ti := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
||||
sourceContainer, _ := utils.GetContainerByName(service.Name, binded.Spec.Template.Spec.Containers)
|
||||
targetContainer, ti := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
|
||||
sourceContainer, _ := utils.GetContainerByName(service.ContainerName, binded.Spec.Template.Spec.Containers)
|
||||
for _, bindedMount := range sourceContainer.VolumeMounts {
|
||||
if bindedMount.Name == bindedVolume.Name {
|
||||
targetContainer.VolumeMounts = append(targetContainer.VolumeMounts, bindedMount)
|
||||
@@ -305,10 +305,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
if len(service.Environment) == 0 {
|
||||
return
|
||||
}
|
||||
inSamePod := false
|
||||
if len(samePod) > 0 && samePod[0] {
|
||||
inSamePod = true
|
||||
}
|
||||
inSamePod := len(samePod) > 0 && samePod[0]
|
||||
|
||||
drop := []string{}
|
||||
secrets := []string{}
|
||||
@@ -323,7 +320,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
}()
|
||||
|
||||
// secrets from label
|
||||
labelSecrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
labelSecrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -411,7 +408,7 @@ func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secret
|
||||
})
|
||||
}
|
||||
|
||||
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
||||
container, index := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
|
||||
if container == nil {
|
||||
utils.Warn("Container not found for service " + service.Name)
|
||||
return nil, -1
|
||||
@@ -660,11 +657,13 @@ func (d *Deployment) appendFileToConfigMap(service types.ServiceConfig, appName
|
||||
d.configMaps[pathname].mountPath = mp
|
||||
|
||||
}
|
||||
cm.AppendFile(volume.Source)
|
||||
if err := cm.AppendFile(volume.Source); err != nil {
|
||||
log.Fatal("Error adding file to configmap:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod bool, tobind map[string]bool, service types.ServiceConfig, appName string) {
|
||||
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
||||
container, index := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
|
||||
|
||||
defer func(d *Deployment, container *corev1.Container, index int) {
|
||||
d.Spec.Template.Spec.Containers[index] = *container
|
||||
|
@@ -4,8 +4,10 @@ import (
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
yaml3 "gopkg.in/yaml.v3"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
@@ -324,14 +326,172 @@ services:
|
||||
Environment map[string]string `yaml:"environment"`
|
||||
} `yaml:"web"`
|
||||
}{}
|
||||
if err := yaml.Unmarshal(valuesContent, &mapping); err != nil {
|
||||
if err := yaml3.Unmarshal(valuesContent, &mapping); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
if _, ok := mapping.Web.Environment["FOO"]; !ok {
|
||||
if v, ok := mapping.Web.Environment["FOO"]; !ok {
|
||||
t.Errorf("Expected FOO in web environment")
|
||||
if v != "bar" {
|
||||
t.Errorf("Expected FOO to be bar, got %s", v)
|
||||
}
|
||||
}
|
||||
if _, ok := mapping.Web.Environment["BAZ"]; ok {
|
||||
if v, ok := mapping.Web.Environment["BAZ"]; ok {
|
||||
t.Errorf("Expected BAZ not in web environment")
|
||||
if v != "qux" {
|
||||
t.Errorf("Expected BAZ to be qux, got %s", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithUnderscoreInContainerName(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web-app:
|
||||
image: nginx:1.29
|
||||
container_name: web_app_container
|
||||
environment:
|
||||
FOO: BAR
|
||||
labels:
|
||||
%s/values: |
|
||||
- FOO
|
||||
`
|
||||
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web_app/deployment.yaml")
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
// find container.name
|
||||
containerName := dt.Spec.Template.Spec.Containers[0].Name
|
||||
if strings.Contains(containerName, "_") {
|
||||
t.Errorf("Expected container name to not contain underscores, got %s", containerName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithDashes(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web-app:
|
||||
image: nginx:1.29
|
||||
environment:
|
||||
FOO: BAR
|
||||
labels:
|
||||
%s/values: |
|
||||
- FOO
|
||||
`
|
||||
|
||||
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web_app/deployment.yaml")
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
valuesFile := "./chart/values.yaml"
|
||||
if _, err := os.Stat(valuesFile); os.IsNotExist(err) {
|
||||
t.Errorf("values.yaml does not exist")
|
||||
}
|
||||
valuesContent, err := os.ReadFile(valuesFile)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading values.yaml: %s", err)
|
||||
}
|
||||
mapping := struct {
|
||||
Web struct {
|
||||
Environment map[string]string `yaml:"environment"`
|
||||
} `yaml:"web_app"`
|
||||
}{}
|
||||
if err := yaml3.Unmarshal(valuesContent, &mapping); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
// we must have FOO in web_app environment (not web-app)
|
||||
// this validates that the service name is converted to a valid k8s name
|
||||
if v, ok := mapping.Web.Environment["FOO"]; !ok {
|
||||
t.Errorf("Expected FOO in web_app environment")
|
||||
if v != "BAR" {
|
||||
t.Errorf("Expected FOO to be BAR, got %s", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDashesWithValueFrom(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web-app:
|
||||
image: nginx:1.29
|
||||
environment:
|
||||
FOO: BAR
|
||||
labels:
|
||||
%[1]s/values: |
|
||||
- FOO
|
||||
web2:
|
||||
image: nginx:1.29
|
||||
labels:
|
||||
%[1]s/values-from: |
|
||||
BAR: web-app.FOO
|
||||
`
|
||||
|
||||
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web2/deployment.yaml")
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
valuesFile := "./chart/values.yaml"
|
||||
if _, err := os.Stat(valuesFile); os.IsNotExist(err) {
|
||||
t.Errorf("values.yaml does not exist")
|
||||
}
|
||||
valuesContent, err := os.ReadFile(valuesFile)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading values.yaml: %s", err)
|
||||
}
|
||||
mapping := struct {
|
||||
Web struct {
|
||||
Environment map[string]string `yaml:"environment"`
|
||||
} `yaml:"web_app"`
|
||||
}{}
|
||||
if err := yaml3.Unmarshal(valuesContent, &mapping); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
// we must have FOO in web_app environment (not web-app)
|
||||
// this validates that the service name is converted to a valid k8s name
|
||||
if v, ok := mapping.Web.Environment["FOO"]; !ok {
|
||||
t.Errorf("Expected FOO in web_app environment")
|
||||
if v != "BAR" {
|
||||
t.Errorf("Expected FOO to be BAR, got %s", v)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the deployment has the value from the other service
|
||||
barenv := dt.Spec.Template.Spec.Containers[0].Env[0]
|
||||
if barenv.Value != "" {
|
||||
t.Errorf("Expected value to be empty")
|
||||
}
|
||||
if barenv.ValueFrom == nil {
|
||||
t.Errorf("Expected valueFrom to be set")
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,17 @@
|
||||
/*
|
||||
The generator package generates kubernetes objects from a "compose" file and transforms them into a helm chart.
|
||||
Package generator generates kubernetes objects from a "compose" file and transforms them into a helm chart.
|
||||
|
||||
The generator package is the core of katenary. It is responsible for generating kubernetes objects from a compose file and transforming them into a helm chart.
|
||||
Conversion manipulates Yaml representation of kubernetes object to add conditions, labels, annotations, etc. to the objects. It also create the values to be set to
|
||||
the values.yaml file.
|
||||
The generator package is the core of katenary. It is responsible for generating kubernetes objects from a compose file
|
||||
and transforming them into a helm chart.
|
||||
Conversion manipulates Yaml representation of kubernetes object to add conditions, labels, annotations, etc. to the
|
||||
objects. It also create the values to be set to the values.yaml file.
|
||||
|
||||
The generate.Convert() create an HelmChart object and call "Generate()" method to convert from a compose file to a helm chart.
|
||||
It saves the helm chart in the given directory.
|
||||
The generate.Convert() create an HelmChart object and call "Generate()" method to convert from a compose file to a helm
|
||||
chart. It saves the helm chart in the given directory.
|
||||
|
||||
If you want to change or override the write behavior, you can use the HelmChart.Generate() function and implement your own write function. This function returns
|
||||
the helm chart object containing all kubernetes objects and helm chart ingormation. It does not write the helm chart to the disk.
|
||||
If you want to change or override the write behavior, you can use the HelmChart.Generate() function and implement your
|
||||
own write function. This function returns
|
||||
the helm chart object containing all kubernetes objects and helm chart ingormation. It does not write the helm chart to
|
||||
the disk.
|
||||
*/
|
||||
package generator
|
||||
|
@@ -1,2 +1,2 @@
|
||||
/* extrafiles package provides function to generate the Chart files that are not objects. Like README.md and notes.txt... */
|
||||
/* Package extrafiles provides function to generate the Chart files that are not objects. Like README.md and notes.txt... */
|
||||
package extrafiles
|
||||
|
40
generator/extrafiles/notes_test.go
Normal file
40
generator/extrafiles/notes_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// override the embedded template for testing
|
||||
var testTemplate = `
|
||||
Some header
|
||||
{{ ingress_list }}
|
||||
Some footer
|
||||
`
|
||||
|
||||
func init() {
|
||||
notesTemplate = testTemplate
|
||||
}
|
||||
|
||||
func TestNotesFile_NoServices(t *testing.T) {
|
||||
result := NotesFile([]string{})
|
||||
if !strings.Contains(result, "Some header") || !strings.Contains(result, "Some footer") {
|
||||
t.Errorf("Expected template header/footer in output, got: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotesFile_WithServices(t *testing.T) {
|
||||
services := []string{"svc1", "svc2"}
|
||||
result := NotesFile(services)
|
||||
|
||||
for _, svc := range services {
|
||||
cond := "{{- if and .Values." + svc + ".ingress .Values." + svc + ".ingress.enabled }}"
|
||||
line := "{{- $count = add1 $count -}}{{- $listOfURL = printf \"%s\\n- http://%s\" $listOfURL (tpl .Values." + svc + ".ingress.host .) -}}"
|
||||
if !strings.Contains(result, cond) {
|
||||
t.Errorf("Expected condition for service %s in output", svc)
|
||||
}
|
||||
if !strings.Contains(result, line) {
|
||||
t.Errorf("Expected line for service %s in output", svc)
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
@@ -20,7 +21,7 @@ type chart struct {
|
||||
Values []string
|
||||
}
|
||||
|
||||
func parseValues(prefix string, values map[string]interface{}, result map[string]string) {
|
||||
func parseValues(prefix string, values map[string]any, result map[string]string) {
|
||||
for key, value := range values {
|
||||
path := key
|
||||
if prefix != "" {
|
||||
@@ -28,11 +29,11 @@ func parseValues(prefix string, values map[string]interface{}, result map[string
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case []interface{}:
|
||||
case []any:
|
||||
for i, u := range v {
|
||||
parseValues(fmt.Sprintf("%s[%d]", path, i), map[string]interface{}{"value": u}, result)
|
||||
parseValues(fmt.Sprintf("%s[%d]", path, i), map[string]any{"value": u}, result)
|
||||
}
|
||||
case map[string]interface{}:
|
||||
case map[string]any:
|
||||
parseValues(path, v, result)
|
||||
default:
|
||||
strValue := fmt.Sprintf("`%v`", value)
|
||||
@@ -48,7 +49,9 @@ func ReadMeFile(charname, description string, values map[string]any) string {
|
||||
|
||||
vv := map[string]any{}
|
||||
out, _ := yaml.Marshal(values)
|
||||
yaml.Unmarshal(out, &vv)
|
||||
if err := yaml.Unmarshal(out, &vv); err != nil {
|
||||
log.Printf("Error parsing values: %s", err)
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
parseValues("", vv, result)
|
||||
|
33
generator/extrafiles/readme_test.go
Normal file
33
generator/extrafiles/readme_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadMeFile_Basic(t *testing.T) {
|
||||
values := map[string]any{
|
||||
"replicas": 2,
|
||||
"image": map[string]any{
|
||||
"repository": "nginx",
|
||||
"tag": "latest",
|
||||
},
|
||||
}
|
||||
|
||||
result := ReadMeFile("testchart", "A test chart", values)
|
||||
t.Logf("Generated README content:\n%s", result)
|
||||
paramerRegExp := regexp.MustCompile(`\|\s+` + "`" + `(.*?)` + "`" + `\s+\|\s+` + "`" + `(.*?)` + "`" + `\s+\|`)
|
||||
matches := paramerRegExp.FindAllStringSubmatch(result, -1)
|
||||
if len(matches) != 3 {
|
||||
t.Errorf("Expected 5 lines in the table for headers and parameters, got %d", len(matches))
|
||||
}
|
||||
if matches[0][1] != "image.repository" || matches[0][2] != "nginx" {
|
||||
t.Errorf("Expected third line to be image.repository, got %s", matches[1])
|
||||
}
|
||||
if matches[1][1] != "image.tag" || matches[1][2] != "latest" {
|
||||
t.Errorf("Expected fourth line to be image.tag, got %s", matches[2])
|
||||
}
|
||||
if matches[2][1] != "replicas" || matches[2][2] != "2" {
|
||||
t.Errorf("Expected second line to be replicas, got %s", matches[0])
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"regexp"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// Generate a chart from a compose project.
|
||||
@@ -43,6 +45,16 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
Annotations[labels.LabelName("compose-hash")] = hash
|
||||
chart.composeHash = &hash
|
||||
|
||||
// drop all services with the "ignore" label
|
||||
dropIngoredServices(project)
|
||||
|
||||
fixContainerNames(project)
|
||||
|
||||
// rename all services name to remove dashes
|
||||
if err := fixResourceNames(project); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// find the "main-app" label, and set chart.AppVersion to the tag if exists
|
||||
mainCount := 0
|
||||
for _, service := range project.Services {
|
||||
@@ -107,7 +119,10 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
for _, s := range project.Services {
|
||||
for _, d := range s.GetDependencies() {
|
||||
if dep, ok := deployments[d]; ok {
|
||||
deployments[s.Name].DependsOn(dep, d)
|
||||
err := deployments[s.Name].DependsOn(dep, d)
|
||||
if err != nil {
|
||||
log.Printf("error creating init container for service %[1]s: %[2]s", s.Name, err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("service %[1]s depends on %[2]s, but %[2]s is not defined", s.Name, d)
|
||||
}
|
||||
@@ -119,7 +134,9 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
}
|
||||
|
||||
// generate configmaps with environment variables
|
||||
chart.generateConfigMapsAndSecrets(project)
|
||||
if err := chart.generateConfigMapsAndSecrets(project); err != nil {
|
||||
log.Fatalf("error generating configmaps and secrets: %s", err)
|
||||
}
|
||||
|
||||
// if the env-from label is set, we need to add the env vars from the configmap
|
||||
// to the environment of the service
|
||||
@@ -187,6 +204,52 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
return chart, nil
|
||||
}
|
||||
|
||||
// dropIngoredServices removes all services with the "ignore" label set to true (or yes).
|
||||
func dropIngoredServices(project *types.Project) {
|
||||
for i, service := range project.Services {
|
||||
if isIgnored(service) {
|
||||
project.Services = append(project.Services[:i], project.Services[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fixResourceNames renames all services and related resources to remove dashes.
|
||||
func fixResourceNames(project *types.Project) error {
|
||||
// rename all services name to remove dashes
|
||||
for i, service := range project.Services {
|
||||
if service.Name != utils.AsResourceName(service.Name) {
|
||||
fixed := utils.AsResourceName(service.Name)
|
||||
for j, s := range project.Services {
|
||||
// for the same-pod services, we need to keep the original name
|
||||
if samepod, ok := s.Labels[labels.LabelSamePod]; ok && samepod == service.Name {
|
||||
s.Labels[labels.LabelSamePod] = fixed
|
||||
project.Services[j] = s
|
||||
}
|
||||
// also, the value-from label should be updated
|
||||
if valuefrom, ok := s.Labels[labels.LabelValueFrom]; ok {
|
||||
vf, err := labelstructs.GetValueFrom(valuefrom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for varname, bind := range *vf {
|
||||
log.Printf("service %s, varname %s, bind %s", service.Name, varname, bind)
|
||||
bind := strings.ReplaceAll(bind, service.Name, fixed)
|
||||
(*vf)[varname] = bind
|
||||
}
|
||||
output, err := yaml.Marshal(vf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Labels[labels.LabelValueFrom] = string(output)
|
||||
}
|
||||
}
|
||||
service.Name = fixed
|
||||
project.Services[i] = service
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// serviceIsMain returns true if the service is the main app.
|
||||
func serviceIsMain(service types.ServiceConfig) bool {
|
||||
if main, ok := service.Labels[labels.LabelMainApp]; ok {
|
||||
@@ -204,7 +267,7 @@ func addStaticVolumes(deployments map[string]*Deployment, service types.ServiceC
|
||||
return
|
||||
}
|
||||
|
||||
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
||||
container, index := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
|
||||
if container == nil { // may append for the same-pod services
|
||||
return
|
||||
}
|
||||
@@ -256,7 +319,7 @@ func computeNIndent(b []byte) []byte {
|
||||
startSpaces = spaces[0]
|
||||
}
|
||||
line = []byte(startSpaces + strings.TrimLeft(string(line), " "))
|
||||
line = bytes.ReplaceAll(line, []byte("__indent__"), []byte(fmt.Sprintf("%d", len(startSpaces))))
|
||||
line = bytes.ReplaceAll(line, []byte("__indent__"), fmt.Appendf(nil, "%d", len(startSpaces)))
|
||||
lines[i] = line
|
||||
}
|
||||
return bytes.Join(lines, []byte("\n"))
|
||||
@@ -329,7 +392,7 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
|
||||
return false
|
||||
}
|
||||
|
||||
if service.Volumes == nil || len(service.Volumes) == 0 {
|
||||
if len(service.Volumes) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -355,3 +418,15 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func fixContainerNames(project *types.Project) {
|
||||
// fix container names to be unique
|
||||
for i, service := range project.Services {
|
||||
if service.ContainerName == "" {
|
||||
service.ContainerName = utils.FixedResourceName(service.Name)
|
||||
} else {
|
||||
service.ContainerName = utils.FixedResourceName(service.ContainerName)
|
||||
}
|
||||
project.Services[i] = service
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ package generator
|
||||
|
||||
import (
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"strings"
|
||||
@@ -17,6 +17,7 @@ var _ Yaml = (*Ingress)(nil)
|
||||
type Ingress struct {
|
||||
*networkv1.Ingress
|
||||
service *types.ServiceConfig `yaml:"-"`
|
||||
appName string `yaml:"-"`
|
||||
}
|
||||
|
||||
// NewIngress creates a new Ingress from a compose service.
|
||||
@@ -32,7 +33,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
return nil
|
||||
}
|
||||
|
||||
mapping, err := labelStructs.IngressFrom(label)
|
||||
mapping, err := labelstructs.IngressFrom(label)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse ingress label: %s\n", err)
|
||||
}
|
||||
@@ -42,7 +43,11 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
|
||||
// create the ingress
|
||||
pathType := networkv1.PathTypeImplementationSpecific
|
||||
serviceName := `{{ include "` + appName + `.fullname" . }}-` + service.Name
|
||||
|
||||
// fix the service name, and create the full name from variable name
|
||||
// which is injected in the YAML() method
|
||||
serviceName := strings.ReplaceAll(service.Name, "_", "-")
|
||||
fullName := `{{ $fullname }}-` + serviceName
|
||||
|
||||
// Add the ingress host to the values.yaml
|
||||
if Chart.Values[service.Name] == nil {
|
||||
@@ -63,7 +68,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
|
||||
servicePortName := utils.GetServiceNameByPort(int(*mapping.Port))
|
||||
ingressService := &networkv1.IngressServiceBackend{
|
||||
Name: serviceName,
|
||||
Name: fullName,
|
||||
Port: networkv1.ServiceBackendPort{},
|
||||
}
|
||||
if servicePortName != "" {
|
||||
@@ -74,26 +79,27 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
|
||||
ing := &Ingress{
|
||||
service: &service,
|
||||
appName: appName,
|
||||
Ingress: &networkv1.Ingress{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Ingress",
|
||||
APIVersion: "networking.k8s.io/v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: utils.TplName(service.Name, appName),
|
||||
Labels: GetLabels(service.Name, appName),
|
||||
Name: fullName,
|
||||
Labels: GetLabels(serviceName, appName),
|
||||
Annotations: Annotations,
|
||||
},
|
||||
Spec: networkv1.IngressSpec{
|
||||
IngressClassName: &ingressClassName,
|
||||
Rules: []networkv1.IngressRule{
|
||||
{
|
||||
Host: utils.TplValue(service.Name, "ingress.host"),
|
||||
Host: utils.TplValue(serviceName, "ingress.host"),
|
||||
IngressRuleValue: networkv1.IngressRuleValue{
|
||||
HTTP: &networkv1.HTTPIngressRuleValue{
|
||||
Paths: []networkv1.HTTPIngressPath{
|
||||
{
|
||||
Path: utils.TplValue(service.Name, "ingress.path"),
|
||||
Path: utils.TplValue(serviceName, "ingress.path"),
|
||||
PathType: &pathType,
|
||||
Backend: networkv1.IngressBackend{
|
||||
Service: ingressService,
|
||||
@@ -107,9 +113,9 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
TLS: []networkv1.IngressTLS{
|
||||
{
|
||||
Hosts: []string{
|
||||
`{{ tpl .Values.` + service.Name + `.ingress.host . }}`,
|
||||
`{{ tpl .Values.` + serviceName + `.ingress.host . }}`,
|
||||
},
|
||||
SecretName: `{{ include "` + appName + `.fullname" . }}-` + service.Name + `-tls`,
|
||||
SecretName: `{{ .Values.` + serviceName + `.ingress.tls.secretName | default $tlsname }}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -131,9 +137,7 @@ func (ingress *Ingress) Yaml() ([]byte, error) {
|
||||
}
|
||||
|
||||
serviceName := ingress.service.Name
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = UnWrapTPL(ret)
|
||||
|
||||
lines := strings.Split(string(ret), "\n")
|
||||
@@ -141,9 +145,7 @@ func (ingress *Ingress) Yaml() ([]byte, error) {
|
||||
// first pass, wrap the tls part with `{{- if .Values.serviceName.ingress.tlsEnabled -}}`
|
||||
// and `{{- end -}}`
|
||||
|
||||
from := -1
|
||||
to := -1
|
||||
spaces := -1
|
||||
from, to, spaces := -1, -1, -1
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, "tls:") {
|
||||
from = i
|
||||
@@ -167,6 +169,8 @@ func (ingress *Ingress) Yaml() ([]byte, error) {
|
||||
|
||||
out := []string{
|
||||
`{{- if .Values.` + serviceName + `.ingress.enabled -}}`,
|
||||
`{{- $fullname := include "` + ingress.appName + `.fullname" . -}}`,
|
||||
`{{- $tlsname := printf "%s-%s-tls" $fullname "` + ingress.service.Name + `" -}}`,
|
||||
}
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "loadBalancer: ") {
|
||||
|
@@ -31,7 +31,11 @@ services:
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web/ingress.yaml", "--set", "web.ingress.enabled=true")
|
||||
output := internalCompileTest(
|
||||
t,
|
||||
"-s", "templates/web/ingress.yaml",
|
||||
"--set", "web.ingress.enabled=true",
|
||||
)
|
||||
ingress := v1.Ingress{}
|
||||
if err := yaml.Unmarshal([]byte(output), &ingress); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -43,3 +47,82 @@ services:
|
||||
t.Errorf("Expected host to be my.test.tld, got %s", ingress.Spec.Rules[0].Host)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
labels:
|
||||
%s/ingress: |-
|
||||
hostname: my.test.tld
|
||||
port: 80
|
||||
`
|
||||
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(
|
||||
t,
|
||||
"-s", "templates/web/ingress.yaml",
|
||||
"--set", "web.ingress.enabled=true",
|
||||
)
|
||||
ingress := v1.Ingress{}
|
||||
if err := yaml.Unmarshal([]byte(output), &ingress); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
// find the tls section
|
||||
tls := ingress.Spec.TLS
|
||||
if len(tls) != 1 {
|
||||
t.Errorf("Expected 1 tls section, got %d", len(tls))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSName(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
labels:
|
||||
%s/ingress: |-
|
||||
hostname: my.test.tld
|
||||
port: 80
|
||||
`
|
||||
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(
|
||||
t,
|
||||
"-s",
|
||||
"templates/web/ingress.yaml",
|
||||
"--set", "web.ingress.enabled=true",
|
||||
"--set", "web.ingress.tls.secretName=mysecret",
|
||||
)
|
||||
ingress := v1.Ingress{}
|
||||
if err := yaml.Unmarshal([]byte(output), &ingress); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
// find the tls section
|
||||
tls := ingress.Spec.TLS
|
||||
if len(tls) != 1 {
|
||||
t.Errorf("Expected 1 tls section, got %d", len(tls))
|
||||
}
|
||||
if tls[0].SecretName != "mysecret" {
|
||||
t.Errorf("Expected secretName to be mysecret, got %s", tls[0].SecretName)
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"os"
|
||||
@@ -27,20 +27,20 @@ type StringOrMap any
|
||||
type Service struct {
|
||||
MainApp *bool `json:"main-app,omitempty" jsonschema:"title=Is this service the main application"`
|
||||
Values []StringOrMap `json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"`
|
||||
Secrets *labelStructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
|
||||
Ports *labelStructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
|
||||
Ingress *labelStructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
|
||||
HealthCheck *labelStructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
|
||||
Secrets *labelstructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
|
||||
Ports *labelstructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
|
||||
Ingress *labelstructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
|
||||
HealthCheck *labelstructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
|
||||
SamePod *string `json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"`
|
||||
Description *string `json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"`
|
||||
Ignore *bool `json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"`
|
||||
Dependencies []labelStructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
|
||||
ConfigMapFile *labelStructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
|
||||
MapEnv *labelStructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
|
||||
CronJob *labelStructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
|
||||
EnvFrom *labelStructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
|
||||
ExchangeVolumes []*labelStructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
|
||||
ValuesFrom *labelStructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
|
||||
Dependencies []labelstructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
|
||||
ConfigMapFile *labelstructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
|
||||
MapEnv *labelstructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
|
||||
CronJob *labelstructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
|
||||
EnvFrom *labelstructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
|
||||
ExchangeVolumes []*labelstructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
|
||||
ValuesFrom *labelstructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
|
||||
}
|
||||
|
||||
// OverrideWithConfig overrides the project with the katenary.yaml file. It
|
||||
@@ -75,24 +75,30 @@ func OverrideWithConfig(project *types.Project) {
|
||||
if project.Services[i].Labels == nil {
|
||||
project.Services[i].Labels = make(map[string]string)
|
||||
}
|
||||
mustGetLabelContent := func(o any, s *types.ServiceConfig, labelName string) {
|
||||
err := getLabelContent(o, s, labelName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if s, ok := services[name]; ok {
|
||||
getLabelContent(s.MainApp, &project.Services[i], labels.LabelMainApp)
|
||||
getLabelContent(s.Values, &project.Services[i], labels.LabelValues)
|
||||
getLabelContent(s.Secrets, &project.Services[i], labels.LabelSecrets)
|
||||
getLabelContent(s.Ports, &project.Services[i], labels.LabelPorts)
|
||||
getLabelContent(s.Ingress, &project.Services[i], labels.LabelIngress)
|
||||
getLabelContent(s.HealthCheck, &project.Services[i], labels.LabelHealthCheck)
|
||||
getLabelContent(s.SamePod, &project.Services[i], labels.LabelSamePod)
|
||||
getLabelContent(s.Description, &project.Services[i], labels.LabelDescription)
|
||||
getLabelContent(s.Ignore, &project.Services[i], labels.LabelIgnore)
|
||||
getLabelContent(s.Dependencies, &project.Services[i], labels.LabelDependencies)
|
||||
getLabelContent(s.ConfigMapFile, &project.Services[i], labels.LabelConfigMapFiles)
|
||||
getLabelContent(s.MapEnv, &project.Services[i], labels.LabelMapEnv)
|
||||
getLabelContent(s.CronJob, &project.Services[i], labels.LabelCronJob)
|
||||
getLabelContent(s.EnvFrom, &project.Services[i], labels.LabelEnvFrom)
|
||||
getLabelContent(s.ExchangeVolumes, &project.Services[i], labels.LabelExchangeVolume)
|
||||
getLabelContent(s.ValuesFrom, &project.Services[i], labels.LabelValueFrom)
|
||||
mustGetLabelContent(s.MainApp, &project.Services[i], labels.LabelMainApp)
|
||||
mustGetLabelContent(s.Values, &project.Services[i], labels.LabelValues)
|
||||
mustGetLabelContent(s.Secrets, &project.Services[i], labels.LabelSecrets)
|
||||
mustGetLabelContent(s.Ports, &project.Services[i], labels.LabelPorts)
|
||||
mustGetLabelContent(s.Ingress, &project.Services[i], labels.LabelIngress)
|
||||
mustGetLabelContent(s.HealthCheck, &project.Services[i], labels.LabelHealthCheck)
|
||||
mustGetLabelContent(s.SamePod, &project.Services[i], labels.LabelSamePod)
|
||||
mustGetLabelContent(s.Description, &project.Services[i], labels.LabelDescription)
|
||||
mustGetLabelContent(s.Ignore, &project.Services[i], labels.LabelIgnore)
|
||||
mustGetLabelContent(s.Dependencies, &project.Services[i], labels.LabelDependencies)
|
||||
mustGetLabelContent(s.ConfigMapFile, &project.Services[i], labels.LabelConfigMapFiles)
|
||||
mustGetLabelContent(s.MapEnv, &project.Services[i], labels.LabelMapEnv)
|
||||
mustGetLabelContent(s.CronJob, &project.Services[i], labels.LabelCronJob)
|
||||
mustGetLabelContent(s.EnvFrom, &project.Services[i], labels.LabelEnvFrom)
|
||||
mustGetLabelContent(s.ExchangeVolumes, &project.Services[i], labels.LabelExchangeVolume)
|
||||
mustGetLabelContent(s.ValuesFrom, &project.Services[i], labels.LabelValueFrom)
|
||||
}
|
||||
}
|
||||
fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.")
|
||||
@@ -111,7 +117,7 @@ func getLabelContent(o any, service *types.ServiceConfig, labelName string) erro
|
||||
val := strings.TrimSpace(string(c))
|
||||
if labelName == labels.LabelIngress {
|
||||
// special case, values must be set from some defaults
|
||||
ing, err := labelStructs.IngressFrom(val)
|
||||
ing, err := labelstructs.IngressFrom(val)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
@@ -155,5 +161,5 @@ func GenerateSchema() string {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
return string(out.Bytes())
|
||||
return out.String()
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ webapp:
|
||||
// create /tmp/katenary-test-override directory, save the compose.yaml file
|
||||
tmpDir, err := os.MkdirTemp("", "katenary-test-override")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatalf("Failed to create temp directory: %s", err.Error())
|
||||
}
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
katenaryFile := filepath.Join(tmpDir, "katenary.yaml")
|
||||
@@ -57,6 +57,9 @@ webapp:
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create project from options: %s", err.Error())
|
||||
}
|
||||
|
||||
OverrideWithConfig(project)
|
||||
w := project.Services[0].Labels
|
||||
@@ -83,7 +86,7 @@ webapp:
|
||||
// create /tmp/katenary-test-override directory, save the compose.yaml file
|
||||
tmpDir, err := os.MkdirTemp("", "katenary-test-override")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatalf("Failed to create temp directory: %s", err.Error())
|
||||
}
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
katenaryFile := filepath.Join(tmpDir, "katenary.yaml")
|
||||
@@ -107,6 +110,9 @@ webapp:
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create project from options: %s", err.Error())
|
||||
}
|
||||
|
||||
OverrideWithConfig(project)
|
||||
w := project.Services[0].Labels
|
||||
|
2
generator/labels/doc.go
Normal file
2
generator/labels/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package labels provides functionality to parse and manipulate labels.
|
||||
package labels
|
@@ -5,6 +5,7 @@ import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -83,7 +84,7 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the help for the labels.
|
||||
// GetLabelHelp return the help for the labels.
|
||||
func GetLabelHelp(asMarkdown bool) string {
|
||||
names := GetLabelNames() // sorted
|
||||
if !asMarkdown {
|
||||
@@ -125,23 +126,30 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
template.Must(template.New("shorthelp").Parse(help.Long)).Execute(&buf, struct {
|
||||
var err error
|
||||
err = template.Must(template.New("shorthelp").Parse(help.Long)).Execute(&buf, struct {
|
||||
KatenaryPrefix string
|
||||
}{
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
help.Long = buf.String()
|
||||
buf.Reset()
|
||||
|
||||
template.Must(template.New("example").Parse(help.Example)).Execute(&buf, struct {
|
||||
err = template.Must(template.New("example").Parse(help.Example)).Execute(&buf, struct {
|
||||
KatenaryPrefix string
|
||||
}{
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
help.Example = buf.String()
|
||||
buf.Reset()
|
||||
|
||||
template.Must(template.New("complete").Parse(helpTemplate)).Execute(&buf, struct {
|
||||
err = template.Must(template.New("complete").Parse(helpTemplate)).Execute(&buf, struct {
|
||||
Name string
|
||||
Help Help
|
||||
KatenaryPrefix string
|
||||
@@ -150,6 +158,9 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
||||
Help: help,
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
@@ -338,9 +338,9 @@
|
||||
MARIADB_USER: myuser
|
||||
MARIADB_PASSWORD: mypassword
|
||||
labels:
|
||||
# it can be a secret
|
||||
# we can declare secrets
|
||||
{{ .KatenaryPrefix }}/secrets: |-
|
||||
- DB_PASSWORD
|
||||
- MARIADB_PASSWORD
|
||||
php:
|
||||
image: php:7.4-fpm
|
||||
environment:
|
||||
|
@@ -1,2 +0,0 @@
|
||||
// labelStructs is a package that contains the structs used to represent the labels in the yaml files.
|
||||
package labelStructs
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
17
generator/labels/labelstructs/configMap_test.go
Normal file
17
generator/labels/labelstructs/configMap_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package labelstructs_test
|
||||
|
||||
import (
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfigMapFileFrom(t *testing.T) {
|
||||
ts := "- foo/bar"
|
||||
tc2, _ := labelstructs.ConfigMapFileFrom(ts)
|
||||
if len(tc2) != 1 {
|
||||
t.Errorf("Expected ConfigMapFile to have 1 item, got %d", len(tc2))
|
||||
}
|
||||
if tc2[0] != "foo/bar" {
|
||||
t.Errorf("Expected ConfigMapFile to contain 'foo/bar', got %s", tc2[0])
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
25
generator/labels/labelstructs/cronJob_test.go
Normal file
25
generator/labels/labelstructs/cronJob_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCronJobFrom(t *testing.T) {
|
||||
ts := `
|
||||
image: fooimage
|
||||
command: thecommand
|
||||
schedule: "0/3 0 * * *"
|
||||
Rbac: false
|
||||
`
|
||||
tc, _ := CronJobFrom(ts)
|
||||
if tc.Image != "fooimage" {
|
||||
t.Errorf("Expected CronJob image to be 'fooimage', got %s", tc.Image)
|
||||
}
|
||||
if tc.Command != "thecommand" {
|
||||
t.Errorf("Expected CronJob command to be 'thecommand', got %s", tc.Command)
|
||||
}
|
||||
if tc.Schedule != "0/3 0 * * *" {
|
||||
t.Errorf("Expected CronJob schedule to be '0/3 0 * * *', got %s", tc.Schedule)
|
||||
}
|
||||
if tc.Rbac != false {
|
||||
t.Errorf("Expected CronJob rbac to be false, got %t", tc.Rbac)
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
14
generator/labels/labelstructs/dependencies_test.go
Normal file
14
generator/labels/labelstructs/dependencies_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDependenciesLabel(t *testing.T) {
|
||||
ts := "- name: mongodb"
|
||||
tc, _ := DependenciesFrom(ts)
|
||||
if len(tc) != 1 {
|
||||
t.Errorf("Expected DependenciesLabel to have 1 item, got %d", len(tc))
|
||||
}
|
||||
if tc[0].Name != "mongodb" {
|
||||
t.Errorf("Expected DependenciesLabel to contain 'mongodb', got %s", tc[0].Name)
|
||||
}
|
||||
}
|
2
generator/labels/labelstructs/doc.go
Normal file
2
generator/labels/labelstructs/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package labelstructs is a package that contains the structs used to represent the labels in the yaml files.
|
||||
package labelstructs
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
17
generator/labels/labelstructs/envFrom_test.go
Normal file
17
generator/labels/labelstructs/envFrom_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEnvFromLabel(t *testing.T) {
|
||||
ts := "- foo\n- bar"
|
||||
tc, _ := EnvFromFrom(ts)
|
||||
if len(tc) != 2 {
|
||||
t.Errorf("Expected EnvFrom to have 2 items, got %d", len(tc))
|
||||
}
|
||||
if tc[0] != "foo" {
|
||||
t.Errorf("Expected EnvFrom to contain 'foo', got %s", tc[0])
|
||||
}
|
||||
if tc[1] != "bar" {
|
||||
t.Errorf("Expected EnvFrom to contain 'bar', got %s", tc[1])
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
17
generator/labels/labelstructs/exchangeVolume_test.go
Normal file
17
generator/labels/labelstructs/exchangeVolume_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestExchangeVolumeLabel(t *testing.T) {
|
||||
ts := "- name: exchange-volume\n mountPath: /exchange\n readOnly: true"
|
||||
tc, _ := NewExchangeVolumes(ts)
|
||||
if len(tc) != 1 {
|
||||
t.Errorf("Expected ExchangeVolumeLabel to have 1 item, got %d", len(tc))
|
||||
}
|
||||
if tc[0].Name != "exchange-volume" {
|
||||
t.Errorf("Expected ExchangeVolumeLabel to contain 'exchange-volume', got %s", tc[0].Name)
|
||||
}
|
||||
if tc[0].MountPath != "/exchange" {
|
||||
t.Errorf("Expected MountPath to be '/exchange', got %s", tc[0].MountPath)
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -14,10 +14,10 @@ type TLS struct {
|
||||
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"`
|
||||
Hostname string `yaml:"hostname,omitempty" 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"`
|
||||
Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
|
||||
TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
|
||||
}
|
||||
|
31
generator/labels/labelstructs/ingress_test.go
Normal file
31
generator/labels/labelstructs/ingress_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIngressLabel(t *testing.T) {
|
||||
ts := "\nhostname: example.com\npath: /\nenabled: true\nport: 8888"
|
||||
tc, err := IngressFrom(ts)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing IngressLabel: %v", err)
|
||||
}
|
||||
if tc.Hostname != "example.com" {
|
||||
t.Errorf("Expected IngressLabel to contain 'example.com', got %s", tc.Hostname)
|
||||
}
|
||||
if tc.Path == nil || *tc.Path != "/" {
|
||||
t.Errorf("Expected IngressLabel to contain '/', got %v", tc.Path)
|
||||
}
|
||||
if tc.Enabled != true {
|
||||
t.Errorf("Expected IngressLabel to be enabled, got %v", tc.Enabled)
|
||||
}
|
||||
if tc.Port == nil || *tc.Port != 8888 {
|
||||
t.Errorf("Expected IngressLabel to have port 8888, got %d", tc.Port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIngressLabelNoPort(t *testing.T) {
|
||||
ts := "\nhostname: example.com\npath: /\nenabled: true"
|
||||
_, err := IngressFrom(ts)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error when parsing IngressLabel without port, got nil")
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
11
generator/labels/labelstructs/mapenv_test.go
Normal file
11
generator/labels/labelstructs/mapenv_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestConfigMapLabel(t *testing.T) {
|
||||
ts := "foo: bar"
|
||||
tc, _ := MapEnvFrom(ts)
|
||||
if len(tc) != 1 {
|
||||
t.Errorf("Expected ConfigMapFile to have 1 item, got %d", len(tc))
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
23
generator/labels/labelstructs/ports_test.go
Normal file
23
generator/labels/labelstructs/ports_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestPortsFromLabel(t *testing.T) {
|
||||
data := "- 8080\n- 9090\n"
|
||||
expected := Ports{8080, 9090}
|
||||
|
||||
ports, err := PortsFrom(data)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if len(ports) != len(expected) {
|
||||
t.Fatalf("expected length %d, got %d", len(expected), len(ports))
|
||||
}
|
||||
|
||||
for i, port := range ports {
|
||||
if port != expected[i] {
|
||||
t.Errorf("expected port %d at index %d, got %d", expected[i], i, port)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
16
generator/labels/labelstructs/probes_test.go
Normal file
16
generator/labels/labelstructs/probes_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestProbesLabel(t *testing.T) {
|
||||
readiness := "readinessProbe:\n httpGet:\n path: /healthz\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 10"
|
||||
tc, err := ProbeFrom(readiness)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing ProbesLabel: %v %v", err, tc)
|
||||
}
|
||||
liveness := "livenessProbe:\n httpGet:\n path: /healthz\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 10"
|
||||
tc2, err := ProbeFrom(liveness)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing ProbesLabel: %v %v", err, tc2)
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
17
generator/labels/labelstructs/secrets_test.go
Normal file
17
generator/labels/labelstructs/secrets_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package labelstructs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSecretLabel(t *testing.T) {
|
||||
data := "- foo\n- bar"
|
||||
tc, err := SecretsFrom(data)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing SecretLabel: %v %v", err, tc)
|
||||
}
|
||||
items := []string{"foo", "bar"}
|
||||
for i, item := range tc {
|
||||
if item != items[i] {
|
||||
t.Errorf("Expected SecretLabel to contain '%s', got '%s'", items[i], item)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package labelStructs
|
||||
package labelstructs
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
25
generator/labels/labelstructs/valueFrom_test.go
Normal file
25
generator/labels/labelstructs/valueFrom_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package labelstructs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValueFromLabel(t *testing.T) {
|
||||
data := "data: foo\ndata2: bar"
|
||||
tc, err := GetValueFrom(data)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if tc == nil {
|
||||
t.Fatalf("expected non-nil map, got nil")
|
||||
}
|
||||
if len(*tc) != 2 {
|
||||
t.Errorf("expected 2 items, got %d", len(*tc))
|
||||
}
|
||||
if (*tc)["data"] != "foo" {
|
||||
t.Errorf("expected 'data' to be 'foo', got %s", (*tc)["data"])
|
||||
}
|
||||
if (*tc)["data2"] != "bar" {
|
||||
t.Errorf("expected 'data2' to be 'bar', got %s", (*tc)["data2"])
|
||||
}
|
||||
}
|
@@ -82,7 +82,9 @@ services:
|
||||
AppVersion: appVersion,
|
||||
ChartVersion: chartVersion,
|
||||
}
|
||||
Convert(convertOptions, "compose.yml")
|
||||
if err := Convert(convertOptions, "compose.yml"); err != nil {
|
||||
t.Fatalf("Failed to convert compose file: %s", err)
|
||||
}
|
||||
c, err := os.ReadFile("chart/values.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@@ -49,6 +49,7 @@ func internalCompileTest(t *testing.T, options ...string) string {
|
||||
ChartVersion: chartVersion,
|
||||
}
|
||||
if err := Convert(convertOptions, "compose.yml"); err != nil {
|
||||
log.Printf("Failed to convert: %s", err)
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@ package generator
|
||||
|
||||
import (
|
||||
"katenary/generator/labels"
|
||||
"katenary/generator/labels/labelStructs"
|
||||
"katenary/generator/labels/labelstructs"
|
||||
"katenary/utils"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -50,11 +50,11 @@ func fixPorts(service *types.ServiceConfig) error {
|
||||
if portsLabel, ok = service.Labels[labels.LabelPorts]; !ok {
|
||||
return nil
|
||||
}
|
||||
ports, err := labelStructs.PortsFrom(portsLabel)
|
||||
ports, err := labelstructs.PortsFrom(portsLabel)
|
||||
if err != nil {
|
||||
// maybe it's a string, comma separated
|
||||
parts := strings.Split(portsLabel, ",")
|
||||
for _, part := range parts {
|
||||
parts := strings.SplitSeq(portsLabel, ",")
|
||||
for part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
@@ -87,7 +87,7 @@ func UnWrapTPL(in []byte) []byte {
|
||||
return regexpLineWrap.ReplaceAll(in, []byte(" }}"))
|
||||
}
|
||||
|
||||
func ToK8SYaml(obj interface{}) ([]byte, error) {
|
||||
func ToK8SYaml(obj any) ([]byte, error) {
|
||||
if o, err := yaml.Marshal(obj); err != nil {
|
||||
return nil, nil
|
||||
} else {
|
||||
|
@@ -3,6 +3,7 @@ package generator
|
||||
import (
|
||||
"fmt"
|
||||
"katenary/generator/labels"
|
||||
"katenary/utils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -21,11 +22,11 @@ services:
|
||||
composeFileContent = fmt.Sprintf(composeFileContent, labels.KatenaryLabelPrefix)
|
||||
tmpDir, err := os.MkdirTemp("", "katenary-test-override")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
|
||||
os.MkdirAll(tmpDir, 0755)
|
||||
os.MkdirAll(tmpDir, utils.DirectoryPermission)
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
@@ -38,6 +39,9 @@ services:
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixPorts(&project.Services[0]); err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
@@ -66,11 +70,11 @@ services:
|
||||
composeFileContent = fmt.Sprintf(composeFileContent, labels.KatenaryLabelPrefix)
|
||||
tmpDir, err := os.MkdirTemp("", "katenary-test-override")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
|
||||
os.MkdirAll(tmpDir, 0755)
|
||||
os.MkdirAll(tmpDir, utils.DirectoryPermission)
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
@@ -83,6 +87,9 @@ services:
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixPorts(&project.Services[0]); err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
@@ -21,7 +21,8 @@ type PersistenceValue struct {
|
||||
}
|
||||
|
||||
type TLS struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
SecretName string `yaml:"secretName"`
|
||||
}
|
||||
|
||||
// IngressValue is a ingress configuration that will be saved in values.yaml.
|
||||
@@ -92,6 +93,10 @@ func (v *Value) AddIngress(host, path string) {
|
||||
Host: host,
|
||||
Path: path,
|
||||
Class: "-",
|
||||
TLS: TLS{
|
||||
Enabled: true,
|
||||
SecretName: "",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
func TestVersion(t *testing.T) {
|
||||
// we build on "devel" branch
|
||||
v := GetVersion()
|
||||
if strings.Contains(v, "(devel)") {
|
||||
if !strings.Contains(v, "(devel)") {
|
||||
t.Errorf("Expected version to be set, got %s", v)
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"image/color"
|
||||
"image/png"
|
||||
"katenary/generator/labels"
|
||||
"katenary/utils"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -16,7 +17,11 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const htmlContent = "<html><body><h1>Hello, World!</h1></body></html>"
|
||||
const (
|
||||
htmlContent = "<html><body><h1>Hello, World!</h1></body></html>"
|
||||
developementFile = "templates/web/deployment.yaml"
|
||||
indexHMLFile = "index.html"
|
||||
)
|
||||
|
||||
func TestGenerateWithBoundVolume(t *testing.T) {
|
||||
composeFile := `
|
||||
@@ -35,7 +40,7 @@ volumes:
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
@@ -43,7 +48,7 @@ volumes:
|
||||
}
|
||||
|
||||
if dt.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name != "data" {
|
||||
t.Errorf("Expected volume name to be data: %v", dt)
|
||||
t.Errorf("Expected container volume name to be data: %v", dt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +69,7 @@ services:
|
||||
|
||||
// create a static directory with an index.html file
|
||||
staticDir := tmpDir + "/static"
|
||||
os.Mkdir(staticDir, 0o755)
|
||||
os.Mkdir(staticDir, utils.DirectoryPermission)
|
||||
indexFile, err := os.Create(staticDir + "/index.html")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create index.html: %s", err)
|
||||
@@ -76,7 +81,7 @@ services:
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -102,8 +107,8 @@ services:
|
||||
if len(data) != 1 {
|
||||
t.Errorf("Expected 1 data, got %d", len(data))
|
||||
}
|
||||
if data["index.html"] != htmlContent {
|
||||
t.Errorf("Expected index.html to be "+htmlContent+", got %s", data["index.html"])
|
||||
if data[indexHMLFile] != htmlContent {
|
||||
t.Errorf("Expected index.html to be "+htmlContent+", got %s", data[indexHMLFile])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +129,7 @@ services:
|
||||
|
||||
// create a static directory with an index.html file
|
||||
staticDir := tmpDir + "/static"
|
||||
os.Mkdir(staticDir, 0o755)
|
||||
os.Mkdir(staticDir, utils.DirectoryPermission)
|
||||
indexFile, err := os.Create(staticDir + "/index.html")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create index.html: %s", err)
|
||||
@@ -136,7 +141,7 @@ services:
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -149,7 +154,7 @@ services:
|
||||
}
|
||||
// but this time, we need a subpath
|
||||
subPath := dt.Spec.Template.Spec.Containers[0].VolumeMounts[0].SubPath
|
||||
if subPath != "index.html" {
|
||||
if subPath != indexHMLFile {
|
||||
t.Errorf("Expected subpath to be index.html, got %s", subPath)
|
||||
}
|
||||
}
|
||||
@@ -170,15 +175,15 @@ services:
|
||||
log.Println(tmpDir)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
|
||||
os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)
|
||||
|
||||
// create a png image
|
||||
pngFile := tmpDir + "/images/foo.png"
|
||||
w, h := 100, 100
|
||||
img := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
red := color.RGBA{255, 0, 0, 255}
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
for y := range h {
|
||||
for x := range w {
|
||||
img.Set(x, y, red)
|
||||
}
|
||||
}
|
||||
@@ -199,7 +204,7 @@ services:
|
||||
}
|
||||
png.Encode(f, img)
|
||||
f.Close()
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
d := v1.Deployment{}
|
||||
yaml.Unmarshal([]byte(output), &d)
|
||||
volumes := d.Spec.Template.Spec.Volumes
|
||||
@@ -211,6 +216,9 @@ services:
|
||||
cmContent, err := helmTemplate(ConvertOptions{
|
||||
OutputDir: "chart",
|
||||
}, "-s", "templates/web/statics/images/configmap.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
yaml.Unmarshal([]byte(cmContent), &cm)
|
||||
if im, ok := cm.BinaryData["foo.png"]; !ok {
|
||||
t.Errorf("Expected foo.png to be in the configmap")
|
||||
@@ -237,15 +245,15 @@ services:
|
||||
log.Println(tmpDir)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
|
||||
os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)
|
||||
|
||||
// create a png image
|
||||
pngFile := tmpDir + "/images/foo.png"
|
||||
w, h := 100, 100
|
||||
img := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
red := color.RGBA{255, 0, 0, 255}
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
for y := range h {
|
||||
for x := range w {
|
||||
img.Set(x, y, red)
|
||||
}
|
||||
}
|
||||
@@ -266,7 +274,7 @@ services:
|
||||
}
|
||||
png.Encode(f, img)
|
||||
f.Close()
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
d := v1.Deployment{}
|
||||
yaml.Unmarshal([]byte(output), &d)
|
||||
volumes := d.Spec.Template.Spec.Volumes
|
||||
@@ -278,6 +286,9 @@ services:
|
||||
cmContent, err := helmTemplate(ConvertOptions{
|
||||
OutputDir: "chart",
|
||||
}, "-s", "templates/web/statics/images/configmap.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
yaml.Unmarshal([]byte(cmContent), &cm)
|
||||
if im, ok := cm.BinaryData["foo.png"]; !ok {
|
||||
t.Errorf("Expected foo.png to be in the configmap")
|
||||
@@ -317,17 +328,17 @@ volumes:
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
|
||||
output := internalCompileTest(t, "-s", developementFile)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
// both containers should have the same volume mount
|
||||
if dt.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name != "data" {
|
||||
t.Errorf("Expected volume name to be data: %v", dt)
|
||||
t.Errorf("Expected container 0 volume name to be data: %v", dt)
|
||||
}
|
||||
if dt.Spec.Template.Spec.Containers[1].VolumeMounts[0].Name != "data" {
|
||||
t.Errorf("Expected volume name to be data: %v", dt)
|
||||
t.Errorf("Expected container 1 volume name to be data: %v", dt)
|
||||
}
|
||||
}
|
||||
|
||||
|
41
go.mod
41
go.mod
@@ -1,19 +1,19 @@
|
||||
module katenary // github.com/metal3d/katenary
|
||||
|
||||
go 1.23
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.23.2
|
||||
toolchain go1.24.3
|
||||
|
||||
require (
|
||||
github.com/compose-spec/compose-go v1.20.2
|
||||
github.com/invopop/jsonschema v0.12.0
|
||||
github.com/invopop/jsonschema v0.13.0
|
||||
github.com/mitchellh/go-wordwrap v1.0.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/thediveo/netdb v1.1.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.31.3
|
||||
k8s.io/apimachinery v0.31.3
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
k8s.io/api v0.33.2
|
||||
k8s.io/apimachinery v0.33.2
|
||||
sigs.k8s.io/yaml v1.5.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -22,14 +22,15 @@ require (
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
@@ -37,20 +38,22 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
)
|
||||
|
111
go.sum
111
go.sum
@@ -4,41 +4,37 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
|
||||
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
|
||||
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
@@ -47,8 +43,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
@@ -60,31 +56,30 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
||||
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/thediveo/netdb v1.1.2 h1:XdLx/YJPutxrSkPYtmCAIY5sgAvxtkS1Tz+Z0UX2I+U=
|
||||
github.com/thediveo/netdb v1.1.2/go.mod h1:KJczM//7VIIiovQO1qDooHvM8+0pt6RdRt3rVDZxEGM=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
@@ -100,40 +95,44 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
|
||||
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
|
||||
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -148,17 +147,21 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
|
||||
k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
|
||||
k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
|
||||
k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
|
||||
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
|
||||
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
|
||||
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
|
||||
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
|
||||
|
36
install.sh
36
install.sh
@@ -18,28 +18,28 @@ COMON_INSTALL_PATHS="$HOME/.local/bin $HOME/.bin $HOME/bin"
|
||||
|
||||
INSTALL_PATH=""
|
||||
for p in $COMON_INSTALL_PATHS; do
|
||||
if [ -d $p ]; then
|
||||
INSTALL_PATH=$p
|
||||
break
|
||||
fi
|
||||
if [ -d $p ]; then
|
||||
INSTALL_PATH=$p
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# check if the user has write access to the INSTALL_PATH
|
||||
if [ -z "$INSTALL_PATH" ]; then
|
||||
INSTALL_PATH="/usr/local/bin"
|
||||
if [ ! -w $INSTALL_PATH ]; then
|
||||
echo "You don't have write access to $INSTALL_PATH"
|
||||
echo "Please, run with sudo or install locally"
|
||||
exit 1
|
||||
fi
|
||||
INSTALL_PATH="/usr/local/bin"
|
||||
if [ ! -w $INSTALL_PATH ]; then
|
||||
echo "You don't have write access to $INSTALL_PATH"
|
||||
echo "Please, run with sudo or install locally"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ensure that $INSTALL_PATH is in the PATH
|
||||
if ! echo $PATH | grep -q $INSTALL_PATH; then
|
||||
echo "Sorry, $INSTALL_PATH is not in the PATH"
|
||||
echo "Please, add it to your PATH in your shell configuration file"
|
||||
echo "then restart your shell and run this script again"
|
||||
exit 1
|
||||
if ! echo "$PATH" | grep -q "$INSTALL_PATH"; then
|
||||
echo "Sorry, ${INSTALL_PATH} is not in the PATH"
|
||||
echo "Please, add it to your PATH in your shell configuration file"
|
||||
echo "then restart your shell and run this script again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Where to download the binary
|
||||
@@ -47,7 +47,7 @@ BASE="https://github.com/metal3d/katenary/releases/latest/download/"
|
||||
|
||||
# for compatibility with older ARM versions
|
||||
if [ $ARCH = "x86_64" ]; then
|
||||
ARCH="amd64"
|
||||
ARCH="amd64"
|
||||
fi
|
||||
|
||||
BIN_URL="$BASE/katenary-$OS-$ARCH"
|
||||
@@ -58,8 +58,8 @@ echo "Downloading $BIN_URL"
|
||||
T=$(mktemp -u)
|
||||
curl -SL -# $BIN_URL -o $T || (echo "Failed to download katenary" && rm -f $T && exit 1)
|
||||
|
||||
mv $T $INSTALL_PATH/katenary
|
||||
chmod +x $INSTALL_PATH/katenary
|
||||
mv "$T" "${INSTALL_PATH}/katenary"
|
||||
chmod +x "${INSTALL_PATH}/katenary"
|
||||
echo
|
||||
echo "Installed to $INSTALL_PATH/katenary"
|
||||
echo "Installation complete! Run 'katenary help' to get started."
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Parser package is a wrapper around compose-go to parse compose files.
|
||||
// Package parser is a wrapper around compose-go to parse compose files.
|
||||
package parser
|
||||
|
||||
import (
|
||||
|
60
parser/main_test.go
Normal file
60
parser/main_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const composeFile = `
|
||||
services:
|
||||
app:
|
||||
image: nginx:latest
|
||||
`
|
||||
|
||||
func setupTest() (string, error) {
|
||||
// write the composeFile to a temporary file
|
||||
tmpDir, err := os.MkdirTemp("", "katenary-test-parse")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
writeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
writeErr := os.WriteFile(writeFile, []byte(composeFile), 0644)
|
||||
return writeFile, writeErr
|
||||
}
|
||||
|
||||
func tearDownTest(tmpDir string) {
|
||||
if tmpDir != "" {
|
||||
if err := os.RemoveAll(tmpDir); err != nil {
|
||||
log.Fatalf("Failed to remove temporary directory %s: %s", tmpDir, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
file, err := setupTest()
|
||||
dirname := filepath.Dir(file)
|
||||
currentDir, _ := os.Getwd()
|
||||
if err := os.Chdir(dirname); err != nil {
|
||||
t.Fatalf("Failed to change directory to %s: %s", dirname, err.Error())
|
||||
}
|
||||
defer func() {
|
||||
tearDownTest(dirname)
|
||||
if err := os.Chdir(currentDir); err != nil {
|
||||
t.Fatalf("Failed to change back to original directory %s: %s", currentDir, err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to setup test: %s", err.Error())
|
||||
}
|
||||
|
||||
Project, err := Parse(nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse compose file: %s", err.Error())
|
||||
}
|
||||
if Project == nil {
|
||||
t.Fatal("Expected project to be not nil")
|
||||
}
|
||||
}
|
@@ -1,2 +1,3 @@
|
||||
// Utils package provides some utility functions used in katenary. It defines some constants and functions used in the whole project.
|
||||
// Package utils provides some utility functions used in katenary.
|
||||
// It defines some constants and functions used in the whole project.
|
||||
package utils
|
||||
|
13
utils/hash_test.go
Normal file
13
utils/hash_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package utils
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
h, err := HashComposefiles([]string{"./hash.go"})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to hash compose files: %v", err)
|
||||
}
|
||||
if len(h) == 0 {
|
||||
t.Fatal("hash should not be empty")
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
// Warn prints a warning message
|
||||
func Warn(msg ...interface{}) {
|
||||
func Warn(msg ...any) {
|
||||
orange := "\033[38;5;214m"
|
||||
reset := "\033[0m"
|
||||
fmt.Print(IconWarning, orange, " ")
|
||||
|
@@ -14,6 +14,9 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// DirectoryPermission is the default values for permissions apply to created directories.
|
||||
const DirectoryPermission = 0o755
|
||||
|
||||
// TplName returns the name of the kubernetes resource as a template string.
|
||||
// It is used in the templates and defined in _helper.tpl file.
|
||||
func TplName(serviceName, appname string, suffix ...string) string {
|
||||
@@ -90,7 +93,7 @@ func GetContainerByName(name string, containers []corev1.Container) (*corev1.Con
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// GetContainerByName returns a container by name and its index in the array.
|
||||
// TplValue returns a container by name and its index in the array.
|
||||
func TplValue(serviceName, variable string, pipes ...string) string {
|
||||
if len(pipes) == 0 {
|
||||
return `{{ tpl .Values.` + serviceName + `.` + variable + ` $ }}`
|
||||
@@ -136,12 +139,12 @@ func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[str
|
||||
switch val := value.(type) {
|
||||
case string:
|
||||
descriptions[val] = nil
|
||||
case map[string]interface{}:
|
||||
for k, v := range value.(map[string]interface{}) {
|
||||
case map[string]any:
|
||||
for k, v := range value.(map[string]any) {
|
||||
descriptions[k] = &EnvConfig{Service: service, Description: v.(string)}
|
||||
}
|
||||
case map[interface{}]interface{}:
|
||||
for k, v := range value.(map[interface{}]interface{}) {
|
||||
case map[any]any:
|
||||
for k, v := range value.(map[any]any) {
|
||||
descriptions[k.(string)] = &EnvConfig{Service: service, Description: v.(string)}
|
||||
}
|
||||
default:
|
||||
@@ -165,7 +168,9 @@ func Confirm(question string, icon ...Icon) bool {
|
||||
fmt.Print(question + " [y/N] ")
|
||||
}
|
||||
var response string
|
||||
fmt.Scanln(&response)
|
||||
if _, err := fmt.Scanln(&response); err != nil {
|
||||
log.Fatalf("Error parsing response: %s", err.Error())
|
||||
}
|
||||
return strings.ToLower(response) == "y"
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user