foundation

package module
v0.0.82 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2023 License: MIT Imports: 27 Imported by: 58

README

Estafette

The estafette-foundation library is part of the Estafette CI system documented at https://estafette.io.

Please file any issues related to Estafette CI at https://github.com/estafette/estafette-ci-central/issues

Estafette-foundation

This library provides building blocks for creating

This library has contracts for requests / responses between various components of the Estafette CI system.

Development

To start development run

git clone git@github.com:estafette/estafette-foundation.git
cd estafette-foundation

Before committing your changes run

go test ./...
go mod tidy

Usage

To add this module to your golang application run

go get github.com/estafette/estafette-foundation
Initialize logging
import "github.com/estafette/estafette-foundation"

foundation.InitLogging(app, version, branch, revision, buildDate)
Initialize Prometheus metrics endpoint
import "github.com/estafette/estafette-foundation"

foundation.InitMetrics()
Handle graceful shutdown
import "github.com/estafette/estafette-foundation"

gracefulShutdown, waitGroup := foundation.InitGracefulShutdownHandling()

// your core application logic, making use of the waitGroup for critical sections

foundation.HandleGracefulShutdown(gracefulShutdown, waitGroup)
Watch mounted folder for changes
import "github.com/estafette/estafette-foundation"

foundation.WatchForFileChanges("/path/to/mounted/secret/or/configmap", func(event fsnotify.Event) {
  // reinitialize parts making use of the mounted data
})
Apply jitter to a number to introduce randomness

Inspired by http://highscalability.com/blog/2012/4/17/youtube-strategy-adding-jitter-isnt-a-bug.html you want to add jitter to a lot of parts of your platform, like cache durations, polling intervals, etc.

import "github.com/estafette/estafette-foundation"

sleepTime := foundation.ApplyJitter(30)
time.Sleep(time.Duration(sleepTime) * time.Second)
Retry

In order to retry a function you can use the Retry function to which you can pass a retryable function with signature func() error:

import "github.com/estafette/estafette-foundation"

foundation.Retry(func() error { do something that can fail })

Without passing any additional options it will by default try 3 times, with exponential backoff with jitter applied to the interval for any error returned by the retryable function.

In order to override the defaults you can pass them in with the following options:

import "github.com/estafette/estafette-foundation"

foundation.Retry(func() error { do something that can fail }, Attempts(5), DelayMillisecond(10), Fixed())

The following options can be passed in:

Option Config property Description
Attempts Attempts Sets the number of attempts the retryable function will be attempted before returning the error
DelayMillisecond DelayMillisecond Sets the base number of milliseconds between the retries or to base the exponential backoff delay on
ExponentialJitterBackoff DelayType
ExponentialBackoff DelayType
Fixed DelayType
AnyError IsRetryableError
Custom options

You can also override any of the config properties by passing in a custom option with signature func(*RetryConfig), which could look like:

import "github.com/estafette/estafette-foundation"

isRetryableErrorCustomOption := func(c *foundation.RetryConfig) {
  c.IsRetryableError = func(err error) bool {
    switch e := err.(type) {
      case *googleapi.Error:
        return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
      default:
        return false
    }
  }
}

foundation.Retry(func() error { do something that can fail }, isRetryableErrorCustomOption)
Limit concurrency with a semaphore

To run code in a loop concurrently with a maximum of simultanuous running goroutines do the following:

import "github.com/estafette/estafette-foundation"

// limit concurrency using a semaphore
maxConcurrency := 5
semaphore := foundation.NewSemaphore(maxConcurrency)

for _, i := range items {
  // try to acquire a lock, which only succeeds if there's less than maxConcurrency active goroutines
  semaphore.Acquire()

  go func(i Item) {
    // release the lock when done with the slow task
    defer semaphore.Release()

    // do some slow work
  }(i)
}

// wait until all concurrent goroutines are done
semaphore.Wait()

If you want to run Acquire within a select statement do so as follows:

import "github.com/estafette/estafette-foundation"

// limit concurrency using a semaphore
maxConcurrency := 5
semaphore := foundation.NewSemaphore(maxConcurrency)

for _, i := range items {
  select {
  case semaphore.GetAcquireChannel() <- struct{}{}:
    // try to acquire a lock, which only succeeds if there's less than maxConcurrency active goroutines
    semaphore.Acquire()

    go func(i Item) {
      // release the lock when done with the slow task
      defer semaphore.Release()

      // do some slow work
    }(i)

  case <-time.After(1 * time.Second):
    // running the goroutines took to long, exit instead
    return
  }
}

// wait until all concurrent goroutines are done
semaphore.Wait()

Documentation

Index

Constants

View Source
const (
	// LogFormatPlainText outputs logs in plain text without colorization and with timestamp; is the default if log format isn't specified
	LogFormatPlainText = "plaintext"
	// LogFormatConsole outputs logs in plain text with colorization and without timestamp
	LogFormatConsole = "console"
	// LogFormatJSON outputs logs in json including appgroup, app, appversion and other metadata
	LogFormatJSON = "json"
	// LogFormatStackdriver outputs a format similar to JSON format but with 'severity' instead of 'level' field
	LogFormatStackdriver = "stackdriver"
	// LogFormatV3 ouputs an internal format used at Travix in JSON format with nested payload and a specific set of required metadata
	LogFormatV3 = "v3"
)

Variables

This section is empty.

Functions

func AnyErrorIsRetryable added in v0.0.58

func AnyErrorIsRetryable(err error) bool

AnyErrorIsRetryable is a IsRetryableErrorFunc which returns whether an error should be retried

func ApplyJitter

func ApplyJitter(input int) (output int)

ApplyJitter adds +-25% jitter to the input

func DirExists added in v0.0.69

func DirExists(directory string) bool

DirExists checks if a directory exists

func ExponentialBackOffDelay added in v0.0.44

func ExponentialBackOffDelay(n uint, config *RetryConfig) time.Duration

ExponentialBackOffDelay is a DelayType which increases delay between consecutive retries exponentially

func ExponentialJitterBackoffDelay added in v0.0.44

func ExponentialJitterBackoffDelay(n uint, config *RetryConfig) time.Duration

ExponentialJitterBackoffDelay returns ever increasing backoffs by a power of 2 with +/- 0-25% to prevent sychronized requests.

func FileExists added in v0.0.22

func FileExists(filename string) bool

FileExists checks if a file exists

func FixedDelay added in v0.0.44

func FixedDelay(_ uint, config *RetryConfig) time.Duration

FixedDelay is a DelayType which keeps delay the same through all iterations

func GetCommandInDirectoryOutput added in v0.0.68

func GetCommandInDirectoryOutput(ctx context.Context, dir string, command string, args ...interface{}) (string, error)

GetCommandInDirectoryOutput runs a full command string and replaces placeholders with the arguments from the specified directory; it returns the output as a string and an error if command execution failed output, err := GetCommandInDirectoryOutput(ctx, "directory other than working dir", "kubectl logs -l app=%v -n %v", app, namespace)

func GetCommandOutput added in v0.0.63

func GetCommandOutput(ctx context.Context, command string, args ...interface{}) (string, error)

GetCommandOutput runs a full command string and replaces placeholders with the arguments; it returns the output as a string and an error if command execution failed output, err := GetCommandOutput(ctx, "kubectl logs -l app=%v -n %v", app, namespace)

func GetCommandWithArgsInDirectoryOutput added in v0.0.67

func GetCommandWithArgsInDirectoryOutput(ctx context.Context, dir string, command string, args []string) (string, error)

GetCommandWithArgsInDirectoryOutput runs a single command and passes the arguments from the specified directory; it returns the output as a string and an error if command execution failed output, err := GetCommandWithArgsOutput(ctx, "directory other than working dir", "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func GetCommandWithArgsOutput added in v0.0.37

func GetCommandWithArgsOutput(ctx context.Context, command string, args []string) (string, error)

GetCommandWithArgsOutput runs a single command and passes the arguments; it returns the output as a string and an error if command execution failed output, err := GetCommandWithArgsOutput(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func HandleError added in v0.0.22

func HandleError(err error)

HandleError logs a fatal when the error is not nil

func HandleGracefulShutdown

func HandleGracefulShutdown(gracefulShutdown chan os.Signal, waitGroup *sync.WaitGroup, functionsOnShutdown ...func())

HandleGracefulShutdown waits for SIGTERM to unblock gracefulShutdown and waits for the waitgroup to await pending work

func InitCancellationContext added in v0.0.36

func InitCancellationContext(ctx context.Context) context.Context

InitCancellationContext adds cancelation to a context and on sigterm triggers the cancel function

func InitGracefulShutdownHandling

func InitGracefulShutdownHandling() (gracefulShutdown chan os.Signal, waitGroup *sync.WaitGroup)

InitGracefulShutdownHandling generates the channel that listens to SIGTERM and a waitgroup to use for finishing work when shutting down

func InitLiveness added in v0.0.51

func InitLiveness()

InitLiveness initializes the /liveness endpoint on port 5000

func InitLivenessAndReadiness added in v0.0.61

func InitLivenessAndReadiness()

InitLivenessAndReadiness initializes the /liveness and /readiness endpoint on port 5000

func InitLivenessAndReadinessWithPort added in v0.0.61

func InitLivenessAndReadinessWithPort(port int)

InitLivenessAndReadinessWithPort initializes the /liveness and /readiness endpoint on specified port

func InitLivenessWithPort added in v0.0.51

func InitLivenessWithPort(port int)

InitLivenessWithPort initializes the /liveness endpoint on specified port

func InitLoggingByFormat added in v0.0.31

func InitLoggingByFormat(applicationInfo ApplicationInfo, logFormat string)

InitLoggingByFormat initalializes a logger with specified format and outputs a startup message

func InitLoggingByFormatSilent added in v0.0.38

func InitLoggingByFormatSilent(applicationInfo ApplicationInfo, logFormat string)

InitLoggingByFormatSilent initializes a logger with specified format without outputting a startup message

func InitLoggingFromEnv added in v0.0.31

func InitLoggingFromEnv(applicationInfo ApplicationInfo)

InitLoggingFromEnv initalializes a logger with format specified in envvar ESTAFETTE_LOG_FORMAT and outputs a startup message

func InitMetrics

func InitMetrics()

InitMetrics initializes the prometheus endpoint /metrics on port 9101

func InitMetricsWithPort added in v0.0.13

func InitMetricsWithPort(port int)

InitMetricsWithPort initializes the prometheus endpoint /metrics on specified port

func InitReadiness added in v0.0.61

func InitReadiness()

InitReadiness initializes the /readiness endpoint on port 5000

func InitReadinessWithPort added in v0.0.61

func InitReadinessWithPort(port int)

InitReadinessWithPort initializes the /readiness endpoint on specified port

func InitTracingFromEnv added in v0.0.41

func InitTracingFromEnv(app string) io.Closer

InitTracingFromEnv initializes a Jaeger Tracer and returns a closer which can be defer closed in your main routine https://github.com/jaegertracing/jaeger-client-go#environment-variables

func IntArrayContains added in v0.0.57

func IntArrayContains(array []int, search int) bool

IntArrayContains checks if an array contains a specific value

func PathExists added in v0.0.69

func PathExists(path string) bool

PathExists checks if a directory exists

func Retry added in v0.0.43

func Retry(retryableFunc func() error, opts ...RetryOption) error

Retry retries a function

func RunCommand added in v0.0.22

func RunCommand(ctx context.Context, command string, args ...interface{})

RunCommand runs a full command string and replaces placeholders with the arguments; it logs a fatal on error RunCommand(ctx, "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandExtended added in v0.0.22

func RunCommandExtended(ctx context.Context, command string, args ...interface{}) error

RunCommandExtended runs a full command string and replaces placeholders with the arguments; it returns an error if command execution failed err := RunCommandExtended(ctx, "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandExtendedCombinedStdErr added in v0.0.80

func RunCommandExtendedCombinedStdErr(ctx context.Context, command string, args ...interface{}) error

RunCommandExtended runs a full command string and replaces placeholders with the arguments; it returns an error combined stderr if command execution failed err := RunCommandExtended(ctx, "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandInDirectory added in v0.0.67

func RunCommandInDirectory(ctx context.Context, dir string, command string, args ...interface{})

RunCommandInDirectory runs a full command string and replaces placeholders with the arguments from the specified directory; it logs a fatal on error RunCommandInDirectory(ctx, "directory other than working dir", "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandInDirectoryExtended added in v0.0.67

func RunCommandInDirectoryExtended(ctx context.Context, dir string, command string, args ...interface{}) error

RunCommandInDirectoryExtended runs a full command string and replaces placeholders with the arguments from the specified directory; it returns an error if command execution failed err := RunCommandInDirectoryExtended(ctx, "directory other than working dir", "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandInDirectoryExtendedCombinedStdErr added in v0.0.79

func RunCommandInDirectoryExtendedCombinedStdErr(ctx context.Context, dir string, command string, args ...interface{}) error

RunCommandInDirectoryExtended runs a full command string and replaces placeholders with the arguments from the specified directory; it returns an error combined stderr if command execution failed err := RunCommandInDirectoryExtended(ctx, "directory other than working dir", "kubectl logs -l app=%v -n %v", app, namespace)

func RunCommandInDirectoryWithArgs added in v0.0.67

func RunCommandInDirectoryWithArgs(ctx context.Context, dir string, command string, args []string)

RunCommandInDirectoryWithArgs runs a single command and passes the arguments from the specified directory; it logs a fatal on error RunCommandInDirectoryWithArgs(ctx, "directory other than working dir", "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandInDirectoryWithArgsExtended added in v0.0.67

func RunCommandInDirectoryWithArgsExtended(ctx context.Context, dir string, command string, args []string) error

RunCommandInDirectoryWithArgsExtended runs a single command and passes the arguments from the specified directory; it returns an error if command execution failed err := RunCommandInDirectoryWithArgsExtended(ctx, "directory other than working dir", "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandInDirectoryWithArgsExtendedCombinedStdErr added in v0.0.79

func RunCommandInDirectoryWithArgsExtendedCombinedStdErr(ctx context.Context, dir string, command string, args []string) error

RunCommandInDirectoryWithArgsExtended runs a single command and passes the arguments from the specified directory; it returns an error combined stderr if command execution failed err := RunCommandInDirectoryWithArgsExtended(ctx, "directory other than working dir", "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandWithArgs added in v0.0.22

func RunCommandWithArgs(ctx context.Context, command string, args []string)

RunCommandWithArgs runs a single command and passes the arguments; it logs a fatal on error RunCommandWithArgs(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandWithArgsExtended added in v0.0.22

func RunCommandWithArgsExtended(ctx context.Context, command string, args []string) error

RunCommandWithArgsExtended runs a single command and passes the arguments; it returns an error if command execution failed err := RunCommandWithArgsExtended(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandWithArgsExtendedCombinedStdErr added in v0.0.80

func RunCommandWithArgsExtendedCombinedStdErr(ctx context.Context, command string, args []string) error

RunCommandWithArgsExtendedCombinedStdErr runs a single command and passes the arguments; it returns an error combined stderr if command execution failed err := RunCommandWithArgsExtended(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandWithArgsExtendedWithoutLog added in v0.0.82

func RunCommandWithArgsExtendedWithoutLog(ctx context.Context, command string, args []string) error

RunCommandWithArgsExtendedWithoutLog runs a single command and passes the arguments; it returns an error if command execution failed without any log output err := RunCommandWithArgsExtendedWithoutLog(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func RunCommandWithArgsWithoutLog added in v0.0.82

func RunCommandWithArgsWithoutLog(ctx context.Context, command string, args []string)

RunCommandWithArgsWithoutLog runs a single command and passes the arguments; it logs a fatal on error without any log output RunCommandWithArgsWithoutLog(ctx, "kubectl", []string{"logs", "-l", "app="+app, "-n", namespace)

func SetLoggingLevelFromEnv added in v0.0.49

func SetLoggingLevelFromEnv()

SetLoggingLevelFromEnv sets the logging level from which log messages and higher are outputted via envvar ESTAFETTE_LOG_LEVEL

func StringArrayContains added in v0.0.42

func StringArrayContains(array []string, search string) bool

StringArrayContains checks if an array contains a specific value

func ToLowerSnakeCase added in v0.0.45

func ToLowerSnakeCase(in string) string

ToLowerSnakeCase turns any input string into an lower snake cased string

func ToUpperSnakeCase added in v0.0.45

func ToUpperSnakeCase(in string) string

ToUpperSnakeCase turns any input string into an upper snake cased string

func WatchForFileChanges

func WatchForFileChanges(filePath string, functionOnChange func(fsnotify.Event))

WatchForFileChanges waits for a change to the provided file path and then executes the function

Types

type ApplicationInfo added in v0.0.39

type ApplicationInfo struct {
	AppGroup  string
	App       string
	Version   string
	Branch    string
	Revision  string
	BuildDate string
}

ApplicationInfo contains basic information about an application

func NewApplicationInfo added in v0.0.40

func NewApplicationInfo(appgroup, app, version, branch, revision, buildDate string) ApplicationInfo

NewApplicationInfo returns an ApplicationInfo object

func (*ApplicationInfo) GoVersion added in v0.0.39

func (ai *ApplicationInfo) GoVersion() string

GoVersion returns the golang version used to build an application

func (*ApplicationInfo) OperatingSystem added in v0.0.39

func (ai *ApplicationInfo) OperatingSystem() string

OperatingSystem returns the current operating system

type DelayTypeFunc added in v0.0.43

type DelayTypeFunc func(n uint, config *RetryConfig) time.Duration

DelayTypeFunc allows to override the DelayType

type IsRetryableErrorFunc added in v0.0.58

type IsRetryableErrorFunc func(err error) bool

IsRetryableErrorFunc allows to apply custom logic to whether an error is retryable

type RetryConfig added in v0.0.43

type RetryConfig struct {
	Attempts         uint
	DelayMillisecond int
	DelayType        DelayTypeFunc
	LastErrorOnly    bool
	IsRetryableError IsRetryableErrorFunc
}

RetryConfig is used to configure the Retry function

type RetryError added in v0.0.43

type RetryError []error

RetryError contains all errors for each failed attempt

func (RetryError) Error added in v0.0.43

func (e RetryError) Error() string

Error method return string representation of Error It is an implementation of error interface

type RetryOption added in v0.0.43

type RetryOption func(*RetryConfig)

RetryOption allows to override config

func AnyError added in v0.0.58

func AnyError() RetryOption

AnyError is sets AnyErrorIsRetryable as IsRetryableError

func Attempts added in v0.0.43

func Attempts(attempts uint) RetryOption

Attempts set count of retry default is 3

func DelayMillisecond added in v0.0.43

func DelayMillisecond(delayMilliSeconds int) RetryOption

DelayMillisecond sets delay between retries default is 100ms

func ExponentialBackOff added in v0.0.58

func ExponentialBackOff() RetryOption

ExponentialBackOff sets ExponentialBackOffDelay as DelayType

func ExponentialJitterBackoff added in v0.0.43

func ExponentialJitterBackoff() RetryOption

ExponentialJitterBackoff sets ExponentialJitterBackoffDelay as DelayType

func Fixed added in v0.0.58

func Fixed() RetryOption

Fixed sets FixedDelay as DelayType

func LastErrorOnly added in v0.0.59

func LastErrorOnly(value bool) RetryOption

LastErrorOnly sets LastErrorOnly config value

type Semaphore added in v0.0.70

type Semaphore interface {
	// Acquire tries to get a lock and blocks until it does
	Acquire()
	// GetAcquireChannel returns the inner channel to be used to acquire a lock within a select statement
	GetAcquireChannel() chan struct{}
	// Release releases a lock
	Release()
	// Wait until all locks are released
	Wait()
}

func NewSemaphore added in v0.0.70

func NewSemaphore(maxConcurrency int) Semaphore

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL