27 Commits

Author SHA1 Message Date
58d1e8e450 Merge pull request #92 from metal3d/develop
doc(refresh): Refresh doc after changing functions
2024-12-03 14:47:52 +01:00
d0790f37a8 doc(refresh): Refresh doc after changing functions 2024-12-03 14:45:27 +01:00
62b0576c2d Merge pull request #91 from metal3d/develop
Fix binary data, Add tests, Error management
2024-12-03 14:44:19 +01:00
e574a2e2a8 chore(errors): Better error management
We must remove all "Fatal" calls and use errors instead, to be returned
and managed globally.
This is the first step, but it is, at this time, a real problem. Tests
are complicated without this.
2024-12-03 14:37:13 +01:00
eb760d4299 test(subdir): Add globally mount binary files 2024-12-03 14:03:36 +01:00
3833037862 doc(refresh): after changing names and adding functions 2024-12-03 13:52:22 +01:00
6dc92df4b5 chore(icons): Better icons for warning and info 2024-12-03 13:51:39 +01:00
d458cdbd73 chore(configmap): Manage binary data in configMap
We should be now able to detect and manage binary files to be injected
in configMaps
2024-12-03 13:50:58 +01:00
628b35d471 doc(readme): fix the schema location 2024-12-01 08:48:33 +01:00
84363be0e8 Fix Readme after merging master into develop 2024-11-27 09:27:28 +01:00
5284cdf5cc Merge pull request #90 from metal3d/develop
Remove update functions and fix dependabot target branch
2024-11-27 09:23:44 +01:00
632ffc2b66 chore(module): update dependencies
Updated k8s.io/api, x/exp, x/net, and structured-merge-diff
2024-11-27 09:21:33 +01:00
2ff705164e chore(module): Cleanup 2024-11-27 09:17:45 +01:00
73ab867509 chore(update): remove the update methods
The update functions were not linked and absolutely not stable anyway. I
will find a better way to propose a check-update method later.
2024-11-27 09:16:49 +01:00
45e44dee14 wip(update): the update function is not clean 2024-11-27 00:46:15 +01:00
689c2a4803 Use develop branch please 2024-11-27 00:26:25 +01:00
e023544c8a Merge pull request #88 from metal3d/develop
Enhance doc, description, examples
2024-11-27 00:00:58 +01:00
957cc4bcf6 Merge pull request #87 from metal3d/develop
Add schema to the root, fix test coverage
2024-11-26 17:55:46 +01:00
6b301f3171 Merge pull request #86 from metal3d/develop
Add "values-from" and more tests
2024-11-26 16:29:14 +01:00
5f20585fb2 Merge pull request #85 from metal3d/develop
test(codecov): remove codecov
2024-11-26 09:10:48 +01:00
456e7f41f2 Merge pull request #82 from metal3d/develop
Some fixes on "same-pod" and volumes + add some tests
2024-11-25 23:17:56 +01:00
49045a2ccd Merge pull request #81 from metal3d/develop
Cleanup, re-factorization and allow the use of a katenary.yaml file.
Fixing a wrapping string problem.
Move the label management in a package.
2024-11-19 13:44:04 +01:00
315f5da970 Merge pull request #79 from metal3d/develop
Activable tls
2024-11-09 13:57:35 +01:00
427f2909d5 Merge pull request #78 from metal3d/develop
Fixes template injection and variable names on volumes
2024-11-08 15:03:20 +01:00
6023ca4508 Merge pull request #77 from metal3d/develop
Merge Develop to prepare V3
2024-10-29 17:45:05 +01:00
e0c829c2ce Merge branch 'master' into develop 2024-10-29 17:42:17 +01:00
10b9342607 Update README.md
Alert on v3 version
2024-04-23 14:37:19 +02:00
15 changed files with 254 additions and 257 deletions

View File

@@ -9,3 +9,4 @@ updates:
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
schedule: schedule:
interval: "daily" interval: "daily"
target-branch: develop

View File

@@ -260,7 +260,7 @@ return {
settings = { settings = {
yaml = { yaml = {
schemas = { schemas = {
["https://raw.githubusercontent.com/metal3d/katenary/refs/heads/master/katenary.json"] = "katenary.yaml", ["https://raw.githubusercontent.com/metal3d/katenary/master/katenary.json"] = "katenary.yaml",
}, },
}, },
}, },
@@ -276,12 +276,12 @@ Use this address to validate the `katenary.yaml` file in VSCode:
```json ```json
{ {
"yaml.schemas": { "yaml.schemas": {
"https://raw.githubusercontent.com/metal3d/katenary/refs/heads/master/katenary.json": "katenary.yaml" "https://raw.githubusercontent.com/metal3d/katenary/master/katenary.json": "katenary.yaml"
} }
} }
``` ```
> You can, of course, replace the `refs/heads/master` with a specific tag or branch. > You can, of course, replace the `master` with a specific tag or branch.
## What a name… ## What a name…

View File

@@ -141,11 +141,11 @@ func generateConvertCommand() *cobra.Command {
convertCmd := &cobra.Command{ convertCmd := &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",
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
if givenAppVersion != "" { if givenAppVersion != "" {
appVersion = &givenAppVersion appVersion = &givenAppVersion
} }
generator.Convert(generator.ConvertOptions{ return generator.Convert(generator.ConvertOptions{
Force: force, Force: force,
OutputDir: outputDir, OutputDir: outputDir,
Profiles: profiles, Profiles: profiles,

View File

@@ -38,7 +38,7 @@ var Version = "master" // changed at compile time
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L93>) ## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L93>)
```go ```go
func Convert(config ConvertOptions, dockerComposeFile ...string) 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.
@@ -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#L35-L40>) ## type [ConfigMap](<https://github.com/metal3d/katenary/blob/develop/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#L44>) ### func [NewConfigMap](<https://github.com/metal3d/katenary/blob/develop/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#L117>) ### func [NewConfigMapFromDirectory](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L119>)
```go ```go
func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap
@@ -148,8 +148,17 @@ 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>
### func \(\*ConfigMap\) [AddBinaryData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L155>)
```go
func (c *ConfigMap) AddBinaryData(key string, value []byte)
```
AddBinaryData adds binary data to the configmap. Append or overwrite the value if the key already exists.
<a name="ConfigMap.AddData"></a> <a name="ConfigMap.AddData"></a>
### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L148>) ### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L150>)
```go ```go
func (c *ConfigMap) AddData(key, value string) func (c *ConfigMap) AddData(key, value string)
@@ -158,25 +167,25 @@ 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#L154>) ### func \(\*ConfigMap\) [AppendDir](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L164>)
```go ```go
func (c *ConfigMap) AppendDir(path string) 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. 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.
<a name="ConfigMap.AppendFile"></a> <a name="ConfigMap.AppendFile"></a>
### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L189>) ### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L211>)
```go ```go
func (c *ConfigMap) AppendFile(path string) 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#L207>) ### func \(\*ConfigMap\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L235>)
```go ```go
func (c *ConfigMap) Filename() string func (c *ConfigMap) Filename() string
@@ -185,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#L217>) ### func \(\*ConfigMap\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L245>)
```go ```go
func (c *ConfigMap) SetData(data map[string]string) func (c *ConfigMap) SetData(data map[string]string)
@@ -194,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#L222>) ### func \(\*ConfigMap\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L250>)
```go ```go
func (c *ConfigMap) Yaml() ([]byte, error) func (c *ConfigMap) Yaml() ([]byte, error)
@@ -421,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#L19>) ## type [FileMapUsage](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L21>)
FileMapUsage is the usage of the filemap. FileMapUsage is the usage of the filemap.

View File

@@ -196,13 +196,13 @@ type Icon string
const ( const (
IconSuccess Icon = "✅" IconSuccess Icon = "✅"
IconFailure Icon = "❌" IconFailure Icon = "❌"
IconWarning Icon = "⚠️'" IconWarning Icon = ""
IconNote Icon = "📝" IconNote Icon = "📝"
IconWorld Icon = "🌐" IconWorld Icon = "🌐"
IconPlug Icon = "🔌" IconPlug Icon = "🔌"
IconPackage Icon = "📦" IconPackage Icon = "📦"
IconCabinet Icon = "🗄️" IconCabinet Icon = "🗄️"
IconInfo Icon = "" IconInfo Icon = "🔵"
IconSecret Icon = "🔒" IconSecret Icon = "🔒"
IconConfig Icon = "🔧" IconConfig Icon = "🔧"
IconDependency Icon = "🔗" IconDependency Icon = "🔗"

View File

@@ -1,6 +1,7 @@
package generator package generator
import ( import (
"fmt"
"katenary/generator/labels" "katenary/generator/labels"
"katenary/generator/labels/labelStructs" "katenary/generator/labels/labelStructs"
"katenary/utils" "katenary/utils"
@@ -9,6 +10,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"unicode/utf8"
"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"
@@ -149,58 +151,84 @@ func (c *ConfigMap) AddData(key, value string) {
c.Data[key] = value c.Data[key] = value
} }
// AddBinaryData adds binary data to the configmap. Append or overwrite the value if the key already exists.
func (c *ConfigMap) AddBinaryData(key string, value []byte) {
if c.BinaryData == nil {
c.BinaryData = make(map[string][]byte)
}
c.BinaryData[key] = value
}
// AddFile adds files from given path to the configmap. It is not recursive, to add all files in a directory, // 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. // you need to call this function for each subdirectory.
func (c *ConfigMap) AppendDir(path string) { 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 {
log.Fatalf("Path %s does not exist\n", path) return fmt.Errorf("Path %s does not exist, %w\n", 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() {
files, err := os.ReadDir(path) files, err := os.ReadDir(path)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
for _, file := range files { for _, file := range files {
if file.IsDir() { if file.IsDir() {
utils.Warn("Subdirectories are ignored for the moment, skipping", filepath.Join(path, file.Name()))
continue continue
} }
path := filepath.Join(path, file.Name()) path := filepath.Join(path, file.Name())
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
// remove the path from the file // remove the path from the file
filename := filepath.Base(path) filename := filepath.Base(path)
if utf8.Valid(content) {
c.AddData(filename, string(content)) c.AddData(filename, string(content))
} else {
c.AddBinaryData(filename, content)
}
} }
} else { } else {
// add the file to the configmap // add the file to the configmap
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
c.AddData(filepath.Base(path), string(content)) filename := filepath.Base(path)
if utf8.Valid(content) {
c.AddData(filename, string(content))
} else {
c.AddBinaryData(filename, content)
} }
} }
return nil
}
func (c *ConfigMap) AppendFile(path string) { 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 {
log.Fatalf("Path %s does not exist\n", path) 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() {
// add the file to the configmap // add the file to the configmap
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
if utf8.Valid(content) {
c.AddData(filepath.Base(path), string(content)) c.AddData(filepath.Base(path), string(content))
} else {
c.AddBinaryData(filepath.Base(path), content)
} }
}
return nil
} }
// 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.

View File

@@ -6,6 +6,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/compose-spec/compose-go/types"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@@ -73,3 +74,19 @@ services:
t.Errorf("Expected FOO to be baz, got %s", v) t.Errorf("Expected FOO to be baz, got %s", v)
} }
} }
func TestAppendBadFile(t *testing.T) {
cm := NewConfigMap(types.ServiceConfig{}, "app", true)
err := cm.AppendFile("foo")
if err == nil {
t.Errorf("Expected error, got nil")
}
}
func TestAppendBadDir(t *testing.T) {
cm := NewConfigMap(types.ServiceConfig{}, "app", true)
err := cm.AppendDir("foo")
if err == nil {
t.Errorf("Expected error, got nil")
}
}

View File

@@ -90,7 +90,7 @@ var keyRegExp = regexp.MustCompile(`^\s*[^#]+:.*`)
// Convert a compose (docker, podman...) project to a helm chart. // Convert a compose (docker, podman...) project to a helm chart.
// It calls Generate() to generate the chart and then write it to the disk. // It calls Generate() to generate the chart and then write it to the disk.
func Convert(config ConvertOptions, dockerComposeFile ...string) { func Convert(config ConvertOptions, dockerComposeFile ...string) error {
var ( var (
templateDir = filepath.Join(config.OutputDir, "templates") templateDir = filepath.Join(config.OutputDir, "templates")
helpersPath = filepath.Join(config.OutputDir, "templates", "_helpers.tpl") helpersPath = filepath.Join(config.OutputDir, "templates", "_helpers.tpl")
@@ -105,7 +105,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
// go to the root of the project // go to the root of the project
if err := os.Chdir(filepath.Dir(dockerComposeFile[0])); err != nil { if err := os.Chdir(filepath.Dir(dockerComposeFile[0])); err != nil {
fmt.Println(utils.IconFailure, err) fmt.Println(utils.IconFailure, err)
os.Exit(1) return err
} }
defer os.Chdir(currentDir) // after the generation, go back to the original directory defer os.Chdir(currentDir) // after the generation, go back to the original directory
@@ -118,13 +118,13 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
project, err := parser.Parse(config.Profiles, config.EnvFiles, dockerComposeFile...) project, err := parser.Parse(config.Profiles, config.EnvFiles, dockerComposeFile...)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) return err
} }
// check older version of labels // check older version of labels
if err := checkOldLabels(project); err != nil { if err := checkOldLabels(project); err != nil {
fmt.Println(utils.IconFailure, err) fmt.Println(utils.IconFailure, err)
os.Exit(1) return err
} }
// TODO: use katenary.yaml file here to set the labels // TODO: use katenary.yaml file here to set the labels
@@ -140,7 +140,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
) )
if !overwrite { if !overwrite {
fmt.Println("Aborting") fmt.Println("Aborting")
os.Exit(126) // 126 is the exit code for "Command invoked cannot execute" return nil
} }
} }
fmt.Println() // clean line fmt.Println() // clean line
@@ -150,7 +150,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
chart, err := Generate(project) chart, err := Generate(project)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) return err
} }
// if the app version is set from the command line, use it // if the app version is set from the command line, use it
@@ -194,6 +194,7 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
// call helm update if needed // call helm update if needed
callHelmUpdate(config) callHelmUpdate(config)
return nil
} }
func addChartDoc(values []byte, project *types.Project) []byte { func addChartDoc(values []byte, project *types.Project) []byte {

View File

@@ -48,7 +48,9 @@ func internalCompileTest(t *testing.T, options ...string) string {
AppVersion: appVersion, AppVersion: appVersion,
ChartVersion: chartVersion, ChartVersion: chartVersion,
} }
Convert(convertOptions, "compose.yml") if err := Convert(convertOptions, "compose.yml"); err != nil {
return err.Error()
}
// launch helm lint to check the generated chart // launch helm lint to check the generated chart
if helmLint(convertOptions) != nil { if helmLint(convertOptions) != nil {

View File

@@ -2,8 +2,13 @@ package generator
import ( import (
"fmt" "fmt"
"image"
"image/color"
"image/png"
"katenary/generator/labels" "katenary/generator/labels"
"log"
"os" "os"
"path/filepath"
"testing" "testing"
v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/apps/v1"
@@ -149,6 +154,140 @@ services:
} }
} }
func TestBinaryMount(t *testing.T) {
composeFile := `
services:
web:
image: nginx
volumes:
- ./images/foo.png:/var/www/foo
labels:
%[1]s/configmap-files: |-
- ./images/foo.png
`
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
tmpDir := setup(composeFile)
log.Println(tmpDir)
defer teardown(tmpDir)
os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
// create a png image
pngFile := tmpDir + "/images/foo.png"
w, h := 100, 100
img := image.NewRGBA(image.Rect(0, 0, w, h))
red := color.RGBA{255, 0, 0, 255}
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
img.Set(x, y, red)
}
}
blue := color.RGBA{0, 0, 255, 255}
for y := 30; y < 70; y++ {
for x := 30; x < 70; x++ {
img.Set(x, y, blue)
}
}
currentDir, _ := os.Getwd()
os.Chdir(tmpDir)
defer os.Chdir(currentDir)
f, err := os.Create(pngFile)
if err != nil {
t.Fatal(err)
}
png.Encode(f, img)
f.Close()
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
d := v1.Deployment{}
yaml.Unmarshal([]byte(output), &d)
volumes := d.Spec.Template.Spec.Volumes
if len(volumes) != 1 {
t.Errorf("Expected 1 volume, got %d", len(volumes))
}
cm := corev1.ConfigMap{}
cmContent, err := helmTemplate(ConvertOptions{
OutputDir: "chart",
}, "-s", "templates/web/statics/images/configmap.yaml")
yaml.Unmarshal([]byte(cmContent), &cm)
if im, ok := cm.BinaryData["foo.png"]; !ok {
t.Errorf("Expected foo.png to be in the configmap")
} else {
if len(im) == 0 {
t.Errorf("Expected image to be non-empty")
}
}
}
func TestGloballyBinaryMount(t *testing.T) {
composeFile := `
services:
web:
image: nginx
volumes:
- ./images:/var/www/foo
labels:
%[1]s/configmap-files: |-
- ./images
`
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
tmpDir := setup(composeFile)
log.Println(tmpDir)
defer teardown(tmpDir)
os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
// create a png image
pngFile := tmpDir + "/images/foo.png"
w, h := 100, 100
img := image.NewRGBA(image.Rect(0, 0, w, h))
red := color.RGBA{255, 0, 0, 255}
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
img.Set(x, y, red)
}
}
blue := color.RGBA{0, 0, 255, 255}
for y := 30; y < 70; y++ {
for x := 30; x < 70; x++ {
img.Set(x, y, blue)
}
}
currentDir, _ := os.Getwd()
os.Chdir(tmpDir)
defer os.Chdir(currentDir)
f, err := os.Create(pngFile)
if err != nil {
t.Fatal(err)
}
png.Encode(f, img)
f.Close()
output := internalCompileTest(t, "-s", "templates/web/deployment.yaml")
d := v1.Deployment{}
yaml.Unmarshal([]byte(output), &d)
volumes := d.Spec.Template.Spec.Volumes
if len(volumes) != 1 {
t.Errorf("Expected 1 volume, got %d", len(volumes))
}
cm := corev1.ConfigMap{}
cmContent, err := helmTemplate(ConvertOptions{
OutputDir: "chart",
}, "-s", "templates/web/statics/images/configmap.yaml")
yaml.Unmarshal([]byte(cmContent), &cm)
if im, ok := cm.BinaryData["foo.png"]; !ok {
t.Errorf("Expected foo.png to be in the configmap")
} else {
if len(im) == 0 {
t.Errorf("Expected image to be non-empty")
}
}
}
func TestBindFrom(t *testing.T) { func TestBindFrom(t *testing.T) {
composeFile := ` composeFile := `
services: services:

11
go.mod
View File

@@ -10,10 +10,9 @@ require (
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.8.1
github.com/thediveo/netdb v1.1.2 github.com/thediveo/netdb v1.1.2
golang.org/x/mod v0.22.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.31.2 k8s.io/api v0.31.3
k8s.io/apimachinery v0.31.2 k8s.io/apimachinery v0.31.3
sigs.k8s.io/yaml v1.4.0 sigs.k8s.io/yaml v1.4.0
) )
@@ -44,8 +43,8 @@ require (
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-20241009180824-f66d83c29e7c // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.31.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/text v0.20.0 // indirect
@@ -53,5 +52,5 @@ require (
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect
) )

26
go.sum
View File

@@ -103,18 +103,16 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
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-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
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/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
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=
@@ -134,8 +132,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
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.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
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=
@@ -150,17 +148,17 @@ 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.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
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-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno= k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A=
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
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=

View File

@@ -1,148 +0,0 @@
/* Update package is used to check if a new version of katenary is available.*/
package update
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"runtime"
"time"
"golang.org/x/mod/semver"
)
var (
exe, _ = os.Executable()
Version = "master" // reset by cmd/main.go
)
// Asset is a github asset from release url.
type Asset struct {
Name string `json:"name"`
URL string `json:"browser_download_url"`
}
// CheckLatestVersion check katenary latest version from release and propose to download it
func CheckLatestVersion() (string, []Asset, error) {
githuburl := "https://api.github.com/repos/metal3d/katenary/releases/latest"
// Create a HTTP client with 1s timeout
client := &http.Client{
Timeout: time.Second * 1,
}
// Create a request
req, err := http.NewRequest("GET", githuburl, nil)
if err != nil {
return "", nil, err
}
// Send the request via a client
resp, err := client.Do(req)
if err != nil {
return "", nil, err
}
defer resp.Body.Close()
// Get tag_name from the json response
release := struct {
TagName string `json:"tag_name"`
Assets []Asset `json:"assets"`
PreRelease bool `json:"prerelease"`
}{}
err = json.NewDecoder(resp.Body).Decode(&release)
if err != nil {
return "", nil, err
}
// if it's a prerelease, don't update
if release.PreRelease {
return "", nil, errors.New("prerelease detected, not updating")
}
// no tag, don't update
if release.TagName == "" {
return "", nil, errors.New("no release found")
}
// compare the current version, if the current version is the same or lower than the latest version, don't update
versions := []string{Version, release.TagName}
semver.Sort(versions)
if versions[1] == Version {
return "", nil, errors.New("current version is the latest version")
}
return release.TagName, release.Assets, nil
}
// DownloadLatestVersion will download the latest version of katenary.
func DownloadLatestVersion(assets []Asset) error {
defer func() {
if r := recover(); r != nil {
os.Rename(exe+".old", exe)
}
}()
// Download the latest version
fmt.Println("Downloading the latest version...")
// ok, replace this from the current version to the latest version
err := os.Rename(exe, exe+".old")
if err != nil {
return err
}
// Download the latest version for the current OS
for _, asset := range assets {
switch runtime.GOOS {
case "windows":
if asset.Name == "katenary.exe" {
err = DownloadFile(asset.URL, exe)
}
case "linux":
switch runtime.GOARCH {
case "amd64":
if asset.Name == "katenary-linux-amd64" {
err = DownloadFile(asset.URL, exe)
}
case "arm64":
if asset.Name == "katenary-linux-arm64" {
err = DownloadFile(asset.URL, exe)
}
}
case "darwin":
if asset.Name == "katenary-darwin" {
err = DownloadFile(asset.URL, exe)
}
default:
fmt.Println("Unsupported OS")
err = errors.New("unsupported OS")
}
}
if err == nil {
// remove the old version
os.Remove(exe + ".old")
} else {
// restore the old version
os.Rename(exe+".old", exe)
}
return err
}
// DownloadFile will download a url to a local file. It also ensure that the file is executable.
func DownloadFile(url, exe string) error {
// Download the url binary to exe path
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
fp, err := os.OpenFile(exe, os.O_WRONLY|os.O_CREATE, 0o755)
if err != nil {
return err
}
defer fp.Close()
_, err = io.Copy(fp, resp.Body)
return err
}

View File

@@ -1,49 +0,0 @@
package update
import (
"fmt"
"os"
"testing"
)
func TestDownloadLatestRelease(t *testing.T) {
// Reset the version to test the latest release
Version = "0.0.0"
// change "exe" to /tmp/test-katenary
exe = "/tmp/test-katenary"
defer os.Remove(exe)
// Now call the CheckLatestVersion function
version, assets, err := CheckLatestVersion()
if err != nil {
t.Errorf("Error getting latest version: %s", err)
}
fmt.Println("Version found", version)
// Touch exe binary
f, _ := os.OpenFile(exe, os.O_RDONLY|os.O_CREATE, 0o755)
f.Write(nil)
f.Close()
err = DownloadLatestVersion(assets)
if err != nil {
t.Errorf("Error: %s", err)
}
}
func TestAlreadyUpToDate(t *testing.T) {
Version = "99999.999.99"
exe = "/tmp/test-katenary"
defer os.Remove(exe)
// Call the version check
version, _, err := CheckLatestVersion()
if err == nil {
t.Errorf("Error: %s", err)
}
t.Log("Version is already the most recent", version)
}

View File

@@ -9,13 +9,13 @@ type Icon string
const ( const (
IconSuccess Icon = "✅" IconSuccess Icon = "✅"
IconFailure Icon = "❌" IconFailure Icon = "❌"
IconWarning Icon = "⚠️'" IconWarning Icon = ""
IconNote Icon = "📝" IconNote Icon = "📝"
IconWorld Icon = "🌐" IconWorld Icon = "🌐"
IconPlug Icon = "🔌" IconPlug Icon = "🔌"
IconPackage Icon = "📦" IconPackage Icon = "📦"
IconCabinet Icon = "🗄️" IconCabinet Icon = "🗄️"
IconInfo Icon = "" IconInfo Icon = "🔵"
IconSecret Icon = "🔒" IconSecret Icon = "🔒"
IconConfig Icon = "🔧" IconConfig Icon = "🔧"
IconDependency Icon = "🔗" IconDependency Icon = "🔗"