141 Commits

Author SHA1 Message Date
c85e61f5d0 Merge branch 'master' of repo.katenary.io:Katenary/katenary
All checks were successful
Go-Tests / tests (push) Successful in 1m49s
Go-Tests / sonar (push) Successful in 49s
2025-08-19 23:20:12 +02:00
f1c31b0eeb feat(doc): move some things in README
As we moved project to repo.katenary.io, badges were not OK
2025-08-19 22:31:50 +02:00
677b0d7b3c Merge pull request 'feat(actions): Change action to Gitea' (#161) from test-workflow into master
All checks were successful
Go-Tests / tests (push) Successful in 1m59s
Go-Tests / sonar (push) Successful in 1m7s
Reviewed-on: #161
2025-08-19 19:59:17 +00:00
f539be8f52 Remove proxy
All checks were successful
Go-Tests / tests (pull_request) Successful in 2m29s
Go-Tests / sonar (pull_request) Successful in 51s
2025-08-19 21:54:01 +02:00
4336490a72 feat(actions): Change action to Gitea
- Build and packages on Gitea action
- Use go 1.25
- Update dependencies
2025-08-19 21:52:33 +02:00
9f75f874d1 Features/buildah build (#159)
* feat(oci): Build using pure Buildah
2025-08-13 10:20:48 +02:00
90eda75219 feat(oci): Use Buildah
And set version the right way...
2025-08-04 16:18:35 +02:00
b13e922966 feat(package) Version were not correctly set
As the code moved in "internal" package, we need to set the version to
the new location
2025-08-04 16:13:35 +02:00
0d36a48f93 fix(securty): Fix security alert
Code scanning alert: we need to specify permissions on this action.
2025-08-03 23:29:39 +02:00
60016b8c3e Merge pull request #157 from Katenary/features/oci-image
Features/oci image
2025-08-03 23:06:06 +02:00
07263520b6 feat(oci): remove testing on push branches 2025-08-03 23:01:54 +02:00
0f3812b666 feat(oci): Add OCI image generation
Not fully tested but it should produce an image in ghcr.io
2025-08-03 22:54:19 +02:00
50a9d0ddde feat(md): fixes typo and rules 2025-08-03 22:53:53 +02:00
f5d3005c3b Merge pull request #156 from Katenary/feat-move-to-internal
feat(refacto): move everything in internal package
2025-08-03 16:03:17 +02:00
76b3b83d07 feat(workflow): change when to make CI
We will abandon develop branch for a while. It's better to work with
feature branches.
2025-08-03 15:59:00 +02:00
14ca5bf0ea feat(refacto): move everything in internal package
This allows to install katenary with `go install` and to clean up the
project folder.
2025-08-03 15:54:58 +02:00
d1768e5742 Merge pull request #155 from Katenary/develop
Develop
2025-08-03 14:20:17 +02:00
0fcf0f60e8 chore(modules): Update versions 2025-08-03 14:15:55 +02:00
e9ad85a0ac chore(make): Split and enhancements
- split Makefile in several sub files
- use a separated container for tests
-
2025-08-03 14:15:35 +02:00
b4b122fe7f Do not ignore cmd/katenary directory 2025-08-03 14:14:29 +02:00
6aaeda7a3c chore(modernize): use iterator 2025-08-03 14:13:57 +02:00
0b3f7b2b5c chore(code): remove dead code 2025-08-03 14:13:42 +02:00
e9e7c5f7b5 chore(test): fix concurrency problem 2025-08-03 14:12:49 +02:00
0df53ed5ae Merge pull request #154 from Katenary/develop
fix(configmap): File from the root of project ends by a dash
2025-08-03 13:16:21 +02:00
136478aff7 fix(configmap): File from the root of project ends by a dash
fixes #150

If we mount a file from the root of project, the names ends by a dash.
That makes helm failing to install the package.
2025-08-03 10:20:11 +02:00
5b812b30f7 Merge pull request #146 from Katenary/develop
fix(katenaryfile): Schema is broken without json annotation
2025-07-15 21:25:39 +02:00
f2b5c16e71 fix(katenaryfile): Schema is broken without json annotation
We need to add json annotation. The yaml annoation is not enought when
generating the schema.
2025-07-15 21:24:17 +02:00
df1f29c0ff Merge pull request #145 from Katenary/develop
fix(katenaryfile): Fix parsing katenary file
2025-07-15 21:18:45 +02:00
afbd6fc1ac fix(katenaryfile): Fix parsing katenary file
It seems that "json" annotation fails to get dashed names (like
configmap-files). That means that all labels in katernay.yaml file
couldn't be parsed.

Using `yaml` annotaiton fixes the problem. Fixes #144.
2025-07-15 21:13:22 +02:00
327e0aa799 Merge pull request #142 from Katenary/develop
chore(make): manpage requirements are now in requirements
2025-07-15 13:58:48 +02:00
b7e948954b chore(make): manpage requirements are now in requirements 2025-07-15 13:57:35 +02:00
93c0658c19 Merge pull request #141 from Katenary/develop
Develop
2025-07-15 13:53:20 +02:00
bdf74f2deb chore(cleanup): removed unecessary file 2025-07-15 13:51:21 +02:00
2435bb9f8a chore(doc): Rebuild label list and description 2025-07-15 13:50:07 +02:00
5ee38dcf7f Merge pull request #140 from Katenary/develop
Develop
2025-07-15 13:45:38 +02:00
a754dc9275 fix(make): no need to auto retrieve key now 2025-07-15 13:44:25 +02:00
732e080da3 Merge branch 'master' into develop 2025-07-15 13:42:15 +02:00
22e1ebdce1 chore(make): huge refactor, add more tests
- more test on gpg signature
- change build target in the help message
- refactor upx compression
-
2025-07-15 13:41:49 +02:00
e4280f2c4e chore(build): Fixes cache, add better cleanup, add PHONY 2025-07-15 10:27:24 +02:00
a99609d21d Merge pull request #139 from Katenary/develop
fix(doc): Fix documentation linkg
2025-07-13 15:41:01 +02:00
e55658d382 fix(doc): Fix documentation linkg
No translation, so remove "en" from the url.
2025-07-13 15:40:30 +02:00
9dbe9e1114 Merge pull request #138 from Katenary/develop
Develop
2025-07-13 15:37:31 +02:00
eea198786a fix(doc): Readthedocs needs manpage plugin
A pitty, I wanted to leave it separated
2025-07-13 15:29:16 +02:00
da9c0a7b58 chore(doc): regenerate and fixes a typo 2025-07-13 15:16:39 +02:00
d582b884bf chore(rules): Avoid mardownlint to complain 2025-07-13 15:16:20 +02:00
aa3e4c64ee chore(ignore): ignoring binary in the current directory 2025-07-13 15:08:32 +02:00
ce479629f6 fix(service): Fixes naming service ports
- ports should be named "port-XXX" with XXX to be the port number if the
port name cannot be discovered
- it follows what we do in Deployment objects
- this should fix #132
2025-07-13 15:02:26 +02:00
89fd516b20 Merge pull request #137 from Katenary/develop
Develop
2025-07-13 00:53:45 +02:00
8bbb991afb chore(doc): Move to new repository 2025-07-13 00:43:21 +02:00
4c5c9ba553 chore(doc): Move to new repository 2025-07-13 00:39:25 +02:00
ef1511d4f7 Merge pull request #134 from Katenary/develop
Develop
2025-07-13 00:21:15 +02:00
a290219c81 chore(licence): I prefer to mention the project 2025-07-13 00:19:02 +02:00
c4e406f855 chore(moving): Moved repository to organization 2025-07-13 00:17:48 +02:00
2beac5f4dd Merge pull request #135 from Katenary/issue-133
fix(deployment): Missed the command from compose file
2025-07-13 00:10:22 +02:00
5f5cd0268a fix(deployment): Missed the command from compose file
Fixes #133
2025-07-13 00:07:07 +02:00
796cbb6d30 chore(package): Rewrite package targets
- rewrite to make packages building more consistent
- add rpm signature with GPG
- auto test packages in several distributions to ensure the packages are
OK

Even if loops to build stuffs are sometimes easier to automate, it's
simpler to fixup if some rules (targets) are explicitly defined.
2025-07-12 09:12:12 +02:00
39ebf7eb78 chore(package): change description, add a final dot 2025-07-12 09:08:41 +02:00
a1c5161ff7 chore(package): Be able to sign RPM 2025-07-12 09:08:28 +02:00
2307ad667e chore(dev): changed how to test version
- force release version check to use "v" (or not) as first character
- one line condtion
2025-07-11 09:17:33 +02:00
a26e832fed fix(doc): recompiled documentation 2025-07-11 09:16:43 +02:00
8582010d90 fix(versionning): Fix version
Version should be x.y.z for releases. It makes things homogenous for
debian version (that needs a number as first char) and it is
semantically better.

At this time, the Makefile is OK. Maybe we don't need `PKG_VERSION`
later.
2025-07-10 15:15:25 +02:00
b7186eb8b4 chore(makefile): Refacto
Refactor the makefile:

- use the "package" container image to build windows installer
- cleanup and reorder targets
- enhance the way we named packages (add version and architecture to the
name)
2025-07-10 08:13:49 +02:00
0f3528818f chore(package): Add NSIS to the package image
This container image can make Windows installer too.
2025-07-10 08:11:39 +02:00
9fadc77979 chore(package): Add application in registry
Allow the application to appear in "Install/Uninstall" Windows
parameters.
2025-07-10 08:10:11 +02:00
13d231a62c feat(package): Add RPM, deb, pacman and tar packages and manpage
Build package using fpm. As I don't want ruby/gem in my computer, the
build system creates an OCI image with Podman (at this time), and
generate dist pacakges.

To enhance the packages, a manpage is now generated from the
documentation.
2025-07-09 14:11:46 +02:00
6cbaa06bec chore(license): Change date and copyright
I keep MIT license, just changed date and pseudo
2025-07-07 23:50:03 +02:00
1552e9c877 Merge pull request #131 from metal3d/develop
Develop
2025-07-07 23:02:13 +02:00
3b2cd37ea4 chore(test): add tests 2025-07-07 22:48:13 +02:00
4c566cbc1a fix(doc): Fix function doc 2025-07-07 22:47:59 +02:00
69c528e5e0 chore(doc): Enhance documentation, fix typo 2025-07-07 22:10:27 +02:00
42bf35593f chore(makefile): rewrite correctly some rules
- cleanup
- sign and check gpg signature
- fixup NSIS installer method
- also sign windows installer
2025-07-07 21:58:15 +02:00
4e739c5f08 fix(doc): Fixing duplicated package 2025-07-07 21:57:14 +02:00
f75623b4ff chore(nsis): sort language
Sort all languages, excepting the first one wich is the default language
2025-07-07 21:31:58 +02:00
d82b5e4a98 feat(nsis): Add more languages, files and license page
- Include maximum of language for the Windows installer
- Add licence page to inform the user that Katenary is free (as freedom)
2025-07-07 18:18:20 +02:00
42c738211c fix(build): Fixing build, do not use alpine
Alpine image seems to break the Windows binary (striped by error) and
makes katenary unusable.
2025-07-07 17:59:16 +02:00
c54bc35c9f feat(nsis): Create installer for Windows
Use nsis to create an installer for Windows user. It installs the binary
for the user (for now) and set the Path to access katenary binary from
cmd or Powershell.
2025-07-07 17:58:21 +02:00
1f406dc558 Merge pull request #130 from metal3d/develop
fix(build): Windows is a shame
2025-07-07 13:50:31 +02:00
0c0b50b0df fix(build): Windows is a shame
- Windows defender says that UPX compressed files are virus
(https://github.com/upx/upx/issues/437) so I stop using this for
Windows. Sorry, you will download a huge binary
- Windows, one more time, stop making the binary working when it's
stripped. Then, one more time, I cannot reduce the binary size

I'm thinking very seriously about no longer offering support for Windows
and letting people compile Katenary on their own.
2025-07-07 13:47:27 +02:00
6efee2fbae Merge pull request #129 from metal3d/develop
Many fixes on code quality and CI
2025-07-06 15:37:08 +02:00
47e149e20b chore(doc): Regenerated doc 2025-07-06 15:36:43 +02:00
d163700147 feat(tests): Add tests for label structures 2025-07-06 15:31:21 +02:00
fa3befaa88 fix(tests): Fixing unbound error 2025-07-06 15:31:05 +02:00
e5b7c0d550 fix(doc): Respect Go recommandation in docstring 2025-07-06 15:30:31 +02:00
9e4663cc6e chore(convention): Respect Go convention, package name should be lowercase 2025-07-06 14:34:16 +02:00
1a5c95d240 fix(ci): typo in permission block 2025-07-06 14:26:20 +02:00
21845c5de1 fix(ci): typo in permission block 2025-07-06 14:24:12 +02:00
4a91d458fd fix(ci): try to add permission block 2025-07-06 14:21:56 +02:00
a52b20efab Merge pull request #128 from metal3d/feat-change-actions
Feat change actions
2025-07-06 14:16:38 +02:00
02c4c5168b feat(ci): Changes CI
- use SonarQube action
- remove the helm installation as it is already present
- changes types and branches activation
2025-07-06 14:13:23 +02:00
7b875454cb feat(chore): use range over int
More readable range
2025-07-06 11:53:56 +02:00
2da5d9df08 feat(chore): modernize code 2025-07-06 11:53:24 +02:00
a0eb3c0bb6 fix(doc): Fix doc string 2025-07-06 11:52:48 +02:00
7e76543c48 fix(doc): Fix the docstring following Go recommandation 2025-07-06 11:41:19 +02:00
09c2c86d59 fix(permission): globalize and fixes
Permission alert frop OpenGrep is wrong, as the directory must use 0755.
To make things working and to ease futur changes, I set the default
permission in a constant.
2025-07-06 11:39:19 +02:00
e58948bb44 feat(code): use better check on empty string 2025-07-06 10:53:18 +02:00
a00b03b2aa feat(chore): Add SAST with opengrep 2025-07-06 10:52:56 +02:00
b47b956798 fix(install): Enhance checks and code
- Opengrep complains about non quoted strings
- Bad indentation fixed
2025-07-06 10:52:35 +02:00
a409a1347e feat(chore): rename variable 2025-07-06 10:51:25 +02:00
8999aabc21 fix(security): Change access rights on generated directories
Ppengrep complains, it is right.
2025-07-06 10:51:09 +02:00
14e8907437 feat(doc): Add package doc for labels 2025-07-06 10:49:54 +02:00
740c400b9a Merge pull request #127 from metal3d/develop
feat(doc): regenerate the package docs
2025-07-04 15:05:34 +02:00
7cd38bbd23 feat(doc): regenerate the package docs 2025-07-04 14:59:49 +02:00
8c509b5bff Merge pull request #126 from metal3d/develop
Merge branch 'master' into develop
2025-07-04 14:53:00 +02:00
28b22a0b30 Merge branch 'master' into develop 2025-07-04 14:49:35 +02:00
748d0bf1ea Merge pull request #120 from metal3d/develop 2025-06-27 00:27:49 +02:00
130e6d4e24 chore(dependencies): Update dependencies 2025-06-26 23:57:44 +02:00
a66fec07e1 chore(optim): Optimizing some piece of code
Simply use modern methods
2025-06-26 23:57:19 +02:00
a3d1e9342f fix(doc): Follow Go recommendations 2025-06-26 23:56:06 +02:00
72bc88661a fix(convension): Fix APIVersion
Sonarlint complains about "ApiVersion"
2025-06-26 23:37:20 +02:00
e2b897eb9d fix(generation): Fix container name
Container names were built using the service name. We didn't checked the
name and leave underscores inside.

This commit does:
- fix all service and rename containers (`container_name`)
- use `ContainerName` everywhere we need to get the container by name

See #106
2025-06-26 23:37:20 +02:00
9fcce059e5 fix(doc): Fixing method name in comment 2025-06-26 23:18:11 +02:00
36f6413917 feat(build): UPX compression
UPX can compress binaries from 22Mo to 7Mo on Linux / Windows and 14Mo
on MacOS. Let's use it to reduce binary size.

I don't know why it doesn't work on FreeBSD.
2025-06-15 16:02:45 +02:00
8c729f3c57 fix(build): remove "-it" options
Building in parallel make a warn message as TTY is not OK
2025-06-15 16:01:16 +02:00
063cc9d439 Merge pull request #119 from metal3d/develop
Develop
2025-06-15 16:14:10 +03:00
ac5317e600 feat(doc): regenerate docs 2025-06-15 14:48:35 +02:00
bc0b65006d feat(doc): Add doc target
This only regenerates docs for packages.
2025-06-15 14:48:24 +02:00
933f04bf5e feat(version): change Go version 2025-06-15 14:43:58 +02:00
7d46435ba2 Merge pull request #118 from metal3d/develop
Develop
2025-06-04 15:22:09 +02:00
d94bb8ac32 feat(doc): regenerate documentation 2025-06-04 15:18:11 +02:00
b143f743ef feat(chore): Add tests and use "any" instead of "inteface" 2025-06-04 15:17:26 +02:00
a8341a9b44 feat(tests): .Close() can be "unchecked" 2025-06-04 14:41:53 +02:00
def5d097a4 feat(tests): Fixing linter problems
Using golangci-lint
2025-06-04 14:29:13 +02:00
ba0ae1bc60 Merge pull request #117 from metal3d/develop
Develop
2025-06-04 09:51:48 +02:00
d77029b597 feat(version): update dependencies
New versions for:
- Cobra
- K8S API
- indirect subpackages
2025-06-04 09:48:52 +02:00
b5f62d43af fix(test): Fix non constant string format
Go 1.24 made several changes about formatting messages:
https://tip.golang.org/doc/go1.24#vet

These changes make tests (and vet) craching.

The fix is to use a string format and give error message as argument.
2025-06-04 09:46:13 +02:00
9220dc3278 fix(test): Fix bad test
We were failing if the test is OK...
2025-06-04 09:24:33 +02:00
36c72fb665 Merge pull request #114 from GSergeevich/readme_fix
Fix example of docker-compose.yml
2025-04-02 15:01:06 +02:00
Герман Плотников
c90504f4f1 Fix example of docker-compose.yml 2025-03-26 18:57:47 +03:00
9ef961ae7c issue(107): Really drop ignored services
It's, at this time, not needed to keep the ignored services inside the
project. Maybe later someone will ask to keep env variables, or
something like this... But at this time, it's a source of bug like #107.
2025-01-19 23:38:17 +01:00
fe6663f9f4 issue(106): Fix service names with dashes
See #106, I need to add a test on "same-pod" label.
2025-01-19 23:24:09 +01:00
1190b316bb Merge pull request #108 from metal3d/develop
Bump versions
2025-01-17 22:19:42 +01:00
7068dc229c Merge pull request #104 from metal3d/dependabot/go_modules/develop/k8s.io/api-0.32.1
chore(deps): bump k8s.io/api from 0.32.0 to 0.32.1
2025-01-17 22:12:36 +01:00
dependabot[bot]
61ce6fb25b chore(deps): bump k8s.io/api from 0.32.0 to 0.32.1
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.32.0 to 0.32.1.
- [Commits](https://github.com/kubernetes/api/compare/v0.32.0...v0.32.1)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-17 21:10:36 +00:00
116ef658d8 Merge pull request #103 from metal3d/dependabot/go_modules/develop/github.com/invopop/jsonschema-0.13.0
chore(deps): bump github.com/invopop/jsonschema from 0.12.0 to 0.13.0
2025-01-17 22:09:53 +01:00
d7b354de8c Merge pull request #105 from metal3d/dependabot/go_modules/develop/k8s.io/apimachinery-0.32.1
chore(deps): bump k8s.io/apimachinery from 0.32.0 to 0.32.1
2025-01-17 22:09:28 +01:00
dependabot[bot]
d06c0574fb chore(deps): bump k8s.io/apimachinery from 0.32.0 to 0.32.1
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.32.0 to 0.32.1.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.0...v0.32.1)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-16 22:31:32 +00:00
dependabot[bot]
bcd7894e3b chore(deps): bump github.com/invopop/jsonschema from 0.12.0 to 0.13.0
Bumps [github.com/invopop/jsonschema](https://github.com/invopop/jsonschema) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/invopop/jsonschema/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: github.com/invopop/jsonschema
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-31 22:51:12 +00:00
80aba05f66 Merge pull request #101 from metal3d/develop
Enhance tests
2024-12-17 18:25:34 +01:00
c97b398914 Merge pull request #96 from metal3d/develop
Fixing docs
2024-12-05 09:47:29 +01:00
0986f73f06 Merge pull request #95 from metal3d/develop
Add SecretName in TLS + adapt github actions
2024-12-05 07:16:33 +01:00
72ddb8aa74 Merge pull request #94 from metal3d/develop
chore(presentation): Update README
2024-12-03 15:14:54 +01:00
130 changed files with 2914 additions and 1249 deletions

View File

@@ -0,0 +1,47 @@
name: Build and push OCI image
on:
push:
tags:
- "**"
env:
REGISTRY: repo.katenary.io
IMAGE_NAME: ${{ gitea.repository }}
VERSION: ${{ gitea.ref_name }}
STORAGE_DRIVER: vfs
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Install Buildah
run: |-
env
if ! command -v buildah 2>/dev/null; then
echo "Install Buildah"
sudo apt-get update
sudo apt-get install -y buildah
else
echo "Buildah already installed"
fi
- name: Login to repository
run: |
buildah login $REGISTRY -u ${{ gitea.actor }} -p ${{ secrets.ACCESS_TOKEN }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Build and tag
run: |-
buildah build --isolation=chroot --build-arg VERSION=$VERSION -t katenary -f ./oci/katenary/Containerfile .
buildah tag katenary $REGISTRY/${IMAGE_NAME,,}:$VERSION
buildah tag katenary $REGISTRY/${IMAGE_NAME,,}:latest
- name: Push image
run: |-
buildah push $REGISTRY/${IMAGE_NAME,,}:$VERSION
buildah push $REGISTRY/${IMAGE_NAME,,}:latest

View File

@@ -0,0 +1,68 @@
name: Go-Tests
on:
pull_request:
types:
- opened
- edited
push:
branches:
- "master"
- "main"
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
jobs:
tests:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.25
- name: Install helm
run: |
command -v helm || curl -sSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Tidy
run: |
go mod tidy
- name: Launch Test
run: |
go vet ./...
go test -coverprofile=coverprofile.out -json -v ./... > gotest.json
# - uses: actions/upload-artifact@v4
- name: Upload artifact
uses: christopherhx/gitea-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:
- name: Checkout
uses: actions/checkout@v4
#- uses: actions/download-artifact@v4
- name: Download artifact
uses: christopherhx/gitea-download-artifact@v4
with:
name: tests-results
- name: Sonar
run: |
export SONAR_SCANNER_VERSION=7.2.0.5079
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux-x64
curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux-x64.zip
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
sonar-scanner \
-Dsonar.organization=katenary \
-Dsonar.projectKey=katenary_katenary

View File

@@ -1,12 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/" # Location of package manifests
schedule:
interval: "daily"
target-branch: develop

View File

@@ -1,47 +0,0 @@
name: Go-Tests
on:
pull_request:
branches:
- develop
push:
branches:
- master
- develop
jobs:
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
- name: Launch Test
run: |
go mod tidy
go vet ./... && go test -coverprofile=coverprofile.out -json -v ./... > gotest.json
- uses: actions/upload-artifact@v4
with:
name: tests-results
path: |
coverprofile.out
gotest.json
sonar:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: tests-results
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

17
.gitignore vendored
View File

@@ -13,8 +13,21 @@ cover*
.config/ .config/
*/venv */venv
# local binary
./katenary
# will be treated later # will be treated later
/examples/* /examples/*
# nsis
nsis/*.dll
nsis/*.exe
doc/share
__pycache__
.rpmmacros
*.gpg
# local binaries
katenary
!cmd/katenary
!oci/katenary

26
.golangci.yml Normal file
View 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"

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2022-2024 Patrice Ferlet Copyright (c) 2022-2025 The Katenary authors
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

235
Makefile
View File

@@ -1,42 +1,64 @@
CUR_SHA=$(shell git log -n1 --pretty='%h') # Strict mode
CUR_BRANCH=$(shell git branch --show-current)
VERSION=$(shell git describe --exact-match --tags $(CUR_SHA) 2>/dev/null || echo $(CUR_BRANCH)-$(CUR_SHA))
CTN:=$(shell which podman 2>&1 1>/dev/null && echo "podman" || echo "docker")
PREFIX=~/.local
GOVERSION=1.23
GO=container
OUT=katenary
RELEASE=""
BLD_CMD=go build -ldflags="-X 'katenary/generator.Version=$(RELEASE)$(VERSION)'" -o $(OUT) ./cmd/katenary
GOOS=linux
GOARCH=amd64
SIGNER=metal3d@gmail.com
BUILD_IMAGE=docker.io/golang:$(GOVERSION)-alpine
# SHELL=/bin/bash
# List of source files
SOURCES=$(wildcard ./*.go ./*/*.go ./*/*/*.go)
# List of binaries to build and sign
BINARIES=dist/katenary-linux-amd64 dist/katenary-linux-arm64 dist/katenary.exe dist/katenary-darwin-amd64 dist/katenary-freebsd-amd64 dist/katenary-freebsd-arm64
# List of signatures to build
ASC_BINARIES=$(patsubst %,%.asc,$(BINARIES))
# defaults
BROWSER=$(shell command -v epiphany || echo xdg-open)
SHELL := bash SHELL := bash
# strict mode
.SHELLFLAGS := -eu -o pipefail -c .SHELLFLAGS := -eu -o pipefail -c
# One session per target
.ONESHELL: .ONESHELL:
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
.PHONY: all binaries build check-dist-all check-dist-archlinux check-dist-debian check-dist-fedora check-dist-rocky check-dist-ubuntu check-sign clean-all clean-dist clean-go-cache clean-package-signer cover deb dist dist-full doc freebsd gpg-sign help install install-gomarkdoc katenary manpage packager-oci-image packages pacman prepare pull rpm rpm-sign sast serve-doc show-cover tar test uninstall upx warn-docker
MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-builtin-rules
.PHONY: help clean build install tests test
# Get a version string from git
CUR_SHA=$(shell git log -n1 --pretty='%h')
CUR_BRANCH=$(shell git branch --show-current)
VERSION=$(shell git describe --exact-match --tags $(CUR_SHA) 2>/dev/null || echo $(CUR_BRANCH)-$(CUR_SHA))# use by golang flags
# Go build command and environment variables for target OS and architecture
GOVERSION=1.25
GO=container# container, local
OUTPUT=katenary
GOOS=linux
GOARCH=amd64
CGO_ENABLED=0
PREFIX=~/.local
# UPX compression
UPX_OPTS =
UPX ?= upx $(UPX_OPTS)
# List of source files
SOURCES=$(shell find -name "*.go" -or -name "*.tpl" -type f | grep -v -P "^./example|^./vendor")
# List of binaries to build and sign
BINARIES=\
dist/katenary-linux-amd64\
dist/katenary-linux-arm64\
dist/katenary-darwin-amd64\
dist/katenary-freebsd-amd64\
dist/katenary-freebsd-arm64\
dist/katenary.exe\
dist/katenary-windows-setup.exe
## GPG
# List of signatures to build
ASC_BINARIES=$(patsubst %,%.asc,$(BINARIES))
# GPG signer
SIGNER=metal3d@gmail.com
# Browser command to see coverage report after tests
BROWSER=$(shell command -v epiphany || echo xdg-open)
include makefiles/build.mk
include makefiles/containers.mk
include makefiles/doc.mk
include makefiles/gpg.mk
include makefiles/packager.mk
include makefiles/test.mk
all: build all: build
# if docker is used instead of podman, we warn the user
warn-docker:
@echo -e "\033[1;31mWarning: Docker is not recommended, use Podman instead.\033[0m"
sleep 5
help: help:
@cat <<EOF | fold -s -w 80 @cat <<EOF | fold -s -w 80
@@ -71,81 +93,11 @@ help:
This will build the binary for darwin amd64. This will build the binary for darwin amd64.
Or you can build all versions: Or you can build all versions:
$$ make build-all $$ make binaries
EOF EOF
## Standard build ## installation and uninstallation
build: pull katenary
pull:
ifneq ($(GO),local)
@echo -e "\033[1;32mPulling $(BUILD_IMAGE) docker image\033[0m"
@$(CTN) pull $(BUILD_IMAGE)
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)
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)
endif
echo "=> Stripping if possible"
strip $(OUT) 2>/dev/null || echo "=> No strip available"
## Release build
dist: prepare $(BINARIES) $(ASC_BINARIES)
prepare: pull
mkdir -p dist
dist/katenary-linux-amd64:
@echo
@echo -e "\033[1;32mBuilding katenary $(VERSION) for linux-amd64...\033[0m"
$(MAKE) katenary GOOS=linux GOARCH=amd64 OUT=$@
dist/katenary-linux-arm64:
@echo
@echo -e "\033[1;32mBuilding katenary $(VERSION) for linux-arm...\033[0m"
$(MAKE) katenary GOOS=linux GOARCH=arm64 OUT=$@
dist/katenary.exe:
@echo
@echo -e "\033[1;32mBuilding katenary $(VERSION) for windows...\033[0m"
$(MAKE) katenary GOOS=windows GOARCH=amd64 OUT=$@
dist/katenary-darwin-amd64:
@echo
@echo -e "\033[1;32mBuilding katenary $(VERSION) for darwin...\033[0m"
$(MAKE) katenary GOOS=darwin GOARCH=amd64 OUT=$@
dist/katenary-freebsd-amd64:
@echo
@echo -e "\033[1;32mBuilding katenary $(VERSION) for freebsd...\033[0m"
$(MAKE) katenary GOOS=freebsd GOARCH=amd64 OUT=$@
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)
dist/%.asc: dist/%
gpg --armor --detach-sign --default-key $(SIGNER) $< &>/dev/null || exit 1
install: build install: build
install -Dm755 katenary $(PREFIX)/bin/katenary install -Dm755 katenary $(PREFIX)/bin/katenary
@@ -153,78 +105,17 @@ install: build
uninstall: uninstall:
rm -f $(PREFIX)/bin/katenary rm -f $(PREFIX)/bin/katenary
clean: ## Miscellaneous
rm -rf katenary dist/* release.id
clean-all: clean-dist clean-package-signer clean-go-cache
serve-doc: __label_doc clean-dist:
@cd doc && \ rm -rf dist
[ -d venv ] || python -m venv venv; \ rm -f katenary
source venv/bin/activate && \
echo "==> Installing requirements in the virtual env..."
pip install -qq -r requirements.txt && \
echo "==> Serving doc with mkdocs..." && \
mkdocs serve
tests: test clean-package-signer:
test: rm -f .secret.gpg .rpmmacros
@echo -e "\033[1;33mTesting katenary $(VERSION)...\033[0m"
go test -coverprofile=cover.out ./...
$(MAKE) cover
cover: clean-go-cache:
go tool cover -func=cover.out | grep "total:" $(CTN) volume rm -f go-cache
go tool cover -html=cover.out -o cover.html
if [ "$(BROWSER)" = "xdg-open" ]; then
xdg-open cover.html
else
$(BROWSER) -i --new-window cover.html
fi
push-release: build-all
@rm -f release.id
# read personal access token from .git-credentials
TOKEN=$(shell cat .credentials)
# create a new release based on current tag and get the release id
@curl -sSL -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $$TOKEN" \
-d "{\"tag_name\": \"$(VERSION)\", \"target_commitish\": \"\", \"name\": \"$(VERSION)\", \"draft\": true, \"prerelease\": true}" \
https://api.github.com/repos/metal3d/katenary/releases | jq -r '.id' > release.id
@echo "Release id: $$(cat release.id) created"
@echo "Uploading assets..."
# push all dist binary as assets to the release
@for i in $$(find dist -type f -name "katenary*"); do
curl -sSL -H "Authorization: token $$TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/octet-stream" \
--data-binary @$$i \
https://uploads.github.com/repos/metal3d/katenary/releases/$$(cat release.id)/assets?name=$$(basename $$i)
done
@rm -f release.id
__label_doc:
@command -v gomarkdoc || (echo "==> We need to install gomarkdoc..." && \
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest)
@echo "=> Generating labels doc..."
# short label doc
go run ./cmd/katenary help-labels -m | \
sed -i '
/START_LABEL_DOC/,/STOP_LABEL_DOC/{/<!--/!d};
/START_LABEL_DOC/,/STOP_LABEL_DOC/r/dev/stdin
' doc/docs/labels.md
# detailed label doc
go run ./cmd/katenary help-labels -am | sed 's/^##/###/' | \
sed -i '
/START_DETAILED_DOC/,/STOP_DETAILED_DOC/{/<!--/!d};
/START_DETAILED_DOC/,/STOP_DETAILED_DOC/r/dev/stdin
' doc/docs/labels.md
echo "=> Generating Code documentation..."
PACKAGES=$$(for f in $$(find . -name "*.go" -type f); do dirname $$f; done | sort -u)
for pack in $$PACKAGES; do
echo "-> Generating doc for $$pack"
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

187
README.md
View File

@@ -4,14 +4,10 @@
<div style="text-align:center; margin: auto 0 4em 0" align="center"> <div style="text-align:center; margin: auto 0 4em 0" align="center">
[![Documentation Status](https://readthedocs.org/projects/katenary/badge/?version=latest)](https://katenary.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/katenary/badge/?version=latest)](https://katenary.readthedocs.io/latest/?badge=latest)
[![Go Report Card](https://goreportcard.com/badge/github.com/metal3d/katenary)](https://goreportcard.com/report/github.com/metal3d/katenary) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=katenary_katenary&metric=coverage)](https://sonarcloud.io/summary/new_code?id=katenary_katenary)
[![GitHub release](https://img.shields.io/github/v/release/metal3d/katenary)](https://github.com/metal3d/katenary/releases) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=katenary_katenary&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=katenary_katenary)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=metal3d_katenary&metric=coverage)](https://sonarcloud.io/summary/new_code?id=metal3d_katenary) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=katenary_katenary&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=katenary_katenary)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=metal3d_katenary&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=metal3d_katenary&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=metal3d_katenary&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=metal3d_katenary)
</div> </div>
@@ -41,16 +37,16 @@ The main developer is [Patrice FERLET](https://github.com/metal3d).
## Install ## Install
You can download the binaries from the [Release](https://github.com/metal3d/katenary/releases) section. Copy the binary You can download the binaries from the [Release](https://github.com/Katenary/katenary/releases) section. Copy the binary
and rename it to `katenary`. Place the binary inside your `PATH`. You should now be able to call the `katenary` command. and rename it to `katenary`. Place the binary inside your `PATH`. You should now be able to call the `katenary` command.
You can of course get the binary with `go install -u github.com/metal3d/katenary/cmd/katenary/...` but the `main` branch You can of course get the binary with `go install -u github.com/Katenary/katenary/cmd/katenary/...` but the `main` branch
is continuously updated. It's preferable to use releases. is continuously updated. It's preferable to use releases.
You can use this commands on Linux: You can use this commands on Linux:
```bash ```bash
sh <(curl -sSL https://raw.githubusercontent.com/metal3d/katenary/master/install.sh) sh <(curl -sSL https://raw.githubusercontent.com/Katenary/katenary/master/install.sh)
``` ```
## Or, build yourself ## Or, build yourself
@@ -111,6 +107,7 @@ katenary completion fish | source
## Usage ## Usage
```text ```text
Katenary is a tool to convert compose files to Helm Charts. Katenary is a tool to convert compose files to Helm Charts.
Each [command] and subcommand has got an "help" and "--help" flag to show more information. Each [command] and subcommand has got an "help" and "--help" flag to show more information.
@@ -137,69 +134,69 @@ Flags:
Use "katenary [command] --help" for more information about a command. Use "katenary [command] --help" for more information about a command.
``` ```
Katenary will try to find a `docker-compose.yaml` or `docker-compose.yml` file inside the current directory. It will Katenary will try to find a `docker-compose.yaml` or `docker-compose.yml` file inside the current directory. It will
check *the existence of the `chart` directory to create a new Helm Chart inside a named subdirectory. Katenary will ask check \*the existence of the `chart` directory to create a new Helm Chart inside a named subdirectory. Katenary will ask
you if you want to delete it before recreating. you if you want to delete it before recreating.
It creates a subdirectory inside `chart` that is named with the `appname` option (default is `MyApp`) It creates a subdirectory inside `chart` that is named with the `appname` option (default is `MyApp`)
> To respect the ability to install the same application in the same namespace, Katenary will create variable names > To respect the ability to install the same application in the same namespace, Katenary will create variable names
> like `{{ .Release.Name }}-servicename`. So, you will need to use some labels inside your docker-compose file to help > like `{{ .Release.Name }}-servicename`. So, you will need to use some labels inside your docker-compose file to help
> Katenary to build a correct helm chart. > Katenary to build a correct helm chart.
Example of a possible `docker-compose.yaml` file: Example of a possible `docker-compose.yaml` file:
```yaml ```yaml
services: services:
webapp: webapp:
image: php:7-apache image: php:7-apache
environment: environment:
# note that "database" is a "compose" service name # note that "database" is a "compose" service name
# so we need to adapt it with the map-env label # so we need to adapt it with the map-env label
DB_HOST: database DB_HOST: database
# a pitty to repeat this values, isn't it? # a pitty to repeat this values, isn't it?
# so, let's change them with "values-from" label # so, let's change them with "values-from" label
DB_USER: foo DB_USER: foo
DB_PASSWORD: bar DB_PASSWORD: bar
expose: expose:
- 80 - 80
depends_on: depends_on:
# this will create a init container waiting for 3306 port # this will create a init container waiting for 3306 port
# because it's the "exposed" port # because it's the "exposed" port
- database - database
labels: labels:
# expose the port 80 as an ingress # expose the port 80 as an ingress
katenary.v3/ingress: |- katenary.v3/ingress: |-
hostname: myapp.example.com hostname: myapp.example.com
port: 80 port: 80
# make adaptations, DB_HOST environment is actually the service name # make adaptations, DB_HOST environment is actually the service name
katenary.v3/map-env: |- katenary.v3/map-env: |-
DB_HOST: '{{ .Release.Name }}-database' DB_HOST: '{{ .Release.Name }}-database'
# get the values from the "database" service # get the values from the "database" service
# this will use the database secrets and environment, # this will use the database secrets and environment,
# see the "database" service to see the values # see the "database" service to see the values
katenary.v3/values-from: |- katenary.v3/values-from: |-
DB_USER: databse.MARIADB_USER DB_USER: database.MARIADB_USER
DB_PASSWORD: database.MARIADB_PASSWORD DB_PASSWORD: database.MARIADB_PASSWORD
database: database:
image: mariadb:10 image: mariadb:10
env_file: env_file:
# this valuse will be added in a configMap # this values will be added in a configMap
- my_env.env - my_env.env
environment: environment:
MARIADB_USER: foo MARIADB_USER: foo
MARIADB_ROOT_PASSWORD: foobar MARIADB_ROOT_PASSWORD: foobar
MARIADB_PASSWORD: bar MARIADB_PASSWORD: bar
labels: labels:
# no need to declare this port in docker-compose # no need to declare this port in docker-compose
# but katenary will need it # but katenary will need it
katenary.v3/ports: |- katenary.v3/ports: |-
- 3306 - 3306
# these variables are secrets # these variables are secrets
katenary.v3/secrets: |- katenary.v3/secrets: |-
- MARIADB_ROOT_PASSWORD - MARIADB_ROOT_PASSWORD
- MARIADB_PASSWORD - MARIADB_PASSWORD
``` ```
## Labels ## Labels
@@ -210,22 +207,22 @@ These labels could be found by `katenary help-labels`, and can be placed as labe
To get more information about a label, use `katenary help-label <name_without_prefix> To get more information about a label, use `katenary help-label <name_without_prefix>
e.g. katenary help-label dependencies e.g. katenary help-label dependencies
katenary.v3/configmap-files: list of strings Add files to the configmap. katenary.v3/configmap-files: []string Inject files as Configmap.
katenary.v3/cronjob: object Create a cronjob from the service. katenary.v3/cronjob: object Create a cronjob from the service.
katenary.v3/dependencies: list of objects Add Helm dependencies to the service. katenary.v3/dependencies: []object Add Helm dependencies to the service.
katenary.v3/description: string Description of the service katenary.v3/description: string Description of the service
katenary.v3/env-from: list of strings Add environment variables from antoher service. katenary.v3/env-from: []string Add environment variables from another service.
katenary.v3/exchange-volumes: list of objects Add exchange volumes (empty directory on the node) to share data katenary.v3/exchange-volumes: []object Add exchange volumes (empty directory on the node) to share data
katenary.v3/health-check: object Health check to be added to the deployment. katenary.v3/health-check: object Health check to be added to the deployment.
katenary.v3/ignore: bool Ignore the service katenary.v3/ignore: bool Ignore the service
katenary.v3/ingress: object Ingress rules to be added to the service. katenary.v3/ingress: object Ingress rules to be added to the service.
katenary.v3/main-app: bool Mark the service as the main app. katenary.v3/main-app: bool Mark the service as the main app.
katenary.v3/map-env: object Map env vars from the service to the deployment. katenary.v3/map-env: map[string]string Map env vars from the service to the deployment.
katenary.v3/ports: list of uint32 Ports to be added to the service. katenary.v3/ports: []uint32 Ports to be added to the service.
katenary.v3/same-pod: string Move the same-pod deployment to the target deployment. katenary.v3/same-pod: string Move the same-pod deployment to the target deployment.
katenary.v3/secrets: list of string Env vars to be set as secrets. katenary.v3/secrets: []string Env vars to be set as secrets.
katenary.v3/values: list of string or map Environment variables to be added to the values.yaml katenary.v3/values: []string or map[string]string Environment variables to be added to the values.yaml
katenary.v3/values-from: map[string]string Add values from another service. katenary.v3/values-from: map[string]string Add values from another service.
``` ```
## Katenary.yaml file and schema validation ## Katenary.yaml file and schema validation
@@ -237,25 +234,25 @@ For example, instead of using this:
```yaml ```yaml
services: services:
web: web:
image: nginx:latest image: nginx:latest
katenary.v3/ingress: |- katenary.v3/ingress: |-
hostname: myapp.example.com hostname: myapp.example.com
port: 80 port: 80
``` ```
You can remove the labels, and use a kanetary.yaml file: You can remove the labels, and use a `katenary.yaml` file:
```yaml ```yaml
web: web:
ingress: ingress:
hostname: myapp.example.com hostname: myapp.example.com
port: 80 port: 80
``` ```
To validate the `katenary.yaml` file, you can use the JSON schema using the "master" raw content: To validate the `katenary.yaml` file, you can use the JSON schema using the "master" raw content:
`https://raw.githubusercontent.com/metal3d/katenary/refs/heads/master/katenary.json` `https://raw.githubusercontent.com/Katenary/katenary/refs/heads/master/katenary.json`
It's easy to configure in [LazyVim](https://www.lazyvim.org/), using `nvim-lspconfig`, It's easy to configure in [LazyVim](https://www.lazyvim.org/), using `nvim-lspconfig`,
create a Lua file in your `plugins` directory, or apply the settings as the example below: create a Lua file in your `plugins` directory, or apply the settings as the example below:
@@ -272,7 +269,7 @@ return {
settings = { settings = {
yaml = { yaml = {
schemas = { schemas = {
["https://raw.githubusercontent.com/metal3d/katenary/master/katenary.json"] = "katenary.yaml", ["https://raw.githubusercontent.com/Katenary/katenary/master/katenary.json"] = "katenary.yaml",
}, },
}, },
}, },
@@ -287,9 +284,9 @@ Use this address to validate the `katenary.yaml` file in VSCode:
```json ```json
{ {
"yaml.schemas": { "yaml.schemas": {
"https://raw.githubusercontent.com/metal3d/katenary/master/katenary.json": "katenary.yaml" "https://raw.githubusercontent.com/Katenary/katenary/master/katenary.json": "katenary.yaml"
} }
} }
``` ```

View File

@@ -6,13 +6,15 @@ package main
import ( import (
"fmt" "fmt"
"katenary/generator" "log"
"katenary/generator/katenaryfile"
"katenary/generator/labels"
"katenary/utils"
"os" "os"
"strings" "strings"
"github.com/katenary/katenary/internal/generator"
"github.com/katenary/katenary/internal/generator/katenaryfile"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/cli" "github.com/compose-spec/compose-go/cli"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -24,7 +26,10 @@ Each [command] and subcommand has got an "help" and "--help" flag to show more i
func main() { func main() {
rootCmd := buildRootCmd() rootCmd := buildRootCmd()
rootCmd.Execute()
if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}
} }
func buildRootCmd() *cobra.Command { func buildRootCmd() *cobra.Command {
@@ -97,26 +102,26 @@ func generateCompletionCommand(name string) *cobra.Command {
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
Short: "Generates completion scripts", Short: "Generates completion scripts",
Long: fmt.Sprintf(completionHelp, name), Long: fmt.Sprintf(completionHelp, name),
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {
cmd.Help() return cmd.Help()
return
} }
switch args[0] { switch args[0] {
case "bash": case "bash":
// get the bash version // get the bash version
if cmd.Flags().Changed("bash-v1") { if cmd.Flags().Changed("bash-v1") {
cmd.Root().GenBashCompletion(os.Stdout) return cmd.Root().GenBashCompletion(os.Stdout)
return
} }
cmd.Root().GenBashCompletionV2(os.Stdout, true) return cmd.Root().GenBashCompletionV2(os.Stdout, true)
case "zsh": case "zsh":
cmd.Root().GenZshCompletion(os.Stdout) return cmd.Root().GenZshCompletion(os.Stdout)
case "fish": case "fish":
cmd.Root().GenFishCompletion(os.Stdout, true) return cmd.Root().GenFishCompletion(os.Stdout, true)
case "powershell": case "powershell":
cmd.Root().GenPowerShellCompletion(os.Stdout) return cmd.Root().GenPowerShellCompletion(os.Stdout)
} }
return fmt.Errorf("unknown completion type: %s", args[0])
}, },
} }
@@ -142,7 +147,7 @@ func generateConvertCommand() *cobra.Command {
Use: "convert", Use: "convert",
Short: "Converts a docker-compose file to a Helm Chart", Short: "Converts a docker-compose file to a Helm Chart",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
if givenAppVersion != "" { if len(strings.TrimSpace(givenAppVersion)) > 0 {
appVersion = &givenAppVersion appVersion = &givenAppVersion
} }
return generator.Convert(generator.ConvertOptions{ return generator.Convert(generator.ConvertOptions{

View File

@@ -13,8 +13,7 @@ func TestBuildCommand(t *testing.T) {
rootCmd := buildRootCmd() rootCmd := buildRootCmd()
if rootCmd == nil { if rootCmd == nil {
t.Errorf("Expected rootCmd to be defined") t.Errorf("Expected rootCmd to be defined")
} } else if rootCmd.Use != "katenary" {
if rootCmd.Use != "katenary" {
t.Errorf("Expected rootCmd.Use to be katenary, got %s", rootCmd.Use) t.Errorf("Expected rootCmd.Use to be katenary, got %s", rootCmd.Use)
} }
numCommands := 6 numCommands := 6
@@ -53,18 +52,27 @@ func TestSchemaCommand(t *testing.T) {
} }
schema := generateSchemaCommand() schema := generateSchemaCommand()
old := os.Stdout old := os.Stdout
r, w, _ := os.Pipe() r, w, err := os.Pipe()
if err != nil {
t.Fatalf("Failed to create pipe: %v", err)
}
os.Stdout = w os.Stdout = w
schema.Run(cmd, nil)
w.Close()
os.Stdout = old
var buf bytes.Buffer var buf bytes.Buffer
done := make(chan struct{})
go func() {
schema.Run(cmd, nil)
w.Close()
close(done)
}()
io.Copy(&buf, r) io.Copy(&buf, r)
output := buf.String() <-done
os.Stdout = old
// try to parse json // try to parse json
schemaContent := make(map[string]interface{}) schemaContent := make(map[string]any)
if err := json.Unmarshal([]byte(output), &schemaContent); err != nil { if err := json.Unmarshal(buf.Bytes(), &schemaContent); err != nil {
t.Errorf("Expected valid json, got %s", output) t.Errorf("Expected valid json")
} }
} }

View File

@@ -0,0 +1,9 @@
MD012: false
MD013: false
MD022: false
MD033: false
MD041: false
MD046: false
# list indentation
MD007:
indent: 4

View File

@@ -4,7 +4,7 @@ Katenary uses `compose-go` and several Kubernetes official packages.
- `github.com/compose-spec/compose-go`: to parse compose files. It ensures : - `github.com/compose-spec/compose-go`: to parse compose files. It ensures :
- that the project respects the "compose" specification - that the project respects the "compose" specification
- that Katenary uses the "compose" struct exactly the same way `podman compose` or `docker copose` does - that Katenary uses the "compose" struct exactly the same way `podman compose` or `docker compose` does
- `github.com/spf13/cobra`: to parse command line arguments, sub-commands and flags. It also generates completion for - `github.com/spf13/cobra`: to parse command line arguments, sub-commands and flags. It also generates completion for
bash, zsh, fish and PowerShell. bash, zsh, fish and PowerShell.
- `github.com/thediveo/netdb`: to get the standard names of a service from its port number - `github.com/thediveo/netdb`: to get the standard names of a service from its port number

View File

@@ -19,9 +19,10 @@ and flexibility.
Kompose is able to generate Helm charts, but [it could be not the case in future releases](https://github.com/kubernetes/kompose/issues/1716) for several reasons[^2]. Kompose is able to generate Helm charts, but [it could be not the case in future releases](https://github.com/kubernetes/kompose/issues/1716) for several reasons[^2].
[^2]: The author of Kompose explains that they have no bandwidth to maintain the Helm chart generation. It's a complex [^2]:
task, and we can confirm. Katenary takes a lot of time to be developed and maintained. This issue mentions Katenary as The author of Kompose explains that they have no bandwidth to maintain the Helm chart generation. It's a complex
an alternative to Helm chart generation :smile: task, and we can confirm. Katenary takes a lot of time to be developed and maintained. This issue mentions Katenary as
an alternative to Helm chart generation :smile:
The project is focused on Kubernetes manifests and proposes to use "Kustomize" to adapt the manifests. Helm seems to be The project is focused on Kubernetes manifests and proposes to use "Kustomize" to adapt the manifests. Helm seems to be
not the priority. not the priority.
@@ -86,9 +87,9 @@ tested some concepts.
You can help us in many ways. You can help us in many ways.
- The first things we really need, more than money, more than anything else, is to have feedback. If you use Katenary, - The first things we really need, more than money, more than anything else, is to have feedback. If you use Katenary,
if you have some issues, if you have some ideas, please open an issue on the [GitHub repository](https://github.com/metal3d/katenary). if you have some issues, if you have some ideas, please open an issue on the [GitHub repository](https://github.com/Katenary/katenary).
- The second thing is to help us to fix issues. If you're a Go developer, or if you want to fix the documentation, - The second thing is to help us to fix issues. If you're a Go developer, or if you want to fix the documentation,
your help is greatly appreciated. your help is greatly appreciated.
- And then, of course, we need money, or sponsors. - And then, of course, we need money, or sponsors.
### If you're a company ### If you're a company
@@ -105,6 +106,7 @@ All main contributors[^3] will be listed on the website and in the documentation
> If you want to be anonymous, please tell us. > If you want to be anonymous, please tell us.
[^3]: Main contributors are the people who have made a significant contribution to the project. It could be code, [^3]:
documentation, or any other help. There is no defined rules, at this time, to evaluate the contribution. Main contributors are the people who have made a significant contribution to the project. It could be code,
It's a subjective decision. documentation, or any other help. There is no defined rules, at this time, to evaluate the contribution.
It's a subjective decision.

View File

@@ -42,13 +42,13 @@ share it with the community.
The main developer is [Patrice FERLET](https://github.com/metal3d). The main developer is [Patrice FERLET](https://github.com/metal3d).
The project source The project source
code is hosted on the [:fontawesome-brands-github: Katenary GitHub Repository](https://github.com/metal3d/katenary). code is hosted on the [:fontawesome-brands-github: Katenary GitHub Repository](https://github.com/Katenary/katenary).
## Install Katenary ## Install Katenary
Katenary is developed using the :fontawesome-brands-golang:{ .gopher } [Go](https://go.dev) language. Katenary is developed using the :fontawesome-brands-golang:{ .gopher } [Go](https://go.dev) language.
The binary is statically linked, so you can simply download it from the [release The binary is statically linked, so you can simply download it from the [release
page](https://github.com/metal3d/katenary/releases) of the project in GitHub. page](https://github.com/Katenary/katenary/releases) of the project in GitHub.
You need to select the right binary for your operating system and architecture, and copy the binary in a directory You need to select the right binary for your operating system and architecture, and copy the binary in a directory
that is in your `PATH`. that is in your `PATH`.
@@ -57,17 +57,17 @@ If you are a Linux user, you can use the "one line installation command" which w
`$HOME/.local/bin` directory if it exists. `$HOME/.local/bin` directory if it exists.
```bash ```bash
sh <(curl -sSL https://raw.githubusercontent.com/metal3d/katenary/master/install.sh) sh <(curl -sSL https://raw.githubusercontent.com/Katenary/katenary/master/install.sh)
``` ```
!!! Info "Upgrading is integrated to the `katenary` command" !!! Info "Upgrading is integrated to the `katenary` command"
Katenary propose a `upgrade` sub-command to update the current binary to the latest stable release. Katenary propose a `upgrade` sub-command to update the current binary to the latest stable release.
Of course, you need to install Katenary once :smile: Of course, you need to install Katenary once :smile:
!!! Note "You prefer to compile it, no need to install Go" !!! Note "You prefer to compile it, no need to install Go"
You can also build and install it yourself, the provided Makefile has got a `build` command that uses `podman` or You can also build and install it yourself, the provided Makefile has got a `build` command that uses `podman` or
`docker` to build the binary. `docker` to build the binary.
So, you don't need to install Go compiler :+1:. So, you don't need to install Go compiler :+1:.
@@ -77,7 +77,7 @@ sh <(curl -sSL https://raw.githubusercontent.com/metal3d/katenary/master/install
To compile it, you can use the following commands: To compile it, you can use the following commands:
```bash ```bash
git clone https://github.com/metal3d/katenary.git git clone https://github.com/Katenary/katenary.git
cd katenary cd katenary
make build make build
make install make install
@@ -127,7 +127,7 @@ thing! :heart:
!!! Edit "Special thanks" !!! Edit "Special thanks"
**Katenary is built with:** <br /> **Katenary is built with:** <br />
<a href="https://go.dev" target="_blank">:fontawesome-brands-golang:{ .go-logo }</a> <a href="https://go.dev" target="_blank">:fontawesome-brands-golang:{ .go-logo }</a>

View File

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

View File

@@ -3,7 +3,7 @@
# katenary # katenary
```go ```go
import "katenary/cmd/katenary" import "github.com/katenary/katenary/cmd/katenary"
``` ```
Katenary CLI, main package. Katenary CLI, main package.

View File

@@ -1,67 +0,0 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# katenaryfile
```go
import "katenary/generator/katenaryfile"
```
Package katenaryfile is a package for reading and writing katenary files.
A katenary file, named "katenary.yml" or "katenary.yaml", is a file where you can define the configuration of the conversion avoiding the use of labels in the compose file.
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>)
```go
func GenerateSchema() string
```
GenerateSchema generates the schema for the katenary.yaml file.
<a name="OverrideWithConfig"></a>
## func [OverrideWithConfig](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryfile/main.go#L49>)
```go
func OverrideWithConfig(project *types.Project)
```
OverrideWithConfig overrides the project with the katenary.yaml file. It will set the labels of the services with the values from the katenary.yaml file. It work in memory, so it will not modify the original project.
<a name="Service"></a>
## type [Service](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryfile/main.go#L27-L44>)
Service is a struct that contains the service configuration for katenary
```go
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"`
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)"`
}
```
<a name="StringOrMap"></a>
## type [StringOrMap](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryfile/main.go#L24>)
StringOrMap is a struct that can be either a string or a map of strings. It's a helper struct to unmarshal the katenary.yaml file and produce the schema
```go
type StringOrMap any
```
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -3,10 +3,10 @@
# generator # generator
```go ```go
import "katenary/generator" import "github.com/katenary/katenary/internal/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. 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> <a name="Convert"></a>
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L93>) ## func [Convert](<https://github.com/katenary/katenary/blob/master/internal/generator/converter.go#L100>)
```go ```go
func Convert(config ConvertOptions, dockerComposeFile ...string) error func Convert(config ConvertOptions, dockerComposeFile ...string) error
@@ -44,7 +44,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error
Convert a compose \(docker, podman...\) project to a helm chart. It calls Generate\(\) to generate the chart and then write it to the disk. Convert a compose \(docker, podman...\) project to a helm chart. It calls Generate\(\) to generate the chart and then write it to the disk.
<a name="GetLabels"></a> <a name="GetLabels"></a>
## func [GetLabels](<https://github.com/metal3d/katenary/blob/develop/generator/labels.go#L12>) ## func [GetLabels](<https://github.com/katenary/katenary/blob/master/internal/generator/labels.go#L12>)
```go ```go
func GetLabels(serviceName, appName string) map[string]string func GetLabels(serviceName, appName string) map[string]string
@@ -53,7 +53,7 @@ func GetLabels(serviceName, appName string) map[string]string
GetLabels returns the labels for a service. It uses the appName to replace the \_\_replace\_\_ in the labels. This is used to generate the labels in the templates. GetLabels returns the labels for a service. It uses the appName to replace the \_\_replace\_\_ in the labels. This is used to generate the labels in the templates.
<a name="GetMatchLabels"></a> <a name="GetMatchLabels"></a>
## func [GetMatchLabels](<https://github.com/metal3d/katenary/blob/develop/generator/labels.go#L25>) ## func [GetMatchLabels](<https://github.com/katenary/katenary/blob/master/internal/generator/labels.go#L25>)
```go ```go
func GetMatchLabels(serviceName, appName string) map[string]string func GetMatchLabels(serviceName, appName string) map[string]string
@@ -62,7 +62,7 @@ func GetMatchLabels(serviceName, appName string) map[string]string
GetMatchLabels returns the matchLabels for a service. It uses the appName to replace the \_\_replace\_\_ in the labels. This is used to generate the matchLabels in the templates. GetMatchLabels returns the matchLabels for a service. It uses the appName to replace the \_\_replace\_\_ in the labels. This is used to generate the matchLabels in the templates.
<a name="GetVersion"></a> <a name="GetVersion"></a>
## func [GetVersion](<https://github.com/metal3d/katenary/blob/develop/generator/version.go#L14>) ## func [GetVersion](<https://github.com/katenary/katenary/blob/master/internal/generator/version.go#L14>)
```go ```go
func GetVersion() string func GetVersion() string
@@ -71,7 +71,7 @@ func GetVersion() string
GetVersion return the version of katneary. It's important to understand that the version is set at compile time for the github release. But, it the user get katneary using \`go install\`, the version should be different. GetVersion return the version of katneary. It's important to understand that the version is set at compile time for the github release. But, it the user get katneary using \`go install\`, the version should be different.
<a name="Helper"></a> <a name="Helper"></a>
## func [Helper](<https://github.com/metal3d/katenary/blob/develop/generator/helper.go#L15>) ## func [Helper](<https://github.com/katenary/katenary/blob/master/internal/generator/helper.go#L15>)
```go ```go
func Helper(name string) string func Helper(name string) string
@@ -80,7 +80,7 @@ func Helper(name string) string
Helper returns the \_helpers.tpl file for a chart. Helper returns the \_helpers.tpl file for a chart.
<a name="NewCronJob"></a> <a name="NewCronJob"></a>
## func [NewCronJob](<https://github.com/metal3d/katenary/blob/develop/generator/cronJob.go#L28>) ## func [NewCronJob](<https://github.com/katenary/katenary/blob/master/internal/generator/cronJob.go#L28>)
```go ```go
func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (*CronJob, *RBAC) func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (*CronJob, *RBAC)
@@ -89,16 +89,16 @@ func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (
NewCronJob creates a new CronJob from a compose service. The appName is the name of the application taken from the project name. NewCronJob creates a new CronJob from a compose service. The appName is the name of the application taken from the project name.
<a name="ToK8SYaml"></a> <a name="ToK8SYaml"></a>
## func [ToK8SYaml](<https://github.com/metal3d/katenary/blob/develop/generator/utils.go#L90>) ## func [ToK8SYaml](<https://github.com/katenary/katenary/blob/master/internal/generator/utils.go#L91>)
```go ```go
func ToK8SYaml(obj interface{}) ([]byte, error) func ToK8SYaml(obj any) ([]byte, error)
``` ```
<a name="UnWrapTPL"></a> <a name="UnWrapTPL"></a>
## func [UnWrapTPL](<https://github.com/metal3d/katenary/blob/develop/generator/utils.go#L86>) ## func [UnWrapTPL](<https://github.com/katenary/katenary/blob/master/internal/generator/utils.go#L87>)
```go ```go
func UnWrapTPL(in []byte) []byte func UnWrapTPL(in []byte) []byte
@@ -107,7 +107,7 @@ func UnWrapTPL(in []byte) []byte
UnWrapTPL removes the line wrapping from a template. UnWrapTPL removes the line wrapping from a template.
<a name="ChartTemplate"></a> <a name="ChartTemplate"></a>
## type [ChartTemplate](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L19-L22>) ## type [ChartTemplate](<https://github.com/katenary/katenary/blob/master/internal/generator/chart.go#L22-L25>)
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. 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.
@@ -119,7 +119,7 @@ type ChartTemplate struct {
``` ```
<a name="ConfigMap"></a> <a name="ConfigMap"></a>
## type [ConfigMap](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L37-L42>) ## type [ConfigMap](<https://github.com/katenary/katenary/blob/master/internal/generator/configMap.go#L37-L42>)
ConfigMap is a kubernetes ConfigMap. Implements the DataMap interface. ConfigMap is a kubernetes ConfigMap. Implements the DataMap interface.
@@ -131,7 +131,7 @@ type ConfigMap struct {
``` ```
<a name="NewConfigMap"></a> <a name="NewConfigMap"></a>
### func [NewConfigMap](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L46>) ### func [NewConfigMap](<https://github.com/katenary/katenary/blob/master/internal/generator/configMap.go#L46>)
```go ```go
func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *ConfigMap func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *ConfigMap
@@ -140,7 +140,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
NewConfigMap creates a new ConfigMap from a compose service. The appName is the name of the application taken from the project name. The ConfigMap is filled by environment variables and labels "map\-env". NewConfigMap creates a new ConfigMap from a compose service. The appName is the name of the application taken from the project name. The ConfigMap is filled by environment variables and labels "map\-env".
<a name="NewConfigMapFromDirectory"></a> <a name="NewConfigMapFromDirectory"></a>
### func [NewConfigMapFromDirectory](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L119>) ### func [NewConfigMapFromDirectory](<https://github.com/katenary/katenary/blob/master/internal/generator/configMap.go#L119>)
```go ```go
func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap
@@ -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. 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> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L157>)
```go ```go
func (c *ConfigMap) AddBinaryData(key string, value []byte) 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. AddBinaryData adds binary data to the configmap. Append or overwrite the value if the key already exists.
<a name="ConfigMap.AddData"></a> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L152>)
```go ```go
func (c *ConfigMap) AddData(key, value string) 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. AddData adds a key value pair to the configmap. Append or overwrite the value if the key already exists.
<a name="ConfigMap.AppendDir"></a> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L166>)
```go ```go
func (c *ConfigMap) AppendDir(path string) error 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> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L213>)
```go ```go
func (c *ConfigMap) AppendFile(path string) error func (c *ConfigMap) AppendFile(path string) error
@@ -185,7 +185,7 @@ func (c *ConfigMap) AppendFile(path string) error
<a name="ConfigMap.Filename"></a> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L237>)
```go ```go
func (c *ConfigMap) Filename() string 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. Filename returns the filename of the configmap. If the configmap is used for files, the filename contains the path.
<a name="ConfigMap.SetData"></a> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L247>)
```go ```go
func (c *ConfigMap) SetData(data map[string]string) 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. SetData sets the data of the configmap. It replaces the entire data.
<a name="ConfigMap.Yaml"></a> <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/katenary/katenary/blob/master/internal/generator/configMap.go#L252>)
```go ```go
func (c *ConfigMap) Yaml() ([]byte, error) func (c *ConfigMap) Yaml() ([]byte, error)
@@ -212,7 +212,7 @@ func (c *ConfigMap) Yaml() ([]byte, error)
Yaml returns the yaml representation of the configmap Yaml returns the yaml representation of the configmap
<a name="ConfigMapMount"></a> <a name="ConfigMapMount"></a>
## type [ConfigMapMount](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L28-L31>) ## type [ConfigMapMount](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L28-L31>)
@@ -223,7 +223,7 @@ type ConfigMapMount struct {
``` ```
<a name="ConvertOptions"></a> <a name="ConvertOptions"></a>
## type [ConvertOptions](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L25-L34>) ## type [ConvertOptions](<https://github.com/katenary/katenary/blob/master/internal/generator/chart.go#L28-L37>)
ConvertOptions are the options to convert a compose project to a helm chart. ConvertOptions are the options to convert a compose project to a helm chart.
@@ -241,7 +241,7 @@ type ConvertOptions struct {
``` ```
<a name="CronJob"></a> <a name="CronJob"></a>
## type [CronJob](<https://github.com/metal3d/katenary/blob/develop/generator/cronJob.go#L22-L25>) ## type [CronJob](<https://github.com/katenary/katenary/blob/master/internal/generator/cronJob.go#L22-L25>)
CronJob is a kubernetes CronJob. CronJob is a kubernetes CronJob.
@@ -253,7 +253,7 @@ type CronJob struct {
``` ```
<a name="CronJob.Filename"></a> <a name="CronJob.Filename"></a>
### func \(\*CronJob\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/cronJob.go#L114>) ### func \(\*CronJob\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/cronJob.go#L114>)
```go ```go
func (c *CronJob) Filename() string func (c *CronJob) Filename() string
@@ -264,7 +264,7 @@ Filename returns the filename of the cronjob.
Implements the Yaml interface. Implements the Yaml interface.
<a name="CronJob.Yaml"></a> <a name="CronJob.Yaml"></a>
### func \(\*CronJob\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/cronJob.go#L121>) ### func \(\*CronJob\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/cronJob.go#L121>)
```go ```go
func (c *CronJob) Yaml() ([]byte, error) func (c *CronJob) Yaml() ([]byte, error)
@@ -275,7 +275,7 @@ Yaml returns the yaml representation of the cronjob.
Implements the Yaml interface. Implements the Yaml interface.
<a name="CronJobValue"></a> <a name="CronJobValue"></a>
## type [CronJobValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L113-L118>) ## type [CronJobValue](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L118-L123>)
CronJobValue is a cronjob configuration that will be saved in values.yaml. CronJobValue is a cronjob configuration that will be saved in values.yaml.
@@ -289,7 +289,7 @@ type CronJobValue struct {
``` ```
<a name="DataMap"></a> <a name="DataMap"></a>
## type [DataMap](<https://github.com/metal3d/katenary/blob/develop/generator/types.go#L4-L7>) ## type [DataMap](<https://github.com/katenary/katenary/blob/master/internal/generator/types.go#L4-L7>)
DataMap is a kubernetes ConfigMap or Secret. It can be used to add data to the ConfigMap or Secret. DataMap is a kubernetes ConfigMap or Secret. It can be used to add data to the ConfigMap or Secret.
@@ -301,7 +301,7 @@ type DataMap interface {
``` ```
<a name="Deployment"></a> <a name="Deployment"></a>
## type [Deployment](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L34-L44>) ## type [Deployment](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L34-L44>)
Deployment is a kubernetes Deployment. Deployment is a kubernetes Deployment.
@@ -313,7 +313,7 @@ type Deployment struct {
``` ```
<a name="NewDeployment"></a> <a name="NewDeployment"></a>
### func [NewDeployment](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L48>) ### func [NewDeployment](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L48>)
```go ```go
func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment
@@ -322,7 +322,7 @@ func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment
NewDeployment creates a new Deployment from a compose service. The appName is the name of the application taken from the project name. It also creates the Values map that will be used to create the values.yaml file. NewDeployment creates a new Deployment from a compose service. The appName is the name of the application taken from the project name. It also creates the Values map that will be used to create the values.yaml file.
<a name="Deployment.AddContainer"></a> <a name="Deployment.AddContainer"></a>
### func \(\*Deployment\) [AddContainer](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L115>) ### func \(\*Deployment\) [AddContainer](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L115>)
```go ```go
func (d *Deployment) AddContainer(service types.ServiceConfig) func (d *Deployment) AddContainer(service types.ServiceConfig)
@@ -331,7 +331,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig)
AddContainer adds a container to the deployment. AddContainer adds a container to the deployment.
<a name="Deployment.AddHealthCheck"></a> <a name="Deployment.AddHealthCheck"></a>
### func \(\*Deployment\) [AddHealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L160>) ### func \(\*Deployment\) [AddHealthCheck](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L161>)
```go ```go
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container)
@@ -340,7 +340,7 @@ func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *core
<a name="Deployment.AddIngress"></a> <a name="Deployment.AddIngress"></a>
### func \(\*Deployment\) [AddIngress](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L189>) ### func \(\*Deployment\) [AddIngress](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L190>)
```go ```go
func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *Ingress func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *Ingress
@@ -349,7 +349,7 @@ func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *In
AddIngress adds an ingress to the deployment. It creates the ingress object. AddIngress adds an ingress to the deployment. It creates the ingress object.
<a name="Deployment.AddLegacyVolume"></a> <a name="Deployment.AddLegacyVolume"></a>
### func \(\*Deployment\) [AddLegacyVolume](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L219>) ### func \(\*Deployment\) [AddLegacyVolume](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L220>)
```go ```go
func (d *Deployment) AddLegacyVolume(name, kind string) func (d *Deployment) AddLegacyVolume(name, kind string)
@@ -358,7 +358,7 @@ func (d *Deployment) AddLegacyVolume(name, kind string)
<a name="Deployment.AddVolumes"></a> <a name="Deployment.AddVolumes"></a>
### func \(\*Deployment\) [AddVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L195>) ### func \(\*Deployment\) [AddVolumes](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L196>)
```go ```go
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string)
@@ -367,7 +367,7 @@ func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string)
AddVolumes adds a volume to the deployment. It does not create the PVC, it only adds the volumes to the deployment. If the volume is a bind volume it will warn the user that it is not supported yet. AddVolumes adds a volume to the deployment. It does not create the PVC, it only adds the volumes to the deployment. If the volume is a bind volume it will warn the user that it is not supported yet.
<a name="Deployment.BindFrom"></a> <a name="Deployment.BindFrom"></a>
### func \(\*Deployment\) [BindFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L240>) ### func \(\*Deployment\) [BindFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L241>)
```go ```go
func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment)
@@ -376,7 +376,7 @@ func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment)
<a name="Deployment.BindMapFilesToContainer"></a> <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/katenary/katenary/blob/master/internal/generator/deployment.go#L375>)
```go ```go
func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secrets []string, appName string) (*corev1.Container, int) func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secrets []string, appName string) (*corev1.Container, int)
@@ -385,7 +385,7 @@ func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secret
<a name="Deployment.DependsOn"></a> <a name="Deployment.DependsOn"></a>
### func \(\*Deployment\) [DependsOn](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L268>) ### func \(\*Deployment\) [DependsOn](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L269>)
```go ```go
func (d *Deployment) DependsOn(to *Deployment, servicename string) error func (d *Deployment) DependsOn(to *Deployment, servicename string) error
@@ -394,7 +394,7 @@ func (d *Deployment) DependsOn(to *Deployment, servicename string) error
DependsOn adds a initContainer to the deployment that will wait for the service to be up. DependsOn adds a initContainer to the deployment that will wait for the service to be up.
<a name="Deployment.Filename"></a> <a name="Deployment.Filename"></a>
### func \(\*Deployment\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L299>) ### func \(\*Deployment\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L300>)
```go ```go
func (d *Deployment) Filename() string func (d *Deployment) Filename() string
@@ -403,7 +403,7 @@ func (d *Deployment) Filename() string
Filename returns the filename of the deployment. Filename returns the filename of the deployment.
<a name="Deployment.MountExchangeVolumes"></a> <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/katenary/katenary/blob/master/internal/generator/deployment.go#L426>)
```go ```go
func (d *Deployment) MountExchangeVolumes() func (d *Deployment) MountExchangeVolumes()
@@ -412,7 +412,7 @@ func (d *Deployment) MountExchangeVolumes()
<a name="Deployment.SetEnvFrom"></a> <a name="Deployment.SetEnvFrom"></a>
### func \(\*Deployment\) [SetEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L304>) ### func \(\*Deployment\) [SetEnvFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/deployment.go#L305>)
```go ```go
func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, samePod ...bool) func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, samePod ...bool)
@@ -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. SetEnvFrom sets the environment variables to a configmap. The configmap is created.
<a name="Deployment.Yaml"></a> <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/katenary/katenary/blob/master/internal/generator/deployment.go#L450>)
```go ```go
func (d *Deployment) Yaml() ([]byte, error) func (d *Deployment) Yaml() ([]byte, error)
@@ -430,7 +430,7 @@ func (d *Deployment) Yaml() ([]byte, error)
Yaml returns the yaml representation of the deployment. Yaml returns the yaml representation of the deployment.
<a name="FileMapUsage"></a> <a name="FileMapUsage"></a>
## type [FileMapUsage](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L21>) ## type [FileMapUsage](<https://github.com/katenary/katenary/blob/master/internal/generator/configMap.go#L21>)
FileMapUsage is the usage of the filemap. FileMapUsage is the usage of the filemap.
@@ -448,7 +448,7 @@ const (
``` ```
<a name="HelmChart"></a> <a name="HelmChart"></a>
## type [HelmChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L38-L51>) ## type [HelmChart](<https://github.com/katenary/katenary/blob/master/internal/generator/chart.go#L41-L54>)
HelmChart is a Helm Chart representation. It contains all the templates, values, versions, helpers... 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"` Name string `yaml:"name"`
Icon string `yaml:"icon,omitempty"` Icon string `yaml:"icon,omitempty"`
ApiVersion string `yaml:"apiVersion"` APIVersion string `yaml:"apiVersion"`
Version string `yaml:"version"` Version string `yaml:"version"`
AppVersion string `yaml:"appVersion"` AppVersion string `yaml:"appVersion"`
Description string `yaml:"description"` Description string `yaml:"description"`
Helper string `yaml:"-"` Helper string `yaml:"-"`
Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"` Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty"`
// contains filtered or unexported fields // contains filtered or unexported fields
} }
``` ```
<a name="Generate"></a> <a name="Generate"></a>
### func [Generate](<https://github.com/metal3d/katenary/blob/develop/generator/generator.go#L29>) ### func [Generate](<https://github.com/katenary/katenary/blob/master/internal/generator/generator.go#L32>)
```go ```go
func Generate(project *types.Project) (*HelmChart, error) 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. - Merge the same\-pod services.
<a name="NewChart"></a> <a name="NewChart"></a>
### func [NewChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L54>) ### func [NewChart](<https://github.com/katenary/katenary/blob/master/internal/generator/chart.go#L57>)
```go ```go
func NewChart(name string) *HelmChart func NewChart(name string) *HelmChart
@@ -500,7 +500,7 @@ func NewChart(name string) *HelmChart
NewChart creates a new empty chart with the given name. NewChart creates a new empty chart with the given name.
<a name="HelmChart.SaveTemplates"></a> <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/katenary/katenary/blob/master/internal/generator/chart.go#L72>)
```go ```go
func (chart *HelmChart) SaveTemplates(templateDir string) 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. SaveTemplates the templates of the chart to the given directory.
<a name="Ingress"></a> <a name="Ingress"></a>
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L17-L20>) ## type [Ingress](<https://github.com/katenary/katenary/blob/master/internal/generator/ingress.go#L18-L22>)
@@ -521,7 +521,7 @@ type Ingress struct {
``` ```
<a name="NewIngress"></a> <a name="NewIngress"></a>
### func [NewIngress](<https://github.com/metal3d/katenary/blob/develop/generator/ingress.go#L23>) ### func [NewIngress](<https://github.com/katenary/katenary/blob/master/internal/generator/ingress.go#L25>)
```go ```go
func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress 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. NewIngress creates a new Ingress from a compose service.
<a name="Ingress.Filename"></a> <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/katenary/katenary/blob/master/internal/generator/ingress.go#L129>)
```go ```go
func (ingress *Ingress) Filename() string func (ingress *Ingress) Filename() string
@@ -539,7 +539,7 @@ func (ingress *Ingress) Filename() string
<a name="Ingress.Yaml"></a> <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/katenary/katenary/blob/master/internal/generator/ingress.go#L133>)
```go ```go
func (ingress *Ingress) Yaml() ([]byte, error) func (ingress *Ingress) Yaml() ([]byte, error)
@@ -548,7 +548,7 @@ func (ingress *Ingress) Yaml() ([]byte, error)
<a name="IngressValue"></a> <a name="IngressValue"></a>
## type [IngressValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L28-L35>) ## type [IngressValue](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L29-L36>)
IngressValue is a ingress configuration that will be saved in values.yaml. IngressValue is a ingress configuration that will be saved in values.yaml.
@@ -564,7 +564,7 @@ type IngressValue struct {
``` ```
<a name="PersistenceValue"></a> <a name="PersistenceValue"></a>
## type [PersistenceValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L16-L21>) ## type [PersistenceValue](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L16-L21>)
PersistenceValue is a persistence configuration that will be saved in values.yaml. PersistenceValue is a persistence configuration that will be saved in values.yaml.
@@ -578,7 +578,7 @@ type PersistenceValue struct {
``` ```
<a name="RBAC"></a> <a name="RBAC"></a>
## type [RBAC](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L20-L24>) ## type [RBAC](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L20-L24>)
RBAC is a kubernetes RBAC containing a role, a rolebinding and an associated serviceaccount. RBAC is a kubernetes RBAC containing a role, a rolebinding and an associated serviceaccount.
@@ -591,7 +591,7 @@ type RBAC struct {
``` ```
<a name="NewRBAC"></a> <a name="NewRBAC"></a>
### func [NewRBAC](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L27>) ### func [NewRBAC](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L27>)
```go ```go
func NewRBAC(service types.ServiceConfig, appName string) *RBAC func NewRBAC(service types.ServiceConfig, appName string) *RBAC
@@ -600,7 +600,7 @@ func NewRBAC(service types.ServiceConfig, appName string) *RBAC
NewRBAC creates a new RBAC from a compose service. The appName is the name of the application taken from the project name. NewRBAC creates a new RBAC from a compose service. The appName is the name of the application taken from the project name.
<a name="RepositoryValue"></a> <a name="RepositoryValue"></a>
## type [RepositoryValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L10-L13>) ## type [RepositoryValue](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L10-L13>)
RepositoryValue is a docker repository image and tag that will be saved in values.yaml. RepositoryValue is a docker repository image and tag that will be saved in values.yaml.
@@ -612,7 +612,7 @@ type RepositoryValue struct {
``` ```
<a name="Role"></a> <a name="Role"></a>
## type [Role](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L114-L117>) ## type [Role](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L114-L117>)
Role is a kubernetes Role. Role is a kubernetes Role.
@@ -624,7 +624,7 @@ type Role struct {
``` ```
<a name="Role.Filename"></a> <a name="Role.Filename"></a>
### func \(\*Role\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L119>) ### func \(\*Role\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L119>)
```go ```go
func (r *Role) Filename() string func (r *Role) Filename() string
@@ -633,7 +633,7 @@ func (r *Role) Filename() string
<a name="Role.Yaml"></a> <a name="Role.Yaml"></a>
### func \(\*Role\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L123>) ### func \(\*Role\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L123>)
```go ```go
func (r *Role) Yaml() ([]byte, error) func (r *Role) Yaml() ([]byte, error)
@@ -642,7 +642,7 @@ func (r *Role) Yaml() ([]byte, error)
<a name="RoleBinding"></a> <a name="RoleBinding"></a>
## type [RoleBinding](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L100-L103>) ## type [RoleBinding](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L100-L103>)
RoleBinding is a kubernetes RoleBinding. RoleBinding is a kubernetes RoleBinding.
@@ -654,7 +654,7 @@ type RoleBinding struct {
``` ```
<a name="RoleBinding.Filename"></a> <a name="RoleBinding.Filename"></a>
### func \(\*RoleBinding\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L105>) ### func \(\*RoleBinding\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L105>)
```go ```go
func (r *RoleBinding) Filename() string func (r *RoleBinding) Filename() string
@@ -663,7 +663,7 @@ func (r *RoleBinding) Filename() string
<a name="RoleBinding.Yaml"></a> <a name="RoleBinding.Yaml"></a>
### func \(\*RoleBinding\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L109>) ### func \(\*RoleBinding\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L109>)
```go ```go
func (r *RoleBinding) Yaml() ([]byte, error) func (r *RoleBinding) Yaml() ([]byte, error)
@@ -672,7 +672,7 @@ func (r *RoleBinding) Yaml() ([]byte, error)
<a name="Secret"></a> <a name="Secret"></a>
## type [Secret](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L22-L25>) ## type [Secret](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L22-L25>)
Secret is a kubernetes Secret. Secret is a kubernetes Secret.
@@ -686,7 +686,7 @@ type Secret struct {
``` ```
<a name="NewSecret"></a> <a name="NewSecret"></a>
### func [NewSecret](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L28>) ### func [NewSecret](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L28>)
```go ```go
func NewSecret(service types.ServiceConfig, appName string) *Secret func NewSecret(service types.ServiceConfig, appName string) *Secret
@@ -695,7 +695,7 @@ func NewSecret(service types.ServiceConfig, appName string) *Secret
NewSecret creates a new Secret from a compose service NewSecret creates a new Secret from a compose service
<a name="Secret.AddData"></a> <a name="Secret.AddData"></a>
### func \(\*Secret\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L70>) ### func \(\*Secret\) [AddData](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L70>)
```go ```go
func (s *Secret) AddData(key, value string) func (s *Secret) AddData(key, value string)
@@ -704,7 +704,7 @@ func (s *Secret) AddData(key, value string)
AddData adds a key value pair to the secret. AddData adds a key value pair to the secret.
<a name="Secret.Filename"></a> <a name="Secret.Filename"></a>
### func \(\*Secret\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L86>) ### func \(\*Secret\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L86>)
```go ```go
func (s *Secret) Filename() string func (s *Secret) Filename() string
@@ -713,7 +713,7 @@ func (s *Secret) Filename() string
Filename returns the filename of the secret. Filename returns the filename of the secret.
<a name="Secret.SetData"></a> <a name="Secret.SetData"></a>
### func \(\*Secret\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L91>) ### func \(\*Secret\) [SetData](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L91>)
```go ```go
func (s *Secret) SetData(data map[string]string) func (s *Secret) SetData(data map[string]string)
@@ -722,7 +722,7 @@ func (s *Secret) SetData(data map[string]string)
SetData sets the data of the secret. SetData sets the data of the secret.
<a name="Secret.Yaml"></a> <a name="Secret.Yaml"></a>
### func \(\*Secret\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L98>) ### func \(\*Secret\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/secret.go#L98>)
```go ```go
func (s *Secret) Yaml() ([]byte, error) func (s *Secret) Yaml() ([]byte, error)
@@ -731,7 +731,7 @@ func (s *Secret) Yaml() ([]byte, error)
Yaml returns the yaml representation of the secret. Yaml returns the yaml representation of the secret.
<a name="Service"></a> <a name="Service"></a>
## type [Service](<https://github.com/metal3d/katenary/blob/develop/generator/service.go#L17-L20>) ## type [Service](<https://github.com/katenary/katenary/blob/master/internal/generator/service.go#L18-L21>)
Service is a kubernetes Service. Service is a kubernetes Service.
@@ -743,7 +743,7 @@ type Service struct {
``` ```
<a name="NewService"></a> <a name="NewService"></a>
### func [NewService](<https://github.com/metal3d/katenary/blob/develop/generator/service.go#L23>) ### func [NewService](<https://github.com/katenary/katenary/blob/master/internal/generator/service.go#L24>)
```go ```go
func NewService(service types.ServiceConfig, appName string) *Service func NewService(service types.ServiceConfig, appName string) *Service
@@ -752,7 +752,7 @@ func NewService(service types.ServiceConfig, appName string) *Service
NewService creates a new Service from a compose service. NewService creates a new Service from a compose service.
<a name="Service.AddPort"></a> <a name="Service.AddPort"></a>
### func \(\*Service\) [AddPort](<https://github.com/metal3d/katenary/blob/develop/generator/service.go#L52>) ### func \(\*Service\) [AddPort](<https://github.com/katenary/katenary/blob/master/internal/generator/service.go#L53>)
```go ```go
func (s *Service) AddPort(port types.ServicePortConfig, serviceName ...string) func (s *Service) AddPort(port types.ServicePortConfig, serviceName ...string)
@@ -761,7 +761,7 @@ func (s *Service) AddPort(port types.ServicePortConfig, serviceName ...string)
AddPort adds a port to the service. AddPort adds a port to the service.
<a name="Service.Filename"></a> <a name="Service.Filename"></a>
### func \(\*Service\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/service.go#L76>) ### func \(\*Service\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/service.go#L74>)
```go ```go
func (s *Service) Filename() string func (s *Service) Filename() string
@@ -770,7 +770,7 @@ func (s *Service) Filename() string
Filename returns the filename of the service. Filename returns the filename of the service.
<a name="Service.Yaml"></a> <a name="Service.Yaml"></a>
### func \(\*Service\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/service.go#L81>) ### func \(\*Service\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/service.go#L79>)
```go ```go
func (s *Service) Yaml() ([]byte, error) func (s *Service) Yaml() ([]byte, error)
@@ -779,7 +779,7 @@ func (s *Service) Yaml() ([]byte, error)
Yaml returns the yaml representation of the service. Yaml returns the yaml representation of the service.
<a name="ServiceAccount"></a> <a name="ServiceAccount"></a>
## type [ServiceAccount](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L132-L135>) ## type [ServiceAccount](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L132-L135>)
ServiceAccount is a kubernetes ServiceAccount. ServiceAccount is a kubernetes ServiceAccount.
@@ -791,7 +791,7 @@ type ServiceAccount struct {
``` ```
<a name="ServiceAccount.Filename"></a> <a name="ServiceAccount.Filename"></a>
### func \(\*ServiceAccount\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L137>) ### func \(\*ServiceAccount\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L137>)
```go ```go
func (r *ServiceAccount) Filename() string func (r *ServiceAccount) Filename() string
@@ -800,7 +800,7 @@ func (r *ServiceAccount) Filename() string
<a name="ServiceAccount.Yaml"></a> <a name="ServiceAccount.Yaml"></a>
### func \(\*ServiceAccount\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/rbac.go#L141>) ### func \(\*ServiceAccount\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/rbac.go#L141>)
```go ```go
func (r *ServiceAccount) Yaml() ([]byte, error) func (r *ServiceAccount) Yaml() ([]byte, error)
@@ -809,18 +809,19 @@ func (r *ServiceAccount) Yaml() ([]byte, error)
<a name="TLS"></a> <a name="TLS"></a>
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L23-L25>) ## type [TLS](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L23-L26>)
```go ```go
type TLS struct { type TLS struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`
SecretName string `yaml:"secretName"`
} }
``` ```
<a name="Value"></a> <a name="Value"></a>
## type [Value](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L38-L49>) ## type [Value](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L39-L50>)
Value will be saved in values.yaml. It contains configuration for all deployment and services. 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> <a name="NewValue"></a>
### func [NewValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L56>) ### func [NewValue](<https://github.com/katenary/katenary/blob/master/internal/generator/values.go#L57>)
```go ```go
func NewValue(service types.ServiceConfig, main ...bool) *Value 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. If \`main\` is true, the tag will be empty because it will be set in the helm chart appVersion.
<a name="Value.AddIngress"></a> <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/katenary/katenary/blob/master/internal/generator/values.go#L90>)
```go ```go
func (v *Value) AddIngress(host, path string) func (v *Value) AddIngress(host, path string)
@@ -860,7 +861,7 @@ func (v *Value) AddIngress(host, path string)
<a name="Value.AddPersistence"></a> <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/katenary/katenary/blob/master/internal/generator/values.go#L104>)
```go ```go
func (v *Value) AddPersistence(volumeName string) func (v *Value) AddPersistence(volumeName string)
@@ -869,7 +870,7 @@ func (v *Value) AddPersistence(volumeName string)
AddPersistence adds persistence configuration to the Value. AddPersistence adds persistence configuration to the Value.
<a name="VolumeClaim"></a> <a name="VolumeClaim"></a>
## type [VolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L18-L23>) ## type [VolumeClaim](<https://github.com/katenary/katenary/blob/master/internal/generator/volume.go#L18-L23>)
VolumeClaim is a kubernetes VolumeClaim. This is a PersistentVolumeClaim. VolumeClaim is a kubernetes VolumeClaim. This is a PersistentVolumeClaim.
@@ -881,7 +882,7 @@ type VolumeClaim struct {
``` ```
<a name="NewVolumeClaim"></a> <a name="NewVolumeClaim"></a>
### func [NewVolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L26>) ### func [NewVolumeClaim](<https://github.com/katenary/katenary/blob/master/internal/generator/volume.go#L26>)
```go ```go
func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *VolumeClaim func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *VolumeClaim
@@ -890,7 +891,7 @@ func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *Vo
NewVolumeClaim creates a new VolumeClaim from a compose service. NewVolumeClaim creates a new VolumeClaim from a compose service.
<a name="VolumeClaim.Filename"></a> <a name="VolumeClaim.Filename"></a>
### func \(\*VolumeClaim\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L62>) ### func \(\*VolumeClaim\) [Filename](<https://github.com/katenary/katenary/blob/master/internal/generator/volume.go#L62>)
```go ```go
func (v *VolumeClaim) Filename() string func (v *VolumeClaim) Filename() string
@@ -899,7 +900,7 @@ func (v *VolumeClaim) Filename() string
Filename returns the suggested filename for a VolumeClaim. Filename returns the suggested filename for a VolumeClaim.
<a name="VolumeClaim.Yaml"></a> <a name="VolumeClaim.Yaml"></a>
### func \(\*VolumeClaim\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L67>) ### func \(\*VolumeClaim\) [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/volume.go#L67>)
```go ```go
func (v *VolumeClaim) Yaml() ([]byte, error) func (v *VolumeClaim) Yaml() ([]byte, error)
@@ -908,7 +909,7 @@ func (v *VolumeClaim) Yaml() ([]byte, error)
Yaml marshals a VolumeClaim into yaml. Yaml marshals a VolumeClaim into yaml.
<a name="Yaml"></a> <a name="Yaml"></a>
## type [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/types.go#L10-L13>) ## type [Yaml](<https://github.com/katenary/katenary/blob/master/internal/generator/types.go#L10-L13>)
Yaml is a kubernetes object that can be converted to yaml. Yaml is a kubernetes object that can be converted to yaml.

View File

@@ -3,12 +3,12 @@
# extrafiles # extrafiles
```go ```go
import "katenary/generator/extrafiles" import "github.com/katenary/katenary/internal/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>) ## func [NotesFile](<https://github.com/katenary/katenary/blob/master/internal/generator/extrafiles/notes.go#L13>)
```go ```go
func NotesFile(services []string) string func NotesFile(services []string) string
@@ -17,7 +17,7 @@ func NotesFile(services []string) string
NotesFile returns the content of the note.txt file. NotesFile returns the content of the note.txt file.
<a name="ReadMeFile"></a> <a name="ReadMeFile"></a>
## func [ReadMeFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/readme.go#L45>) ## func [ReadMeFile](<https://github.com/katenary/katenary/blob/master/internal/generator/extrafiles/readme.go#L46>)
```go ```go
func ReadMeFile(charname, description string, values map[string]any) string func ReadMeFile(charname, description string, values map[string]any) string

View File

@@ -0,0 +1,67 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# katenaryfile
```go
import "github.com/katenary/katenary/internal/generator/katenaryfile"
```
Package katenaryfile is a package for reading and writing katenary files.
A katenary file, named "katenary.yml" or "katenary.yaml", is a file where you can define the configuration of the conversion avoiding the use of labels in the compose file.
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/katenary/katenary/blob/master/internal/generator/katenaryfile/main.go#L137>)
```go
func GenerateSchema() string
```
GenerateSchema generates the schema for the katenary.yaml file.
<a name="OverrideWithConfig"></a>
## func [OverrideWithConfig](<https://github.com/katenary/katenary/blob/master/internal/generator/katenaryfile/main.go#L49>)
```go
func OverrideWithConfig(project *types.Project)
```
OverrideWithConfig overrides the project with the katenary.yaml file. It will set the labels of the services with the values from the katenary.yaml file. It work in memory, so it will not modify the original project.
<a name="Service"></a>
## type [Service](<https://github.com/katenary/katenary/blob/master/internal/generator/katenaryfile/main.go#L27-L44>)
Service is a struct that contains the service configuration for katenary
```go
type Service struct {
MainApp *bool `yaml:"main-app,omitempty" json:"main-app,omitempty" jsonschema:"title=Is this service the main application"`
Values []StringOrMap `yaml:"values,omitempty" json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"`
Secrets *labelstructs.Secrets `yaml:"secrets,omitempty" json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
Ports *labelstructs.Ports `yaml:"ports,omitempty" json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
Ingress *labelstructs.Ingress `yaml:"ingress,omitempty" json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
HealthCheck *labelstructs.HealthCheck `yaml:"health-check,omitempty" json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
SamePod *string `yaml:"same-pod,omitempty" json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"`
Description *string `yaml:"description,omitempty" json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"`
Ignore *bool `yaml:"ignore,omitempty" json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"`
Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty" json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
ConfigMapFiles *labelstructs.ConfigMapFiles `yaml:"configmap-files,omitempty" json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
MapEnv *labelstructs.MapEnv `yaml:"map-env,omitempty" json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
CronJob *labelstructs.CronJob `yaml:"cron-job,omitempty" json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
EnvFrom *labelstructs.EnvFrom `yaml:"env-from,omitempty" json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
ExchangeVolumes []*labelstructs.ExchangeVolume `yaml:"exchange-volumes,omitempty" json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
ValuesFrom *labelstructs.ValueFrom `yaml:"values-from,omitempty" json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
}
```
<a name="StringOrMap"></a>
## type [StringOrMap](<https://github.com/katenary/katenary/blob/master/internal/generator/katenaryfile/main.go#L24>)
StringOrMap is a struct that can be either a string or a map of strings. It's a helper struct to unmarshal the katenary.yaml file and produce the schema
```go
type StringOrMap any
```
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -3,9 +3,11 @@
# labels # labels
```go ```go
import "katenary/generator/labels" import "github.com/katenary/katenary/internal/generator/labels"
``` ```
Package labels provides functionality to parse and manipulate labels.
## Constants ## Constants
<a name="KatenaryLabelPrefix"></a> <a name="KatenaryLabelPrefix"></a>
@@ -15,16 +17,16 @@ const KatenaryLabelPrefix = "katenary.v3"
``` ```
<a name="GetLabelHelp"></a> <a name="GetLabelHelp"></a>
## func [GetLabelHelp](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L87>) ## func [GetLabelHelp](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L88>)
```go ```go
func GetLabelHelp(asMarkdown bool) string func GetLabelHelp(asMarkdown bool) string
``` ```
Generate the help for the labels. GetLabelHelp return the help for the labels.
<a name="GetLabelHelpFor"></a> <a name="GetLabelHelpFor"></a>
## func [GetLabelHelpFor](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L96>) ## func [GetLabelHelpFor](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L97>)
```go ```go
func GetLabelHelpFor(labelname string, asMarkdown bool) string 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. GetLabelHelpFor returns the help for a specific label.
<a name="GetLabelNames"></a> <a name="GetLabelNames"></a>
## func [GetLabelNames](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L71>) ## func [GetLabelNames](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L72>)
```go ```go
func GetLabelNames() []string func GetLabelNames() []string
@@ -42,7 +44,7 @@ func GetLabelNames() []string
GetLabelNames returns a sorted list of all katenary label names. GetLabelNames returns a sorted list of all katenary label names.
<a name="Prefix"></a> <a name="Prefix"></a>
## func [Prefix](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L224>) ## func [Prefix](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L235>)
```go ```go
func Prefix() string func Prefix() string
@@ -51,7 +53,7 @@ func Prefix() string
<a name="Help"></a> <a name="Help"></a>
## type [Help](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L63-L68>) ## type [Help](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L64-L69>)
Help is the documentation of a label. Help is the documentation of a label.
@@ -65,7 +67,7 @@ type Help struct {
``` ```
<a name="Label"></a> <a name="Label"></a>
## type [Label](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L56>) ## type [Label](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L57>)
Label is a katenary label to find in compose files. Label is a katenary label to find in compose files.
@@ -92,12 +94,12 @@ const (
LabelCronJob Label = KatenaryLabelPrefix + "/cronjob" LabelCronJob Label = KatenaryLabelPrefix + "/cronjob"
LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from" LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from"
LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes" LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes"
LabelValueFrom Label = KatenaryLabelPrefix + "/values-from" LabelValuesFrom Label = KatenaryLabelPrefix + "/values-from"
) )
``` ```
<a name="LabelName"></a> <a name="LabelName"></a>
### func [LabelName](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L58>) ### func [LabelName](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/katenaryLabels.go#L59>)
```go ```go
func LabelName(name string) Label func LabelName(name string) Label

View File

@@ -1,32 +1,32 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT --> <!-- Code generated by gomarkdoc. DO NOT EDIT -->
# labelStructs # labelstructs
```go ```go
import "katenary/generator/labels/labelStructs" import "github.com/katenary/katenary/internal/generator/labels/labelstructs"
``` ```
labelStructs is a package that contains the structs used to represent the labels in the yaml files. 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>) ## type [ConfigMapFiles](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/configMap.go#L5>)
```go ```go
type ConfigMapFile []string type ConfigMapFiles []string
``` ```
<a name="ConfigMapFileFrom"></a> <a name="ConfigMapFileFrom"></a>
### func [ConfigMapFileFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/configMap.go#L7>) ### func [ConfigMapFileFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/configMap.go#L7>)
```go ```go
func ConfigMapFileFrom(data string) (ConfigMapFile, error) func ConfigMapFileFrom(data string) (ConfigMapFiles, error)
``` ```
<a name="CronJob"></a> <a name="CronJob"></a>
## type [CronJob](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/cronJob.go#L5-L10>) ## type [CronJob](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/cronJob.go#L5-L10>)
@@ -40,7 +40,7 @@ type CronJob struct {
``` ```
<a name="CronJobFrom"></a> <a name="CronJobFrom"></a>
### func [CronJobFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/cronJob.go#L12>) ### func [CronJobFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/cronJob.go#L12>)
```go ```go
func CronJobFrom(data string) (*CronJob, error) func CronJobFrom(data string) (*CronJob, error)
@@ -49,7 +49,7 @@ func CronJobFrom(data string) (*CronJob, error)
<a name="Dependency"></a> <a name="Dependency"></a>
## type [Dependency](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/dependencies.go#L6-L12>) ## type [Dependency](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/dependencies.go#L6-L12>)
Dependency is a dependency of a chart to other charts. Dependency is a dependency of a chart to other charts.
@@ -64,7 +64,7 @@ type Dependency struct {
``` ```
<a name="DependenciesFrom"></a> <a name="DependenciesFrom"></a>
### func [DependenciesFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/dependencies.go#L15>) ### func [DependenciesFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/dependencies.go#L15>)
```go ```go
func DependenciesFrom(data string) ([]Dependency, error) func DependenciesFrom(data string) ([]Dependency, error)
@@ -73,7 +73,7 @@ func DependenciesFrom(data string) ([]Dependency, error)
DependenciesFrom returns a slice of dependencies from the given string. DependenciesFrom returns a slice of dependencies from the given string.
<a name="EnvFrom"></a> <a name="EnvFrom"></a>
## type [EnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/envFrom.go#L5>) ## type [EnvFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/envFrom.go#L5>)
@@ -82,7 +82,7 @@ type EnvFrom []string
``` ```
<a name="EnvFromFrom"></a> <a name="EnvFromFrom"></a>
### func [EnvFromFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/envFrom.go#L8>) ### func [EnvFromFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/envFrom.go#L8>)
```go ```go
func EnvFromFrom(data string) (EnvFrom, error) func EnvFromFrom(data string) (EnvFrom, error)
@@ -91,7 +91,7 @@ func EnvFromFrom(data string) (EnvFrom, error)
EnvFromFrom returns a EnvFrom from the given string. EnvFromFrom returns a EnvFrom from the given string.
<a name="ExchangeVolume"></a> <a name="ExchangeVolume"></a>
## type [ExchangeVolume](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/exchangeVolume.go#L5-L10>) ## type [ExchangeVolume](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/exchangeVolume.go#L5-L10>)
@@ -105,7 +105,7 @@ type ExchangeVolume struct {
``` ```
<a name="NewExchangeVolumes"></a> <a name="NewExchangeVolumes"></a>
### func [NewExchangeVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/exchangeVolume.go#L12>) ### func [NewExchangeVolumes](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/exchangeVolume.go#L12>)
```go ```go
func NewExchangeVolumes(data string) ([]*ExchangeVolume, error) func NewExchangeVolumes(data string) ([]*ExchangeVolume, error)
@@ -114,7 +114,7 @@ func NewExchangeVolumes(data string) ([]*ExchangeVolume, error)
<a name="HealthCheck"></a> <a name="HealthCheck"></a>
## type [HealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/probes.go#L11-L14>) ## type [HealthCheck](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/probes.go#L11-L14>)
@@ -126,7 +126,7 @@ type HealthCheck struct {
``` ```
<a name="ProbeFrom"></a> <a name="ProbeFrom"></a>
### func [ProbeFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/probes.go#L16>) ### func [ProbeFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/probes.go#L16>)
```go ```go
func ProbeFrom(data string) (*HealthCheck, error) func ProbeFrom(data string) (*HealthCheck, error)
@@ -135,7 +135,7 @@ func ProbeFrom(data string) (*HealthCheck, error)
<a name="Ingress"></a> <a name="Ingress"></a>
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L14-L22>) ## type [Ingress](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/ingress.go#L14-L22>)
@@ -143,16 +143,16 @@ func ProbeFrom(data string) (*HealthCheck, error)
type Ingress struct { type Ingress struct {
Port *int32 `yaml:"port,omitempty" json:"port,omitempty"` Port *int32 `yaml:"port,omitempty" json:"port,omitempty"`
Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,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"` Path *string `yaml:"path,omitempty" json:"path,omitempty"`
Class *string `yaml:"class,omitempty" json:"class,omitempty" jsonschema:"default:-"` 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"` TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
} }
``` ```
<a name="IngressFrom"></a> <a name="IngressFrom"></a>
### func [IngressFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L25>) ### func [IngressFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/ingress.go#L25>)
```go ```go
func IngressFrom(data string) (*Ingress, error) func IngressFrom(data string) (*Ingress, error)
@@ -161,7 +161,7 @@ func IngressFrom(data string) (*Ingress, error)
IngressFrom creates a new Ingress from a compose service. IngressFrom creates a new Ingress from a compose service.
<a name="MapEnv"></a> <a name="MapEnv"></a>
## type [MapEnv](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/mapenv.go#L5>) ## type [MapEnv](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/mapenv.go#L5>)
@@ -170,7 +170,7 @@ type MapEnv map[string]string
``` ```
<a name="MapEnvFrom"></a> <a name="MapEnvFrom"></a>
### func [MapEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/mapenv.go#L8>) ### func [MapEnvFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/mapenv.go#L8>)
```go ```go
func MapEnvFrom(data string) (MapEnv, error) func MapEnvFrom(data string) (MapEnv, error)
@@ -179,7 +179,7 @@ func MapEnvFrom(data string) (MapEnv, error)
MapEnvFrom returns a MapEnv from the given string. MapEnvFrom returns a MapEnv from the given string.
<a name="Ports"></a> <a name="Ports"></a>
## type [Ports](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ports.go#L5>) ## type [Ports](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/ports.go#L5>)
@@ -188,7 +188,7 @@ type Ports []uint32
``` ```
<a name="PortsFrom"></a> <a name="PortsFrom"></a>
### func [PortsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ports.go#L8>) ### func [PortsFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/ports.go#L8>)
```go ```go
func PortsFrom(data string) (Ports, error) func PortsFrom(data string) (Ports, error)
@@ -197,7 +197,7 @@ func PortsFrom(data string) (Ports, error)
PortsFrom returns a Ports from the given string. PortsFrom returns a Ports from the given string.
<a name="Secrets"></a> <a name="Secrets"></a>
## type [Secrets](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/secrets.go#L5>) ## type [Secrets](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/secrets.go#L5>)
@@ -206,7 +206,7 @@ type Secrets []string
``` ```
<a name="SecretsFrom"></a> <a name="SecretsFrom"></a>
### func [SecretsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/secrets.go#L7>) ### func [SecretsFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/secrets.go#L7>)
```go ```go
func SecretsFrom(data string) (Secrets, error) func SecretsFrom(data string) (Secrets, error)
@@ -215,7 +215,7 @@ func SecretsFrom(data string) (Secrets, error)
<a name="TLS"></a> <a name="TLS"></a>
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/ingress.go#L10-L12>) ## type [TLS](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/ingress.go#L10-L12>)
@@ -226,7 +226,7 @@ type TLS struct {
``` ```
<a name="ValueFrom"></a> <a name="ValueFrom"></a>
## type [ValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/valueFrom.go#L5>) ## type [ValueFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/valueFrom.go#L5>)
@@ -235,7 +235,7 @@ type ValueFrom map[string]string
``` ```
<a name="GetValueFrom"></a> <a name="GetValueFrom"></a>
### func [GetValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelStructs/valueFrom.go#L7>) ### func [GetValueFrom](<https://github.com/katenary/katenary/blob/master/internal/generator/labels/labelstructs/valueFrom.go#L7>)
```go ```go
func GetValueFrom(data string) (*ValueFrom, error) func GetValueFrom(data string) (*ValueFrom, error)

View File

@@ -3,12 +3,12 @@
# parser # parser
```go ```go
import "katenary/parser" import "github.com/katenary/katenary/internal/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>) ## func [Parse](<https://github.com/katenary/katenary/blob/master/internal/parser/main.go#L29>)
```go ```go
func Parse(profiles []string, envFiles []string, dockerComposeFile ...string) (*types.Project, error) func Parse(profiles []string, envFiles []string, dockerComposeFile ...string) (*types.Project, error)

View File

@@ -3,12 +3,21 @@
# utils # utils
```go ```go
import "katenary/utils" import "github.com/katenary/katenary/internal/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/katenary/katenary/blob/master/internal/utils/utils.go#L196>)
```go ```go
func AsResourceName(name string) string 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. AsResourceName returns a resource name with underscores to respect the kubernetes naming convention. It's the opposite of FixedResourceName.
<a name="Confirm"></a> <a name="Confirm"></a>
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L161>) ## func [Confirm](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L164>)
```go ```go
func Confirm(question string, icon ...Icon) bool 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. Confirm asks a question and returns true if the answer is y.
<a name="CountStartingSpaces"></a> <a name="CountStartingSpaces"></a>
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L38>) ## func [CountStartingSpaces](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L41>)
```go ```go
func CountStartingSpaces(line string) int 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. CountStartingSpaces counts the number of spaces at the beginning of a string.
<a name="EncodeBasicYaml"></a> <a name="EncodeBasicYaml"></a>
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L173>) ## func [EncodeBasicYaml](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L178>)
```go ```go
func EncodeBasicYaml(data any) ([]byte, error) func EncodeBasicYaml(data any) ([]byte, error)
@@ -44,7 +53,7 @@ func EncodeBasicYaml(data any) ([]byte, error)
EncodeBasicYaml encodes a basic yaml from an interface. EncodeBasicYaml encodes a basic yaml from an interface.
<a name="FixedResourceName"></a> <a name="FixedResourceName"></a>
## func [FixedResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L185>) ## func [FixedResourceName](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L190>)
```go ```go
func FixedResourceName(name string) string 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. FixedResourceName returns a resource name without underscores to respect the kubernetes naming convention.
<a name="GetContainerByName"></a> <a name="GetContainerByName"></a>
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L84>) ## func [GetContainerByName](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L87>)
```go ```go
func GetContainerByName(name string, containers []corev1.Container) (*corev1.Container, int) 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. GetContainerByName returns a container by name and its index in the array. It returns nil, \-1 if not found.
<a name="GetKind"></a> <a name="GetKind"></a>
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L51>) ## func [GetKind](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L54>)
```go ```go
func GetKind(path string) (kind string) 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. GetKind returns the kind of the resource from the file path.
<a name="GetServiceNameByPort"></a> <a name="GetServiceNameByPort"></a>
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L74>) ## func [GetServiceNameByPort](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L77>)
```go ```go
func GetServiceNameByPort(port int) string 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. GetServiceNameByPort returns the service name for a port. It the service name is not found, it returns an empty string.
<a name="GetValuesFromLabel"></a> <a name="GetValuesFromLabel"></a>
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L126>) ## func [GetValuesFromLabel](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L129>)
```go ```go
func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[string]*EnvConfig func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[string]*EnvConfig
@@ -89,7 +98,7 @@ func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[str
GetValuesFromLabel returns a map of values from a label. GetValuesFromLabel returns a map of values from a label.
<a name="HashComposefiles"></a> <a name="HashComposefiles"></a>
## func [HashComposefiles](<https://github.com/metal3d/katenary/blob/develop/utils/hash.go#L12>) ## func [HashComposefiles](<https://github.com/katenary/katenary/blob/master/internal/utils/hash.go#L12>)
```go ```go
func HashComposefiles(files []string) (string, error) func HashComposefiles(files []string) (string, error)
@@ -98,7 +107,7 @@ func HashComposefiles(files []string) (string, error)
HashComposefiles returns a hash of the compose files. HashComposefiles returns a hash of the compose files.
<a name="Int32Ptr"></a> <a name="Int32Ptr"></a>
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L32>) ## func [Int32Ptr](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L35>)
```go ```go
func Int32Ptr(i int32) *int32 func Int32Ptr(i int32) *int32
@@ -107,7 +116,7 @@ func Int32Ptr(i int32) *int32
Int32Ptr returns a pointer to an int32. Int32Ptr returns a pointer to an int32.
<a name="PathToName"></a> <a name="PathToName"></a>
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L103>) ## func [PathToName](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L106>)
```go ```go
func PathToName(path string) string func PathToName(path string) string
@@ -116,7 +125,7 @@ func PathToName(path string) string
PathToName converts a path to a kubernetes complient name. PathToName converts a path to a kubernetes complient name.
<a name="StrPtr"></a> <a name="StrPtr"></a>
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L35>) ## func [StrPtr](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L38>)
```go ```go
func StrPtr(s string) *string func StrPtr(s string) *string
@@ -125,7 +134,7 @@ func StrPtr(s string) *string
StrPtr returns a pointer to a string. StrPtr returns a pointer to a string.
<a name="TplName"></a> <a name="TplName"></a>
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L19>) ## func [TplName](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L22>)
```go ```go
func TplName(serviceName, appname string, suffix ...string) string 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. 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> <a name="TplValue"></a>
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L94>) ## func [TplValue](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L97>)
```go ```go
func TplValue(serviceName, variable string, pipes ...string) string func TplValue(serviceName, variable string, pipes ...string) string
``` ```
GetContainerByName returns a container by name and its index in the array. TplValue returns a string that can be used in a template to access a value from the values file.
<a name="Warn"></a> <a name="Warn"></a>
## func [Warn](<https://github.com/metal3d/katenary/blob/develop/utils/icons.go#L25>) ## func [Warn](<https://github.com/katenary/katenary/blob/master/internal/utils/icons.go#L25>)
```go ```go
func Warn(msg ...interface{}) func Warn(msg ...any)
``` ```
Warn prints a warning message Warn prints a warning message
<a name="WordWrap"></a> <a name="WordWrap"></a>
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L156>) ## func [WordWrap](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L159>)
```go ```go
func WordWrap(text string, lineWidth int) string 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. 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> <a name="Wrap"></a>
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L68>) ## func [Wrap](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L71>)
```go ```go
func Wrap(src, above, below string) string 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. Wrap wraps a string with a string above and below. It will respect the indentation of the src string.
<a name="EnvConfig"></a> <a name="EnvConfig"></a>
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L120-L123>) ## type [EnvConfig](<https://github.com/katenary/katenary/blob/master/internal/utils/utils.go#L123-L126>)
EnvConfig is a struct to hold the description of an environment variable. EnvConfig is a struct to hold the description of an environment variable.
@@ -182,7 +191,7 @@ type EnvConfig struct {
``` ```
<a name="Icon"></a> <a name="Icon"></a>
## type [Icon](<https://github.com/metal3d/katenary/blob/develop/utils/icons.go#L6>) ## type [Icon](<https://github.com/katenary/katenary/blob/master/internal/utils/icons.go#L6>)
Icon is a unicode icon Icon is a unicode icon

View File

@@ -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>)

View File

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

View File

@@ -1,8 +1,18 @@
site_name: Katenary documentation site_name: Katenary documentation
docs_dir: ./docs docs_dir: ./docs
plugins: plugins:
- search - search
- inline-svg - inline-svg
- manpage:
enabled: !ENV [MANPAGE, false]
preprocess: preprocess.py
pages:
- title: Katenary
header: Katenary helm chart generator
output: share/man/man1/katenary.1
inputs:
- usage.md
- labels.md
theme: theme:
name: material name: material
custom_dir: overrides custom_dir: overrides
@@ -42,25 +52,23 @@ extra:
generator: false generator: false
social: social:
- icon: fontawesome/brands/github - icon: fontawesome/brands/github
link: https://github.com/metal3d/katenary link: https://github.com/katenary/katenary
nav: nav:
- "Home": index.md - "Home": index.md
- usage.md - usage.md
- labels.md - labels.md
- Behind the scene: - Behind the scene:
- coding.md - coding.md
- dependencies.md - dependencies.md
- FAQ: faq.md - FAQ: faq.md
- Go Packages: - Go Packages:
- packages/cmd/katenary.md - packages/cmd/katenary.md
- packages/parser.md - packages/internal/parser.md
- packages/update.md - packages/internal/utils.md
- packages/utils.md - Generator:
- Generator: - Index: packages/internal/generator.md
- Index: packages/generator.md - ExtraFiles: packages/internal/generator/extrafiles.md
- ExtraFiles: packages/generator/extrafiles.md - labels:
- labels: - packages/internal/generator/labels.md
- packages/generator/labels.md - Labelstructs: packages/internal/generator/labels/labelstructs.md
- LabelStructs: packages/generator/labels/labelStructs.md - KatenaryFile: packages/internal/generator/katenaryfile.md
- KatenaryFile: packages/generator/katenaryfile.md

22
doc/preprocess.py Normal file
View File

@@ -0,0 +1,22 @@
"""Called by mkdocs to preprocess files and build manpages"""
from bs4 import BeautifulSoup, Tag
def to_remove(tag: Tag) -> bool:
"""Removes images, SVGs, links containing images or SVGs, and permalinks from the BeautifulSoup object."""
if tag.name in {"img", "svg"}:
return True
# remove links containing images or SVGs
if tag.name == "a" and tag.img and to_remove(tag.img):
return True
# remove permalinks
if tag.name == "a" and "headerlink" in tag.get("class", ()):
return True
return False
def preprocess(soup: BeautifulSoup, output: str) -> None:
"""Preprocess the BeautifulSoup object to remove unwanted elements."""
for element in soup.find_all(to_remove):
element.decompose()

View File

@@ -5,3 +5,5 @@ pymdown-extensions==10.*
mkdocs-material==9.* mkdocs-material==9.*
mkdocs-material-extensions==1.* mkdocs-material-extensions==1.*
mkdocs-plugin-inline-svg-mod mkdocs-plugin-inline-svg-mod
beautifulsoup4==4.*
mkdocs-manpage[preprocess]

View File

@@ -1,14 +0,0 @@
/*
The generator package 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 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.
*/
package generator

View File

@@ -1,159 +0,0 @@
package katenaryfile
import (
"bytes"
"encoding/json"
"fmt"
"katenary/generator/labels"
"katenary/generator/labels/labelStructs"
"katenary/utils"
"log"
"os"
"reflect"
"strings"
"github.com/compose-spec/compose-go/types"
"github.com/invopop/jsonschema"
"gopkg.in/yaml.v3"
)
var allowedKatenaryYamlFileNames = []string{"katenary.yaml", "katenary.yml"}
// StringOrMap is a struct that can be either a string or a map of strings.
// It's a helper struct to unmarshal the katenary.yaml file and produce the schema
type StringOrMap any
// 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"`
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)"`
}
// OverrideWithConfig overrides the project with the katenary.yaml file. It
// will set the labels of the services with the values from the katenary.yaml file.
// It work in memory, so it will not modify the original project.
func OverrideWithConfig(project *types.Project) {
var yamlFile string
var err error
for _, yamlFile = range allowedKatenaryYamlFileNames {
_, err = os.Stat(yamlFile)
if err == nil {
break
}
}
if err != nil {
// no katenary file found
return
}
fmt.Println(utils.IconInfo, "Using katenary file", yamlFile)
services := make(map[string]Service)
fp, err := os.Open(yamlFile)
if err != nil {
return
}
if err := yaml.NewDecoder(fp).Decode(&services); err != nil {
log.Fatal(err)
return
}
for i, p := range project.Services {
name := p.Name
if project.Services[i].Labels == nil {
project.Services[i].Labels = make(map[string]string)
}
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)
}
}
fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.")
}
func getLabelContent(o any, service *types.ServiceConfig, labelName string) error {
if reflect.ValueOf(o).IsZero() {
return nil
}
c, err := yaml.Marshal(o)
if err != nil {
log.Println(err)
return err
}
val := strings.TrimSpace(string(c))
if labelName == labels.LabelIngress {
// special case, values must be set from some defaults
ing, err := labelStructs.IngressFrom(val)
if err != nil {
log.Fatal(err)
return err
}
c, err := yaml.Marshal(ing)
if err != nil {
return err
}
val = strings.TrimSpace(string(c))
}
service.Labels[labelName] = val
return nil
}
// GenerateSchema generates the schema for the katenary.yaml file.
func GenerateSchema() string {
s := jsonschema.Reflect(map[string]Service{})
// redefine the IntOrString type from k8s
s.Definitions["IntOrString"] = &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{Type: "integer"},
{Type: "string"},
},
}
// same for the StringOrMap type, that can be either a string or a map of string:string
s.Definitions["StringOrMap"] = &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{Type: "string"},
{Type: "object", AdditionalProperties: &jsonschema.Schema{Type: "string"}},
},
}
c, _ := s.MarshalJSON()
// indent the json
var out bytes.Buffer
err := json.Indent(&out, c, "", " ")
if err != nil {
return err.Error()
}
return string(out.Bytes())
}

View File

@@ -1,13 +0,0 @@
package labelStructs
import "gopkg.in/yaml.v3"
type ConfigMapFile []string
func ConfigMapFileFrom(data string) (ConfigMapFile, error) {
var mapping ConfigMapFile
if err := yaml.Unmarshal([]byte(data), &mapping); err != nil {
return nil, err
}
return mapping, nil
}

View File

@@ -1,2 +0,0 @@
// labelStructs is a package that contains the structs used to represent the labels in the yaml files.
package labelStructs

View File

@@ -1,21 +0,0 @@
package generator
import (
"strings"
"testing"
)
func TestVersion(t *testing.T) {
// we build on "devel" branch
v := GetVersion()
if strings.Contains(v, "(devel)") {
t.Errorf("Expected version to be set, got %s", v)
}
// now, imagine we are on a release branch
Version = "release-1.0.0"
v = GetVersion()
if !strings.Contains(v, "release-1.0.0") {
t.Errorf("Expected version to be set, got %s", v)
}
}

44
go.mod
View File

@@ -1,31 +1,29 @@
module katenary // github.com/metal3d/katenary module github.com/katenary/katenary
go 1.23.0 go 1.25
toolchain go1.23.4
require ( require (
github.com/compose-spec/compose-go v1.20.2 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/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 github.com/thediveo/netdb v1.1.2
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.32.0 k8s.io/api v0.33.4
k8s.io/apimachinery v0.32.0 k8s.io/apimachinery v0.33.4
sigs.k8s.io/yaml v1.4.0 sigs.k8s.io/yaml v1.6.0
) )
require ( require (
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.2 // 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/gogo/protobuf v1.3.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@@ -38,20 +36,22 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.7 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/net v0.32.0 // indirect golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
golang.org/x/sync v0.10.0 // indirect golang.org/x/net v0.43.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
) )

106
go.sum
View File

@@ -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/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 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= 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/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.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.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 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= 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.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= 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/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.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 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/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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= 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/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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= 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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -68,23 +64,23 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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.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.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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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 h1:XdLx/YJPutxrSkPYtmCAIY5sgAvxtkS1Tz+Z0UX2I+U=
github.com/thediveo/netdb v1.1.2/go.mod h1:KJczM//7VIIiovQO1qDooHvM8+0pt6RdRt3rVDZxEGM= 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= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
@@ -100,40 +96,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/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.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/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-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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/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-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-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-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.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-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.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.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-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-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-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.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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-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-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.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -148,17 +148,21 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 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-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= 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.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

View File

@@ -2,7 +2,7 @@
# Install the latest version of the Katenary detecting the right OS and architecture. # Install the latest version of the Katenary detecting the right OS and architecture.
# Can be launched with the following command: # Can be launched with the following command:
# sh <(curl -sSL https://raw.githubusercontent.com/metal3d/katenary/master/install.sh) # sh <(curl -sSL https://raw.githubusercontent.com/Katenary/katenary/master/install.sh)
set -e set -e
@@ -18,36 +18,36 @@ COMON_INSTALL_PATHS="$HOME/.local/bin $HOME/.bin $HOME/bin"
INSTALL_PATH="" INSTALL_PATH=""
for p in $COMON_INSTALL_PATHS; do for p in $COMON_INSTALL_PATHS; do
if [ -d $p ]; then if [ -d $p ]; then
INSTALL_PATH=$p INSTALL_PATH=$p
break break
fi fi
done done
# check if the user has write access to the INSTALL_PATH # check if the user has write access to the INSTALL_PATH
if [ -z "$INSTALL_PATH" ]; then if [ -z "$INSTALL_PATH" ]; then
INSTALL_PATH="/usr/local/bin" INSTALL_PATH="/usr/local/bin"
if [ ! -w $INSTALL_PATH ]; then if [ ! -w $INSTALL_PATH ]; then
echo "You don't have write access to $INSTALL_PATH" echo "You don't have write access to $INSTALL_PATH"
echo "Please, run with sudo or install locally" echo "Please, run with sudo or install locally"
exit 1 exit 1
fi fi
fi fi
# ensure that $INSTALL_PATH is in the PATH # ensure that $INSTALL_PATH is in the PATH
if ! echo $PATH | grep -q $INSTALL_PATH; then if ! echo "$PATH" | grep -q "$INSTALL_PATH"; then
echo "Sorry, $INSTALL_PATH is not in the PATH" echo "Sorry, ${INSTALL_PATH} is not in the PATH"
echo "Please, add it to your PATH in your shell configuration file" echo "Please, add it to your PATH in your shell configuration file"
echo "then restart your shell and run this script again" echo "then restart your shell and run this script again"
exit 1 exit 1
fi fi
# Where to download the binary # Where to download the binary
BASE="https://github.com/metal3d/katenary/releases/latest/download/" BASE="https://github.com/Katenary/katenary/releases/latest/download/"
# for compatibility with older ARM versions # for compatibility with older ARM versions
if [ $ARCH = "x86_64" ]; then if [ $ARCH = "x86_64" ]; then
ARCH="amd64" ARCH="amd64"
fi fi
BIN_URL="$BASE/katenary-$OS-$ARCH" BIN_URL="$BASE/katenary-$OS-$ARCH"
@@ -58,8 +58,8 @@ echo "Downloading $BIN_URL"
T=$(mktemp -u) T=$(mktemp -u)
curl -SL -# $BIN_URL -o $T || (echo "Failed to download katenary" && rm -f $T && exit 1) curl -SL -# $BIN_URL -o $T || (echo "Failed to download katenary" && rm -f $T && exit 1)
mv $T $INSTALL_PATH/katenary mv "$T" "${INSTALL_PATH}/katenary"
chmod +x $INSTALL_PATH/katenary chmod +x "${INSTALL_PATH}/katenary"
echo echo
echo "Installed to $INSTALL_PATH/katenary" echo "Installed to $INSTALL_PATH/katenary"
echo "Installation complete! Run 'katenary help' to get started." echo "Installation complete! Run 'katenary help' to get started."

View File

@@ -2,14 +2,17 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels"
"katenary/generator/labels/labelStructs"
"katenary/utils"
"log" "log"
"maps"
"os" "os"
"path/filepath" "path/filepath"
"slices"
"strings" "strings"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/generator/labels/labelstructs"
"github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@@ -42,12 +45,12 @@ type HelmChart struct {
composeHash *string `yaml:"-"` composeHash *string `yaml:"-"`
Name string `yaml:"name"` Name string `yaml:"name"`
Icon string `yaml:"icon,omitempty"` Icon string `yaml:"icon,omitempty"`
ApiVersion string `yaml:"apiVersion"` APIVersion string `yaml:"apiVersion"`
Version string `yaml:"version"` Version string `yaml:"version"`
AppVersion string `yaml:"appVersion"` AppVersion string `yaml:"appVersion"`
Description string `yaml:"description"` Description string `yaml:"description"`
Helper string `yaml:"-"` 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. // NewChart creates a new empty chart with the given name.
@@ -56,7 +59,7 @@ func NewChart(name string) *HelmChart {
Name: name, Name: name,
Templates: make(map[string]*ChartTemplate, 0), Templates: make(map[string]*ChartTemplate, 0),
Description: "A Helm chart for " + name, Description: "A Helm chart for " + name,
ApiVersion: "v2", APIVersion: "v2",
Version: "", Version: "",
AppVersion: "", // set to 0.1.0 by default if no "main-app" label is found AppVersion: "", // set to 0.1.0 by default if no "main-app" label is found
Values: map[string]any{ Values: map[string]any{
@@ -93,7 +96,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
} }
servicename := template.Servicename 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) fmt.Println(utils.IconFailure, err)
os.Exit(1) os.Exit(1)
} }
@@ -101,7 +104,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
// if the name is a path, create the directory // if the name is a path, create the directory
if strings.Contains(name, string(filepath.Separator)) { if strings.Contains(name, string(filepath.Separator)) {
name = filepath.Join(templateDir, name) name = filepath.Join(templateDir, name)
err := os.MkdirAll(filepath.Dir(name), 0o755) err := os.MkdirAll(filepath.Dir(name), utils.DirectoryPermission)
if err != nil { if err != nil {
fmt.Println(utils.IconFailure, err) fmt.Println(utils.IconFailure, err)
os.Exit(1) os.Exit(1)
@@ -116,9 +119,11 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
fmt.Println(utils.IconFailure, err) fmt.Println(utils.IconFailure, err)
os.Exit(1) 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 +131,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) error { func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) error {
appName := chart.Name appName := chart.Name
for _, s := range project.Services { for _, s := range project.Services {
if s.Environment == nil || len(s.Environment) == 0 { if len(s.Environment) == 0 {
continue continue
} }
@@ -134,12 +139,10 @@ func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) err
secretsVar := types.MappingWithEquals{} secretsVar := types.MappingWithEquals{}
// copy env to originalEnv // copy env to originalEnv
for k, v := range s.Environment { maps.Copy(originalEnv, s.Environment)
originalEnv[k] = v
}
if v, ok := s.Labels[labels.LabelSecrets]; ok { if v, ok := s.Labels[labels.LabelSecrets]; ok {
list, err := labelStructs.SecretsFrom(v) list, err := labelstructs.SecretsFrom(v)
if err != nil { if err != nil {
log.Fatal("error unmarshaling secrets label:", err) log.Fatal("error unmarshaling secrets label:", err)
} }
@@ -212,7 +215,7 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme
if exchange, ok := service.Labels[labels.LabelExchangeVolume]; ok { if exchange, ok := service.Labels[labels.LabelExchangeVolume]; ok {
// we need to add a volume and a mount point // we need to add a volume and a mount point
ex, err := labelStructs.NewExchangeVolumes(exchange) ex, err := labelstructs.NewExchangeVolumes(exchange)
if err != nil { if err != nil {
return err return err
} }
@@ -296,7 +299,7 @@ func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string)
func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) { func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) {
// helm dependency // helm dependency
if v, ok := service.Labels[labels.LabelDependencies]; ok { if v, ok := service.Labels[labels.LabelDependencies]; ok {
d, err := labelStructs.DependenciesFrom(v) d, err := labelstructs.DependenciesFrom(v)
if err != nil { if err != nil {
return false, err return false, err
} }
@@ -324,7 +327,7 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m
if _, ok := service.Labels[labels.LabelEnvFrom]; !ok { if _, ok := service.Labels[labels.LabelEnvFrom]; !ok {
return return
} }
fromservices, err := labelStructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom]) fromservices, err := labelstructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
if err != nil { if err != nil {
log.Fatal("error unmarshaling env-from label:", err) log.Fatal("error unmarshaling env-from label:", err)
} }
@@ -346,10 +349,10 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m
// setEnvironmentValuesFrom sets the environment values from another service. // setEnvironmentValuesFrom sets the environment values from another service.
func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, deployments map[string]*Deployment) { func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, deployments map[string]*Deployment) {
if _, ok := service.Labels[labels.LabelValueFrom]; !ok { if _, ok := service.Labels[labels.LabelValuesFrom]; !ok {
return return
} }
mapping, err := labelStructs.GetValueFrom(service.Labels[labels.LabelValueFrom]) mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValuesFrom])
if err != nil { if err != nil {
log.Fatal("error unmarshaling values-from label:", err) log.Fatal("error unmarshaling values-from label:", err)
} }
@@ -372,7 +375,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
if dep == nil || target == nil { if dep == nil || target == nil {
log.Fatalf("deployment %s or %s not found", depName[0], service.Name) 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 { if container == nil {
log.Fatalf("Container %s not found", target.GetName()) log.Fatalf("Container %s not found", target.GetName())
} }
@@ -381,13 +384,10 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
// is it a secret? // is it a secret?
isSecret := false isSecret := false
secrets, err := labelStructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets]) secrets, err := labelstructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets])
if err == nil { if err == nil {
for _, secret := range secrets { if slices.Contains(secrets, depName[1]) {
if secret == depName[1] { isSecret = true
isSecret = true
break
}
} }
} }

View File

@@ -2,11 +2,12 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels"
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/katenary/katenary/internal/generator/labels"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"

View File

@@ -2,9 +2,9 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"katenary/generator/labels/labelStructs" "github.com/katenary/katenary/internal/generator/labels/labelstructs"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@@ -65,7 +65,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
} }
// get the secrets from the labels // 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 { if err != nil {
log.Fatal(err) 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 // do not bind env variables to the configmap
// remove the variables that are already defined in the environment // remove the variables that are already defined in the environment
if l, ok := service.Labels[labels.LabelMapEnv]; ok { if l, ok := service.Labels[labels.LabelMapEnv]; ok {
envmap, err := labelStructs.MapEnvFrom(l) envmap, err := labelstructs.MapEnvFrom(l)
if err != nil { if err != nil {
log.Fatal("Error parsing map-env", err) 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 // cumulate the path to the WorkingDir
path = filepath.Join(service.WorkingDir, path) path = filepath.Join(service.WorkingDir, path)
path = filepath.Clean(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 return cm
} }
@@ -159,13 +161,13 @@ func (c *ConfigMap) AddBinaryData(key string, value []byte) {
c.BinaryData[key] = value 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. // you need to call this function for each subdirectory.
func (c *ConfigMap) AppendDir(path string) error { func (c *ConfigMap) AppendDir(path string) error {
// read all files in the path and add them to the configmap // read all files in the path and add them to the configmap
stat, err := os.Stat(path) stat, err := os.Stat(path)
if err != nil { 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 // recursively read all files in the path and add them to the configmap
if stat.IsDir() { 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 // read all files in the path and add them to the configmap
stat, err := os.Stat(path) stat, err := os.Stat(path)
if err != nil { 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 // recursively read all files in the path and add them to the configmap
if !stat.IsDir() { if !stat.IsDir() {

View File

@@ -2,8 +2,10 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "io"
"github.com/katenary/katenary/internal/generator/labels"
"os" "os"
"regexp"
"testing" "testing"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
@@ -90,3 +92,41 @@ func TestAppendBadDir(t *testing.T) {
t.Errorf("Expected error, got nil") t.Errorf("Expected error, got nil")
} }
} }
func TestRootConfigmapfile(t *testing.T) {
composeFile := `
services:
web:
image: nginx
volumes:
- ./foo.txt:/etc/foo.txt
labels:
%[1]s/configmap-files: |-
- ./foo.txt
`
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
tmpDir := setup(composeFile)
defer teardown(tmpDir)
currentDir, _ := os.Getwd()
os.Chdir(tmpDir)
defer os.Chdir(currentDir)
fooTxt := "foo content"
fooFp, _ := os.Create("foo.txt")
io.WriteString(fooFp, fooTxt)
fooFp.Close()
output := internalCompileTest(t, "-s", "templates/web/statics/configmap.yaml")
configMap := v1.ConfigMap{}
if err := yaml.Unmarshal([]byte(output), &configMap); err != nil {
t.Errorf(unmarshalError, err)
}
if configMap.Data == nil {
t.Error("Expected configmap data to not be nil")
}
// if the configmap.Name ends by anything that is not alphanumeric, there is a problem
valid := regexp.MustCompile(`.*[a-zA-Z0-9]+$`)
if !valid.MatchString(configMap.Name) {
t.Errorf("ConfigMap name %s is not valid", configMap.Name)
}
}

View File

@@ -4,12 +4,6 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"katenary/generator/extrafiles"
"katenary/generator/katenaryfile"
"katenary/generator/labels"
"katenary/generator/labels/labelStructs"
"katenary/parser"
"katenary/utils"
"log" "log"
"os" "os"
"os/exec" "os/exec"
@@ -18,6 +12,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/katenary/katenary/internal/generator/extrafiles"
"github.com/katenary/katenary/internal/generator/katenaryfile"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/generator/labels/labelstructs"
"github.com/katenary/katenary/internal/parser"
"github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
) )
@@ -113,7 +114,11 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
fmt.Println(utils.IconFailure, err) fmt.Println(utils.IconFailure, err)
return 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 // repove the directory part of the docker-compose files
for i, f := range dockerComposeFile { for i, f := range dockerComposeFile {
@@ -169,9 +174,8 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
os.RemoveAll(config.OutputDir) os.RemoveAll(config.OutputDir)
// create the chart directory // create the chart directory
if err := os.MkdirAll(templateDir, 0o755); err != nil { if err := os.MkdirAll(templateDir, utils.DirectoryPermission); err != nil {
fmt.Println(utils.IconFailure, err) return err
os.Exit(1)
} }
// add icon from the command line // add icon from the command line
@@ -255,7 +259,7 @@ func addCommentsToValues(values []byte) []byte {
return []byte(strings.Join(lines, "\n")) 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 { for _, d := range dependencies {
name := d.Name name := d.Name
if d.Alias != "" { if d.Alias != "" {
@@ -518,16 +522,16 @@ func buildCharYamlFile(chart *HelmChart, project *types.Project, chartPath strin
os.Exit(1) os.Exit(1)
} }
// concat chart adding a comment with hash of services on top // 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 // add the list of compose files
files := []string{} files := []string{}
for _, file := range project.ComposeFiles { for _, file := range project.ComposeFiles {
base := filepath.Base(file) base := filepath.Base(file)
files = append(files, base) 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 // 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 // document Chart.yaml file
yamlChart = addChartDoc(yamlChart, project) yamlChart = addChartDoc(yamlChart, project)
@@ -627,7 +631,11 @@ func writeContent(path string, content []byte) {
os.Exit(1) os.Exit(1)
} }
defer f.Close() 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. // helmLint runs "helm lint" on the output directory.

View File

@@ -1,9 +1,9 @@
package generator package generator
import ( import (
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"katenary/generator/labels/labelStructs" "github.com/katenary/katenary/internal/generator/labels/labelstructs"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"log" "log"
"strings" "strings"
@@ -30,7 +30,7 @@ func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (
if !ok { if !ok {
return nil, nil return nil, nil
} }
mapping, err := labelStructs.CronJobFrom(labels) mapping, err := labelstructs.CronJobFrom(labels)
if err != nil { if err != nil {
log.Fatalf("Error parsing cronjob labels: %s", err) log.Fatalf("Error parsing cronjob labels: %s", err)
return nil, nil return nil, nil

View File

@@ -2,9 +2,9 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"katenary/generator/labels/labelStructs" "github.com/katenary/katenary/internal/generator/labels/labelstructs"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@@ -39,7 +39,7 @@ type Deployment struct {
service *types.ServiceConfig `yaml:"-"` service *types.ServiceConfig `yaml:"-"`
defaultTag string `yaml:"-"` defaultTag string `yaml:"-"`
isMainApp bool `yaml:"-"` isMainApp bool `yaml:"-"`
exchangesVolumes map[string]*labelStructs.ExchangeVolume `yaml:"-"` exchangesVolumes map[string]*labelstructs.ExchangeVolume `yaml:"-"`
boundEnvVar []string `yaml:"-"` // environement to remove boundEnvVar []string `yaml:"-"` // environement to remove
} }
@@ -94,7 +94,7 @@ func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
}, },
configMaps: make(map[string]*ConfigMapMount), configMaps: make(map[string]*ConfigMapMount),
volumeMap: make(map[string]string), volumeMap: make(map[string]string),
exchangesVolumes: map[string]*labelStructs.ExchangeVolume{}, exchangesVolumes: map[string]*labelstructs.ExchangeVolume{},
boundEnvVar: []string{}, boundEnvVar: []string{},
} }
@@ -131,11 +131,12 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
Image: utils.TplValue(service.Name, "repository.image") + ":" + Image: utils.TplValue(service.Name, "repository.image") + ":" +
utils.TplValue(service.Name, "repository.tag", d.defaultTag), utils.TplValue(service.Name, "repository.tag", d.defaultTag),
Ports: ports, Ports: ports,
Name: service.Name, Name: service.ContainerName,
ImagePullPolicy: corev1.PullIfNotPresent, ImagePullPolicy: corev1.PullIfNotPresent,
Resources: corev1.ResourceRequirements{ Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{}, Requests: corev1.ResourceList{},
}, },
Command: service.Command,
} }
if _, ok := d.chart.Values[service.Name]; !ok { if _, ok := d.chart.Values[service.Name]; !ok {
d.chart.Values[service.Name] = NewValue(service, d.isMainApp) d.chart.Values[service.Name] = NewValue(service, d.isMainApp)
@@ -160,7 +161,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) { func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
// get the label for healthcheck // get the label for healthcheck
if v, ok := service.Labels[labels.LabelHealthCheck]; ok { if v, ok := service.Labels[labels.LabelHealthCheck]; ok {
probes, err := labelStructs.ProbeFrom(v) probes, err := labelstructs.ProbeFrom(v)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -195,7 +196,7 @@ func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *In
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) { func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
tobind := map[string]bool{} tobind := map[string]bool{}
if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok { if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok {
binds, err := labelStructs.ConfigMapFileFrom(v) binds, err := labelstructs.ConfigMapFileFrom(v)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -253,8 +254,8 @@ func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) {
// get the container // get the container
} }
// add volume mount to the container // add volume mount to the container
targetContainer, ti := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers) targetContainer, ti := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
sourceContainer, _ := utils.GetContainerByName(service.Name, binded.Spec.Template.Spec.Containers) sourceContainer, _ := utils.GetContainerByName(service.ContainerName, binded.Spec.Template.Spec.Containers)
for _, bindedMount := range sourceContainer.VolumeMounts { for _, bindedMount := range sourceContainer.VolumeMounts {
if bindedMount.Name == bindedVolume.Name { if bindedMount.Name == bindedVolume.Name {
targetContainer.VolumeMounts = append(targetContainer.VolumeMounts, bindedMount) targetContainer.VolumeMounts = append(targetContainer.VolumeMounts, bindedMount)
@@ -305,10 +306,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
if len(service.Environment) == 0 { if len(service.Environment) == 0 {
return return
} }
inSamePod := false inSamePod := len(samePod) > 0 && samePod[0]
if len(samePod) > 0 && samePod[0] {
inSamePod = true
}
drop := []string{} drop := []string{}
secrets := []string{} secrets := []string{}
@@ -323,7 +321,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
}() }()
// secrets from label // secrets from label
labelSecrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets]) labelSecrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -411,7 +409,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 { if container == nil {
utils.Warn("Container not found for service " + service.Name) utils.Warn("Container not found for service " + service.Name)
return nil, -1 return nil, -1
@@ -637,12 +635,16 @@ func (d *Deployment) appendFileToConfigMap(service types.ServiceConfig, appName
// in generate.go // in generate.go
dirname := filepath.Dir(volume.Source) dirname := filepath.Dir(volume.Source)
pathname := utils.PathToName(dirname) pathname := utils.PathToName(dirname)
pathname = strings.TrimSpace(pathname)
if len(pathname) != 0 {
pathname += "-" + pathname
}
var cm *ConfigMap var cm *ConfigMap
if v, ok := d.configMaps[pathname]; !ok { if v, ok := d.configMaps[pathname]; !ok {
cm = NewConfigMap(*d.service, appName, true) cm = NewConfigMap(*d.service, appName, true)
cm.usage = FileMapUsageFiles cm.usage = FileMapUsageFiles
cm.path = dirname cm.path = dirname
cm.Name = utils.TplName(service.Name, appName) + "-" + pathname cm.Name = utils.TplName(service.Name, appName) + pathname
d.configMaps[pathname] = &ConfigMapMount{ d.configMaps[pathname] = &ConfigMapMount{
configMap: cm, configMap: cm,
mountPath: []mountPathConfig{{ mountPath: []mountPathConfig{{
@@ -660,11 +662,13 @@ func (d *Deployment) appendFileToConfigMap(service types.ServiceConfig, appName
d.configMaps[pathname].mountPath = mp 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) { 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) { defer func(d *Deployment, container *corev1.Container, index int) {
d.Spec.Template.Spec.Containers[index] = *container d.Spec.Template.Spec.Containers[index] = *container

View File

@@ -2,10 +2,12 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"os" "os"
"strings"
"testing" "testing"
yaml3 "gopkg.in/yaml.v3"
v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@@ -324,14 +326,208 @@ services:
Environment map[string]string `yaml:"environment"` Environment map[string]string `yaml:"environment"`
} `yaml:"web"` } `yaml:"web"`
}{} }{}
if err := yaml.Unmarshal(valuesContent, &mapping); err != nil { if err := yaml3.Unmarshal(valuesContent, &mapping); err != nil {
t.Errorf(unmarshalError, err) 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") 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") 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")
}
}
func TestCheckCommand(t *testing.T) {
composeFile := `
services:
web-app:
image: nginx:1.29
command:
- sh
- -c
- |-
echo "Hello, World!"
echo "Done"
`
// 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 the command in the container
command := dt.Spec.Template.Spec.Containers[0].Command
if len(command) != 3 {
t.Errorf("Expected command to have 3 elements, got %d", len(command))
}
if command[0] != "sh" || command[1] != "-c" {
t.Errorf("Expected command to be 'sh -c', got %s", strings.Join(command, " "))
} }
} }

17
internal/generator/doc.go Normal file
View File

@@ -0,0 +1,17 @@
/*
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 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.
*/
package generator

View File

@@ -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 package extrafiles

View 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)
}
}
}

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
_ "embed" _ "embed"
"fmt" "fmt"
"log"
"sort" "sort"
"strings" "strings"
"text/template" "text/template"
@@ -20,7 +21,7 @@ type chart struct {
Values []string 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 { for key, value := range values {
path := key path := key
if prefix != "" { if prefix != "" {
@@ -28,11 +29,11 @@ func parseValues(prefix string, values map[string]interface{}, result map[string
} }
switch v := value.(type) { switch v := value.(type) {
case []interface{}: case []any:
for i, u := range v { 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) parseValues(path, v, result)
default: default:
strValue := fmt.Sprintf("`%v`", value) strValue := fmt.Sprintf("`%v`", value)
@@ -48,7 +49,9 @@ func ReadMeFile(charname, description string, values map[string]any) string {
vv := map[string]any{} vv := map[string]any{}
out, _ := yaml.Marshal(values) 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) result := make(map[string]string)
parseValues("", vv, result) parseValues("", vv, result)

View 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])
}
}

View File

@@ -3,14 +3,17 @@ package generator
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"katenary/generator/labels"
"katenary/utils"
"log" "log"
"regexp" "regexp"
"strings" "strings"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/generator/labels/labelstructs"
"github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
) )
// Generate a chart from a compose project. // Generate a chart from a compose project.
@@ -43,6 +46,16 @@ func Generate(project *types.Project) (*HelmChart, error) {
Annotations[labels.LabelName("compose-hash")] = hash Annotations[labels.LabelName("compose-hash")] = hash
chart.composeHash = &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 // find the "main-app" label, and set chart.AppVersion to the tag if exists
mainCount := 0 mainCount := 0
for _, service := range project.Services { for _, service := range project.Services {
@@ -107,7 +120,10 @@ func Generate(project *types.Project) (*HelmChart, error) {
for _, s := range project.Services { for _, s := range project.Services {
for _, d := range s.GetDependencies() { for _, d := range s.GetDependencies() {
if dep, ok := deployments[d]; ok { 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 { } else {
log.Printf("service %[1]s depends on %[2]s, but %[2]s is not defined", s.Name, d) log.Printf("service %[1]s depends on %[2]s, but %[2]s is not defined", s.Name, d)
} }
@@ -119,7 +135,9 @@ func Generate(project *types.Project) (*HelmChart, error) {
} }
// generate configmaps with environment variables // 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 // if the env-from label is set, we need to add the env vars from the configmap
// to the environment of the service // to the environment of the service
@@ -187,6 +205,52 @@ func Generate(project *types.Project) (*HelmChart, error) {
return chart, nil 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.LabelValuesFrom]; 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.LabelValuesFrom] = string(output)
}
}
service.Name = fixed
project.Services[i] = service
}
}
return nil
}
// serviceIsMain returns true if the service is the main app. // serviceIsMain returns true if the service is the main app.
func serviceIsMain(service types.ServiceConfig) bool { func serviceIsMain(service types.ServiceConfig) bool {
if main, ok := service.Labels[labels.LabelMainApp]; ok { if main, ok := service.Labels[labels.LabelMainApp]; ok {
@@ -204,7 +268,7 @@ func addStaticVolumes(deployments map[string]*Deployment, service types.ServiceC
return 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 if container == nil { // may append for the same-pod services
return return
} }
@@ -256,7 +320,7 @@ func computeNIndent(b []byte) []byte {
startSpaces = spaces[0] startSpaces = spaces[0]
} }
line = []byte(startSpaces + strings.TrimLeft(string(line), " ")) 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 lines[i] = line
} }
return bytes.Join(lines, []byte("\n")) return bytes.Join(lines, []byte("\n"))
@@ -329,7 +393,7 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
return false return false
} }
if service.Volumes == nil || len(service.Volumes) == 0 { if len(service.Volumes) == 0 {
return false return false
} }
@@ -355,3 +419,15 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
} }
return false 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
}
}

View File

@@ -1,8 +1,9 @@
package generator package generator
import ( import (
"katenary/generator/labels"
"regexp" "regexp"
"github.com/katenary/katenary/internal/generator/labels"
) )
var ( var (

View File

@@ -2,7 +2,7 @@ package generator
import ( import (
_ "embed" _ "embed"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"strings" "strings"
) )

View File

@@ -1,12 +1,13 @@
package generator package generator
import ( import (
"katenary/generator/labels"
"katenary/generator/labels/labelStructs"
"katenary/utils"
"log" "log"
"strings" "strings"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/generator/labels/labelstructs"
"github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
networkv1 "k8s.io/api/networking/v1" networkv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -33,7 +34,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
return nil return nil
} }
mapping, err := labelStructs.IngressFrom(label) mapping, err := labelstructs.IngressFrom(label)
if err != nil { if err != nil {
log.Fatalf("Failed to parse ingress label: %s\n", err) log.Fatalf("Failed to parse ingress label: %s\n", err)
} }

View File

@@ -2,7 +2,7 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"os" "os"
"testing" "testing"

View File

@@ -0,0 +1,165 @@
package katenaryfile
import (
"bytes"
"encoding/json"
"fmt"
"github.com/katenary/katenary/internal/generator/labels"
"github.com/katenary/katenary/internal/generator/labels/labelstructs"
"github.com/katenary/katenary/internal/utils"
"log"
"os"
"reflect"
"strings"
"github.com/compose-spec/compose-go/types"
"github.com/invopop/jsonschema"
"gopkg.in/yaml.v3"
)
var allowedKatenaryYamlFileNames = []string{"katenary.yaml", "katenary.yml"}
// StringOrMap is a struct that can be either a string or a map of strings.
// It's a helper struct to unmarshal the katenary.yaml file and produce the schema
type StringOrMap any
// Service is a struct that contains the service configuration for katenary
type Service struct {
MainApp *bool `yaml:"main-app,omitempty" json:"main-app,omitempty" jsonschema:"title=Is this service the main application"`
Values []StringOrMap `yaml:"values,omitempty" json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"`
Secrets *labelstructs.Secrets `yaml:"secrets,omitempty" json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
Ports *labelstructs.Ports `yaml:"ports,omitempty" json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
Ingress *labelstructs.Ingress `yaml:"ingress,omitempty" json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
HealthCheck *labelstructs.HealthCheck `yaml:"health-check,omitempty" json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
SamePod *string `yaml:"same-pod,omitempty" json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"`
Description *string `yaml:"description,omitempty" json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"`
Ignore *bool `yaml:"ignore,omitempty" json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"`
Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty" json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
ConfigMapFiles *labelstructs.ConfigMapFiles `yaml:"configmap-files,omitempty" json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
MapEnv *labelstructs.MapEnv `yaml:"map-env,omitempty" json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
CronJob *labelstructs.CronJob `yaml:"cron-job,omitempty" json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
EnvFrom *labelstructs.EnvFrom `yaml:"env-from,omitempty" json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
ExchangeVolumes []*labelstructs.ExchangeVolume `yaml:"exchange-volumes,omitempty" json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
ValuesFrom *labelstructs.ValueFrom `yaml:"values-from,omitempty" 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
// will set the labels of the services with the values from the katenary.yaml file.
// It work in memory, so it will not modify the original project.
func OverrideWithConfig(project *types.Project) {
var yamlFile string
var err error
for _, yamlFile = range allowedKatenaryYamlFileNames {
_, err = os.Stat(yamlFile)
if err == nil {
break
}
}
if err != nil {
// no katenary file found
return
}
fmt.Println(utils.IconInfo, "Using katenary file", yamlFile)
services := make(map[string]Service)
fp, err := os.Open(yamlFile)
if err != nil {
return
}
if err := yaml.NewDecoder(fp).Decode(&services); err != nil {
log.Fatal(err)
return
}
for i, p := range project.Services {
name := p.Name
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 {
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.ConfigMapFiles, &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.LabelValuesFrom)
}
}
fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.")
}
func getLabelContent(o any, service *types.ServiceConfig, labelName string) error {
if reflect.ValueOf(o).IsZero() {
return nil
}
c, err := yaml.Marshal(o)
if err != nil {
log.Println(err)
return err
}
val := strings.TrimSpace(string(c))
if labelName == labels.LabelIngress {
// special case, values must be set from some defaults
ing, err := labelstructs.IngressFrom(val)
if err != nil {
log.Fatal(err)
return err
}
c, err := yaml.Marshal(ing)
if err != nil {
return err
}
val = strings.TrimSpace(string(c))
}
service.Labels[labelName] = val
return nil
}
// GenerateSchema generates the schema for the katenary.yaml file.
func GenerateSchema() string {
s := jsonschema.Reflect(map[string]Service{})
// redefine the IntOrString type from k8s
s.Definitions["IntOrString"] = &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{Type: "integer"},
{Type: "string"},
},
}
// same for the StringOrMap type, that can be either a string or a map of string:string
s.Definitions["StringOrMap"] = &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{Type: "string"},
{Type: "object", AdditionalProperties: &jsonschema.Schema{Type: "string"}},
},
}
c, _ := s.MarshalJSON()
// indent the json
var out bytes.Buffer
err := json.Indent(&out, c, "", " ")
if err != nil {
return err.Error()
}
return out.String()
}

View File

@@ -1,7 +1,7 @@
package katenaryfile package katenaryfile
import ( import (
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@@ -33,7 +33,7 @@ webapp:
// create /tmp/katenary-test-override directory, save the compose.yaml file // create /tmp/katenary-test-override directory, save the compose.yaml file
tmpDir, err := os.MkdirTemp("", "katenary-test-override") tmpDir, err := os.MkdirTemp("", "katenary-test-override")
if err != nil { if err != nil {
t.Fatalf(err.Error()) t.Fatalf("Failed to create temp directory: %s", err.Error())
} }
composeFile := filepath.Join(tmpDir, "compose.yaml") composeFile := filepath.Join(tmpDir, "compose.yaml")
katenaryFile := filepath.Join(tmpDir, "katenary.yaml") katenaryFile := filepath.Join(tmpDir, "katenary.yaml")
@@ -57,6 +57,9 @@ webapp:
cli.WithDefaultConfigPath, cli.WithDefaultConfigPath,
) )
project, err := cli.ProjectFromOptions(options) project, err := cli.ProjectFromOptions(options)
if err != nil {
t.Fatalf("Failed to create project from options: %s", err.Error())
}
OverrideWithConfig(project) OverrideWithConfig(project)
w := project.Services[0].Labels w := project.Services[0].Labels
@@ -83,7 +86,7 @@ webapp:
// create /tmp/katenary-test-override directory, save the compose.yaml file // create /tmp/katenary-test-override directory, save the compose.yaml file
tmpDir, err := os.MkdirTemp("", "katenary-test-override") tmpDir, err := os.MkdirTemp("", "katenary-test-override")
if err != nil { if err != nil {
t.Fatalf(err.Error()) t.Fatalf("Failed to create temp directory: %s", err.Error())
} }
composeFile := filepath.Join(tmpDir, "compose.yaml") composeFile := filepath.Join(tmpDir, "compose.yaml")
katenaryFile := filepath.Join(tmpDir, "katenary.yaml") katenaryFile := filepath.Join(tmpDir, "katenary.yaml")
@@ -107,6 +110,9 @@ webapp:
cli.WithDefaultConfigPath, cli.WithDefaultConfigPath,
) )
project, err := cli.ProjectFromOptions(options) project, err := cli.ProjectFromOptions(options)
if err != nil {
t.Fatalf("Failed to create project from options: %s", err.Error())
}
OverrideWithConfig(project) OverrideWithConfig(project)
w := project.Services[0].Labels w := project.Services[0].Labels
@@ -117,3 +123,58 @@ webapp:
t.Fatal("Expected ingress to be defined", v) t.Fatal("Expected ingress to be defined", v)
} }
} }
func TestOverrideConfigMapFiles(t *testing.T) {
composeContent := `
services:
webapp:
image: nginx:latest
`
katenaryfileContent := `
webapp:
configmap-files:
- foo/bar
ports:
- 80
ingress:
port: 80
`
// create /tmp/katenary-test-override directory, save the compose.yaml file
tmpDir, err := os.MkdirTemp("", "katenary-test-override")
if err != nil {
t.Fatalf("Failed to create temp directory: %s", err.Error())
}
composeFile := filepath.Join(tmpDir, "compose.yaml")
katenaryFile := filepath.Join(tmpDir, "katenary.yaml")
os.MkdirAll(tmpDir, 0755)
if err := os.WriteFile(composeFile, []byte(composeContent), 0644); err != nil {
t.Log(err)
}
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0644); err != nil {
t.Log(err)
}
defer os.RemoveAll(tmpDir)
c, _ := os.ReadFile(composeFile)
log.Println(string(c))
// chand dir to this directory
os.Chdir(tmpDir)
options, _ := cli.NewProjectOptions(nil,
cli.WithWorkingDirectory(tmpDir),
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
if v, ok := w[labels.LabelConfigMapFiles]; !ok {
t.Fatal("Expected configmap-files to be defined", v)
}
}

View File

@@ -2,7 +2,7 @@ package generator
import ( import (
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
) )
var componentLabel = labels.LabelName("component") var componentLabel = labels.LabelName("component")

View File

@@ -0,0 +1,2 @@
// Package labels provides functionality to parse and manipulate labels.
package labels

View File

@@ -4,7 +4,8 @@ import (
"bytes" "bytes"
_ "embed" _ "embed"
"fmt" "fmt"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"log"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
@@ -33,7 +34,7 @@ const (
LabelCronJob Label = KatenaryLabelPrefix + "/cronjob" LabelCronJob Label = KatenaryLabelPrefix + "/cronjob"
LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from" LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from"
LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes" LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes"
LabelValueFrom Label = KatenaryLabelPrefix + "/values-from" LabelValuesFrom Label = KatenaryLabelPrefix + "/values-from"
) )
var ( var (
@@ -83,7 +84,7 @@ func init() {
} }
} }
// Generate the help for the labels. // GetLabelHelp return the help for the labels.
func GetLabelHelp(asMarkdown bool) string { func GetLabelHelp(asMarkdown bool) string {
names := GetLabelNames() // sorted names := GetLabelNames() // sorted
if !asMarkdown { if !asMarkdown {
@@ -125,23 +126,30 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
} }
var buf bytes.Buffer 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 string
}{ }{
KatenaryPrefix: KatenaryLabelPrefix, KatenaryPrefix: KatenaryLabelPrefix,
}) })
if err != nil {
log.Fatalf("Error executing template: %v", err)
}
help.Long = buf.String() help.Long = buf.String()
buf.Reset() 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 string
}{ }{
KatenaryPrefix: KatenaryLabelPrefix, KatenaryPrefix: KatenaryLabelPrefix,
}) })
if err != nil {
log.Fatalf("Error executing template: %v", err)
}
help.Example = buf.String() help.Example = buf.String()
buf.Reset() 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 Name string
Help Help Help Help
KatenaryPrefix string KatenaryPrefix string
@@ -150,6 +158,9 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
Help: help, Help: help,
KatenaryPrefix: KatenaryLabelPrefix, KatenaryPrefix: KatenaryLabelPrefix,
}) })
if err != nil {
log.Fatalf("Error executing template: %v", err)
}
return buf.String() return buf.String()
} }

View File

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

View File

@@ -0,0 +1,13 @@
package labelstructs
import "gopkg.in/yaml.v3"
type ConfigMapFiles []string
func ConfigMapFileFrom(data string) (ConfigMapFiles, error) {
var mapping ConfigMapFiles
if err := yaml.Unmarshal([]byte(data), &mapping); err != nil {
return nil, err
}
return mapping, nil
}

View File

@@ -0,0 +1,17 @@
package labelstructs_test
import (
"github.com/katenary/katenary/internal/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])
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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)
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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)
}
}

View 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

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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])
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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)
}
}

View File

@@ -1,8 +1,8 @@
package labelStructs package labelstructs
import ( import (
"fmt" "fmt"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@@ -14,10 +14,10 @@ type TLS struct {
type Ingress struct { type Ingress struct {
Port *int32 `yaml:"port,omitempty" json:"port,omitempty"` Port *int32 `yaml:"port,omitempty" json:"port,omitempty"`
Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,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"` Path *string `yaml:"path,omitempty" json:"path,omitempty"`
Class *string `yaml:"class,omitempty" json:"class,omitempty" jsonschema:"default:-"` 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"` TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
} }

View 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")
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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))
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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)
}
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import ( import (
"encoding/json" "encoding/json"

View 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)
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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)
}
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs package labelstructs
import "gopkg.in/yaml.v3" import "gopkg.in/yaml.v3"

View 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"])
}
}

View File

@@ -1,7 +1,7 @@
package generator package generator
import ( import (
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"

View File

@@ -2,8 +2,8 @@ package generator
import ( import (
"encoding/base64" "encoding/base64"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"katenary/utils" "github.com/katenary/katenary/internal/utils"
"strings" "strings"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"

View File

@@ -3,7 +3,7 @@ package generator
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"katenary/generator/labels" "github.com/katenary/katenary/internal/generator/labels"
"os" "os"
"testing" "testing"
@@ -82,7 +82,9 @@ services:
AppVersion: appVersion, AppVersion: appVersion,
ChartVersion: chartVersion, 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") c, err := os.ReadFile("chart/values.yaml")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@@ -1,7 +1,8 @@
package generator package generator
import ( import (
"katenary/utils" "fmt"
"github.com/katenary/katenary/internal/utils"
"regexp" "regexp"
"strings" "strings"
@@ -50,15 +51,12 @@ func NewService(service types.ServiceConfig, appName string) *Service {
// AddPort adds a port to the service. // AddPort adds a port to the service.
func (s *Service) AddPort(port types.ServicePortConfig, serviceName ...string) { func (s *Service) AddPort(port types.ServicePortConfig, serviceName ...string) {
name := s.service.Name var name string
if len(serviceName) > 0 {
name = serviceName[0]
}
var finalport intstr.IntOrString var finalport intstr.IntOrString
if targetPort := utils.GetServiceNameByPort(int(port.Target)); targetPort == "" { if targetPort := utils.GetServiceNameByPort(int(port.Target)); targetPort == "" {
finalport = intstr.FromInt(int(port.Target)) finalport = intstr.FromInt(int(port.Target))
name = fmt.Sprintf("port-%d", port.Target)
} else { } else {
finalport = intstr.FromString(targetPort) finalport = intstr.FromString(targetPort)
name = targetPort name = targetPort
@@ -86,7 +84,7 @@ func (s *Service) Yaml() ([]byte, error) {
} }
lines := []string{} lines := []string{}
for _, line := range strings.Split(string(y), "\n") { for line := range strings.SplitSeq(string(y), "\n") {
if regexp.MustCompile(`^\s*loadBalancer:\s*`).MatchString(line) { if regexp.MustCompile(`^\s*loadBalancer:\s*`).MatchString(line) {
continue continue
} }

View File

@@ -47,3 +47,37 @@ services:
t.Errorf("Expected 2 ports, got %d", foundPort) t.Errorf("Expected 2 ports, got %d", foundPort)
} }
} }
func TestWithSeveralUnknownPorts(t *testing.T) {
composeFile := `
services:
multi:
image: nginx
ports:
- 12443
- 12480
labels:
katenary.v3/ingress: |-
port: 12443
`
tmpDir := setup(composeFile)
defer teardown(tmpDir)
currentDir, _ := os.Getwd()
os.Chdir(tmpDir)
defer os.Chdir(currentDir)
output := internalCompileTest(t, "-s", "templates/multi/service.yaml")
service := v1.Service{}
if err := yaml.Unmarshal([]byte(output), &service); err != nil {
t.Errorf(unmarshalError, err)
}
if len(service.Spec.Ports) != 2 {
t.Errorf("Expected 2 ports, got %d", len(service.Spec.Ports))
}
// ensure that both port names are different
if service.Spec.Ports[0].Name == service.Spec.Ports[1].Name {
t.Errorf("Expected different port names, got %s and %s", service.Spec.Ports[0].Name, service.Spec.Ports[1].Name)
}
}

View File

@@ -1,11 +1,12 @@
package generator package generator
import ( import (
"katenary/parser"
"log" "log"
"os" "os"
"os/exec" "os/exec"
"testing" "testing"
"github.com/katenary/katenary/internal/parser"
) )
const unmarshalError = "Failed to unmarshal the output: %s" const unmarshalError = "Failed to unmarshal the output: %s"
@@ -49,6 +50,7 @@ func internalCompileTest(t *testing.T, options ...string) string {
ChartVersion: chartVersion, ChartVersion: chartVersion,
} }
if err := Convert(convertOptions, "compose.yml"); err != nil { if err := Convert(convertOptions, "compose.yml"); err != nil {
log.Printf("Failed to convert: %s", err)
return err.Error() return err.Error()
} }

Some files were not shown because too many files have changed in this diff Show More