chore(tests): enhance output
All checks were successful
Go-Tests / tests (push) Successful in 2m18s
Go-Tests / sonar (push) Successful in 55s

- use a better logger separation
- use tags not not overload the CI output
- removed lot of log.Println/Fatal/Error
This commit is contained in:
2025-09-15 13:02:54 +02:00
parent 9472952d65
commit debe43ce34
14 changed files with 106 additions and 77 deletions

View File

@@ -33,7 +33,8 @@ jobs:
- name: Launch Test
run: |
go vet ./...
go test -coverprofile=coverprofile.out -json -v ./... > gotest.json
go test -tags ci -coverprofile=coverprofile.out -v ./...
go test -tags ci -coverprofile=coverprofile.out -json -v ./... > gotest.json
go tool cover -func=coverprofile.out
# - uses: actions/upload-artifact@v4
- name: Upload artifact

View File

@@ -11,6 +11,7 @@ import (
"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"
@@ -77,36 +78,36 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
// t = addModeline(t)
kind := utils.GetKind(name)
var icon utils.Icon
var icon logger.Icon
switch kind {
case "deployment":
icon = utils.IconPackage
icon = logger.IconPackage
case "service":
icon = utils.IconPlug
icon = logger.IconPlug
case "ingress":
icon = utils.IconWorld
icon = logger.IconWorld
case "volumeclaim":
icon = utils.IconCabinet
icon = logger.IconCabinet
case "configmap":
icon = utils.IconConfig
icon = logger.IconConfig
case "secret":
icon = utils.IconSecret
icon = logger.IconSecret
default:
icon = utils.IconInfo
icon = logger.IconInfo
}
servicename := template.Servicename
if err := os.MkdirAll(filepath.Join(templateDir, servicename), utils.DirectoryPermission); err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure(err.Error())
os.Exit(1)
}
fmt.Println(icon, "Creating", kind, servicename)
logger.Log(icon, "Creating ", kind, " ", name)
// if the name is a path, create the directory
if strings.Contains(name, string(filepath.Separator)) {
name = filepath.Join(templateDir, name)
err := os.MkdirAll(filepath.Dir(name), utils.DirectoryPermission)
if err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure(err.Error())
os.Exit(1)
}
} else {
@@ -116,14 +117,14 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
}
f, err := os.Create(name)
if err != nil {
fmt.Println(utils.IconFailure, err)
fmt.Println(logger.IconFailure, err)
os.Exit(1)
}
defer f.Close()
if _, err := f.Write(t); err != nil {
log.Fatal("error writing template file:", err)
logger.Failure("error wrting template file: ", err.Error())
os.Exit(1)
}
}
}
@@ -144,14 +145,15 @@ func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) err
if v, ok := s.Labels[labels.LabelSecrets]; ok {
list, err := labelstructs.SecretsFrom(v)
if err != nil {
log.Fatal("error unmarshaling secrets label:", err)
logger.Failure("error unmarshaling secrets label:", err)
os.Exit(1)
}
for _, secret := range list {
if secret == "" {
continue
}
if _, ok := s.Environment[secret]; !ok {
fmt.Printf("%s secret %s not found in environment", utils.IconWarning, secret)
fmt.Printf("%s secret %s not found in environment", logger.IconWarning, secret)
continue
}
secretsVar[secret] = s.Environment[secret]
@@ -195,7 +197,7 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme
// isgnored service
if isIgnored(service) {
fmt.Printf("%s Ignoring service %s\n", utils.IconInfo, service.Name)
logger.Info("Ignoring service ", service.Name)
return nil
}
@@ -305,7 +307,7 @@ func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, erro
}
for _, dep := range d {
fmt.Printf("%s Adding dependency to %s\n", utils.IconDependency, dep.Name)
logger.Log(logger.IconDependency, "Adding dependency to ", dep.Name)
chart.Dependencies = append(chart.Dependencies, dep)
name := dep.Name
if dep.Alias != "" {

View File

@@ -11,6 +11,7 @@ import (
"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"
@@ -178,7 +179,7 @@ func (c *ConfigMap) AppendDir(path string) error {
}
for _, file := range files {
if file.IsDir() {
utils.Warn("Subdirectories are ignored for the moment, skipping", filepath.Join(path, file.Name()))
logger.Warn("Subdirectories are ignored for the moment, skipping", filepath.Join(path, file.Name()))
continue
}
path := filepath.Join(path, file.Name())

View File

@@ -16,6 +16,7 @@ import (
"katenary.io/internal/generator/katenaryfile"
"katenary.io/internal/generator/labels"
"katenary.io/internal/generator/labels/labelstructs"
"katenary.io/internal/logger"
"katenary.io/internal/parser"
"katenary.io/internal/utils"
@@ -111,12 +112,13 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
currentDir, _ := os.Getwd()
// go to the root of the project
if err := os.Chdir(filepath.Dir(dockerComposeFile[0])); err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure(err.Error())
return err
}
defer func() {
if err := os.Chdir(currentDir); err != nil { // after the generation, go back to the original directory
log.Fatal(err)
logger.Failure(err.Error())
os.Exit(1)
}
}()
@@ -134,7 +136,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
// check older version of labels
if err := checkOldLabels(project); err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure(err.Error())
return err
}
@@ -147,7 +149,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
if _, err := os.Stat(config.OutputDir); err == nil {
overwrite := utils.Confirm(
"The chart directory "+config.OutputDir+" already exists, do you want to overwrite it?",
utils.IconWarning,
logger.IconWarning,
)
if !overwrite {
fmt.Println("Aborting")
@@ -399,7 +401,7 @@ func addMainTagAppDoc(values []byte, project *types.Project) []byte {
} else if v == "false" || v == "no" || v == "0" {
continue
} else {
fmt.Printf("%s Adding main tag app doc %s\n", utils.IconConfig, service.Name)
logger.Log(logger.IconConfig, "Adding main tag app doc for service", service.Name)
}
lines = addMainAppDoc(lines, service)
@@ -579,15 +581,15 @@ func buildValues(chart *HelmChart, project *types.Project, valuesPath string) {
func callHelmUpdate(config ConvertOptions) {
executeAndHandleError := func(fn func(ConvertOptions) error, config ConvertOptions, message string) {
if err := fn(config); err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure("Helm command failed, please check the output above", err.Error())
os.Exit(1)
}
fmt.Println(utils.IconSuccess, message)
logger.Success(message)
}
if config.HelmUpdate {
executeAndHandleError(helmUpdate, config, "Helm dependencies updated")
executeAndHandleError(helmLint, config, "Helm chart linted")
fmt.Println(utils.IconSuccess, "Helm chart created successfully")
logger.Success("Helm chart created successfully")
}
}
@@ -627,7 +629,7 @@ func removeUnwantedLines(values []byte) []byte {
func writeContent(path string, content []byte) {
f, err := os.Create(path)
if err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure("Cannot create file "+path, err.Error())
os.Exit(1)
}
defer f.Close()
@@ -640,10 +642,10 @@ func writeContent(path string, content []byte) {
// helmLint runs "helm lint" on the output directory.
func helmLint(config ConvertOptions) error {
fmt.Println(utils.IconInfo, "Linting...")
logger.Info("Linting...")
helm, err := exec.LookPath("helm")
if err != nil {
fmt.Println(utils.IconFailure, err)
logger.Failure("Helm is not installed or not in your PATH", err.Error())
os.Exit(1)
}
cmd := exec.Command(helm, "lint", config.OutputDir)
@@ -655,10 +657,10 @@ func helmLint(config ConvertOptions) error {
// helmUpdate runs "helm dependency update" on the output directory.
func helmUpdate(config ConvertOptions) error {
// lookup for "helm" binary
fmt.Println(utils.IconInfo, "Updating helm dependencies...")
logger.Info("Updating helm dependencies...")
helm, err := exec.LookPath("helm")
if err != nil {
fmt.Println(utils.IconFailure, err)
fmt.Println(logger.IconFailure, err)
os.Exit(1)
}
// run "helm dependency update"

View File

@@ -11,6 +11,7 @@ import (
"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"
@@ -119,7 +120,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
for _, port := range service.Ports {
name := utils.GetServiceNameByPort(int(port.Target))
if name == "" {
utils.Warn("Port name not found for port ", port.Target, " in service ", service.Name, ". Using port number instead")
logger.Warn("Port name not found for port ", port.Target, " in service ", service.Name, ". Using port number instead")
name = fmt.Sprintf("port-%d", port.Target)
}
ports = append(ports, corev1.ContainerPort{
@@ -274,7 +275,7 @@ func (d *Deployment) DependsOn(to *Deployment, servicename string) error {
for _, container := range to.Spec.Template.Spec.Containers {
commands := []string{}
if len(container.Ports) == 0 {
utils.Warn("No ports found for service ",
logger.Warn("No ports found for service ",
servicename,
". You should declare a port in the service or use "+
labels.LabelPorts+
@@ -340,7 +341,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
_, ok := service.Environment[secret]
if !ok {
drop = append(drop, secret)
utils.Warn("Secret " + secret + " not found in service " + service.Name + " - skpped")
logger.Warn("Secret " + secret + " not found in service " + service.Name + " - skpped")
continue
}
secrets = append(secrets, secret)
@@ -357,7 +358,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
val, ok := service.Environment[value]
if !ok {
drop = append(drop, value)
utils.Warn("Environment variable " + value + " not found in service " + service.Name + " - skpped")
logger.Warn("Environment variable " + value + " not found in service " + service.Name + " - skpped")
continue
}
if d.chart.Values[service.Name].(*Value).Environment == nil {
@@ -413,7 +414,7 @@ func (d *Deployment) BindMapFilesToContainer(service types.ServiceConfig, secret
container, index := utils.GetContainerByName(service.ContainerName, d.Spec.Template.Spec.Containers)
if container == nil {
utils.Warn("Container not found for service " + service.Name)
logger.Warn("Container not found for service " + service.Name)
return nil, -1
}
@@ -677,7 +678,7 @@ func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod boo
}(d, container, index)
if _, found := tobind[volume.Source]; !isSamePod && volume.Type == "bind" && !found {
utils.Warn(
logger.Warn(
"Bind volumes are not supported yet, " +
"excepting for those declared as " +
labels.LabelConfigMapFiles +
@@ -688,7 +689,7 @@ func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod boo
}
if container == nil {
utils.Warn("Container not found for volume", volume.Source)
logger.Warn("Container not found for volume", volume.Source)
return
}

View File

@@ -15,7 +15,6 @@ func TestReadMeFile_Basic(t *testing.T) {
}
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 {

View File

@@ -233,7 +233,6 @@ func fixResourceNames(project *types.Project) error {
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
}

View File

@@ -3,7 +3,6 @@ package katenaryfile
import (
"bytes"
"encoding/json"
"fmt"
"log"
"os"
"reflect"
@@ -11,7 +10,7 @@ import (
"katenary.io/internal/generator/labels"
"katenary.io/internal/generator/labels/labelstructs"
"katenary.io/internal/utils"
"katenary.io/internal/logger"
"github.com/compose-spec/compose-go/types"
"github.com/invopop/jsonschema"
@@ -60,7 +59,7 @@ func OverrideWithConfig(project *types.Project) {
// no katenary file found
return
}
fmt.Println(utils.IconInfo, "Using katenary file", yamlFile)
logger.Info("Using katenary file", yamlFile)
services := make(map[string]Service)
fp, err := os.Open(yamlFile)
@@ -102,7 +101,7 @@ func OverrideWithConfig(project *types.Project) {
mustGetLabelContent(s.ValuesFrom, &project.Services[i], labels.LabelValuesFrom)
}
}
fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.")
logger.Info("Katenary file loaded successfully, the services are now configured.")
}
func getLabelContent(o any, service *types.ServiceConfig, labelName string) error {

View File

@@ -1,7 +1,6 @@
package katenaryfile
import (
"log"
"os"
"path/filepath"
"testing"
@@ -39,18 +38,15 @@ webapp:
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 {
os.MkdirAll(tmpDir, 0o755)
if err := os.WriteFile(composeFile, []byte(composeContent), 0o644); err != nil {
t.Log(err)
}
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0644); err != nil {
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0o644); 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,
@@ -92,18 +88,15 @@ webapp:
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 {
os.MkdirAll(tmpDir, 0o755)
if err := os.WriteFile(composeFile, []byte(composeContent), 0o644); err != nil {
t.Log(err)
}
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0644); err != nil {
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0o644); 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,
@@ -150,18 +143,15 @@ webapp:
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 {
os.MkdirAll(tmpDir, 0o755)
if err := os.WriteFile(composeFile, []byte(composeContent), 0o644); err != nil {
t.Log(err)
}
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0644); err != nil {
if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0o644); 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,

View File

@@ -5,7 +5,6 @@ import (
"image"
"image/color"
"image/png"
"log"
"os"
"path/filepath"
"testing"
@@ -173,7 +172,6 @@ services:
`
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
tmpDir := setup(composeFile)
log.Println(tmpDir)
defer teardown(tmpDir)
os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)
@@ -243,7 +241,6 @@ services:
`
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
tmpDir := setup(composeFile)
log.Println(tmpDir)
defer teardown(tmpDir)
os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)

View File

@@ -1,6 +1,5 @@
package utils
import "fmt"
// Package logger provides simple logging functions with icons and colors.
package logger
// Icon is a unicode icon
type Icon string
@@ -21,11 +20,28 @@ const (
IconDependency Icon = "🔗"
)
const reset = "\033[0m"
func Info(msg ...any) {
message("", IconInfo, msg...)
}
// Warn prints a warning message
func Warn(msg ...any) {
orange := "\033[38;5;214m"
reset := "\033[0m"
fmt.Print(IconWarning, orange, " ")
fmt.Print(msg...)
fmt.Println(reset)
message(orange, IconWarning, msg...)
}
func Success(msg ...any) {
green := "\033[38;5;34m"
message(green, IconSuccess, msg...)
}
func Failure(msg ...any) {
red := "\033[38;5;196m"
message(red, IconFailure, msg...)
}
func Log(icon Icon, msg ...any) {
message("", icon, msg...)
}

View File

@@ -0,0 +1,12 @@
//go:build !ci
// +build !ci
package logger
import "fmt"
func message(color string, icon Icon, msg ...any) {
fmt.Print(icon, " ", color)
fmt.Print(msg...)
fmt.Println(reset)
}

View File

@@ -0,0 +1,9 @@
//go:build ci
// +build ci
package logger
// CI should be no-op
func message(color string, icon Icon, msg ...any) {
// no-op
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/thediveo/netdb"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
"katenary.io/internal/logger"
)
// DirectoryPermission is the default values for permissions apply to created directories.
@@ -64,7 +65,7 @@ func GetKind(path string) (kind string) {
} else {
kind = strings.Split(path, ".")[1]
}
return
return kind
}
// Wrap wraps a string with a string above and below. It will respect the indentation of the src string.
@@ -161,7 +162,7 @@ func WordWrap(text string, lineWidth int) string {
}
// Confirm asks a question and returns true if the answer is y.
func Confirm(question string, icon ...Icon) bool {
func Confirm(question string, icon ...logger.Icon) bool {
if len(icon) > 0 {
fmt.Printf("%s %s [y/N] ", icon[0], question)
} else {