Adding log_rotation
This commit is contained in:
parent
7c636c35fe
commit
1b15eeefe2
|
@ -5,6 +5,7 @@ artifacts
|
||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
coverage
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
22
Makefile
22
Makefile
|
@ -1,6 +1,7 @@
|
||||||
# Inspired from https://dustinspecker.com/posts/go-combined-unit-integration-code-coverage/ and https://netdevops.me/2023/test-coverage-for-go-integration-tests/
|
# Inspired from https://dustinspecker.com/posts/go-combined-unit-integration-code-coverage/ and https://netdevops.me/2023/test-coverage-for-go-integration-tests/
|
||||||
BIN_DIR = $(CURDIR)/artifacts
|
BIN_DIR = $(CURDIR)/artifacts
|
||||||
BINARY = $(BIN_DIR)/gocustomurls
|
BINARY = $(BIN_DIR)/gocustomurls
|
||||||
|
COVERAGE_DIR = $(CURDIR)/coverage
|
||||||
CURRENT_DIR = $(shell pwd)
|
CURRENT_DIR = $(shell pwd)
|
||||||
CUR_TAG = $(shell git tag | sort -g | tail -1 | cut -c 2-)
|
CUR_TAG = $(shell git tag | sort -g | tail -1 | cut -c 2-)
|
||||||
VERSION_NUMBER ?= 0.0.0
|
VERSION_NUMBER ?= 0.0.0
|
||||||
|
@ -30,3 +31,24 @@ lint:
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build:
|
build:
|
||||||
go build -o $(BINARY)
|
go build -o $(BINARY)
|
||||||
|
|
||||||
|
.PHONY: build-debug
|
||||||
|
build-debug:
|
||||||
|
mkdir -p $(BIN_DIR)
|
||||||
|
go build -cover -o $(BINARY) .
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: build-debug
|
||||||
|
rm -rf $(COVERAGE_DIR)
|
||||||
|
mkdir -p $(COVERAGE_DIR)
|
||||||
|
go test -cover ./... -args -test.gocoverdir="$(COVERAGE_DIR)"
|
||||||
|
|
||||||
|
.PHONY: coverage-full
|
||||||
|
coverage-full: test
|
||||||
|
go tool covdata textfmt -i=$(COVERAGE_DIR) -o $(COVERAGE_DIR)/coverage.out
|
||||||
|
go tool cover -func=$(COVERAGE_DIR)/coverage.out
|
||||||
|
|
||||||
|
.PHONY: coverage-html
|
||||||
|
coverage-html: coverage-full
|
||||||
|
go tool cover -html=./coverage/coverage.out -o ./coverage/coverage.html
|
||||||
|
open ./coverage/coverage.html
|
17
conf.go
17
conf.go
|
@ -85,13 +85,20 @@ func getDefaults() (map[string]string, error) {
|
||||||
}
|
}
|
||||||
m["rulesFp"] = filepath.Join(confDir, "gocustomcurls", "rules.json")
|
m["rulesFp"] = filepath.Join(confDir, "gocustomcurls", "rules.json")
|
||||||
m["confFp"] = filepath.Join(confDir, "gocustomcurls", "config.json")
|
m["confFp"] = filepath.Join(confDir, "gocustomcurls", "config.json")
|
||||||
m["logfp"] = filepath.Join(homeDir, ".gocustomurls", "logs", "app.log")
|
m["logFp"] = filepath.Join(homeDir, ".gocustomurls", "logs", "app.log")
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateDefaultConfigFile() (parsedConf, error) {
|
func generateDefaultConfigFile(defaultObj map[string]string) (parsedConf, error) {
|
||||||
var p parsedConf
|
var p parsedConf
|
||||||
defaults, err := getDefaults()
|
var err error
|
||||||
|
var defaults map[string]string
|
||||||
|
if len(defaultObj) == 0 {
|
||||||
|
defaults, err = getDefaults()
|
||||||
|
} else {
|
||||||
|
defaults = defaultObj
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
@ -127,7 +134,7 @@ func checkIfSizeIsConfigured(fsize string) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(found) == 0 {
|
if len(found) == 0 {
|
||||||
return false, fmt.Errorf("%s has the incorrect suffix, Please use one of this suffixes {\"K\", \"KB\",\"M\", \"MB\", \"G\", \"GB\"}", fsize)
|
return false, fmt.Errorf("%s has the incorrect suffix, Please use one of this suffixes {\"KB\", \"MB\", \"GB\"}", fsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -141,7 +148,7 @@ func (c *Config) LoadMainConfigFile(fp string) (parsedConf, error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
// generate config file
|
// generate config file
|
||||||
errorLog.Println("Warning, generating default config file")
|
errorLog.Println("Warning, generating default config file")
|
||||||
conf, err = generateDefaultConfigFile()
|
conf, err = generateDefaultConfigFile(map[string]string{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conf, err
|
return conf, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadMappingFile(t *testing.T) {
|
||||||
|
|
||||||
|
t.Run("load the mapping file correctly - initial load", func(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||||
|
rulesJsonFp := "testData/rules.json"
|
||||||
|
|
||||||
|
expected := fmt.Sprintf("%s/tmp/rules.json", tmpDir)
|
||||||
|
|
||||||
|
cpFileForTest(t, rulesJsonFp, expected)
|
||||||
|
|
||||||
|
cfg := &Config{}
|
||||||
|
|
||||||
|
assert.Equal(t, cfg.MappingFilePath, "")
|
||||||
|
assert.Empty(t, cfg.MappingRules)
|
||||||
|
err := cfg.LoadMappingFile(expected)
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.Equal(t, cfg.MappingFilePath, expected)
|
||||||
|
assert.NotEmpty(t, cfg.MappingRules)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("load the mapping file correctly - reload", func(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||||
|
rulesJsonFp := "testData/rules.json"
|
||||||
|
|
||||||
|
expected := fmt.Sprintf("%s/tmp/rules.json", tmpDir)
|
||||||
|
|
||||||
|
cpFileForTest(t, rulesJsonFp, expected)
|
||||||
|
|
||||||
|
cfg := &Config{}
|
||||||
|
|
||||||
|
assert.Equal(t, cfg.MappingFilePath, "")
|
||||||
|
assert.Empty(t, cfg.MappingRules)
|
||||||
|
err := cfg.LoadMappingFile(expected)
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.Equal(t, cfg.MappingFilePath, expected)
|
||||||
|
assert.NotEmpty(t, cfg.MappingRules)
|
||||||
|
oldRules := cfg.MappingRules
|
||||||
|
|
||||||
|
rulesJsonFp = "testData/rules2.json"
|
||||||
|
|
||||||
|
cpFileForTest(t, rulesJsonFp, expected)
|
||||||
|
|
||||||
|
err = cfg.LoadMappingFile(expected)
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.Equal(t, cfg.MappingFilePath, expected)
|
||||||
|
assert.NotEmpty(t, cfg.MappingRules)
|
||||||
|
|
||||||
|
newRules := cfg.MappingRules
|
||||||
|
|
||||||
|
assert.NotEqualValues(t, oldRules, newRules)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetDefaults(t *testing.T) {
|
||||||
|
actual, err := getDefaults()
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.Contains(t, actual, "rulesFp")
|
||||||
|
assert.Contains(t, actual, "logFp")
|
||||||
|
assert.Contains(t, actual, "confFp")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSizeIsConfigured(t *testing.T) {
|
||||||
|
tests := map[string]struct {
|
||||||
|
input string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
"wrong input - K": {input: "5677.45K", want: false},
|
||||||
|
"wrong input - KiB": {input: "5677.45KiB", want: false},
|
||||||
|
"wrong input - M": {input: "9.45M", want: false},
|
||||||
|
"wrong input - G": {input: "9.45G", want: false},
|
||||||
|
"correct input - KB": {input: "5.45KB", want: true},
|
||||||
|
"correct input - MB": {input: "5677.45MB", want: true},
|
||||||
|
"correct input - GB": {input: "9.45GB", want: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
got, _ := checkIfSizeIsConfigured(tc.input)
|
||||||
|
assert.Equal(t, got, tc.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateConfigFile(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
tempLogsDir := fmt.Sprintf("%s/tmp/logs", tmpDir)
|
||||||
|
tempConfigDir := fmt.Sprintf("%s/tmp/config", tmpDir)
|
||||||
|
|
||||||
|
mkDirForTest(t, tempLogsDir)
|
||||||
|
mkDirForTest(t, tempConfigDir)
|
||||||
|
|
||||||
|
defaultConfig := map[string]string{
|
||||||
|
"rulesFp": fmt.Sprintf("%s/rules.json", tempConfigDir),
|
||||||
|
"confFp": fmt.Sprintf("%s/config.json", tempConfigDir),
|
||||||
|
"logFp": fmt.Sprintf("%s/app.log", tempLogsDir),
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := IsDirEmpty(t, tempConfigDir)
|
||||||
|
assert.Equal(t, ok, true)
|
||||||
|
ok = IsDirEmpty(t, tempLogsDir)
|
||||||
|
assert.Equal(t, ok, true)
|
||||||
|
|
||||||
|
expected, err := generateDefaultConfigFile(defaultConfig)
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.NotEmpty(t, expected)
|
||||||
|
|
||||||
|
ok = IsDirEmpty(t, tempConfigDir)
|
||||||
|
assert.Equal(t, ok, false)
|
||||||
|
ok = IsDirEmpty(t, tempLogsDir)
|
||||||
|
assert.Equal(t, ok, true)
|
||||||
|
|
||||||
|
}
|
8
go.mod
8
go.mod
|
@ -1,3 +1,11 @@
|
||||||
module gocustomurls
|
module gocustomurls
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.9.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"vanity_url":"scale.dev/x/migrate",
|
||||||
|
"protocol":"git",
|
||||||
|
"real_url":"https://github.com/scale/migrate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vanity_url":"localhost:7070/x/touche",
|
||||||
|
"protocol":"git",
|
||||||
|
"real_url":"https://github.com/mine/touche"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"vanity_url":"scale.dev/x/migrate",
|
||||||
|
"protocol":"git",
|
||||||
|
"real_url":"https://github.com/scale/migrate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vanity_url":"codeberg.org/woodpecker-plugins/plugin-gitea-release",
|
||||||
|
"protocol":"git",
|
||||||
|
"real_url":"https://codeberg.org/woodpecker-plugins/gitea-release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vanity_url":"localhost:7070/x/touche",
|
||||||
|
"protocol":"git",
|
||||||
|
"real_url":"https://github.com/mine/touche"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mkDirForTest(t *testing.T, fp string) {
|
||||||
|
err := os.MkdirAll(fp, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpFileForTest(t *testing.T, src string, dst string) {
|
||||||
|
var srcfd *os.File
|
||||||
|
var dstfd *os.File
|
||||||
|
var err error
|
||||||
|
var srcinfo os.FileInfo
|
||||||
|
srcfd, err = os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer srcfd.Close()
|
||||||
|
dstfd, err = os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer dstfd.Close()
|
||||||
|
_, err = io.Copy(dstfd, srcfd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
srcinfo, err = os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = os.Chmod(dst, srcinfo.Mode())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeForTest(t *testing.T, fp string, data []byte) {
|
||||||
|
err := os.WriteFile(fp, data, 0666)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDirEmpty(t *testing.T, name string) bool {
|
||||||
|
f, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// read in ONLY one file
|
||||||
|
_, err = f.Readdir(1)
|
||||||
|
|
||||||
|
// and if the file is EOF... well, the dir is empty.
|
||||||
|
return err == io.EOF
|
||||||
|
}
|
Loading…
Reference in New Issue