Compare commits
14 Commits
releases/3
...
feature/be
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fc9cb31c4 | |||
| 78b5af747e | |||
| 269717eb1c | |||
| 61896baad8 | |||
| feff997aba | |||
| 89e331069e | |||
| 88ce6d4579 | |||
| 3e80221641 | |||
|
|
990eda74eb | ||
| 7230081401 | |||
| f0fc694d50 | |||
| d92cc8a01c | |||
| 3abfaf591c | |||
|
569ca195df
|
@@ -6,16 +6,16 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"katenary.io/internal/generator"
|
||||
"katenary.io/internal/generator/katenaryfile"
|
||||
"katenary.io/internal/generator/labels"
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ func main() {
|
||||
rootCmd := buildRootCmd()
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,8 @@ Katenary transforms compose services this way:
|
||||
- environment variables will be stored inside a `ConfigMap`
|
||||
- image, tags, and ingresses configuration are also stored in `values.yaml` file
|
||||
- if named volumes are declared, Katenary create `PersistentVolumeClaims` - not enabled in values file
|
||||
- `depends_on` needs that the pointed service declared a port. If not, you can use labels to inform Katenary
|
||||
- `depends_on` uses Kubernetes API by default to check if the service endpoint is ready. No port required.
|
||||
Use label `katenary.v3/depends-on: legacy` to use the old netcat method (requires port).
|
||||
|
||||
For any other specific configuration, like binding local files as `ConfigMap`, bind variables, add values with
|
||||
documentation, etc. You'll need to use labels.
|
||||
@@ -147,10 +148,8 @@ Katenary proposes a lot of labels to configure the helm chart generation, but so
|
||||
|
||||
### Work with Depends On?
|
||||
|
||||
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.
|
||||
|
||||
See this compose file:
|
||||
Katenary creates `initContainer` to wait for dependent services to be ready. By default, it uses the Kubernetes API
|
||||
to check if the service endpoint has ready addresses - no port required.
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
@@ -167,9 +166,7 @@ services:
|
||||
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
|
||||
(yet) solution to check the database startup. Katenary wants to create a `initContainer` to hit on the related service.
|
||||
So, instead of exposing the port in the compose definition, let's declare this to Katenary with labels:
|
||||
If you need the old netcat-based method (requires port), add the `katenary.v3/depends-on: legacy` label to the dependent service:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
@@ -179,14 +176,15 @@ services:
|
||||
image: php:8-apache
|
||||
depends_on:
|
||||
- database
|
||||
labels:
|
||||
katenary.v3/depends-on: legacy
|
||||
|
||||
database:
|
||||
image: mariadb
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: foobar
|
||||
labels:
|
||||
katenary.v3/ports: |-
|
||||
- 3306
|
||||
ports:
|
||||
- 3306:3306
|
||||
```
|
||||
|
||||
### Declare ingresses
|
||||
|
||||
40
go.mod
40
go.mod
@@ -5,14 +5,14 @@ go 1.24.0
|
||||
toolchain go1.24.7
|
||||
|
||||
require (
|
||||
github.com/compose-spec/compose-go v1.20.2
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0
|
||||
github.com/invopop/jsonschema v0.13.0
|
||||
github.com/mitchellh/go-wordwrap v1.0.1
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/thediveo/netdb v1.1.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.33.4
|
||||
k8s.io/apimachinery v0.33.4
|
||||
k8s.io/api v0.34.1
|
||||
k8s.io/apimachinery v0.34.1
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
)
|
||||
|
||||
@@ -25,35 +25,33 @@ require (
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.7 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.46.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||
)
|
||||
|
||||
91
go.sum
91
go.sum
@@ -2,8 +2,8 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
|
||||
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0 h1:UHSv/QHlo6QJtrT4igF1rdORgIUhDo1gWuyJUoiNNIM=
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -11,6 +11,8 @@ 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/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/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
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=
|
||||
@@ -21,16 +23,15 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
@@ -43,39 +44,38 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6/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/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -87,53 +87,46 @@ github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
|
||||
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
|
||||
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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
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.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -148,21 +141,19 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk=
|
||||
k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc=
|
||||
k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s=
|
||||
k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
|
||||
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
|
||||
k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
|
||||
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
|
||||
23
install.sh
23
install.sh
@@ -4,20 +4,25 @@
|
||||
# Can be launched with the following command:
|
||||
# sh <(curl -sSL https://raw.githubusercontent.com/Katenary/katenary/master/install.sh)
|
||||
|
||||
set -e
|
||||
|
||||
# Detect the OS and architecture
|
||||
OS=$(uname)
|
||||
ARCH=$(uname -m)
|
||||
|
||||
for c in curl grep cut tr; do
|
||||
if ! command -v $c >/dev/null 2>&1; then
|
||||
echo "Error: $c is not installed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Detect the home directory "bin" directory, it is commonly:
|
||||
# - $HOME/.local/bin
|
||||
# - $HOME/.bin
|
||||
# - $HOME/bin
|
||||
COMON_INSTALL_PATHS="$HOME/.local/bin $HOME/.bin $HOME/bin"
|
||||
COMMON_INSTALL_PATHS="$HOME/.local/bin $HOME/.bin $HOME/bin"
|
||||
|
||||
INSTALL_PATH=""
|
||||
for p in $COMON_INSTALL_PATHS; do
|
||||
for p in $COMMON_INSTALL_PATHS; do
|
||||
if [ -d $p ]; then
|
||||
INSTALL_PATH=$p
|
||||
break
|
||||
@@ -43,20 +48,22 @@ if ! echo "$PATH" | grep -q "$INSTALL_PATH"; then
|
||||
fi
|
||||
|
||||
# Where to download the binary
|
||||
BASE="https://github.com/Katenary/katenary/releases/latest/download/"
|
||||
TAG=$(curl -sLf https://repo.katenary.io/api/v1/repos/katenary/katenary/releases/latest 2>/dev/null | grep -Po '"tag_name":\s*"[^"]*"' | cut -d ":" -f2 | tr -d '"')
|
||||
TAG=${TAG#releases/}
|
||||
|
||||
# for compatibility with older ARM versions
|
||||
# use the right names for the OS and architecture
|
||||
if [ $ARCH = "x86_64" ]; then
|
||||
ARCH="amd64"
|
||||
fi
|
||||
|
||||
BIN_URL="$BASE/katenary-$OS-$ARCH"
|
||||
BIN_URL="https://repo.katenary.io/api/packages/Katenary/generic/katenary/$TAG/katenary-$OS-$ARCH"
|
||||
|
||||
|
||||
echo
|
||||
echo "Downloading $BIN_URL"
|
||||
|
||||
T=$(mktemp -u)
|
||||
curl -SL -# $BIN_URL -o $T || (echo "Failed to download katenary" && rm -f $T && exit 1)
|
||||
curl -sLf -# $BIN_URL -o $T 2>/dev/null || (echo -e "Failed to download katenary version $TAG.\n\nPlease open an issue and explain the problem, following the link:\nhttps://repo.katenary.io/Katenary/katenary/issues/new?title=[install.sh]%20Install%20$TAG%20failed" && rm -f $T && exit 1)
|
||||
|
||||
mv "$T" "${INSTALL_PATH}/katenary"
|
||||
chmod +x "${INSTALL_PATH}/katenary"
|
||||
|
||||
@@ -2,7 +2,6 @@ package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
@@ -331,12 +330,12 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m
|
||||
}
|
||||
fromservices, err := labelstructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
|
||||
if err != nil {
|
||||
log.Fatal("error unmarshaling env-from label:", err)
|
||||
logger.Fatal("error unmarshaling env-from label:", err)
|
||||
}
|
||||
// find the configmap in the chart templates
|
||||
for _, fromservice := range fromservices {
|
||||
if _, ok := chart.Templates[fromservice+".configmap.yaml"]; !ok {
|
||||
log.Printf("configmap %s not found in chart templates", fromservice)
|
||||
logger.Warnf("configmap %s not found in chart templates", fromservice)
|
||||
continue
|
||||
}
|
||||
// find the corresponding target deployment
|
||||
@@ -356,7 +355,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
|
||||
}
|
||||
mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValuesFrom])
|
||||
if err != nil {
|
||||
log.Fatal("error unmarshaling values-from label:", err)
|
||||
logger.Fatal("error unmarshaling values-from label:", err)
|
||||
}
|
||||
|
||||
findDeployment := func(name string) *Deployment {
|
||||
@@ -375,11 +374,11 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
|
||||
dep := findDeployment(depName[0])
|
||||
target := findDeployment(service.Name)
|
||||
if dep == nil || target == nil {
|
||||
log.Fatalf("deployment %s or %s not found", depName[0], service.Name)
|
||||
logger.Fatalf("deployment %s or %s not found", depName[0], service.Name)
|
||||
}
|
||||
container, index := utils.GetContainerByName(target.service.ContainerName, target.Spec.Template.Spec.Containers)
|
||||
if container == nil {
|
||||
log.Fatalf("Container %s not found", target.GetName())
|
||||
logger.Fatalf("Container %s not found", target.GetName())
|
||||
}
|
||||
reourceName := fmt.Sprintf(`{{ include "%s.fullname" . }}-%s`, chart.Name, depName[0])
|
||||
// add environment with from
|
||||
|
||||
@@ -2,7 +2,6 @@ package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -69,7 +68,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
||||
// get the secrets from the labels
|
||||
secrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
// drop the secrets from the environment
|
||||
for _, secret := range secrets {
|
||||
@@ -95,7 +94,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
||||
if l, ok := service.Labels[labels.LabelMapEnv]; ok {
|
||||
envmap, err := labelstructs.MapEnvFrom(l)
|
||||
if err != nil {
|
||||
log.Fatal("Error parsing map-env", err)
|
||||
logger.Fatal("Error parsing map-env", err)
|
||||
}
|
||||
for key, value := range envmap {
|
||||
cm.AddData(key, strings.ReplaceAll(value, "__APP__", appName))
|
||||
@@ -145,7 +144,7 @@ func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string
|
||||
path = filepath.Join(service.WorkingDir, path)
|
||||
path = filepath.Clean(path)
|
||||
if err := cm.AppendDir(path); err != nil {
|
||||
log.Fatal("Error adding files to configmap:", err)
|
||||
logger.Fatal("Error adding files to configmap:", err)
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"katenary.io/internal/generator/labels"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
appv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -20,7 +19,7 @@ import (
|
||||
"katenary.io/internal/parser"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
)
|
||||
|
||||
const ingressClassHelp = `# Default value for ingress.class annotation
|
||||
@@ -596,7 +595,7 @@ func callHelmUpdate(config ConvertOptions) {
|
||||
func removeNewlinesInsideBrackets(values []byte) []byte {
|
||||
re, err := regexp.Compile(`(?s)\{\{(.*?)\}\}`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
return re.ReplaceAllFunc(values, func(b []byte) []byte {
|
||||
// get the first match
|
||||
@@ -635,7 +634,7 @@ func writeContent(path string, content []byte) {
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if _, err := f.Write(content); err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"katenary.io/internal/generator/labels"
|
||||
"katenary.io/internal/generator/labels/labelstructs"
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -33,7 +33,7 @@ func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (
|
||||
}
|
||||
mapping, err := labelstructs.CronJobFrom(labels)
|
||||
if err != nil {
|
||||
log.Fatalf("Error parsing cronjob labels: %s", err)
|
||||
logger.Fatalf("Error parsing cronjob labels: %s", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -166,7 +165,7 @@ func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *core
|
||||
if v, ok := service.Labels[labels.LabelHealthCheck]; ok {
|
||||
probes, err := labelstructs.ProbeFrom(v)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
container.LivenessProbe = probes.LivenessProbe
|
||||
container.ReadinessProbe = probes.ReadinessProbe
|
||||
@@ -201,7 +200,7 @@ func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
||||
if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok {
|
||||
binds, err := labelstructs.ConfigMapFileFrom(v)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
for _, bind := range binds {
|
||||
tobind[bind] = true
|
||||
@@ -263,19 +262,30 @@ func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) {
|
||||
|
||||
// DependsOn adds a initContainer to the deployment that will wait for the service to be up.
|
||||
func (d *Deployment) DependsOn(to *Deployment, servicename string) error {
|
||||
// Add a initContainer with busybox:latest using netcat to check if the service is up
|
||||
// it will wait until the service responds to all ports
|
||||
logger.Info("Adding dependency from ", d.service.Name, " to ", to.service.Name)
|
||||
|
||||
useLegacy := false
|
||||
if label, ok := d.service.Labels[labels.LabelDependsOn]; ok {
|
||||
useLegacy = strings.ToLower(label) == "legacy"
|
||||
}
|
||||
|
||||
if useLegacy {
|
||||
return d.dependsOnLegacy(to, servicename)
|
||||
}
|
||||
|
||||
return d.dependsOnK8sAPI(to)
|
||||
}
|
||||
|
||||
func (d *Deployment) dependsOnLegacy(to *Deployment, servicename string) error {
|
||||
for _, container := range to.Spec.Template.Spec.Containers {
|
||||
commands := []string{}
|
||||
if len(container.Ports) == 0 {
|
||||
logger.Warn("No ports found for service ",
|
||||
logger.Fatal("No ports found for service ",
|
||||
servicename,
|
||||
". You should declare a port in the service or use "+
|
||||
labels.LabelPorts+
|
||||
" label.",
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
for _, port := range container.Ports {
|
||||
command := fmt.Sprintf("until nc -z %s %d; do\n sleep 1;\ndone", to.Name, port.ContainerPort)
|
||||
@@ -293,6 +303,39 @@ func (d *Deployment) DependsOn(to *Deployment, servicename string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Deployment) dependsOnK8sAPI(to *Deployment) error {
|
||||
script := `NAMESPACE=${NAMESPACE:-default}
|
||||
SERVICE=%s
|
||||
KUBERNETES_SERVICE_HOST=${KUBERNETES_SERVICE_HOST:-kubernetes.default.svc}
|
||||
KUBERNETES_SERVICE_PORT=${KUBERNETES_SERVICE_PORT:-443}
|
||||
|
||||
until wget -q -O- --header="Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
|
||||
--cacert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
|
||||
"https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/namespaces/${NAMESPACE}/endpoints/${SERVICE}" \
|
||||
| grep -q '"ready":.*true'; do
|
||||
sleep 2
|
||||
done`
|
||||
|
||||
command := []string{"/bin/sh", "-c", fmt.Sprintf(script, to.Name)}
|
||||
d.Spec.Template.Spec.InitContainers = append(d.Spec.Template.Spec.InitContainers, corev1.Container{
|
||||
Name: "wait-for-" + to.service.Name,
|
||||
Image: "busybox:latest",
|
||||
Command: command,
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "NAMESPACE",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.namespace",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Filename returns the filename of the deployment.
|
||||
func (d *Deployment) Filename() string {
|
||||
return d.service.Name + ".deployment.yaml"
|
||||
@@ -311,7 +354,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
defer func() {
|
||||
c, index := d.BindMapFilesToContainer(service, secrets, appName)
|
||||
if c == nil || index == -1 {
|
||||
log.Println("Container not found for service ", service.Name)
|
||||
logger.Warn("Container not found for service ", service.Name)
|
||||
return
|
||||
}
|
||||
d.Spec.Template.Spec.Containers[index] = *c
|
||||
@@ -320,7 +363,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
// secrets from label
|
||||
labelSecrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
// values from label
|
||||
@@ -335,7 +378,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
_, ok := service.Environment[secret]
|
||||
if !ok {
|
||||
drop = append(drop, secret)
|
||||
logger.Warn("Secret " + secret + " not found in service " + service.Name + " - skpped")
|
||||
logger.Warn("Secret " + secret + " not found in service " + service.Name + " - skipped")
|
||||
continue
|
||||
}
|
||||
secrets = append(secrets, secret)
|
||||
@@ -352,7 +395,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
|
||||
val, ok := service.Environment[value]
|
||||
if !ok {
|
||||
drop = append(drop, value)
|
||||
logger.Warn("Environment variable " + value + " not found in service " + service.Name + " - skpped")
|
||||
logger.Warn("Environment variable " + value + " not found in service " + service.Name + " - skipped")
|
||||
continue
|
||||
}
|
||||
if d.chart.Values[service.Name].(*Value).Environment == nil {
|
||||
@@ -384,8 +427,8 @@ func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secret
|
||||
|
||||
if envSize > 0 {
|
||||
if service.Name == "db" {
|
||||
log.Println("Service ", service.Name, " has environment variables")
|
||||
log.Println(service.Environment)
|
||||
logger.Info("Service ", service.Name, " has environment variables")
|
||||
logger.Info(service.Environment)
|
||||
}
|
||||
fromSources = append(fromSources, corev1.EnvFromSource{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
@@ -615,7 +658,7 @@ func (d *Deployment) appendDirectoryToConfigMap(service types.ServiceConfig, app
|
||||
// TODO: make it recursive to add all files in the directory and subdirectories
|
||||
_, err := os.ReadDir(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
cm := NewConfigMapFromDirectory(service, appName, volume.Source)
|
||||
d.configMaps[pathnme] = &ConfigMapMount{
|
||||
@@ -660,7 +703,7 @@ func (d *Deployment) appendFileToConfigMap(service types.ServiceConfig, appName
|
||||
|
||||
}
|
||||
if err := cm.AppendFile(volume.Source); err != nil {
|
||||
log.Fatal("Error adding file to configmap:", err)
|
||||
logger.Fatal("Error adding file to configmap:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +764,7 @@ func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, tobind map[st
|
||||
// Add volume to container
|
||||
stat, err := os.Stat(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
|
||||
@@ -142,6 +142,86 @@ services:
|
||||
if len(dt.Spec.Template.Spec.InitContainers) != 1 {
|
||||
t.Errorf("Expected 1 init container, got %d", len(dt.Spec.Template.Spec.InitContainers))
|
||||
}
|
||||
|
||||
initContainer := dt.Spec.Template.Spec.InitContainers[0]
|
||||
if !strings.Contains(initContainer.Image, "busybox") {
|
||||
t.Errorf("Expected busybox image, got %s", initContainer.Image)
|
||||
}
|
||||
|
||||
fullCommand := strings.Join(initContainer.Command, " ")
|
||||
if !strings.Contains(fullCommand, "wget") {
|
||||
t.Errorf("Expected wget command (K8s API method), got %s", fullCommand)
|
||||
}
|
||||
|
||||
if !strings.Contains(fullCommand, "/api/v1/namespaces/") {
|
||||
t.Errorf("Expected Kubernetes API call to /api/v1/namespaces/, got %s", fullCommand)
|
||||
}
|
||||
|
||||
if !strings.Contains(fullCommand, "/endpoints/") {
|
||||
t.Errorf("Expected Kubernetes API call to /endpoints/, got %s", fullCommand)
|
||||
}
|
||||
|
||||
if len(initContainer.Env) == 0 {
|
||||
t.Errorf("Expected environment variables to be set for namespace")
|
||||
}
|
||||
|
||||
hasNamespace := false
|
||||
for _, env := range initContainer.Env {
|
||||
if env.Name == "NAMESPACE" && env.ValueFrom != nil && env.ValueFrom.FieldRef != nil {
|
||||
if env.ValueFrom.FieldRef.FieldPath == "metadata.namespace" {
|
||||
hasNamespace = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasNamespace {
|
||||
t.Errorf("Expected NAMESPACE env var with metadata.namespace fieldRef")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependsOnLegacy(t *testing.T) {
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- database
|
||||
labels:
|
||||
katenary.v3/depends-on: legacy
|
||||
|
||||
database:
|
||||
image: mariadb:10.5
|
||||
ports:
|
||||
- 3306:3306
|
||||
`
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := internalCompileTest(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
}
|
||||
|
||||
if len(dt.Spec.Template.Spec.InitContainers) != 1 {
|
||||
t.Errorf("Expected 1 init container, got %d", len(dt.Spec.Template.Spec.InitContainers))
|
||||
}
|
||||
|
||||
initContainer := dt.Spec.Template.Spec.InitContainers[0]
|
||||
if !strings.Contains(initContainer.Image, "busybox") {
|
||||
t.Errorf("Expected busybox image, got %s", initContainer.Image)
|
||||
}
|
||||
|
||||
fullCommand := strings.Join(initContainer.Command, " ")
|
||||
if !strings.Contains(fullCommand, "nc") {
|
||||
t.Errorf("Expected nc (netcat) command for legacy method, got %s", fullCommand)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelmDependencies(t *testing.T) {
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"katenary.io/internal/logger"
|
||||
)
|
||||
|
||||
//go:embed readme.tpl
|
||||
@@ -50,7 +50,7 @@ func ReadMeFile(charname, description string, values map[string]any) string {
|
||||
vv := map[string]any{}
|
||||
out, _ := yaml.Marshal(values)
|
||||
if err := yaml.Unmarshal(out, &vv); err != nil {
|
||||
log.Printf("Error parsing values: %s", err)
|
||||
logger.Warnf("Error parsing values: %s", err)
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
|
||||
@@ -3,7 +3,6 @@ package generator
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -12,7 +11,7 @@ import (
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
@@ -145,7 +144,7 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
|
||||
// generate configmaps with environment variables
|
||||
if err := chart.generateConfigMapsAndSecrets(project); err != nil {
|
||||
log.Fatalf("error generating configmaps and secrets: %s", err)
|
||||
logger.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
|
||||
@@ -216,9 +215,9 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
||||
|
||||
// dropIngoredServices removes all services with the "ignore" label set to true (or yes).
|
||||
func dropIngoredServices(project *types.Project) {
|
||||
for i, service := range project.Services {
|
||||
for name, service := range project.Services {
|
||||
if isIgnored(service) {
|
||||
project.Services = append(project.Services[:i], project.Services[i+1:]...)
|
||||
delete(project.Services, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,7 +279,7 @@ func addStaticVolumes(deployments map[string]*Deployment, service types.ServiceC
|
||||
var d *Deployment
|
||||
var ok bool
|
||||
if d, ok = deployments[service.Name]; !ok {
|
||||
log.Printf("service %s not found in deployments", service.Name)
|
||||
logger.Warnf("service %s not found in deployments", service.Name)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -292,7 +291,7 @@ func addStaticVolumes(deployments map[string]*Deployment, service types.ServiceC
|
||||
var y []byte
|
||||
var err error
|
||||
if y, err = config.configMap.Yaml(); err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
// add the configmap to the chart
|
||||
@@ -434,7 +433,7 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
|
||||
// check if it has the same volume
|
||||
for _, tv := range target.Spec.Template.Spec.Volumes {
|
||||
if tv.Name == v.Source {
|
||||
log.Printf("found same pod volume %s in deployment %s and %s", tv.Name, service.Name, targetDeployment)
|
||||
logger.Warnf("found same pod volume %s in deployment %s and %s", tv.Name, service.Name, targetDeployment)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"katenary.io/internal/generator/labels"
|
||||
"katenary.io/internal/generator/labels/labelstructs"
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
networkv1 "k8s.io/api/networking/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -36,7 +36,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
||||
|
||||
mapping, err := labelstructs.IngressFrom(label)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse ingress label: %s\n", err)
|
||||
logger.Fatalf("Failed to parse ingress label: %s\n", err)
|
||||
}
|
||||
if mapping.Hostname == "" {
|
||||
mapping.Hostname = service.Name + ".tld"
|
||||
|
||||
@@ -3,7 +3,6 @@ package katenaryfile
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -12,7 +11,7 @@ import (
|
||||
"katenary.io/internal/generator/labels/labelstructs"
|
||||
"katenary.io/internal/logger"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/invopop/jsonschema"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -67,38 +66,40 @@ func OverrideWithConfig(project *types.Project) {
|
||||
return
|
||||
}
|
||||
if err := yaml.NewDecoder(fp).Decode(&services); err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
return
|
||||
}
|
||||
for i, p := range project.Services {
|
||||
for _, 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)
|
||||
mustGetLabelContent := func(o any, labelName string) {
|
||||
s, ok := project.Services[name]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
err := getLabelContent(o, &s, labelName)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
project.Services[name] = s
|
||||
}
|
||||
|
||||
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)
|
||||
mustGetLabelContent(s.MainApp, labels.LabelMainApp)
|
||||
mustGetLabelContent(s.Values, labels.LabelValues)
|
||||
mustGetLabelContent(s.Secrets, labels.LabelSecrets)
|
||||
mustGetLabelContent(s.Ports, labels.LabelPorts)
|
||||
mustGetLabelContent(s.Ingress, labels.LabelIngress)
|
||||
mustGetLabelContent(s.HealthCheck, labels.LabelHealthCheck)
|
||||
mustGetLabelContent(s.SamePod, labels.LabelSamePod)
|
||||
mustGetLabelContent(s.Description, labels.LabelDescription)
|
||||
mustGetLabelContent(s.Ignore, labels.LabelIgnore)
|
||||
mustGetLabelContent(s.Dependencies, labels.LabelDependencies)
|
||||
mustGetLabelContent(s.ConfigMapFiles, labels.LabelConfigMapFiles)
|
||||
mustGetLabelContent(s.MapEnv, labels.LabelMapEnv)
|
||||
mustGetLabelContent(s.CronJob, labels.LabelCronJob)
|
||||
mustGetLabelContent(s.EnvFrom, labels.LabelEnvFrom)
|
||||
mustGetLabelContent(s.ExchangeVolumes, labels.LabelExchangeVolume)
|
||||
mustGetLabelContent(s.ValuesFrom, labels.LabelValuesFrom)
|
||||
}
|
||||
}
|
||||
logger.Info("Katenary file loaded successfully, the services are now configured.")
|
||||
@@ -111,7 +112,7 @@ func getLabelContent(o any, service *types.ServiceConfig, labelName string) erro
|
||||
|
||||
c, err := yaml.Marshal(o)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
logger.Failure(err.Error())
|
||||
return err
|
||||
}
|
||||
val := strings.TrimSpace(string(c))
|
||||
@@ -119,7 +120,7 @@ func getLabelContent(o any, service *types.ServiceConfig, labelName string) erro
|
||||
// special case, values must be set from some defaults
|
||||
ing, err := labelstructs.IngressFrom(val)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
return err
|
||||
}
|
||||
c, err := yaml.Marshal(ing)
|
||||
@@ -129,6 +130,9 @@ func getLabelContent(o any, service *types.ServiceConfig, labelName string) erro
|
||||
val = strings.TrimSpace(string(c))
|
||||
}
|
||||
|
||||
if service.Labels == nil {
|
||||
service.Labels = types.Labels{}
|
||||
}
|
||||
service.Labels[labelName] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package katenaryfile
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"katenary.io/internal/generator/labels"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
)
|
||||
|
||||
func TestBuildSchema(t *testing.T) {
|
||||
@@ -53,13 +54,13 @@ webapp:
|
||||
cli.WithWorkingDirectory(tmpDir),
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
project, err := cli.ProjectFromOptions(context.TODO(), options)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create project from options: %s", err.Error())
|
||||
}
|
||||
|
||||
OverrideWithConfig(project)
|
||||
w := project.Services[0].Labels
|
||||
w := project.Services["webapp"].Labels
|
||||
if v, ok := w[labels.LabelPorts]; !ok {
|
||||
t.Fatal("Expected ports to be defined", v)
|
||||
}
|
||||
@@ -103,13 +104,13 @@ webapp:
|
||||
cli.WithWorkingDirectory(tmpDir),
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
project, err := cli.ProjectFromOptions(context.TODO(), options)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create project from options: %s", err.Error())
|
||||
}
|
||||
|
||||
OverrideWithConfig(project)
|
||||
w := project.Services[0].Labels
|
||||
w := project.Services["webapp"].Labels
|
||||
if v, ok := w[labels.LabelPorts]; !ok {
|
||||
t.Fatal("Expected ports to be defined", v)
|
||||
}
|
||||
@@ -158,13 +159,13 @@ webapp:
|
||||
cli.WithWorkingDirectory(tmpDir),
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
project, err := cli.ProjectFromOptions(context.TODO(), options)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create project from options: %s", err.Error())
|
||||
}
|
||||
|
||||
OverrideWithConfig(project)
|
||||
w := project.Services[0].Labels
|
||||
w := project.Services["webapp"].Labels
|
||||
if v, ok := w[labels.LabelConfigMapFiles]; !ok {
|
||||
t.Fatal("Expected configmap-files to be defined", v)
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
@@ -36,6 +36,7 @@ const (
|
||||
LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from"
|
||||
LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes"
|
||||
LabelValuesFrom Label = KatenaryLabelPrefix + "/values-from"
|
||||
LabelDependsOn Label = KatenaryLabelPrefix + "/depends-on"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -134,7 +135,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
logger.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
help.Long = buf.String()
|
||||
buf.Reset()
|
||||
@@ -145,7 +146,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
logger.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
help.Example = buf.String()
|
||||
buf.Reset()
|
||||
@@ -160,7 +161,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
||||
KatenaryPrefix: KatenaryLabelPrefix,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error executing template: %v", err)
|
||||
logger.Fatalf("Error executing template: %v", err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
|
||||
@@ -355,4 +355,25 @@
|
||||
DB_USER: database.MARIADB_USER
|
||||
DB_PASSWORD: database.MARIADB_PASSWORD
|
||||
|
||||
"depends-on":
|
||||
short: "Method to check if a service is ready (for depends_on)."
|
||||
long: |-
|
||||
When a service uses `depends_on`, Katenary creates an initContainer to wait
|
||||
for the dependent service to be ready.
|
||||
|
||||
By default, Katenary uses the Kubernetes API to check if the service endpoint
|
||||
has ready addresses. This method does not require the service to expose a port.
|
||||
|
||||
Set this label to `legacy` to use the old netcat method that requires a port
|
||||
to be defined for the dependent service.
|
||||
example: |-
|
||||
web:
|
||||
image: nginx
|
||||
depends_on:
|
||||
- database
|
||||
labels:
|
||||
# Use legacy netcat method (requires port)
|
||||
{{ .KatenaryPrefix }}/depends-on: legacy
|
||||
type: "string"
|
||||
|
||||
# vim: ft=gotmpl.yaml
|
||||
|
||||
@@ -2,10 +2,10 @@ package labelstructs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"katenary.io/internal/logger"
|
||||
)
|
||||
|
||||
type HealthCheck struct {
|
||||
@@ -24,13 +24,13 @@ func ProbeFrom(data string) (*HealthCheck, error) {
|
||||
if livenessProbe, ok := tmp["livenessProbe"]; ok {
|
||||
livenessProbeBytes, err := json.Marshal(livenessProbe)
|
||||
if err != nil {
|
||||
log.Printf("Error marshalling livenessProbe: %v", err)
|
||||
logger.Warnf("Error marshalling livenessProbe: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
livenessProbe := &corev1.Probe{}
|
||||
err = json.Unmarshal(livenessProbeBytes, livenessProbe)
|
||||
if err != nil {
|
||||
log.Printf("Error unmarshalling livenessProbe: %v", err)
|
||||
logger.Warnf("Error unmarshalling livenessProbe: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
mapping.LivenessProbe = livenessProbe
|
||||
@@ -39,13 +39,13 @@ func ProbeFrom(data string) (*HealthCheck, error) {
|
||||
if readinessProbe, ok := tmp["readinessProbe"]; ok {
|
||||
readinessProbeBytes, err := json.Marshal(readinessProbe)
|
||||
if err != nil {
|
||||
log.Printf("Error marshalling readinessProbe: %v", err)
|
||||
logger.Warnf("Error marshalling readinessProbe: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
readinessProbe := &corev1.Probe{}
|
||||
err = json.Unmarshal(readinessProbeBytes, readinessProbe)
|
||||
if err != nil {
|
||||
log.Printf("Error unmarshalling readinessProbe: %v", err)
|
||||
logger.Warnf("Error unmarshalling readinessProbe: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
mapping.ReadinessProbe = readinessProbe
|
||||
|
||||
@@ -3,7 +3,7 @@ package generator
|
||||
import (
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"katenary.io/internal/generator/labels"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"katenary.io/internal/logger"
|
||||
"katenary.io/internal/parser"
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ func setup(content string) string {
|
||||
|
||||
func teardown(tmpDir string) {
|
||||
// remove the temporary directory
|
||||
log.Println("Removing temporary directory: ", tmpDir)
|
||||
logger.Info("Removing temporary directory: ", tmpDir)
|
||||
if err := os.RemoveAll(tmpDir); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func compileTest(t *testing.T, force bool, options ...string) string {
|
||||
ChartVersion: chartVersion,
|
||||
}
|
||||
if err := Convert(convertOptions, "compose.yml"); err != nil {
|
||||
log.Printf("Failed to convert: %s", err)
|
||||
logger.Warnf("Failed to convert: %s", err)
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"katenary.io/internal/generator/labels/labelstructs"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
"katenary.io/internal/generator/labels"
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
)
|
||||
|
||||
func TestSplitPorts(t *testing.T) {
|
||||
@@ -28,7 +29,7 @@ services:
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
|
||||
os.MkdirAll(tmpDir, utils.DirectoryPermission)
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0o644); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
@@ -39,15 +40,17 @@ services:
|
||||
cli.WithWorkingDirectory(tmpDir),
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
project, err := cli.ProjectFromOptions(context.TODO(), options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixPorts(&project.Services[0]); err != nil {
|
||||
s := project.Services["foo"]
|
||||
if err := fixPorts(&s); err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
project.Services["foo"] = s
|
||||
found := 0
|
||||
for _, p := range project.Services[0].Ports {
|
||||
for _, p := range project.Services["foo"].Ports {
|
||||
switch p.Target {
|
||||
case 80, 443:
|
||||
found++
|
||||
@@ -76,7 +79,7 @@ services:
|
||||
composeFile := filepath.Join(tmpDir, "compose.yaml")
|
||||
|
||||
os.MkdirAll(tmpDir, utils.DirectoryPermission)
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
|
||||
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0o644); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
@@ -87,15 +90,17 @@ services:
|
||||
cli.WithWorkingDirectory(tmpDir),
|
||||
cli.WithDefaultConfigPath,
|
||||
)
|
||||
project, err := cli.ProjectFromOptions(options)
|
||||
project, err := cli.ProjectFromOptions(context.TODO(), options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixPorts(&project.Services[0]); err != nil {
|
||||
s := project.Services["foo"]
|
||||
if err := fixPorts(&s); err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
project.Services["foo"] = s
|
||||
found := 0
|
||||
for _, p := range project.Services[0].Ports {
|
||||
for _, p := range project.Services["foo"].Ports {
|
||||
switch p.Target {
|
||||
case 80, 443, 8080:
|
||||
found++
|
||||
|
||||
@@ -3,7 +3,7 @@ package generator
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
)
|
||||
|
||||
// RepositoryValue is a docker repository image and tag that will be saved in values.yaml.
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"katenary.io/internal/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// Package logger provides simple logging functions with icons and colors.
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Icon is a unicode icon
|
||||
type Icon string
|
||||
|
||||
@@ -22,30 +27,91 @@ const (
|
||||
|
||||
const reset = "\033[0m"
|
||||
|
||||
// Print prints a message without icon.
|
||||
func Print(msg ...any) {
|
||||
fmt.Print(msg...)
|
||||
}
|
||||
|
||||
// Printf prints a formatted message without icon.
|
||||
func Printf(format string, msg ...any) {
|
||||
fmt.Printf(format, msg...)
|
||||
}
|
||||
|
||||
// Info prints an informational message.
|
||||
func Info(msg ...any) {
|
||||
message("", IconInfo, msg...)
|
||||
}
|
||||
|
||||
// Infof prints a formatted informational message.
|
||||
func Infof(format string, msg ...any) {
|
||||
message("", IconInfo, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
// Warn prints a warning message.
|
||||
func Warn(msg ...any) {
|
||||
orange := "\033[38;5;214m"
|
||||
message(orange, IconWarning, msg...)
|
||||
}
|
||||
|
||||
// Warnf prints a formatted warning message.
|
||||
func Warnf(format string, msg ...any) {
|
||||
orange := "\033[38;5;214m"
|
||||
message(orange, IconWarning, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
// Success prints a success message.
|
||||
func Success(msg ...any) {
|
||||
green := "\033[38;5;34m"
|
||||
message(green, IconSuccess, msg...)
|
||||
}
|
||||
|
||||
// Successf prints a formatted success message.
|
||||
func Successf(format string, msg ...any) {
|
||||
green := "\033[38;5;34m"
|
||||
message(green, IconSuccess, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
// Failure prints a failure message.
|
||||
func Failure(msg ...any) {
|
||||
red := "\033[38;5;196m"
|
||||
message(red, IconFailure, msg...)
|
||||
}
|
||||
|
||||
// Failuref prints a formatted failure message.
|
||||
func Failuref(format string, msg ...any) {
|
||||
red := "\033[38;5;196m"
|
||||
message(red, IconFailure, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
// Log prints a message with a custom icon.
|
||||
func Log(icon Icon, msg ...any) {
|
||||
message("", icon, msg...)
|
||||
}
|
||||
|
||||
// Logf prints a formatted message with a custom icon.
|
||||
func Logf(icon Icon, format string, msg ...any) {
|
||||
message("", icon, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
func fatal(red string, icon Icon, msg ...any) {
|
||||
fmt.Print(icon, " ", red)
|
||||
fmt.Print(msg...)
|
||||
fmt.Println(reset)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func fatalf(red string, icon Icon, format string, msg ...any) {
|
||||
fatal(red, icon, fmt.Sprintf(format, msg...))
|
||||
}
|
||||
|
||||
// Fatal prints a fatal error message and exits with code 1.
|
||||
func Fatal(msg ...any) {
|
||||
red := "\033[38;5;196m"
|
||||
fatal(red, IconFailure, msg...)
|
||||
}
|
||||
|
||||
// Fatalf prints a fatal error message with formatting and exits with code 1.
|
||||
func Fatalf(format string, msg ...any) {
|
||||
red := "\033[38;5;196m"
|
||||
fatalf(red, IconFailure, format, msg...)
|
||||
}
|
||||
|
||||
79
internal/logger/logger_test.go
Normal file
79
internal/logger/logger_test.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIcons(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
got Icon
|
||||
expected Icon
|
||||
}{
|
||||
{"IconSuccess", IconSuccess, "✅"},
|
||||
{"IconFailure", IconFailure, "❌"},
|
||||
{"IconWarning", IconWarning, "❕"},
|
||||
{"IconNote", IconNote, "📝"},
|
||||
{"IconWorld", IconWorld, "🌐"},
|
||||
{"IconPlug", IconPlug, "🔌"},
|
||||
{"IconPackage", IconPackage, "📦"},
|
||||
{"IconCabinet", IconCabinet, "🗄️"},
|
||||
{"IconInfo", IconInfo, "🔵"},
|
||||
{"IconSecret", IconSecret, "🔒"},
|
||||
{"IconConfig", IconConfig, "🔧"},
|
||||
{"IconDependency", IconDependency, "🔗"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.got != tt.expected {
|
||||
t.Errorf("got %q, want %q", tt.got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Info panicked: %v", r)
|
||||
}
|
||||
}()
|
||||
Info("test message")
|
||||
}
|
||||
|
||||
func TestWarn(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Warn panicked: %v", r)
|
||||
}
|
||||
}()
|
||||
Warn("test warning")
|
||||
}
|
||||
|
||||
func TestSuccess(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Success panicked: %v", r)
|
||||
}
|
||||
}()
|
||||
Success("test success")
|
||||
}
|
||||
|
||||
func TestFailure(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Failure panicked: %v", r)
|
||||
}
|
||||
}()
|
||||
Failure("test failure")
|
||||
}
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("Log panicked: %v", r)
|
||||
}
|
||||
}()
|
||||
Log(IconInfo, "test log")
|
||||
}
|
||||
@@ -2,11 +2,12 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"log"
|
||||
"context"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"katenary.io/internal/logger"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -36,11 +37,11 @@ func Parse(profiles []string, envFiles []string, dockerComposeFile ...string) (*
|
||||
var err error
|
||||
envFiles[i], err = filepath.Abs(envFiles[i])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
options, err := cli.NewProjectOptions(nil,
|
||||
options, err := cli.NewProjectOptions(dockerComposeFile,
|
||||
cli.WithProfiles(profiles),
|
||||
cli.WithInterpolation(true),
|
||||
cli.WithDefaultConfigPath,
|
||||
@@ -53,5 +54,6 @@ func Parse(profiles []string, envFiles []string, dockerComposeFile ...string) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cli.ProjectFromOptions(options)
|
||||
ctx := context.TODO()
|
||||
return cli.ProjectFromOptions(ctx, options)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"katenary.io/internal/logger"
|
||||
)
|
||||
|
||||
const composeFile = `
|
||||
@@ -27,7 +28,7 @@ func setupTest() (string, error) {
|
||||
func tearDownTest(tmpDir string) {
|
||||
if tmpDir != "" {
|
||||
if err := os.RemoveAll(tmpDir); err != nil {
|
||||
log.Fatalf("Failed to remove temporary directory %s: %s", tmpDir, err.Error())
|
||||
logger.Fatalf("Failed to remove temporary directory %s: %s", tmpDir, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@ package utils
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/mitchellh/go-wordwrap"
|
||||
"github.com/thediveo/netdb"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -133,8 +132,8 @@ func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[str
|
||||
labelContent := []any{}
|
||||
err := yaml.Unmarshal([]byte(v), &labelContent)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing label %s: %s", v, err)
|
||||
log.Fatal(err)
|
||||
logger.Warnf("Error parsing label %s: %s", v, err)
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
for _, value := range labelContent {
|
||||
@@ -150,7 +149,7 @@ func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[str
|
||||
descriptions[k.(string)] = &EnvConfig{Service: service, Description: v.(string)}
|
||||
}
|
||||
default:
|
||||
log.Fatalf("Unknown type in label: %s %T", LabelValues, value)
|
||||
logger.Fatalf("Unknown type in label: %s %T", LabelValues, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +170,7 @@ func Confirm(question string, icon ...logger.Icon) bool {
|
||||
}
|
||||
var response string
|
||||
if _, err := fmt.Scanln(&response); err != nil {
|
||||
log.Fatalf("Error parsing response: %s", err.Error())
|
||||
logger.Fatalf("Error parsing response: %s", err.Error())
|
||||
}
|
||||
return strings.ToLower(response) == "y"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user