Merge pull request #4337 from dokku/4023-logrotate-container-files

Add logrotation to container log files
This commit is contained in:
Jose Diaz-Gonzalez
2021-01-23 14:12:38 -05:00
committed by GitHub
13 changed files with 280 additions and 12 deletions

View File

@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"reflect"
"sort"
"strings"
)
@@ -32,6 +33,7 @@ func CommandPropertySet(pluginName, appName, property, value string, properties
validPropertyList[i] = properties[i].String()
}
sort.Strings(validPropertyList)
LogFail(fmt.Sprintf("Invalid property specified, valid properties include: %s", strings.Join(validPropertyList, ", ")))
}

View File

@@ -2,6 +2,7 @@
/subcommands/*
/triggers/*
/triggers
/docker-args-process-deploy
/install
/post-*
/report

View File

@@ -1,5 +1,5 @@
SUBCOMMANDS = subcommands/failed subcommands/report subcommands/set subcommands/vector-logs subcommands/vector-start subcommands/vector-stop
TRIGGERS = triggers/install triggers/post-delete triggers/report
TRIGGERS = triggers/docker-args-process-deploy triggers/install triggers/logs-get-property triggers/post-delete triggers/report
BUILD = commands subcommands triggers
PLUGIN_NAME = logs

View File

@@ -6,14 +6,19 @@ import (
"github.com/dokku/dokku/plugins/common"
)
// MaxSize is the default max retention size for docker logs
const MaxSize = "10m"
var (
// DefaultProperties is a map of all valid ps properties with corresponding default property values
DefaultProperties = map[string]string{
"max-size": "",
"vector-sink": "",
}
// GlobalProperties is a map of all valid global logs properties
GlobalProperties = map[string]bool{
"max-size": true,
"vector-sink": true,
}
)

View File

@@ -11,8 +11,11 @@ func ReportSingleApp(appName, infoFlag string) error {
}
flags := map[string]common.ReportFunc{
"--logs-vector-sink": reportVectorSink,
"--logs-computed-max-size": reportComputedMaxSize,
"--logs-global-max-size": reportGlobalMaxSize,
"--logs-global-vector-sink": reportGlobalVectorSink,
"--logs-max-size": reportMaxSize,
"--logs-vector-sink": reportVectorSink,
}
flagKeys := []string{}
@@ -26,10 +29,27 @@ func ReportSingleApp(appName, infoFlag string) error {
return common.ReportSingleApp("logs", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter)
}
func reportVectorSink(appName string) string {
return common.PropertyGet("logs", appName, "vector-sink")
func reportComputedMaxSize(appName string) string {
value := reportMaxSize(appName)
if value == "" {
value = reportGlobalMaxSize(appName)
}
return value
}
func reportGlobalMaxSize(appName string) string {
return common.PropertyGetDefault("logs", "--global", "max-size", MaxSize)
}
func reportGlobalVectorSink(appName string) string {
return common.PropertyGet("logs", "--global", "vector-sink")
}
func reportMaxSize(appName string) string {
return common.PropertyGet("logs", appName, "max-size")
}
func reportVectorSink(appName string) string {
return common.PropertyGet("logs", appName, "vector-sink")
}

58
plugins/logs/set.go Normal file
View File

@@ -0,0 +1,58 @@
package logs
import (
"errors"
"fmt"
"strconv"
)
func validateSetValue(appName string, key string, value string) error {
if key == "max-size" {
return validateMaxSize(appName, value)
}
if key == "vector-sink" {
return validateVectorSink(appName, value)
}
return nil
}
func validateMaxSize(appName string, value string) error {
if value == "" {
return nil
}
if value == "unlimited" {
return nil
}
last := value[len(value)-1:]
if last != "k" && last != "m" && last != "g" {
return errors.New("Invalid max-size unit measure, value must end in any of [k, m, g]")
}
if len(value) < 2 {
return errors.New("Invalid max-size value, must be a number followed by a unit of measure [k, m, d]")
}
number := value[:len(value)-1]
if _, err := strconv.Atoi(number); err != nil {
return fmt.Errorf("Invalid max-size value, unable to convert number to int: %s", err.Error())
}
return nil
}
func validateVectorSink(appName string, value string) error {
if value == "" {
return nil
}
_, err := valueToConfig(appName, value)
if err != nil {
return err
}
return nil
}

View File

@@ -35,6 +35,7 @@ func main() {
case "set":
args := flag.NewFlagSet("logs:set", flag.ExitOnError)
global := args.Bool("global", false, "--global: set a global property")
valueOverride := args.Bool("1", false, "-1: negative value (for max-size)")
args.Parse(os.Args[2:])
appName := args.Arg(0)
property := args.Arg(1)
@@ -44,6 +45,11 @@ func main() {
property = args.Arg(0)
value = args.Arg(1)
}
if *valueOverride {
value = "-1"
}
err = logs.CommandSet(appName, property, value)
case "vector-logs":
args := flag.NewFlagSet("logs:vector-logs", flag.ExitOnError)

View File

@@ -18,8 +18,15 @@ func main() {
var err error
switch trigger {
case "docker-args-process-deploy":
appName := flag.Arg(0)
err = logs.TriggerDockerArgsProcessDeploy(appName)
case "install":
err = logs.TriggerInstall()
case "logs-get-property":
appName := flag.Arg(0)
property := flag.Arg(1)
err = logs.TriggerLogsGetProperty(appName, property)
case "post-delete":
appName := flag.Arg(0)
err = logs.TriggerPostDelete(appName)

View File

@@ -69,11 +69,8 @@ func CommandReport(appName string, infoFlag string) error {
// CommandSet sets or clears a logs property for an app
func CommandSet(appName string, property string, value string) error {
if property == "vector-sink" && value != "" {
_, err := valueToConfig(appName, value)
if err != nil {
return err
}
if err := validateSetValue(appName, property, value); err != nil {
return err
}
common.CommandPropertySet("logs", appName, property, value, DefaultProperties, GlobalProperties)

View File

@@ -1,13 +1,35 @@
package logs
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/dokku/dokku/plugins/common"
)
// TriggerDockerArgsProcessDeploy outputs the logs plugin docker options for an app
func TriggerDockerArgsProcessDeploy(appName string) error {
stdin, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
maxSize := common.PropertyGet("logs", appName, "max-size")
if maxSize == "" {
maxSize = common.PropertyGetDefault("logs", "--global", "max-size", MaxSize)
}
if maxSize != "unlimited" {
fmt.Printf(" --log-opt max-size=%s ", maxSize)
}
fmt.Print(string(stdin))
return nil
}
// TriggerInstall initializes app restart policies
func TriggerInstall() error {
if err := common.PropertySetup("logs"); err != nil {
@@ -35,6 +57,21 @@ func TriggerInstall() error {
return nil
}
// TriggerLogsGetProperty writes the logs key to stdout for a given app container
func TriggerLogsGetProperty(appName string, key string) error {
if key != "max-size" {
return errors.New("Invalid logs property specified")
}
value := common.PropertyGet("logs", appName, "max-size")
if value == "" {
value = common.PropertyGetDefault("logs", "--global", "max-size", MaxSize)
}
fmt.Println(value)
return nil
}
// TriggerPostDelete destroys the network property for a given app container
func TriggerPostDelete(appName string) error {
return common.PropertyDestroy("logs", appName)