Update linter
This commit is contained in:
parent
f12c27aa7c
commit
328611c619
157 changed files with 489 additions and 508 deletions
|
@ -49,6 +49,9 @@
|
||||||
"wsl", # Too strict
|
"wsl", # Too strict
|
||||||
"gomnd", # Too strict
|
"gomnd", # Too strict
|
||||||
"stylecheck", # skip because report issues related to some generated files.
|
"stylecheck", # skip because report issues related to some generated files.
|
||||||
|
"testpackage", # Too strict
|
||||||
|
"goerr113", # Too strict
|
||||||
|
"nestif", # Too many false-positive.
|
||||||
]
|
]
|
||||||
|
|
||||||
[issues]
|
[issues]
|
||||||
|
@ -62,7 +65,7 @@
|
||||||
]
|
]
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "(.+)_test.go"
|
path = "(.+)_test.go"
|
||||||
linters = ["goconst", "funlen"]
|
linters = ["goconst", "funlen", "godot"]
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "integration/.+_test.go"
|
path = "integration/.+_test.go"
|
||||||
text = "Error return value of `cmd\\.Process\\.Kill` is not checked"
|
text = "Error return value of `cmd\\.Process\\.Kill` is not checked"
|
||||||
|
@ -105,3 +108,6 @@
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "pkg/tracing/tracing.go"
|
path = "pkg/tracing/tracing.go"
|
||||||
text = "printf-like formatting function 'SetErrorWithEvent' should be named 'SetErrorWithEventf'"
|
text = "printf-like formatting function 'SetErrorWithEvent' should be named 'SetErrorWithEventf'"
|
||||||
|
[[issues.exclude-rules]]
|
||||||
|
path = "pkg/log/deprecated.go"
|
||||||
|
linters = ["godot"]
|
||||||
|
|
|
@ -19,7 +19,7 @@ RUN mkdir -p /usr/local/bin \
|
||||||
&& chmod +x /usr/local/bin/go-bindata
|
&& chmod +x /usr/local/bin/go-bindata
|
||||||
|
|
||||||
# Download golangci-lint binary to bin folder in $GOPATH
|
# Download golangci-lint binary to bin folder in $GOPATH
|
||||||
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.23.8
|
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.26.0
|
||||||
|
|
||||||
# Download misspell binary to bin folder in $GOPATH
|
# Download misspell binary to bin folder in $GOPATH
|
||||||
RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4
|
RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContextWithSignal creates a context canceled when SIGINT or SIGTERM are notified
|
// ContextWithSignal creates a context canceled when SIGINT or SIGTERM are notified.
|
||||||
func ContextWithSignal(ctx context.Context) context.Context {
|
func ContextWithSignal(ctx context.Context) context.Context {
|
||||||
newCtx, cancel := context.WithCancel(ctx)
|
newCtx, cancel := context.WithCancel(ctx)
|
||||||
signals := make(chan os.Signal)
|
signals := make(chan os.Signal)
|
||||||
|
|
|
@ -45,7 +45,7 @@ func runCmd(traefikConfiguration *static.Configuration) func(_ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do try to do a healthcheck
|
// Do try to do a healthcheck.
|
||||||
func Do(staticConfiguration static.Configuration) (*http.Response, error) {
|
func Do(staticConfiguration static.Configuration) (*http.Response, error) {
|
||||||
if staticConfiguration.Ping == nil {
|
if staticConfiguration.Ping == nil {
|
||||||
return nil, errors.New("please enable `ping` to use health check")
|
return nil, errors.New("please enable `ping` to use health check")
|
||||||
|
|
|
@ -274,7 +274,7 @@ func switchRouter(routerFactory *server.RouterFactory, acmeProviders []*acme.Pro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initACMEProvider creates an acme provider from the ACME part of globalConfiguration
|
// initACMEProvider creates an acme provider from the ACME part of globalConfiguration.
|
||||||
func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager) []*acme.Provider {
|
func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager) []*acme.Provider {
|
||||||
challengeStore := acme.NewLocalChallengeStore()
|
challengeStore := acme.NewLocalChallengeStore()
|
||||||
localStores := map[string]*acme.LocalStore{}
|
localStores := map[string]*acme.LocalStore{}
|
||||||
|
|
|
@ -17,7 +17,7 @@ Go version: {{.GoVersion}}
|
||||||
Built: {{.BuildTime}}
|
Built: {{.BuildTime}}
|
||||||
OS/Arch: {{.Os}}/{{.Arch}}`
|
OS/Arch: {{.Os}}/{{.Arch}}`
|
||||||
|
|
||||||
// NewCmd builds a new Version command
|
// NewCmd builds a new Version command.
|
||||||
func NewCmd() *cli.Command {
|
func NewCmd() *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "version",
|
Name: "version",
|
||||||
|
@ -33,7 +33,7 @@ func NewCmd() *cli.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrint write Printable version
|
// GetPrint write Printable version.
|
||||||
func GetPrint(wr io.Writer) error {
|
func GetPrint(wr io.Writer) error {
|
||||||
tmpl, err := template.New("").Parse(versionTemplate)
|
tmpl, err := template.New("").Parse(versionTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -24,7 +24,7 @@ const (
|
||||||
traefikTestAccessLogFile = "access.log"
|
traefikTestAccessLogFile = "access.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessLogSuite
|
// AccessLogSuite tests suite.
|
||||||
type AccessLogSuite struct{ BaseSuite }
|
type AccessLogSuite struct{ BaseSuite }
|
||||||
|
|
||||||
type accessLogValue struct {
|
type accessLogValue struct {
|
||||||
|
@ -562,7 +562,7 @@ func extractLines(c *check.C) []string {
|
||||||
func checkStatsForLogFile(c *check.C) {
|
func checkStatsForLogFile(c *check.C) {
|
||||||
err := try.Do(1*time.Second, func() error {
|
err := try.Do(1*time.Second, func() error {
|
||||||
if _, errStat := os.Stat(traefikTestLogFile); errStat != nil {
|
if _, errStat := os.Stat(traefikTestLogFile); errStat != nil {
|
||||||
return fmt.Errorf("could not get stats for log file: %s", errStat)
|
return fmt.Errorf("could not get stats for log file: %w", errStat)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ACME test suites (using libcompose)
|
// ACME test suites (using libcompose).
|
||||||
type AcmeSuite struct {
|
type AcmeSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
pebbleIP string
|
pebbleIP string
|
||||||
|
@ -74,7 +74,7 @@ func setupPebbleRootCA() (*http.Transport, error) {
|
||||||
|
|
||||||
certPool := x509.NewCertPool()
|
certPool := x509.NewCertPool()
|
||||||
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
||||||
return nil, fmt.Errorf("error creating x509 cert pool from %q: %v", path, err)
|
return nil, fmt.Errorf("error creating x509 cert pool from %q: %w", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http.Transport{
|
return &http.Transport{
|
||||||
|
@ -394,7 +394,7 @@ func (s *AcmeSuite) TestTLSALPN01DomainsInSAN(c *check.C) {
|
||||||
s.retrieveAcmeCertificate(c, testCase)
|
s.retrieveAcmeCertificate(c, testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test Let's encrypt down
|
// Test Let's encrypt down.
|
||||||
func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
||||||
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
|
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
|
||||||
Acme: map[string]static.CertificateResolver{
|
Acme: map[string]static.CertificateResolver{
|
||||||
|
@ -417,7 +417,7 @@ func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doing an HTTPS request and test the response certificate
|
// Doing an HTTPS request and test the response certificate.
|
||||||
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
||||||
if len(testCase.template.PortHTTP) == 0 {
|
if len(testCase.template.PortHTTP) == 0 {
|
||||||
testCase.template.PortHTTP = ":5002"
|
testCase.template.PortHTTP = ":5002"
|
||||||
|
|
|
@ -47,7 +47,7 @@ func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
|
||||||
leader, err := s.consulClient.Status().Leader()
|
leader, err := s.consulClient.Status().Leader()
|
||||||
|
|
||||||
if err != nil || len(leader) == 0 {
|
if err != nil || len(leader) == 0 {
|
||||||
return fmt.Errorf("leader not found. %v", err)
|
return fmt.Errorf("leader not found. %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Consul test suites (using libcompose)
|
// Consul test suites (using libcompose).
|
||||||
type ConsulSuite struct {
|
type ConsulSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
kvClient store.Store
|
kvClient store.Store
|
||||||
|
|
|
@ -18,7 +18,7 @@ const (
|
||||||
composeProject = "minimal"
|
composeProject = "minimal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Docker test suites
|
// Docker tests suite.
|
||||||
type DockerComposeSuite struct {
|
type DockerComposeSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Images to have or pull before the build in order to make it work
|
// Images to have or pull before the build in order to make it work.
|
||||||
// FIXME handle this offline but loading them before build
|
// FIXME handle this offline but loading them before build.
|
||||||
var RequiredImages = map[string]string{
|
var RequiredImages = map[string]string{
|
||||||
"swarm": "1.0.0",
|
"swarm": "1.0.0",
|
||||||
"containous/whoami": "latest",
|
"containous/whoami": "latest",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Docker test suites
|
// Docker tests suite.
|
||||||
type DockerSuite struct {
|
type DockerSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
project *docker.Project
|
project *docker.Project
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrorPagesSuite test suites (using libcompose)
|
// ErrorPagesSuite test suites (using libcompose).
|
||||||
type ErrorPagesSuite struct {
|
type ErrorPagesSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
ErrorPageIP string
|
ErrorPageIP string
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// etcd test suites (using libcompose)
|
// etcd test suites (using libcompose).
|
||||||
type EtcdSuite struct {
|
type EtcdSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
kvClient store.Store
|
kvClient store.Store
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// File test suites
|
// File tests suite.
|
||||||
type FileSuite struct{ BaseSuite }
|
type FileSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *FileSuite) SetUpSuite(c *check.C) {
|
func (s *FileSuite) SetUpSuite(c *check.C) {
|
||||||
|
@ -32,7 +32,7 @@ func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #56 regression test, make sure it does not fail
|
// #56 regression test, make sure it does not fail?
|
||||||
func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) {
|
func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) {
|
||||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
||||||
defer display(c)
|
defer display(c)
|
||||||
|
|
|
@ -24,7 +24,7 @@ var LocalhostKey []byte
|
||||||
|
|
||||||
const randCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
const randCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||||
|
|
||||||
// GRPCSuite
|
// GRPCSuite tests suite.
|
||||||
type GRPCSuite struct{ BaseSuite }
|
type GRPCSuite struct{ BaseSuite }
|
||||||
|
|
||||||
type myserver struct {
|
type myserver struct {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Headers test suites
|
// Headers tests suite.
|
||||||
type HeadersSuite struct{ BaseSuite }
|
type HeadersSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
|
func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HealthCheck test suites (using libcompose)
|
// HealthCheck test suites (using libcompose).
|
||||||
type HealthCheckSuite struct {
|
type HealthCheckSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
whoami1IP string
|
whoami1IP string
|
||||||
|
@ -206,7 +206,7 @@ func (s *HealthCheckSuite) TestPortOverload(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if all the loadbalancers created will correctly update the server status
|
// Checks if all the loadbalancers created will correctly update the server status.
|
||||||
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService(c *check.C) {
|
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService(c *check.C) {
|
||||||
file := s.adaptFile(c, "fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
file := s.adaptFile(c, "fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
||||||
Server1 string
|
Server1 string
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPSSuite
|
// HTTPSSuite tests suite.
|
||||||
type HTTPSSuite struct{ BaseSuite }
|
type HTTPSSuite struct{ BaseSuite }
|
||||||
|
|
||||||
// TestWithSNIConfigHandshake involves a client sending a SNI hostname of
|
// TestWithSNIConfigHandshake involves a client sending a SNI hostname of
|
||||||
|
@ -441,7 +441,7 @@ func (s *HTTPSSuite) TestWithOverlappingDynamicCertificate(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWithClientCertificateAuthentication
|
// TestWithClientCertificateAuthentication
|
||||||
// The client can send a certificate signed by a CA trusted by the server but it's optional
|
// The client can send a certificate signed by a CA trusted by the server but it's optional.
|
||||||
func (s *HTTPSSuite) TestWithClientCertificateAuthentication(c *check.C) {
|
func (s *HTTPSSuite) TestWithClientCertificateAuthentication(c *check.C) {
|
||||||
file := s.adaptFile(c, "fixtures/https/clientca/https_1ca1config.toml", struct{}{})
|
file := s.adaptFile(c, "fixtures/https/clientca/https_1ca1config.toml", struct{}{})
|
||||||
defer os.Remove(file)
|
defer os.Remove(file)
|
||||||
|
@ -499,7 +499,7 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthentication(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWithClientCertificateAuthentication
|
// TestWithClientCertificateAuthentication
|
||||||
// Use two CA:s and test that clients with client signed by either of them can connect
|
// Use two CA:s and test that clients with client signed by either of them can connect.
|
||||||
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAs(c *check.C) {
|
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAs(c *check.C) {
|
||||||
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
||||||
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
||||||
|
@ -596,7 +596,7 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAs(c *check
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWithClientCertificateAuthentication
|
// TestWithClientCertificateAuthentication
|
||||||
// Use two CA:s in two different files and test that clients with client signed by either of them can connect
|
// Use two CA:s in two different files and test that clients with client signed by either of them can connect.
|
||||||
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAsMultipleFiles(c *check.C) {
|
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAsMultipleFiles(c *check.C) {
|
||||||
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
||||||
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
var updateExpected = flag.Bool("update_expected", false, "Update expected files in testdata")
|
var updateExpected = flag.Bool("update_expected", false, "Update expected files in testdata")
|
||||||
|
|
||||||
// K8sSuite
|
// K8sSuite tests suite.
|
||||||
type K8sSuite struct{ BaseSuite }
|
type K8sSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *K8sSuite) SetUpSuite(c *check.C) {
|
func (s *K8sSuite) SetUpSuite(c *check.C) {
|
||||||
|
@ -128,7 +128,7 @@ func matchesConfig(wantConfig string, buf *bytes.Buffer) try.ResponseCondition {
|
||||||
return func(res *http.Response) error {
|
return func(res *http.Response) error {
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read response body: %s", err)
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := res.Body.Close(); err != nil {
|
if err := res.Body.Close(); err != nil {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log rotation integration test suite
|
// Log rotation integration test suite.
|
||||||
type LogRotationSuite struct{ BaseSuite }
|
type LogRotationSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
|
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Marathon test suites (using libcompose)
|
// Marathon test suites (using libcompose).
|
||||||
type MarathonSuite15 struct {
|
type MarathonSuite15 struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
marathonURL string
|
marathonURL string
|
||||||
|
|
|
@ -17,7 +17,7 @@ const (
|
||||||
containerNameMarathon = "marathon"
|
containerNameMarathon = "marathon"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Marathon test suites (using libcompose)
|
// Marathon test suites (using libcompose).
|
||||||
type MarathonSuite struct {
|
type MarathonSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
marathonURL string
|
marathonURL string
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Redis test suites (using libcompose)
|
// Redis test suites (using libcompose).
|
||||||
type RedisSuite struct {
|
type RedisSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
kvClient store.Store
|
kvClient store.Store
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SimpleSuite
|
// SimpleSuite tests suite.
|
||||||
type SimpleSuite struct{ BaseSuite }
|
type SimpleSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *SimpleSuite) TestInvalidConfigShouldFail(c *check.C) {
|
func (s *SimpleSuite) TestInvalidConfigShouldFail(c *check.C) {
|
||||||
|
|
|
@ -12,18 +12,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResponseCondition is a retry condition function.
|
// ResponseCondition is a retry condition function.
|
||||||
// It receives a response, and returns an error
|
// It receives a response, and returns an error if the response failed the condition.
|
||||||
// if the response failed the condition.
|
|
||||||
type ResponseCondition func(*http.Response) error
|
type ResponseCondition func(*http.Response) error
|
||||||
|
|
||||||
// BodyContains returns a retry condition function.
|
// BodyContains returns a retry condition function.
|
||||||
// The condition returns an error if the request body does not contain all the given
|
// The condition returns an error if the request body does not contain all the given strings.
|
||||||
// strings.
|
|
||||||
func BodyContains(values ...string) ResponseCondition {
|
func BodyContains(values ...string) ResponseCondition {
|
||||||
return func(res *http.Response) error {
|
return func(res *http.Response) error {
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read response body: %s", err)
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
|
@ -36,13 +34,12 @@ func BodyContains(values ...string) ResponseCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BodyNotContains returns a retry condition function.
|
// BodyNotContains returns a retry condition function.
|
||||||
// The condition returns an error if the request body contain one of the given
|
// The condition returns an error if the request body contain one of the given strings.
|
||||||
// strings.
|
|
||||||
func BodyNotContains(values ...string) ResponseCondition {
|
func BodyNotContains(values ...string) ResponseCondition {
|
||||||
return func(res *http.Response) error {
|
return func(res *http.Response) error {
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read response body: %s", err)
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
|
@ -55,13 +52,12 @@ func BodyNotContains(values ...string) ResponseCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BodyContainsOr returns a retry condition function.
|
// BodyContainsOr returns a retry condition function.
|
||||||
// The condition returns an error if the request body does not contain one of the given
|
// The condition returns an error if the request body does not contain one of the given strings.
|
||||||
// strings.
|
|
||||||
func BodyContainsOr(values ...string) ResponseCondition {
|
func BodyContainsOr(values ...string) ResponseCondition {
|
||||||
return func(res *http.Response) error {
|
return func(res *http.Response) error {
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read response body: %s", err)
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
|
@ -79,7 +75,7 @@ func HasBody() ResponseCondition {
|
||||||
return func(res *http.Response) error {
|
return func(res *http.Response) error {
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read response body: %s", err)
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(body) == 0 {
|
if len(body) == 0 {
|
||||||
|
@ -182,11 +178,11 @@ func HasHeaderStruct(header http.Header) ResponseCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoCondition is a retry condition function.
|
// DoCondition is a retry condition function.
|
||||||
// It returns an error
|
// It returns an error.
|
||||||
type DoCondition func() error
|
type DoCondition func() error
|
||||||
|
|
||||||
// KVExists is a retry condition function.
|
// KVExists is a retry condition function.
|
||||||
// Verify if a Key exists in the store
|
// Verify if a Key exists in the store.
|
||||||
func KVExists(kv store.Store, key string) DoCondition {
|
func KVExists(kv store.Store, key string) DoCondition {
|
||||||
return func() error {
|
return func() error {
|
||||||
_, err := kv.Exists(key, nil)
|
_, err := kv.Exists(key, nil)
|
||||||
|
|
|
@ -115,7 +115,7 @@ func Do(timeout time.Duration, operation DoCondition) error {
|
||||||
select {
|
select {
|
||||||
case <-stopTimer.C:
|
case <-stopTimer.C:
|
||||||
fmt.Println("-")
|
fmt.Println("-")
|
||||||
return fmt.Errorf("try operation failed: %s", err)
|
return fmt.Errorf("try operation failed: %w", err)
|
||||||
case <-retryTick.C:
|
case <-retryTick.C:
|
||||||
fmt.Print("*")
|
fmt.Print("*")
|
||||||
if err = operation(); err == nil {
|
if err = operation(); err == nil {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WebsocketSuite
|
// WebsocketSuite tests suite.
|
||||||
type WebsocketSuite struct{ BaseSuite }
|
type WebsocketSuite struct{ BaseSuite }
|
||||||
|
|
||||||
func (s *WebsocketSuite) TestBase(c *check.C) {
|
func (s *WebsocketSuite) TestBase(c *check.C) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Zk test suites (using libcompose)
|
// Zk test suites (using libcompose).
|
||||||
type ZookeeperSuite struct {
|
type ZookeeperSuite struct {
|
||||||
BaseSuite
|
BaseSuite
|
||||||
kvClient store.Store
|
kvClient store.Store
|
||||||
|
|
|
@ -15,7 +15,7 @@ const (
|
||||||
maskLarge = maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort
|
maskLarge = maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort
|
||||||
)
|
)
|
||||||
|
|
||||||
// Do configuration.
|
// Do sends configuration.
|
||||||
func Do(baseConfig interface{}, indent bool) (string, error) {
|
func Do(baseConfig interface{}, indent bool) (string, error) {
|
||||||
anomConfig, err := copystructure.Copy(baseConfig)
|
anomConfig, err := copystructure.Copy(baseConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -120,7 +120,7 @@ func reset(field reflect.Value, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isExported return true is a struct field is exported, else false
|
// isExported return true is a struct field is exported, else false.
|
||||||
func isExported(f reflect.StructField) bool {
|
func isExported(f reflect.StructField) bool {
|
||||||
if f.PkgPath != "" && !f.Anonymous {
|
if f.PkgPath != "" && !f.Anonymous {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DashboardHandler expose dashboard routes
|
// DashboardHandler expose dashboard routes.
|
||||||
type DashboardHandler struct {
|
type DashboardHandler struct {
|
||||||
Assets *assetfs.AssetFS
|
Assets *assetfs.AssetFS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append add dashboard routes on a router
|
// Append add dashboard routes on a router.
|
||||||
func (g DashboardHandler) Append(router *mux.Router) {
|
func (g DashboardHandler) Append(router *mux.Router) {
|
||||||
if g.Assets == nil {
|
if g.Assets == nil {
|
||||||
log.WithoutContext().Error("No assets for dashboard")
|
log.WithoutContext().Error("No assets for dashboard")
|
||||||
|
|
|
@ -19,10 +19,10 @@ func goroutines() interface{} {
|
||||||
return runtime.NumGoroutine()
|
return runtime.NumGoroutine()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugHandler expose debug routes
|
// DebugHandler expose debug routes.
|
||||||
type DebugHandler struct{}
|
type DebugHandler struct{}
|
||||||
|
|
||||||
// Append add debug routes on a router
|
// Append add debug routes on a router.
|
||||||
func (g DebugHandler) Append(router *mux.Router) {
|
func (g DebugHandler) Append(router *mux.Router) {
|
||||||
router.Methods(http.MethodGet).Path("/debug/vars").
|
router.Methods(http.MethodGet).Path("/debug/vars").
|
||||||
HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ type Handler struct {
|
||||||
runtimeConfiguration *runtime.Configuration
|
runtimeConfiguration *runtime.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuilder returns a http.Handler builder based on runtime.Configuration
|
// NewBuilder returns a http.Handler builder based on runtime.Configuration.
|
||||||
func NewBuilder(staticConfig static.Configuration) func(*runtime.Configuration) http.Handler {
|
func NewBuilder(staticConfig static.Configuration) func(*runtime.Configuration) http.Handler {
|
||||||
return func(configuration *runtime.Configuration) http.Handler {
|
return func(configuration *runtime.Configuration) http.Handler {
|
||||||
return New(staticConfig, configuration).createRouter()
|
return New(staticConfig, configuration).createRouter()
|
||||||
|
|
|
@ -55,7 +55,7 @@ func execute(cmd *Command, args []string, root bool) error {
|
||||||
// Calls command without args.
|
// Calls command without args.
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
if err := run(cmd, args[1:]); err != nil {
|
if err := run(cmd, args[1:]); err != nil {
|
||||||
return fmt.Errorf("command %s error: %v", args[0], err)
|
return fmt.Errorf("command %s error: %w", args[0], err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ func execute(cmd *Command, args []string, root bool) error {
|
||||||
// then we run the top level command itself.
|
// then we run the top level command itself.
|
||||||
if root && cmd.Name != args[1] && !contains(cmd.subCommands, args[1]) {
|
if root && cmd.Name != args[1] && !contains(cmd.subCommands, args[1]) {
|
||||||
if err := run(cmd, args[1:]); err != nil {
|
if err := run(cmd, args[1:]); err != nil {
|
||||||
return fmt.Errorf("command %s error: %v", filepath.Base(args[0]), err)
|
return fmt.Errorf("command %s error: %w", filepath.Base(args[0]), err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func execute(cmd *Command, args []string, root bool) error {
|
||||||
if len(args) >= 2 && cmd.Name == args[1] {
|
if len(args) >= 2 && cmd.Name == args[1] {
|
||||||
if len(args) < 3 || !contains(cmd.subCommands, args[2]) {
|
if len(args) < 3 || !contains(cmd.subCommands, args[2]) {
|
||||||
if err := run(cmd, args[2:]); err != nil {
|
if err := run(cmd, args[2:]); err != nil {
|
||||||
return fmt.Errorf("command %s error: %v", cmd.Name, err)
|
return fmt.Errorf("command %s error: %w", cmd.Name, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func execute(cmd *Command, args []string, root bool) error {
|
||||||
// No sub-command, calls the current command.
|
// No sub-command, calls the current command.
|
||||||
if len(cmd.subCommands) == 0 {
|
if len(cmd.subCommands) == 0 {
|
||||||
if err := run(cmd, args[1:]); err != nil {
|
if err := run(cmd, args[1:]); err != nil {
|
||||||
return fmt.Errorf("command %s error: %v", cmd.Name, err)
|
return fmt.Errorf("command %s error: %w", cmd.Name, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ func (e *EnvLoader) Load(_ []string, cmd *Command) (bool, error) {
|
||||||
|
|
||||||
if err := env.Decode(vars, env.DefaultNamePrefix, cmd.Configuration); err != nil {
|
if err := env.Decode(vars, env.DefaultNamePrefix, cmd.Configuration); err != nil {
|
||||||
log.WithoutContext().Debug("environment variables", strings.Join(vars, ", "))
|
log.WithoutContext().Debug("environment variables", strings.Join(vars, ", "))
|
||||||
return false, fmt.Errorf("failed to decode configuration from environment variables: %v ", err)
|
return false, fmt.Errorf("failed to decode configuration from environment variables: %w ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithoutContext().Println("Configuration loaded from environment variables.")
|
log.WithoutContext().Println("Configuration loaded from environment variables.")
|
||||||
|
|
|
@ -17,7 +17,7 @@ func (*FlagLoader) Load(args []string, cmd *Command) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := flag.Decode(args, cmd.Configuration); err != nil {
|
if err := flag.Decode(args, cmd.Configuration); err != nil {
|
||||||
return false, fmt.Errorf("failed to decode configuration from flags: %v", err)
|
return false, fmt.Errorf("failed to decode configuration from flags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithoutContext().Println("Configuration loaded from flags.")
|
log.WithoutContext().Println("Configuration loaded from flags.")
|
||||||
|
|
|
@ -16,10 +16,10 @@ import (
|
||||||
"github.com/mitchellh/hashstructure"
|
"github.com/mitchellh/hashstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// collectorURL URL where the stats are send
|
// collectorURL URL where the stats are send.
|
||||||
const collectorURL = "https://collect.traefik.io/9vxmmkcdmalbdi635d4jgc5p5rx0h7h8"
|
const collectorURL = "https://collect.traefik.io/9vxmmkcdmalbdi635d4jgc5p5rx0h7h8"
|
||||||
|
|
||||||
// Collected data
|
// Collected data.
|
||||||
type data struct {
|
type data struct {
|
||||||
Version string
|
Version string
|
||||||
Codename string
|
Codename string
|
||||||
|
|
|
@ -19,7 +19,7 @@ type Configurations map[string]*Configuration
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Configuration is the root of the dynamic configuration
|
// Configuration is the root of the dynamic configuration.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
HTTP *HTTPConfiguration `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
HTTP *HTTPConfiguration `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
||||||
TCP *TCPConfiguration `json:"tcp,omitempty" toml:"tcp,omitempty" yaml:"tcp,omitempty"`
|
TCP *TCPConfiguration `json:"tcp,omitempty" toml:"tcp,omitempty" yaml:"tcp,omitempty"`
|
||||||
|
|
|
@ -47,7 +47,7 @@ type Router struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// RouterTLSConfig holds the TLS configuration for a router
|
// RouterTLSConfig holds the TLS configuration for a router.
|
||||||
type RouterTLSConfig struct {
|
type RouterTLSConfig struct {
|
||||||
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||||
CertResolver string `json:"certResolver,omitempty" toml:"certResolver,omitempty" yaml:"certResolver,omitempty"`
|
CertResolver string `json:"certResolver,omitempty" toml:"certResolver,omitempty" yaml:"certResolver,omitempty"`
|
||||||
|
|
|
@ -95,7 +95,7 @@ type Buffering struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Chain holds a chain of middlewares
|
// Chain holds a chain of middlewares.
|
||||||
type Chain struct {
|
type Chain struct {
|
||||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -191,13 +191,13 @@ type Headers struct {
|
||||||
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty"`
|
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set
|
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set.
|
||||||
func (h *Headers) HasCustomHeadersDefined() bool {
|
func (h *Headers) HasCustomHeadersDefined() bool {
|
||||||
return h != nil && (len(h.CustomResponseHeaders) != 0 ||
|
return h != nil && (len(h.CustomResponseHeaders) != 0 ||
|
||||||
len(h.CustomRequestHeaders) != 0)
|
len(h.CustomRequestHeaders) != 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasCorsHeadersDefined checks to see if any of the cors header elements have been set
|
// HasCorsHeadersDefined checks to see if any of the cors header elements have been set.
|
||||||
func (h *Headers) HasCorsHeadersDefined() bool {
|
func (h *Headers) HasCorsHeadersDefined() bool {
|
||||||
return h != nil && (h.AccessControlAllowCredentials ||
|
return h != nil && (h.AccessControlAllowCredentials ||
|
||||||
len(h.AccessControlAllowHeaders) != 0 ||
|
len(h.AccessControlAllowHeaders) != 0 ||
|
||||||
|
@ -208,7 +208,7 @@ func (h *Headers) HasCorsHeadersDefined() bool {
|
||||||
h.AddVaryHeader)
|
h.AddVaryHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSecureHeadersDefined checks to see if any of the secure header elements have been set
|
// HasSecureHeadersDefined checks to see if any of the secure header elements have been set.
|
||||||
func (h *Headers) HasSecureHeadersDefined() bool {
|
func (h *Headers) HasSecureHeadersDefined() bool {
|
||||||
return h != nil && (len(h.AllowedHosts) != 0 ||
|
return h != nil && (len(h.AllowedHosts) != 0 ||
|
||||||
len(h.HostsProxyHeaders) != 0 ||
|
len(h.HostsProxyHeaders) != 0 ||
|
||||||
|
@ -245,7 +245,7 @@ type IPStrategy struct {
|
||||||
// Get an IP selection strategy.
|
// Get an IP selection strategy.
|
||||||
// If nil return the RemoteAddr strategy
|
// If nil return the RemoteAddr strategy
|
||||||
// else return a strategy base on the configuration using the X-Forwarded-For Header.
|
// else return a strategy base on the configuration using the X-Forwarded-For Header.
|
||||||
// Depth override the ExcludedIPs
|
// Depth override the ExcludedIPs.
|
||||||
func (s *IPStrategy) Get() (ip.Strategy, error) {
|
func (s *IPStrategy) Get() (ip.Strategy, error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return &ip.RemoteAddrStrategy{}, nil
|
return &ip.RemoteAddrStrategy{}, nil
|
||||||
|
@ -420,7 +420,7 @@ type TLSCLientCertificateDNInfo struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Users holds a list of users
|
// Users holds a list of users.
|
||||||
type Users []string
|
type Users []string
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -449,7 +449,7 @@ func (c *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
|
||||||
if _, errCA := os.Stat(c.CA); errCA == nil {
|
if _, errCA := os.Stat(c.CA); errCA == nil {
|
||||||
ca, err = ioutil.ReadFile(c.CA)
|
ca, err = ioutil.ReadFile(c.CA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read CA. %s", err)
|
return nil, fmt.Errorf("failed to read CA. %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ca = []byte(c.CA)
|
ca = []byte(c.CA)
|
||||||
|
@ -478,7 +478,7 @@ func (c *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
|
||||||
if errKeyIsFile == nil {
|
if errKeyIsFile == nil {
|
||||||
cert, err = tls.LoadX509KeyPair(c.Cert, c.Key)
|
cert, err = tls.LoadX509KeyPair(c.Cert, c.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load TLS keypair: %v", err)
|
return nil, fmt.Errorf("failed to load TLS keypair: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("tls cert is a file, but tls key is not")
|
return nil, fmt.Errorf("tls cert is a file, but tls key is not")
|
||||||
|
@ -487,7 +487,7 @@ func (c *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
|
||||||
if errKeyIsFile != nil {
|
if errKeyIsFile != nil {
|
||||||
cert, err = tls.X509KeyPair([]byte(c.Cert), []byte(c.Key))
|
cert, err = tls.X509KeyPair([]byte(c.Cert), []byte(c.Key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load TLS keypair: %v", err)
|
return nil, fmt.Errorf("failed to load TLS keypair: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("TLS key is a file, but tls cert is not")
|
return nil, fmt.Errorf("TLS key is a file, but tls cert is not")
|
||||||
|
|
|
@ -55,7 +55,7 @@ type TCPRouter struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// RouterTCPTLSConfig holds the TLS configuration for a router
|
// RouterTCPTLSConfig holds the TLS configuration for a router.
|
||||||
type RouterTCPTLSConfig struct {
|
type RouterTCPTLSConfig struct {
|
||||||
Passthrough bool `json:"passthrough" toml:"passthrough" yaml:"passthrough"`
|
Passthrough bool `json:"passthrough" toml:"passthrough" yaml:"passthrough"`
|
||||||
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||||
|
@ -76,7 +76,7 @@ type TCPServersLoadBalancer struct {
|
||||||
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults Default values for a TCPServersLoadBalancer
|
// SetDefaults Default values for a TCPServersLoadBalancer.
|
||||||
func (l *TCPServersLoadBalancer) SetDefaults() {
|
func (l *TCPServersLoadBalancer) SetDefaults() {
|
||||||
defaultTerminationDelay := 100 // in milliseconds
|
defaultTerminationDelay := 100 // in milliseconds
|
||||||
l.TerminationDelay = &defaultTerminationDelay
|
l.TerminationDelay = &defaultTerminationDelay
|
||||||
|
@ -101,7 +101,7 @@ func (l *TCPServersLoadBalancer) Mergeable(loadBalancer *TCPServersLoadBalancer)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// TCPServer holds a TCP Server configuration
|
// TCPServer holds a TCP Server configuration.
|
||||||
type TCPServer struct {
|
type TCPServer struct {
|
||||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
|
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
|
||||||
Port string `toml:"-" json:"-" yaml:"-"`
|
Port string `toml:"-" json:"-" yaml:"-"`
|
||||||
|
|
4
pkg/config/env/env.go
vendored
4
pkg/config/env/env.go
vendored
|
@ -17,7 +17,7 @@ const DefaultNamePrefix = "TRAEFIK_"
|
||||||
// env vars -> map
|
// env vars -> map
|
||||||
// map -> tree of untyped nodes
|
// map -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> typed element
|
// "typed" nodes -> typed element.
|
||||||
func Decode(environ []string, prefix string, element interface{}) error {
|
func Decode(environ []string, prefix string, element interface{}) error {
|
||||||
if err := checkPrefix(prefix); err != nil {
|
if err := checkPrefix(prefix); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -40,7 +40,7 @@ func Decode(environ []string, prefix string, element interface{}) error {
|
||||||
// The operation goes through three stages roughly summarized as:
|
// The operation goes through three stages roughly summarized as:
|
||||||
// typed configuration in element -> tree of untyped nodes
|
// typed configuration in element -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> environment variables with default values (determined by type/kind)
|
// "typed" nodes -> environment variables with default values (determined by type/kind).
|
||||||
func Encode(element interface{}) ([]parser.Flat, error) {
|
func Encode(element interface{}) ([]parser.Flat, error) {
|
||||||
if element == nil {
|
if element == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
// The operation goes through three stages roughly summarized as:
|
// The operation goes through three stages roughly summarized as:
|
||||||
// file contents -> tree of untyped nodes
|
// file contents -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> typed element
|
// "typed" nodes -> typed element.
|
||||||
func Decode(filePath string, element interface{}) error {
|
func Decode(filePath string, element interface{}) error {
|
||||||
if element == nil {
|
if element == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
// flag arguments -> parsed map of flags
|
// flag arguments -> parsed map of flags
|
||||||
// map -> tree of untyped nodes
|
// map -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> typed element
|
// "typed" nodes -> typed element.
|
||||||
func Decode(args []string, element interface{}) error {
|
func Decode(args []string, element interface{}) error {
|
||||||
ref, err := Parse(args, element)
|
ref, err := Parse(args, element)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,7 +24,7 @@ func Decode(args []string, element interface{}) error {
|
||||||
// The operation goes through three stages roughly summarized as:
|
// The operation goes through three stages roughly summarized as:
|
||||||
// typed configuration in element -> tree of untyped nodes
|
// typed configuration in element -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> flags with default values (determined by type/kind)
|
// "typed" nodes -> flags with default values (determined by type/kind).
|
||||||
func Encode(element interface{}) ([]parser.Flat, error) {
|
func Encode(element interface{}) ([]parser.Flat, error) {
|
||||||
if element == nil {
|
if element == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// The operation goes through three stages roughly summarized as:
|
// The operation goes through three stages roughly summarized as:
|
||||||
// KV pairs -> tree of untyped nodes
|
// KV pairs -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> typed element
|
// "typed" nodes -> typed element.
|
||||||
func Decode(pairs []*store.KVPair, element interface{}, rootName string) error {
|
func Decode(pairs []*store.KVPair, element interface{}, rootName string) error {
|
||||||
if element == nil {
|
if element == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -28,7 +28,7 @@ func EncodeConfiguration(conf *dynamic.Configuration) (map[string]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode converts the labels to an element.
|
// Decode converts the labels to an element.
|
||||||
// labels -> [ node -> node + metadata (type) ] -> element (node)
|
// labels -> [ node -> node + metadata (type) ] -> element (node).
|
||||||
func Decode(labels map[string]string, element interface{}, filters ...string) error {
|
func Decode(labels map[string]string, element interface{}, filters ...string) error {
|
||||||
return parser.Decode(labels, element, parser.DefaultRootName, filters...)
|
return parser.Decode(labels, element, parser.DefaultRootName, filters...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ type EncoderToNodeOpts struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeToNode converts an element to a node.
|
// EncodeToNode converts an element to a node.
|
||||||
// element -> nodes
|
// element -> nodes.
|
||||||
func EncodeToNode(element interface{}, rootName string, opts EncoderToNodeOpts) (*Node, error) {
|
func EncodeToNode(element interface{}, rootName string, opts EncoderToNodeOpts) (*Node, error) {
|
||||||
rValue := reflect.ValueOf(element)
|
rValue := reflect.ValueOf(element)
|
||||||
node := &Node{Name: rootName}
|
node := &Node{Name: rootName}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
// EncodeNode Converts a node to labels.
|
// EncodeNode Converts a node to labels.
|
||||||
// nodes -> labels
|
// nodes -> labels.
|
||||||
func EncodeNode(node *Node) map[string]string {
|
func EncodeNode(node *Node) map[string]string {
|
||||||
labels := make(map[string]string)
|
labels := make(map[string]string)
|
||||||
encodeNode(labels, node.Name, node)
|
encodeNode(labels, node.Name, node)
|
||||||
|
|
|
@ -6,7 +6,7 @@ package parser
|
||||||
// The operation goes through three stages roughly summarized as:
|
// The operation goes through three stages roughly summarized as:
|
||||||
// labels -> tree of untyped nodes
|
// labels -> tree of untyped nodes
|
||||||
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
// "typed" nodes -> typed element
|
// "typed" nodes -> typed element.
|
||||||
func Decode(labels map[string]string, element interface{}, rootName string, filters ...string) error {
|
func Decode(labels map[string]string, element interface{}, rootName string, filters ...string) error {
|
||||||
node, err := DecodeToNode(labels, rootName, filters...)
|
node, err := DecodeToNode(labels, rootName, filters...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,7 +28,7 @@ func Decode(labels map[string]string, element interface{}, rootName string, filt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode converts an element to labels.
|
// Encode converts an element to labels.
|
||||||
// element -> node (value) -> label (node)
|
// element -> node (value) -> label (node).
|
||||||
func Encode(element interface{}, rootName string) (map[string]string, error) {
|
func Encode(element interface{}, rootName string) (map[string]string, error) {
|
||||||
etnOpts := EncoderToNodeOpts{OmitEmpty: true, TagName: TagLabel, AllowSliceAsStruct: true}
|
etnOpts := EncoderToNodeOpts{OmitEmpty: true, TagName: TagLabel, AllowSliceAsStruct: true}
|
||||||
node, err := EncodeToNode(element, rootName, etnOpts)
|
node, err := EncodeToNode(element, rootName, etnOpts)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status of the router/service
|
// Status of the router/service.
|
||||||
const (
|
const (
|
||||||
StatusEnabled = "enabled"
|
StatusEnabled = "enabled"
|
||||||
StatusDisabled = "disabled"
|
StatusDisabled = "disabled"
|
||||||
|
|
|
@ -179,7 +179,7 @@ func (s *ServiceInfo) UpdateServerStatus(server string, status string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllStatus returns all the statuses of all the servers in ServiceInfo.
|
// GetAllStatus returns all the statuses of all the servers in ServiceInfo.
|
||||||
// It is the responsibility of the caller to check that s is not nil
|
// It is the responsibility of the caller to check that s is not nil.
|
||||||
func (s *ServiceInfo) GetAllStatus() map[string]string {
|
func (s *ServiceInfo) GetAllStatus() map[string]string {
|
||||||
s.serverStatusMu.RLock()
|
s.serverStatusMu.RLock()
|
||||||
defer s.serverStatusMu.RUnlock()
|
defer s.serverStatusMu.RUnlock()
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// all the Routers/Middlewares/Services are considered fully qualified
|
// all the Routers/Middlewares/Services are considered fully qualified.
|
||||||
func TestPopulateUsedBy(t *testing.T) {
|
func TestPopulateUsedBy(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
|
@ -49,7 +49,7 @@ const (
|
||||||
DefaultAcmeCAServer = "https://acme-v02.api.letsencrypt.org/directory"
|
DefaultAcmeCAServer = "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration is the static configuration
|
// Configuration is the static configuration.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
Global *Global `description:"Global configuration options" json:"global,omitempty" toml:"global,omitempty" yaml:"global,omitempty" export:"true"`
|
Global *Global `description:"Global configuration options" json:"global,omitempty" toml:"global,omitempty" yaml:"global,omitempty" export:"true"`
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ type Global struct {
|
||||||
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" export:"true"`
|
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServersTransport options to configure communication between Traefik and the servers
|
// ServersTransport options to configure communication between Traefik and the servers.
|
||||||
type ServersTransport struct {
|
type ServersTransport struct {
|
||||||
InsecureSkipVerify bool `description:"Disable SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
InsecureSkipVerify bool `description:"Disable SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
||||||
RootCAs []tls.FileOrContent `description:"Add cert file for self-signed certificate." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"`
|
RootCAs []tls.FileOrContent `description:"Add cert file for self-signed certificate." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"`
|
||||||
|
@ -89,7 +89,7 @@ type ServersTransport struct {
|
||||||
ForwardingTimeouts *ForwardingTimeouts `description:"Timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"`
|
ForwardingTimeouts *ForwardingTimeouts `description:"Timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// API holds the API configuration
|
// API holds the API configuration.
|
||||||
type API struct {
|
type API struct {
|
||||||
Insecure bool `description:"Activate API directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"`
|
Insecure bool `description:"Activate API directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"`
|
||||||
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
|
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
|
||||||
|
@ -158,7 +158,7 @@ func (t *Tracing) SetDefaults() {
|
||||||
t.SpanNameLimit = 0
|
t.SpanNameLimit = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Providers contains providers configuration
|
// Providers contains providers configuration.
|
||||||
type Providers struct {
|
type Providers struct {
|
||||||
ProvidersThrottleDuration types.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"`
|
ProvidersThrottleDuration types.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"`
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ func (c *Configuration) initACMEProvider() {
|
||||||
legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0)
|
legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateConfiguration validate that configuration is coherent
|
// ValidateConfiguration validate that configuration is coherent.
|
||||||
func (c *Configuration) ValidateConfiguration() error {
|
func (c *Configuration) ValidateConfiguration() error {
|
||||||
var acmeEmail string
|
var acmeEmail string
|
||||||
for name, resolver := range c.CertificatesResolvers {
|
for name, resolver := range c.CertificatesResolvers {
|
||||||
|
|
|
@ -25,8 +25,7 @@ const (
|
||||||
var singleton *HealthCheck
|
var singleton *HealthCheck
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
// Balancer is the set of operations required to manage the list of servers in a
|
// Balancer is the set of operations required to manage the list of servers in a load-balancer.
|
||||||
// load-balancer.
|
|
||||||
type Balancer interface {
|
type Balancer interface {
|
||||||
Servers() []*url.URL
|
Servers() []*url.URL
|
||||||
RemoveServer(u *url.URL) error
|
RemoveServer(u *url.URL) error
|
||||||
|
@ -39,8 +38,9 @@ type BalancerHandler interface {
|
||||||
Balancer
|
Balancer
|
||||||
}
|
}
|
||||||
|
|
||||||
// metricsRegistry is a local interface in the health check package, exposing only the required metrics
|
// metricsRegistry is a local interface in the health check package,
|
||||||
// necessary for the health check package. This makes it easier for the tests.
|
// exposing only the required metrics necessary for the health check package.
|
||||||
|
// This makes it easier for the tests.
|
||||||
type metricsRegistry interface {
|
type metricsRegistry interface {
|
||||||
BackendServerUpGauge() metrics.Gauge
|
BackendServerUpGauge() metrics.Gauge
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ type backendURL struct {
|
||||||
weight int
|
weight int
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendConfig HealthCheck configuration for a backend
|
// BackendConfig HealthCheck configuration for a backend.
|
||||||
type BackendConfig struct {
|
type BackendConfig struct {
|
||||||
Options
|
Options
|
||||||
name string
|
name string
|
||||||
|
@ -92,7 +92,7 @@ func (b *BackendConfig) newRequest(serverURL *url.URL) (*http.Request, error) {
|
||||||
return http.NewRequest(http.MethodGet, u.String(), http.NoBody)
|
return http.NewRequest(http.MethodGet, u.String(), http.NoBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function adds additional http headers and hostname to http.request
|
// this function adds additional http headers and hostname to http.request.
|
||||||
func (b *BackendConfig) addHeadersAndHost(req *http.Request) *http.Request {
|
func (b *BackendConfig) addHeadersAndHost(req *http.Request) *http.Request {
|
||||||
if b.Options.Hostname != "" {
|
if b.Options.Hostname != "" {
|
||||||
req.Host = b.Options.Hostname
|
req.Host = b.Options.Hostname
|
||||||
|
@ -104,14 +104,14 @@ func (b *BackendConfig) addHeadersAndHost(req *http.Request) *http.Request {
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthCheck struct
|
// HealthCheck struct.
|
||||||
type HealthCheck struct {
|
type HealthCheck struct {
|
||||||
Backends map[string]*BackendConfig
|
Backends map[string]*BackendConfig
|
||||||
metrics metricsRegistry
|
metrics metricsRegistry
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBackendsConfiguration set backends configuration
|
// SetBackendsConfiguration set backends configuration.
|
||||||
func (hc *HealthCheck) SetBackendsConfiguration(parentCtx context.Context, backends map[string]*BackendConfig) {
|
func (hc *HealthCheck) SetBackendsConfiguration(parentCtx context.Context, backends map[string]*BackendConfig) {
|
||||||
hc.Backends = backends
|
hc.Backends = backends
|
||||||
if hc.cancel != nil {
|
if hc.cancel != nil {
|
||||||
|
@ -152,28 +152,21 @@ func (hc *HealthCheck) checkBackend(ctx context.Context, backend *BackendConfig)
|
||||||
|
|
||||||
enabledURLs := backend.LB.Servers()
|
enabledURLs := backend.LB.Servers()
|
||||||
var newDisabledURLs []backendURL
|
var newDisabledURLs []backendURL
|
||||||
// FIXME re enable metrics
|
|
||||||
for _, disabledURL := range backend.disabledURLs {
|
for _, disabledURL := range backend.disabledURLs {
|
||||||
// FIXME serverUpMetricValue := float64(0)
|
|
||||||
if err := checkHealth(disabledURL.url, backend); err == nil {
|
if err := checkHealth(disabledURL.url, backend); err == nil {
|
||||||
logger.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d",
|
logger.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d",
|
||||||
backend.name, disabledURL.url.String(), disabledURL.weight)
|
backend.name, disabledURL.url.String(), disabledURL.weight)
|
||||||
if err = backend.LB.UpsertServer(disabledURL.url, roundrobin.Weight(disabledURL.weight)); err != nil {
|
if err = backend.LB.UpsertServer(disabledURL.url, roundrobin.Weight(disabledURL.weight)); err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
// FIXME serverUpMetricValue = 1
|
|
||||||
} else {
|
} else {
|
||||||
logger.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, disabledURL.url.String(), err)
|
logger.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, disabledURL.url.String(), err)
|
||||||
newDisabledURLs = append(newDisabledURLs, disabledURL)
|
newDisabledURLs = append(newDisabledURLs, disabledURL)
|
||||||
}
|
}
|
||||||
// FIXME labelValues := []string{"backend", backend.name, "url", backendurl.url.String()}
|
|
||||||
// FIXME hc.metrics.BackendServerUpGauge().With(labelValues...).Set(serverUpMetricValue)
|
|
||||||
}
|
}
|
||||||
backend.disabledURLs = newDisabledURLs
|
backend.disabledURLs = newDisabledURLs
|
||||||
|
|
||||||
// FIXME re enable metrics
|
|
||||||
for _, enableURL := range enabledURLs {
|
for _, enableURL := range enabledURLs {
|
||||||
// FIXME serverUpMetricValue := float64(1)
|
|
||||||
if err := checkHealth(enableURL, backend); err != nil {
|
if err := checkHealth(enableURL, backend); err != nil {
|
||||||
weight := 1
|
weight := 1
|
||||||
rr, ok := backend.LB.(*roundrobin.RoundRobin)
|
rr, ok := backend.LB.(*roundrobin.RoundRobin)
|
||||||
|
@ -189,35 +182,25 @@ func (hc *HealthCheck) checkBackend(ctx context.Context, backend *BackendConfig)
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
backend.disabledURLs = append(backend.disabledURLs, backendURL{enableURL, weight})
|
backend.disabledURLs = append(backend.disabledURLs, backendURL{enableURL, weight})
|
||||||
// FIXME serverUpMetricValue = 0
|
|
||||||
}
|
}
|
||||||
// FIXME labelValues := []string{"backend", backend.name, "url", enableURL.String()}
|
|
||||||
// FIXME hc.metrics.BackendServerUpGauge().With(labelValues...).Set(serverUpMetricValue)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME re add metrics
|
|
||||||
//func GetHealthCheck(metrics metricsRegistry) *HealthCheck {
|
|
||||||
|
|
||||||
// GetHealthCheck returns the health check which is guaranteed to be a singleton.
|
// GetHealthCheck returns the health check which is guaranteed to be a singleton.
|
||||||
func GetHealthCheck() *HealthCheck {
|
func GetHealthCheck() *HealthCheck {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
singleton = newHealthCheck()
|
singleton = newHealthCheck()
|
||||||
//singleton = newHealthCheck(metrics)
|
|
||||||
})
|
})
|
||||||
return singleton
|
return singleton
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME re add metrics
|
|
||||||
//func newHealthCheck(metrics metricsRegistry) *HealthCheck {
|
|
||||||
func newHealthCheck() *HealthCheck {
|
func newHealthCheck() *HealthCheck {
|
||||||
return &HealthCheck{
|
return &HealthCheck{
|
||||||
Backends: make(map[string]*BackendConfig),
|
Backends: make(map[string]*BackendConfig),
|
||||||
//metrics: metrics,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBackendConfig Instantiate a new BackendConfig
|
// NewBackendConfig Instantiate a new BackendConfig.
|
||||||
func NewBackendConfig(options Options, backendName string) *BackendConfig {
|
func NewBackendConfig(options Options, backendName string) *BackendConfig {
|
||||||
return &BackendConfig{
|
return &BackendConfig{
|
||||||
Options: options,
|
Options: options,
|
||||||
|
@ -230,7 +213,7 @@ func NewBackendConfig(options Options, backendName string) *BackendConfig {
|
||||||
func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
|
func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
|
||||||
req, err := backend.newRequest(serverURL)
|
req, err := backend.newRequest(serverURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create HTTP request: %s", err)
|
return fmt.Errorf("failed to create HTTP request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req = backend.addHeadersAndHost(req)
|
req = backend.addHeadersAndHost(req)
|
||||||
|
@ -248,7 +231,7 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("HTTP request failed: %s", err)
|
return fmt.Errorf("HTTP request failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
@ -260,7 +243,7 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLBStatusUpdater returns a new LbStatusUpdater
|
// NewLBStatusUpdater returns a new LbStatusUpdater.
|
||||||
func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo) *LbStatusUpdater {
|
func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo) *LbStatusUpdater {
|
||||||
return &LbStatusUpdater{
|
return &LbStatusUpdater{
|
||||||
BalancerHandler: bh,
|
BalancerHandler: bh,
|
||||||
|
@ -298,7 +281,7 @@ func (lb *LbStatusUpdater) UpsertServer(u *url.URL, options ...roundrobin.Server
|
||||||
// Balancers is a list of Balancers(s) that implements the Balancer interface.
|
// Balancers is a list of Balancers(s) that implements the Balancer interface.
|
||||||
type Balancers []Balancer
|
type Balancers []Balancer
|
||||||
|
|
||||||
// Servers returns the servers url from all the BalancerHandler
|
// Servers returns the servers url from all the BalancerHandler.
|
||||||
func (b Balancers) Servers() []*url.URL {
|
func (b Balancers) Servers() []*url.URL {
|
||||||
var servers []*url.URL
|
var servers []*url.URL
|
||||||
for _, lb := range b {
|
for _, lb := range b {
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Checker allows to check that addresses are in a trusted IPs
|
// Checker allows to check that addresses are in a trusted IPs.
|
||||||
type Checker struct {
|
type Checker struct {
|
||||||
authorizedIPs []*net.IP
|
authorizedIPs []*net.IP
|
||||||
authorizedIPsNet []*net.IPNet
|
authorizedIPsNet []*net.IPNet
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChecker builds a new Checker given a list of CIDR-Strings to trusted IPs
|
// NewChecker builds a new Checker given a list of CIDR-Strings to trusted IPs.
|
||||||
func NewChecker(trustedIPs []string) (*Checker, error) {
|
func NewChecker(trustedIPs []string) (*Checker, error) {
|
||||||
if len(trustedIPs) == 0 {
|
if len(trustedIPs) == 0 {
|
||||||
return nil, errors.New("no trusted IPs provided")
|
return nil, errors.New("no trusted IPs provided")
|
||||||
|
@ -27,7 +27,7 @@ func NewChecker(trustedIPs []string) (*Checker, error) {
|
||||||
} else {
|
} else {
|
||||||
_, ipAddr, err := net.ParseCIDR(ipMask)
|
_, ipAddr, err := net.ParseCIDR(ipMask)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsing CIDR trusted IPs %s: %v", ipAddr, err)
|
return nil, fmt.Errorf("parsing CIDR trusted IPs %s: %w", ipAddr, err)
|
||||||
}
|
}
|
||||||
checker.authorizedIPsNet = append(checker.authorizedIPsNet, ipAddr)
|
checker.authorizedIPsNet = append(checker.authorizedIPsNet, ipAddr)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func NewChecker(trustedIPs []string) (*Checker, error) {
|
||||||
return checker, nil
|
return checker, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAuthorized checks if provided request is authorized by the trusted IPs
|
// IsAuthorized checks if provided request is authorized by the trusted IPs.
|
||||||
func (ip *Checker) IsAuthorized(addr string) error {
|
func (ip *Checker) IsAuthorized(addr string) error {
|
||||||
var invalidMatches []string
|
var invalidMatches []string
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func (ip *Checker) IsAuthorized(addr string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains checks if provided address is in the trusted IPs
|
// Contains checks if provided address is in the trusted IPs.
|
||||||
func (ip *Checker) Contains(addr string) (bool, error) {
|
func (ip *Checker) Contains(addr string) (bool, error) {
|
||||||
if len(addr) == 0 {
|
if len(addr) == 0 {
|
||||||
return false, errors.New("empty IP address")
|
return false, errors.New("empty IP address")
|
||||||
|
@ -66,13 +66,13 @@ func (ip *Checker) Contains(addr string) (bool, error) {
|
||||||
|
|
||||||
ipAddr, err := parseIP(addr)
|
ipAddr, err := parseIP(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("unable to parse address: %s: %s", addr, err)
|
return false, fmt.Errorf("unable to parse address: %s: %w", addr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip.ContainsIP(ipAddr), nil
|
return ip.ContainsIP(ipAddr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainsIP checks if provided address is in the trusted IPs
|
// ContainsIP checks if provided address is in the trusted IPs.
|
||||||
func (ip *Checker) ContainsIP(addr net.IP) bool {
|
func (ip *Checker) ContainsIP(addr net.IP) bool {
|
||||||
for _, authorizedIP := range ip.authorizedIPs {
|
for _, authorizedIP := range ip.authorizedIPs {
|
||||||
if authorizedIP.Equal(addr) {
|
if authorizedIP.Equal(addr) {
|
||||||
|
|
|
@ -10,15 +10,15 @@ const (
|
||||||
xForwardedFor = "X-Forwarded-For"
|
xForwardedFor = "X-Forwarded-For"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Strategy a strategy for IP selection
|
// Strategy a strategy for IP selection.
|
||||||
type Strategy interface {
|
type Strategy interface {
|
||||||
GetIP(req *http.Request) string
|
GetIP(req *http.Request) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddrStrategy a strategy that always return the remote address
|
// RemoteAddrStrategy a strategy that always return the remote address.
|
||||||
type RemoteAddrStrategy struct{}
|
type RemoteAddrStrategy struct{}
|
||||||
|
|
||||||
// GetIP returns the selected IP
|
// GetIP returns the selected IP.
|
||||||
func (s *RemoteAddrStrategy) GetIP(req *http.Request) string {
|
func (s *RemoteAddrStrategy) GetIP(req *http.Request) string {
|
||||||
ip, _, err := net.SplitHostPort(req.RemoteAddr)
|
ip, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -27,12 +27,12 @@ func (s *RemoteAddrStrategy) GetIP(req *http.Request) string {
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
// DepthStrategy a strategy based on the depth inside the X-Forwarded-For from right to left
|
// DepthStrategy a strategy based on the depth inside the X-Forwarded-For from right to left.
|
||||||
type DepthStrategy struct {
|
type DepthStrategy struct {
|
||||||
Depth int
|
Depth int
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIP return the selected IP
|
// GetIP return the selected IP.
|
||||||
func (s *DepthStrategy) GetIP(req *http.Request) string {
|
func (s *DepthStrategy) GetIP(req *http.Request) string {
|
||||||
xff := req.Header.Get(xForwardedFor)
|
xff := req.Header.Get(xForwardedFor)
|
||||||
xffs := strings.Split(xff, ",")
|
xffs := strings.Split(xff, ",")
|
||||||
|
@ -44,12 +44,12 @@ func (s *DepthStrategy) GetIP(req *http.Request) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckerStrategy a strategy based on an IP Checker
|
// CheckerStrategy a strategy based on an IP Checker
|
||||||
// allows to check that addresses are in a trusted IPs
|
// allows to check that addresses are in a trusted IPs.
|
||||||
type CheckerStrategy struct {
|
type CheckerStrategy struct {
|
||||||
Checker *Checker
|
Checker *Checker
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIP return the selected IP
|
// GetIP return the selected IP.
|
||||||
func (s *CheckerStrategy) GetIP(req *http.Request) string {
|
func (s *CheckerStrategy) GetIP(req *http.Request) string {
|
||||||
if s.Checker == nil {
|
if s.Checker == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -80,7 +80,7 @@ func AddHook(hook logrus.Hook) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomWriterLevel logs writer for a specific level. (with a custom scanner buffer size.)
|
// CustomWriterLevel logs writer for a specific level. (with a custom scanner buffer size.)
|
||||||
// adapted from github.com/Sirupsen/logrus/writer.go
|
// adapted from github.com/Sirupsen/logrus/writer.go.
|
||||||
func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter {
|
func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract from github.com/Sirupsen/logrus/writer.go
|
// extract from github.com/Sirupsen/logrus/writer.go
|
||||||
// Hack the buffer size
|
// Hack the buffer size.
|
||||||
func writerScanner(reader io.ReadCloser, scanTokenSize int, printFunc func(args ...interface{})) {
|
func writerScanner(reader io.ReadCloser, scanTokenSize int, printFunc func(args ...interface{})) {
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package log
|
package log
|
||||||
|
|
||||||
// Log entry name
|
// Log entry names.
|
||||||
const (
|
const (
|
||||||
EntryPointName = "entryPointName"
|
EntryPointName = "entryPointName"
|
||||||
RouterName = "routerName"
|
RouterName = "routerName"
|
||||||
|
|
|
@ -15,7 +15,7 @@ const (
|
||||||
loggerKey contextKey = iota
|
loggerKey contextKey = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logger the Traefik logger
|
// Logger the Traefik logger.
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
logrus.FieldLogger
|
logrus.FieldLogger
|
||||||
WriterLevel(logrus.Level) *io.PipeWriter
|
WriterLevel(logrus.Level) *io.PipeWriter
|
||||||
|
@ -57,14 +57,14 @@ func GetLevel() logrus.Level {
|
||||||
return logrus.GetLevel()
|
return logrus.GetLevel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Str adds a string field
|
// Str adds a string field.
|
||||||
func Str(key, value string) func(logrus.Fields) {
|
func Str(key, value string) func(logrus.Fields) {
|
||||||
return func(fields logrus.Fields) {
|
return func(fields logrus.Fields) {
|
||||||
fields[key] = value
|
fields[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// With Adds fields
|
// With Adds fields.
|
||||||
func With(ctx context.Context, opts ...func(logrus.Fields)) context.Context {
|
func With(ctx context.Context, opts ...func(logrus.Fields)) context.Context {
|
||||||
logger := FromContext(ctx)
|
logger := FromContext(ctx)
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ func With(ctx context.Context, opts ...func(logrus.Fields)) context.Context {
|
||||||
return context.WithValue(ctx, loggerKey, logger)
|
return context.WithValue(ctx, loggerKey, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromContext Gets the logger from context
|
// FromContext Gets the logger from context.
|
||||||
func FromContext(ctx context.Context) Logger {
|
func FromContext(ctx context.Context) Logger {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
panic("nil context")
|
panic("nil context")
|
||||||
|
@ -91,12 +91,12 @@ func FromContext(ctx context.Context) Logger {
|
||||||
return logger
|
return logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithoutContext Gets the main logger
|
// WithoutContext Gets the main logger.
|
||||||
func WithoutContext() Logger {
|
func WithoutContext() Logger {
|
||||||
return mainLogger
|
return mainLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile opens the log file using the specified path
|
// OpenFile opens the log file using the specified path.
|
||||||
func OpenFile(path string) error {
|
func OpenFile(path string) error {
|
||||||
logFilePath = path
|
logFilePath = path
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ func OpenFile(path string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseFile closes the log and sets the Output to stdout
|
// CloseFile closes the log and sets the Output to stdout.
|
||||||
func CloseFile() error {
|
func CloseFile() error {
|
||||||
logrus.SetOutput(os.Stdout)
|
logrus.SetOutput(os.Stdout)
|
||||||
|
|
||||||
|
@ -120,9 +120,8 @@ func CloseFile() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RotateFile closes and reopens the log file to allow for rotation
|
// RotateFile closes and reopens the log file to allow for rotation by an external source.
|
||||||
// by an external source. If the log isn't backed by a file then
|
// If the log isn't backed by a file then it does nothing.
|
||||||
// it does nothing.
|
|
||||||
func RotateFile() error {
|
func RotateFile() error {
|
||||||
logger := FromContext(context.Background())
|
logger := FromContext(context.Background())
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry {
|
||||||
return registry
|
return registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// initInfluxDBTicker creates a influxDBClient
|
// initInfluxDBTicker creates a influxDBClient.
|
||||||
func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Influx {
|
func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Influx {
|
||||||
logger := log.FromContext(ctx)
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Inf
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// initInfluxDBTicker initializes metrics pusher
|
// initInfluxDBTicker initializes metrics pusher.
|
||||||
func initInfluxDBTicker(ctx context.Context, config *types.InfluxDB) *time.Ticker {
|
func initInfluxDBTicker(ctx context.Context, config *types.InfluxDB) *time.Ticker {
|
||||||
report := time.NewTicker(time.Duration(config.PushInterval))
|
report := time.NewTicker(time.Duration(config.PushInterval))
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func initInfluxDBTicker(ctx context.Context, config *types.InfluxDB) *time.Ticke
|
||||||
return report
|
return report
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopInfluxDB stops internal influxDBTicker which controls the pushing of metrics to InfluxDB Agent and resets it to `nil`
|
// StopInfluxDB stops internal influxDBTicker which controls the pushing of metrics to InfluxDB Agent and resets it to `nil`.
|
||||||
func StopInfluxDB() {
|
func StopInfluxDB() {
|
||||||
if influxDBTicker != nil {
|
if influxDBTicker != nil {
|
||||||
influxDBTicker.Stop()
|
influxDBTicker.Stop()
|
||||||
|
|
|
@ -71,7 +71,7 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
|
||||||
return registry
|
return registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// initStatsdTicker initializes metrics pusher and creates a statsdClient if not created already
|
// initStatsdTicker initializes metrics pusher and creates a statsdClient if not created already.
|
||||||
func initStatsdTicker(ctx context.Context, config *types.Statsd) *time.Ticker {
|
func initStatsdTicker(ctx context.Context, config *types.Statsd) *time.Ticker {
|
||||||
address := config.Address
|
address := config.Address
|
||||||
if len(address) == 0 {
|
if len(address) == 0 {
|
||||||
|
@ -87,7 +87,7 @@ func initStatsdTicker(ctx context.Context, config *types.Statsd) *time.Ticker {
|
||||||
return report
|
return report
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopStatsd stops internal statsdTicker which controls the pushing of metrics to StatsD Agent and resets it to `nil`
|
// StopStatsd stops internal statsdTicker which controls the pushing of metrics to StatsD Agent and resets it to `nil`.
|
||||||
func StopStatsd() {
|
func StopStatsd() {
|
||||||
if statsdTicker != nil {
|
if statsdTicker != nil {
|
||||||
statsdTicker.Stop()
|
statsdTicker.Stop()
|
||||||
|
|
|
@ -28,7 +28,7 @@ func newCaptureResponseWriter(rw http.ResponseWriter) capturer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// captureResponseWriter is a wrapper of type http.ResponseWriter
|
// captureResponseWriter is a wrapper of type http.ResponseWriter
|
||||||
// that tracks request status and size
|
// that tracks request status and size.
|
||||||
type captureResponseWriter struct {
|
type captureResponseWriter struct {
|
||||||
rw http.ResponseWriter
|
rw http.ResponseWriter
|
||||||
status int
|
status int
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/vulcand/oxy/utils"
|
"github.com/vulcand/oxy/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FieldApply function hook to add data in accesslog
|
// FieldApply function hook to add data in accesslog.
|
||||||
type FieldApply func(rw http.ResponseWriter, r *http.Request, next http.Handler, data *LogData)
|
type FieldApply func(rw http.ResponseWriter, r *http.Request, next http.Handler, data *LogData)
|
||||||
|
|
||||||
// FieldHandler sends a new field to the logger.
|
// FieldHandler sends a new field to the logger.
|
||||||
|
@ -39,7 +39,7 @@ func (f *FieldHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddServiceFields add service fields
|
// AddServiceFields add service fields.
|
||||||
func AddServiceFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
func AddServiceFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
||||||
data.Core[ServiceURL] = req.URL // note that this is *not* the original incoming URL
|
data.Core[ServiceURL] = req.URL // note that this is *not* the original incoming URL
|
||||||
data.Core[ServiceAddr] = req.URL.Host
|
data.Core[ServiceAddr] = req.URL.Host
|
||||||
|
@ -47,7 +47,7 @@ func AddServiceFields(rw http.ResponseWriter, req *http.Request, next http.Handl
|
||||||
next.ServeHTTP(rw, req)
|
next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOriginFields add origin fields
|
// AddOriginFields add origin fields.
|
||||||
func AddOriginFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
func AddOriginFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
||||||
crw := newCaptureResponseWriter(rw)
|
crw := newCaptureResponseWriter(rw)
|
||||||
start := time.Now().UTC()
|
start := time.Now().UTC()
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewHandler(config *types.AccessLog) (*Handler, error) {
|
||||||
if len(config.FilePath) > 0 {
|
if len(config.FilePath) > 0 {
|
||||||
f, err := openAccessLogFile(config.FilePath)
|
f, err := openAccessLogFile(config.FilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error opening access log file: %s", err)
|
return nil, fmt.Errorf("error opening access log file: %w", err)
|
||||||
}
|
}
|
||||||
file = f
|
file = f
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,12 @@ func openAccessLogFile(filePath string) (*os.File, error) {
|
||||||
dir := filepath.Dir(filePath)
|
dir := filepath.Dir(filePath)
|
||||||
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create log path %s: %s", dir, err)
|
return nil, fmt.Errorf("failed to create log path %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)
|
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error opening file %s: %s", filePath, err)
|
return nil, fmt.Errorf("error opening file %s: %w", filePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, nil
|
return file, nil
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseAccessLog parse line of access log and return a map with each fields
|
// ParseAccessLog parse line of access log and return a map with each fields.
|
||||||
func ParseAccessLog(data string) (map[string]string, error) {
|
func ParseAccessLog(data string) (map[string]string, error) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
buffer.WriteString(`(\S+)`) // 1 - ClientHost
|
buffer.WriteString(`(\S+)`) // 1 - ClientHost
|
||||||
|
|
|
@ -20,7 +20,7 @@ const (
|
||||||
wwwAuthenticate = "Www-Authenticate"
|
wwwAuthenticate = "Www-Authenticate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DigestRequest is a client for digest authentication requests
|
// DigestRequest is a client for digest authentication requests.
|
||||||
type digestRequest struct {
|
type digestRequest struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
username, password string
|
username, password string
|
||||||
|
@ -35,7 +35,7 @@ func (nc nonceCount) String() string {
|
||||||
|
|
||||||
var wanted = []string{algorithm, nonce, opaque, qop, realm}
|
var wanted = []string{algorithm, nonce, opaque, qop, realm}
|
||||||
|
|
||||||
// New makes a DigestRequest instance
|
// New makes a DigestRequest instance.
|
||||||
func newDigestRequest(username, password string, client *http.Client) *digestRequest {
|
func newDigestRequest(username, password string, client *http.Client) *digestRequest {
|
||||||
return &digestRequest{
|
return &digestRequest{
|
||||||
client: client,
|
client: client,
|
||||||
|
@ -44,7 +44,7 @@ func newDigestRequest(username, password string, client *http.Client) *digestReq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do does requests as http.Do does
|
// Do does requests as http.Do does.
|
||||||
func (r *digestRequest) Do(req *http.Request) (*http.Response, error) {
|
func (r *digestRequest) Do(req *http.Request) (*http.Response, error) {
|
||||||
parts, err := r.makeParts(req)
|
parts, err := r.makeParts(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -133,7 +133,7 @@ func (r *digestRequest) makeAuthorization(req *http.Request, parts map[string]st
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRandom generates random string
|
// GenerateRandom generates random string.
|
||||||
func generateRandom(n int) string {
|
func generateRandom(n int) string {
|
||||||
b := make([]byte, 8)
|
b := make([]byte, 8)
|
||||||
_, _ = io.ReadFull(rand.Reader, b)
|
_, _ = io.ReadFull(rand.Reader, b)
|
||||||
|
|
|
@ -18,7 +18,7 @@ type chainBuilder interface {
|
||||||
BuildChain(ctx context.Context, middlewares []string) *alice.Chain
|
BuildChain(ctx context.Context, middlewares []string) *alice.Chain
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a chain middleware
|
// New creates a chain middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.Chain, builder chainBuilder, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.Chain, builder chainBuilder, name string) (http.Handler, error) {
|
||||||
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCircuitBreakerOptions returns a new CircuitBreakerOption
|
// NewCircuitBreakerOptions returns a new CircuitBreakerOption.
|
||||||
func createCircuitBreakerOptions(expression string) cbreaker.CircuitBreakerOption {
|
func createCircuitBreakerOptions(expression string) cbreaker.CircuitBreakerOption {
|
||||||
return cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
return cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression)
|
tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression)
|
||||||
|
|
|
@ -131,12 +131,12 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
func newRequest(baseURL string) (*http.Request, error) {
|
func newRequest(baseURL string) (*http.Request, error) {
|
||||||
u, err := url.Parse(baseURL)
|
u, err := url.Parse(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error pages: error when parse URL: %v", err)
|
return nil, fmt.Errorf("error pages: error when parse URL: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error pages: error when create query: %v", err)
|
return nil, fmt.Errorf("error pages: error when create query: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.RequestURI = u.RequestURI()
|
req.RequestURI = u.RequestURI()
|
||||||
|
@ -250,7 +250,7 @@ func (cc *codeCatcher) WriteHeader(code int) {
|
||||||
cc.headersSent = true
|
cc.headersSent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack hijacks the connection
|
// Hijack hijacks the connection.
|
||||||
func (cc *codeCatcher) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (cc *codeCatcher) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
if hj, ok := cc.responseWriter.(http.Hijacker); ok {
|
if hj, ok := cc.responseWriter.(http.Hijacker); ok {
|
||||||
return hj.Hijack()
|
return hj.Hijack()
|
||||||
|
@ -349,7 +349,7 @@ func (r *responseRecorderWithoutCloseNotify) WriteHeader(code int) {
|
||||||
r.Code = code
|
r.Code = code
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack hijacks the connection
|
// Hijack hijacks the connection.
|
||||||
func (r *responseRecorderWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (r *responseRecorderWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return r.responseWriter.(http.Hijacker).Hijack()
|
return r.responseWriter.(http.Hijacker).Hijack()
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,10 @@ var xHeaders = []string{
|
||||||
xRealIP,
|
xRealIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
// XForwarded is an HTTP handler wrapper that sets the X-Forwarded headers, and other relevant headers for a
|
// XForwarded is an HTTP handler wrapper that sets the X-Forwarded headers,
|
||||||
// reverse-proxy. Unless insecure is set, it first removes all the existing values for those headers if the remote
|
// and other relevant headers for a reverse-proxy.
|
||||||
// address is not one of the trusted ones.
|
// Unless insecure is set,
|
||||||
|
// it first removes all the existing values for those headers if the remote address is not one of the trusted ones.
|
||||||
type XForwarded struct {
|
type XForwarded struct {
|
||||||
insecure bool
|
insecure bool
|
||||||
trustedIps []string
|
trustedIps []string
|
||||||
|
@ -80,15 +81,13 @@ func (x *XForwarded) isTrustedIP(ip string) bool {
|
||||||
return x.ipChecker.IsAuthorized(ip) == nil
|
return x.ipChecker.IsAuthorized(ip) == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has
|
// removeIPv6Zone removes the zone if the given IP is an ipv6 address and it has {zone} information in it,
|
||||||
// {zone} information in it, like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3
|
// like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692".
|
||||||
// Ethernet Adapter - Virtual Switch)]:64692"
|
|
||||||
func removeIPv6Zone(clientIP string) string {
|
func removeIPv6Zone(clientIP string) string {
|
||||||
return strings.Split(clientIP, "%")[0]
|
return strings.Split(clientIP, "%")[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// isWebsocketRequest returns whether the specified HTTP request is a
|
// isWebsocketRequest returns whether the specified HTTP request is a websocket handshake request.
|
||||||
// websocket handshake request
|
|
||||||
func isWebsocketRequest(req *http.Request) bool {
|
func isWebsocketRequest(req *http.Request) bool {
|
||||||
containsHeader := func(name, value string) bool {
|
containsHeader := func(name, value string) bool {
|
||||||
items := strings.Split(req.Header.Get(name), ",")
|
items := strings.Split(req.Header.Get(name), ",")
|
||||||
|
@ -161,7 +160,7 @@ func (x *XForwarded) rewrite(outreq *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP implements http.Handler
|
// ServeHTTP implements http.Handler.
|
||||||
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (x *XForwarded) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
|
if !x.insecure && !x.isTrustedIP(r.RemoteAddr) {
|
||||||
for _, h := range xHeaders {
|
for _, h := range xHeaders {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import (
|
||||||
"github.com/containous/traefik/v2/pkg/safe"
|
"github.com/containous/traefik/v2/pkg/safe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPHandlerSwitcher allows hot switching of http.ServeMux
|
// HTTPHandlerSwitcher allows hot switching of http.ServeMux.
|
||||||
type HTTPHandlerSwitcher struct {
|
type HTTPHandlerSwitcher struct {
|
||||||
handler *safe.Safe
|
handler *safe.Safe
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandlerSwitcher builds a new instance of HTTPHandlerSwitcher
|
// NewHandlerSwitcher builds a new instance of HTTPHandlerSwitcher.
|
||||||
func NewHandlerSwitcher(newHandler http.Handler) (hs *HTTPHandlerSwitcher) {
|
func NewHandlerSwitcher(newHandler http.Handler) (hs *HTTPHandlerSwitcher) {
|
||||||
return &HTTPHandlerSwitcher{
|
return &HTTPHandlerSwitcher{
|
||||||
handler: safe.New(newHandler),
|
handler: safe.New(newHandler),
|
||||||
|
@ -23,13 +23,13 @@ func (h *HTTPHandlerSwitcher) ServeHTTP(rw http.ResponseWriter, req *http.Reques
|
||||||
handlerBackup.ServeHTTP(rw, req)
|
handlerBackup.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHandler returns the current http.ServeMux
|
// GetHandler returns the current http.ServeMux.
|
||||||
func (h *HTTPHandlerSwitcher) GetHandler() (newHandler http.Handler) {
|
func (h *HTTPHandlerSwitcher) GetHandler() (newHandler http.Handler) {
|
||||||
handler := h.handler.Get().(http.Handler)
|
handler := h.handler.Get().(http.Handler)
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateHandler safely updates the current http.ServeMux with a new one
|
// UpdateHandler safely updates the current http.ServeMux with a new one.
|
||||||
func (h *HTTPHandlerSwitcher) UpdateHandler(newHandler http.Handler) {
|
func (h *HTTPHandlerSwitcher) UpdateHandler(newHandler http.Handler) {
|
||||||
h.handler.Set(newHandler)
|
h.handler.Set(newHandler)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,12 @@ func New(ctx context.Context, next http.Handler, config dynamic.InFlightReq, nam
|
||||||
|
|
||||||
sourceMatcher, err := middlewares.GetSourceExtractor(ctxLog, config.SourceCriterion)
|
sourceMatcher, err := middlewares.GetSourceExtractor(ctxLog, config.SourceCriterion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating requests limiter: %v", err)
|
return nil, fmt.Errorf("error creating requests limiter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
handler, err := connlimit.New(next, sourceMatcher, config.Amount)
|
handler, err := connlimit.New(next, sourceMatcher, config.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating connection limit: %v", err)
|
return nil, fmt.Errorf("error creating connection limit: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &inFlightReq{handler: handler, name: name}, nil
|
return &inFlightReq{handler: handler, name: name}, nil
|
||||||
|
|
|
@ -18,7 +18,7 @@ const (
|
||||||
typeName = "IPWhiteLister"
|
typeName = "IPWhiteLister"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ipWhiteLister is a middleware that provides Checks of the Requesting IP against a set of Whitelists
|
// ipWhiteLister is a middleware that provides Checks of the Requesting IP against a set of Whitelists.
|
||||||
type ipWhiteLister struct {
|
type ipWhiteLister struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
whiteLister *ip.Checker
|
whiteLister *ip.Checker
|
||||||
|
@ -26,7 +26,7 @@ type ipWhiteLister struct {
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New builds a new IPWhiteLister given a list of CIDR-Strings to whitelist
|
// New builds a new IPWhiteLister given a list of CIDR-Strings to whitelist.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, name string) (http.Handler, error) {
|
||||||
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
|
@ -37,7 +37,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, nam
|
||||||
|
|
||||||
checker, err := ip.NewChecker(config.SourceRange)
|
checker, err := ip.NewChecker(config.SourceRange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot parse CIDR whitelist %s: %v", config.SourceRange, err)
|
return nil, fmt.Errorf("cannot parse CIDR whitelist %s: %w", config.SourceRange, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy, err := config.IPStrategy.Get()
|
strategy, err := config.IPStrategy.Get()
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (r *responseRecorder) WriteHeader(status int) {
|
||||||
r.statusCode = status
|
r.statusCode = status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack hijacks the connection
|
// Hijack hijacks the connection.
|
||||||
func (r *responseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (r *responseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return r.ResponseWriter.(http.Hijacker).Hijack()
|
return r.ResponseWriter.(http.Hijacker).Hijack()
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||||
// - the `,` is used to separate certificates
|
// - the `,` is used to separate certificates
|
||||||
// - the `;` is used to separate root fields
|
// - the `;` is used to separate root fields
|
||||||
// - the value of root fields is always wrapped by double quote
|
// - the value of root fields is always wrapped by double quote
|
||||||
// - if a field is empty, the field is ignored
|
// - if a field is empty, the field is ignored.
|
||||||
func (p *passTLSClientCert) getCertInfo(ctx context.Context, certs []*x509.Certificate) string {
|
func (p *passTLSClientCert) getCertInfo(ctx context.Context, certs []*x509.Certificate) string {
|
||||||
var headerValues []string
|
var headerValues []string
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,12 @@ const (
|
||||||
typeName = "Pipelining"
|
typeName = "Pipelining"
|
||||||
)
|
)
|
||||||
|
|
||||||
// pipelining returns a middleware
|
// pipelining returns a middleware.
|
||||||
type pipelining struct {
|
type pipelining struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new pipelining instance
|
// New returns a new pipelining instance.
|
||||||
func New(ctx context.Context, next http.Handler, name string) http.Handler {
|
func New(ctx context.Context, next http.Handler, name string) http.Handler {
|
||||||
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func (p *pipelining) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writerWithoutCloseNotify helps to disable closeNotify
|
// writerWithoutCloseNotify helps to disable closeNotify.
|
||||||
type writerWithoutCloseNotify struct {
|
type writerWithoutCloseNotify struct {
|
||||||
W http.ResponseWriter
|
W http.ResponseWriter
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,7 @@ func (w *writerWithoutCloseNotify) Write(buf []byte) (int, error) {
|
||||||
return w.W.Write(buf)
|
return w.W.Write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteHeader sends an HTTP response header with the provided
|
// WriteHeader sends an HTTP response header with the provided status code.
|
||||||
// status code.
|
|
||||||
func (w *writerWithoutCloseNotify) WriteHeader(code int) {
|
func (w *writerWithoutCloseNotify) WriteHeader(code int) {
|
||||||
w.W.WriteHeader(code)
|
w.W.WriteHeader(code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.ReplacePathRegex
|
||||||
|
|
||||||
exp, err := regexp.Compile(strings.TrimSpace(config.Regex))
|
exp, err := regexp.Compile(strings.TrimSpace(config.Regex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error compiling regular expression %s: %s", config.Regex, err)
|
return nil, fmt.Errorf("error compiling regular expression %s: %w", config.Regex, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &replacePathRegex{
|
return &replacePathRegex{
|
||||||
|
|
|
@ -105,7 +105,7 @@ func cnameResolve(ctx context.Context, host string, resolvPath string) (*cnameRe
|
||||||
func getRecord(client *dns.Client, msg *dns.Msg, server string, port string) (*cnameResolv, error) {
|
func getRecord(client *dns.Client, msg *dns.Msg, server string, port string) (*cnameResolv, error) {
|
||||||
resp, _, err := client.Exchange(msg, net.JoinHostPort(server, port))
|
resp, _, err := client.Exchange(msg, net.JoinHostPort(server, port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("exchange error for server %s: %v", server, err)
|
return nil, fmt.Errorf("exchange error for server %s: %w", server, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp == nil || len(resp.Answer) == 0 {
|
if resp == nil || len(resp.Answer) == 0 {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package middlewares
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
// Stateful interface groups all http interfaces that must be
|
// Stateful interface groups all http interfaces that must be
|
||||||
// implemented by a stateful middleware (ie: recorders)
|
// implemented by a stateful middleware (ie: recorders).
|
||||||
type Stateful interface {
|
type Stateful interface {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
http.Hijacker
|
http.Hijacker
|
||||||
|
|
|
@ -27,12 +27,12 @@ func (n MockTracer) Extract(format interface{}, carrier interface{}) (opentracin
|
||||||
return nil, opentracing.ErrSpanContextNotFound
|
return nil, opentracing.ErrSpanContextNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockSpanContext
|
// MockSpanContext.
|
||||||
type MockSpanContext struct{}
|
type MockSpanContext struct{}
|
||||||
|
|
||||||
func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
|
func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
|
||||||
|
|
||||||
// MockSpan
|
// MockSpan.
|
||||||
type MockSpan struct {
|
type MockSpan struct {
|
||||||
OpName string
|
OpName string
|
||||||
Tags map[string]interface{}
|
Tags map[string]interface{}
|
||||||
|
|
|
@ -22,12 +22,12 @@ func (s *statusCodeWithoutCloseNotify) WriteHeader(status int) {
|
||||||
s.ResponseWriter.WriteHeader(status)
|
s.ResponseWriter.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status get response status
|
// Status get response status.
|
||||||
func (s *statusCodeWithoutCloseNotify) Status() int {
|
func (s *statusCodeWithoutCloseNotify) Status() int {
|
||||||
return s.status
|
return s.status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack hijacks the connection
|
// Hijack hijacks the connection.
|
||||||
func (s *statusCodeWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (s *statusCodeWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return s.ResponseWriter.(http.Hijacker).Hijack()
|
return s.ResponseWriter.(http.Hijacker).Hijack()
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ func Wrap(ctx context.Context, constructor alice.Constructor) alice.Constructor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWrapper returns a http.Handler struct
|
// NewWrapper returns a http.Handler struct.
|
||||||
func NewWrapper(next http.Handler, name string, spanKind ext.SpanKindEnum) http.Handler {
|
func NewWrapper(next http.Handler, name string, spanKind ext.SpanKindEnum) http.Handler {
|
||||||
return &Wrapper{
|
return &Wrapper{
|
||||||
next: next,
|
next: next,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"github.com/go-acme/lego/v3/registration"
|
"github.com/go-acme/lego/v3/registration"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Account is used to store lets encrypt registration info
|
// Account is used to store lets encrypt registration info.
|
||||||
type Account struct {
|
type Account struct {
|
||||||
Email string
|
Email string
|
||||||
Registration *registration.Resource
|
Registration *registration.Resource
|
||||||
|
@ -21,11 +21,11 @@ type Account struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RegistrationURLPathV1Regexp is a regexp which match ACME registration URL in the V1 format
|
// RegistrationURLPathV1Regexp is a regexp which match ACME registration URL in the V1 format.
|
||||||
RegistrationURLPathV1Regexp = `^.*/acme/reg/\d+$`
|
RegistrationURLPathV1Regexp = `^.*/acme/reg/\d+$`
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAccount creates an account
|
// NewAccount creates an account.
|
||||||
func NewAccount(ctx context.Context, email string, keyTypeValue string) (*Account, error) {
|
func NewAccount(ctx context.Context, email string, keyTypeValue string) (*Account, error) {
|
||||||
keyType := GetKeyType(ctx, keyTypeValue)
|
keyType := GetKeyType(ctx, keyTypeValue)
|
||||||
|
|
||||||
|
@ -42,17 +42,17 @@ func NewAccount(ctx context.Context, email string, keyTypeValue string) (*Accoun
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEmail returns email
|
// GetEmail returns email.
|
||||||
func (a *Account) GetEmail() string {
|
func (a *Account) GetEmail() string {
|
||||||
return a.Email
|
return a.Email
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRegistration returns lets encrypt registration resource
|
// GetRegistration returns lets encrypt registration resource.
|
||||||
func (a *Account) GetRegistration() *registration.Resource {
|
func (a *Account) GetRegistration() *registration.Resource {
|
||||||
return a.Registration
|
return a.Registration
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrivateKey returns private key
|
// GetPrivateKey returns private key.
|
||||||
func (a *Account) GetPrivateKey() crypto.PrivateKey {
|
func (a *Account) GetPrivateKey() crypto.PrivateKey {
|
||||||
privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey)
|
privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -64,7 +64,7 @@ func (a *Account) GetPrivateKey() crypto.PrivateKey {
|
||||||
return privateKey
|
return privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKeyType used to determine which algo to used
|
// GetKeyType used to determine which algo to used.
|
||||||
func GetKeyType(ctx context.Context, value string) certcrypto.KeyType {
|
func GetKeyType(ctx context.Context, value string) certcrypto.KeyType {
|
||||||
logger := log.FromContext(ctx)
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
var _ Store = (*LocalStore)(nil)
|
var _ Store = (*LocalStore)(nil)
|
||||||
|
|
||||||
// LocalStore Stores implementation for local file
|
// LocalStore Stores implementation for local file.
|
||||||
type LocalStore struct {
|
type LocalStore struct {
|
||||||
saveDataChan chan map[string]*StoredData
|
saveDataChan chan map[string]*StoredData
|
||||||
filename string
|
filename string
|
||||||
|
@ -22,7 +22,7 @@ type LocalStore struct {
|
||||||
storedData map[string]*StoredData
|
storedData map[string]*StoredData
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalStore initializes a new LocalStore with a file name
|
// NewLocalStore initializes a new LocalStore with a file name.
|
||||||
func NewLocalStore(filename string) *LocalStore {
|
func NewLocalStore(filename string) *LocalStore {
|
||||||
store := &LocalStore{filename: filename, saveDataChan: make(chan map[string]*StoredData)}
|
store := &LocalStore{filename: filename, saveDataChan: make(chan map[string]*StoredData)}
|
||||||
store.listenSaveAction()
|
store.listenSaveAction()
|
||||||
|
@ -93,7 +93,7 @@ func (s *LocalStore) get(resolverName string) (*StoredData, error) {
|
||||||
return s.storedData[resolverName], nil
|
return s.storedData[resolverName], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// listenSaveAction listens to a chan to store ACME data in json format into LocalStore.filename
|
// listenSaveAction listens to a chan to store ACME data in json format into `LocalStore.filename`.
|
||||||
func (s *LocalStore) listenSaveAction() {
|
func (s *LocalStore) listenSaveAction() {
|
||||||
safe.Go(func() {
|
safe.Go(func() {
|
||||||
logger := log.WithoutContext().WithField(log.ProviderName, "acme")
|
logger := log.WithoutContext().WithField(log.ProviderName, "acme")
|
||||||
|
@ -111,7 +111,7 @@ func (s *LocalStore) listenSaveAction() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccount returns ACME Account
|
// GetAccount returns ACME Account.
|
||||||
func (s *LocalStore) GetAccount(resolverName string) (*Account, error) {
|
func (s *LocalStore) GetAccount(resolverName string) (*Account, error) {
|
||||||
storedData, err := s.get(resolverName)
|
storedData, err := s.get(resolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -121,7 +121,7 @@ func (s *LocalStore) GetAccount(resolverName string) (*Account, error) {
|
||||||
return storedData.Account, nil
|
return storedData.Account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveAccount stores ACME Account
|
// SaveAccount stores ACME Account.
|
||||||
func (s *LocalStore) SaveAccount(resolverName string, account *Account) error {
|
func (s *LocalStore) SaveAccount(resolverName string, account *Account) error {
|
||||||
storedData, err := s.get(resolverName)
|
storedData, err := s.get(resolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -134,7 +134,7 @@ func (s *LocalStore) SaveAccount(resolverName string, account *Account) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertificates returns ACME Certificates list
|
// GetCertificates returns ACME Certificates list.
|
||||||
func (s *LocalStore) GetCertificates(resolverName string) ([]*CertAndStore, error) {
|
func (s *LocalStore) GetCertificates(resolverName string) ([]*CertAndStore, error) {
|
||||||
storedData, err := s.get(resolverName)
|
storedData, err := s.get(resolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -144,7 +144,7 @@ func (s *LocalStore) GetCertificates(resolverName string) ([]*CertAndStore, erro
|
||||||
return storedData.Certificates, nil
|
return storedData.Certificates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveCertificates stores ACME Certificates list
|
// SaveCertificates stores ACME Certificates list.
|
||||||
func (s *LocalStore) SaveCertificates(resolverName string, certificates []*CertAndStore) error {
|
func (s *LocalStore) SaveCertificates(resolverName string, certificates []*CertAndStore) error {
|
||||||
storedData, err := s.get(resolverName)
|
storedData, err := s.get(resolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -173,7 +173,7 @@ func NewLocalChallengeStore() *LocalChallengeStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHTTPChallengeToken Get the http challenge token from the store
|
// GetHTTPChallengeToken Get the http challenge token from the store.
|
||||||
func (s *LocalChallengeStore) GetHTTPChallengeToken(token, domain string) ([]byte, error) {
|
func (s *LocalChallengeStore) GetHTTPChallengeToken(token, domain string) ([]byte, error) {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
@ -193,7 +193,7 @@ func (s *LocalChallengeStore) GetHTTPChallengeToken(token, domain string) ([]byt
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHTTPChallengeToken Set the http challenge token in the store
|
// SetHTTPChallengeToken Set the http challenge token in the store.
|
||||||
func (s *LocalChallengeStore) SetHTTPChallengeToken(token, domain string, keyAuth []byte) error {
|
func (s *LocalChallengeStore) SetHTTPChallengeToken(token, domain string, keyAuth []byte) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
@ -210,7 +210,7 @@ func (s *LocalChallengeStore) SetHTTPChallengeToken(token, domain string, keyAut
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveHTTPChallengeToken Remove the http challenge token in the store
|
// RemoveHTTPChallengeToken Remove the http challenge token in the store.
|
||||||
func (s *LocalChallengeStore) RemoveHTTPChallengeToken(token, domain string) error {
|
func (s *LocalChallengeStore) RemoveHTTPChallengeToken(token, domain string) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
@ -228,7 +228,7 @@ func (s *LocalChallengeStore) RemoveHTTPChallengeToken(token, domain string) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTLSChallenge Add a certificate to the ACME TLS-ALPN-01 certificates storage
|
// AddTLSChallenge Add a certificate to the ACME TLS-ALPN-01 certificates storage.
|
||||||
func (s *LocalChallengeStore) AddTLSChallenge(domain string, cert *Certificate) error {
|
func (s *LocalChallengeStore) AddTLSChallenge(domain string, cert *Certificate) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
@ -241,7 +241,7 @@ func (s *LocalChallengeStore) AddTLSChallenge(domain string, cert *Certificate)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTLSChallenge Get a certificate from the ACME TLS-ALPN-01 certificates storage
|
// GetTLSChallenge Get a certificate from the ACME TLS-ALPN-01 certificates storage.
|
||||||
func (s *LocalChallengeStore) GetTLSChallenge(domain string) (*Certificate, error) {
|
func (s *LocalChallengeStore) GetTLSChallenge(domain string) (*Certificate, error) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
@ -253,7 +253,7 @@ func (s *LocalChallengeStore) GetTLSChallenge(domain string) (*Certificate, erro
|
||||||
return s.storedData.TLSChallenges[domain], nil
|
return s.storedData.TLSChallenges[domain], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTLSChallenge Remove a certificate from the ACME TLS-ALPN-01 certificates storage
|
// RemoveTLSChallenge Remove a certificate from the ACME TLS-ALPN-01 certificates storage.
|
||||||
func (s *LocalChallengeStore) RemoveTLSChallenge(domain string) error {
|
func (s *LocalChallengeStore) RemoveTLSChallenge(domain string) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckFile checks file permissions and content size
|
// CheckFile checks file permissions and content size.
|
||||||
func CheckFile(name string) (bool, error) {
|
func CheckFile(name string) (bool, error) {
|
||||||
f, err := os.Open(name)
|
f, err := os.Open(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -28,11 +28,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// oscpMustStaple enables OSCP stapling as from https://github.com/go-acme/lego/issues/270
|
// oscpMustStaple enables OSCP stapling as from https://github.com/go-acme/lego/issues/270.
|
||||||
oscpMustStaple = false
|
oscpMustStaple = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration holds ACME configuration provided by users
|
// Configuration holds ACME configuration provided by users.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
Email string `description:"Email address used for registration." json:"email,omitempty" toml:"email,omitempty" yaml:"email,omitempty"`
|
Email string `description:"Email address used for registration." json:"email,omitempty" toml:"email,omitempty" yaml:"email,omitempty"`
|
||||||
CAServer string `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
|
CAServer string `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
|
||||||
|
@ -56,14 +56,14 @@ type CertAndStore struct {
|
||||||
Store string
|
Store string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certificate is a struct which contains all data needed from an ACME certificate
|
// Certificate is a struct which contains all data needed from an ACME certificate.
|
||||||
type Certificate struct {
|
type Certificate struct {
|
||||||
Domain types.Domain `json:"domain,omitempty" toml:"domain,omitempty" yaml:"domain,omitempty"`
|
Domain types.Domain `json:"domain,omitempty" toml:"domain,omitempty" yaml:"domain,omitempty"`
|
||||||
Certificate []byte `json:"certificate,omitempty" toml:"certificate,omitempty" yaml:"certificate,omitempty"`
|
Certificate []byte `json:"certificate,omitempty" toml:"certificate,omitempty" yaml:"certificate,omitempty"`
|
||||||
Key []byte `json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
|
Key []byte `json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSChallenge contains DNS challenge Configuration
|
// DNSChallenge contains DNS challenge Configuration.
|
||||||
type DNSChallenge struct {
|
type DNSChallenge struct {
|
||||||
Provider string `description:"Use a DNS-01 based challenge provider rather than HTTPS." json:"provider,omitempty" toml:"provider,omitempty" yaml:"provider,omitempty"`
|
Provider string `description:"Use a DNS-01 based challenge provider rather than HTTPS." json:"provider,omitempty" toml:"provider,omitempty" yaml:"provider,omitempty"`
|
||||||
DelayBeforeCheck types.Duration `description:"Assume DNS propagates after a delay in seconds rather than finding and querying nameservers." json:"delayBeforeCheck,omitempty" toml:"delayBeforeCheck,omitempty" yaml:"delayBeforeCheck,omitempty"`
|
DelayBeforeCheck types.Duration `description:"Assume DNS propagates after a delay in seconds rather than finding and querying nameservers." json:"delayBeforeCheck,omitempty" toml:"delayBeforeCheck,omitempty" yaml:"delayBeforeCheck,omitempty"`
|
||||||
|
@ -71,12 +71,12 @@ type DNSChallenge struct {
|
||||||
DisablePropagationCheck bool `description:"Disable the DNS propagation checks before notifying ACME that the DNS challenge is ready. [not recommended]" json:"disablePropagationCheck,omitempty" toml:"disablePropagationCheck,omitempty" yaml:"disablePropagationCheck,omitempty"`
|
DisablePropagationCheck bool `description:"Disable the DNS propagation checks before notifying ACME that the DNS challenge is ready. [not recommended]" json:"disablePropagationCheck,omitempty" toml:"disablePropagationCheck,omitempty" yaml:"disablePropagationCheck,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPChallenge contains HTTP challenge Configuration
|
// HTTPChallenge contains HTTP challenge Configuration.
|
||||||
type HTTPChallenge struct {
|
type HTTPChallenge struct {
|
||||||
EntryPoint string `description:"HTTP challenge EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
EntryPoint string `description:"HTTP challenge EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSChallenge contains TLS challenge Configuration
|
// TLSChallenge contains TLS challenge Configuration.
|
||||||
type TLSChallenge struct{}
|
type TLSChallenge struct{}
|
||||||
|
|
||||||
// Provider holds configurations of the provider.
|
// Provider holds configurations of the provider.
|
||||||
|
@ -98,22 +98,22 @@ type Provider struct {
|
||||||
resolvingDomainsMutex sync.RWMutex
|
resolvingDomainsMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTLSManager sets the tls manager to use
|
// SetTLSManager sets the tls manager to use.
|
||||||
func (p *Provider) SetTLSManager(tlsManager *traefiktls.Manager) {
|
func (p *Provider) SetTLSManager(tlsManager *traefiktls.Manager) {
|
||||||
p.tlsManager = tlsManager
|
p.tlsManager = tlsManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfigListenerChan initializes the configFromListenerChan
|
// SetConfigListenerChan initializes the configFromListenerChan.
|
||||||
func (p *Provider) SetConfigListenerChan(configFromListenerChan chan dynamic.Configuration) {
|
func (p *Provider) SetConfigListenerChan(configFromListenerChan chan dynamic.Configuration) {
|
||||||
p.configFromListenerChan = configFromListenerChan
|
p.configFromListenerChan = configFromListenerChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenConfiguration sets a new Configuration into the configFromListenerChan
|
// ListenConfiguration sets a new Configuration into the configFromListenerChan.
|
||||||
func (p *Provider) ListenConfiguration(config dynamic.Configuration) {
|
func (p *Provider) ListenConfiguration(config dynamic.Configuration) {
|
||||||
p.configFromListenerChan <- config
|
p.configFromListenerChan <- config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init for compatibility reason the BaseProvider implements an empty Init
|
// Init for compatibility reason the BaseProvider implements an empty Init.
|
||||||
func (p *Provider) Init() error {
|
func (p *Provider) Init() error {
|
||||||
ctx := log.With(context.Background(), log.Str(log.ProviderName, p.ResolverName+".acme"))
|
ctx := log.With(context.Background(), log.Str(log.ProviderName, p.ResolverName+".acme"))
|
||||||
logger := log.FromContext(ctx)
|
logger := log.FromContext(ctx)
|
||||||
|
@ -125,7 +125,7 @@ func (p *Provider) Init() error {
|
||||||
var err error
|
var err error
|
||||||
p.account, err = p.Store.GetAccount(p.ResolverName)
|
p.account, err = p.Store.GetAccount(p.ResolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get ACME account: %v", err)
|
return fmt.Errorf("unable to get ACME account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Account if caServer changed, thus registration URI can be updated
|
// Reset Account if caServer changed, thus registration URI can be updated
|
||||||
|
@ -136,7 +136,7 @@ func (p *Provider) Init() error {
|
||||||
|
|
||||||
p.certificates, err = p.Store.GetCertificates(p.ResolverName)
|
p.certificates, err = p.Store.GetCertificates(p.ResolverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get ACME certificates : %v", err)
|
return fmt.Errorf("unable to get ACME certificates : %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the currently resolved domain map
|
// Init the currently resolved domain map
|
||||||
|
@ -442,7 +442,7 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain,
|
||||||
|
|
||||||
client, err := p.getClient()
|
client, err := p.getClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot get ACME client %v", err)
|
return nil, fmt.Errorf("cannot get ACME client %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
request := certificate.ObtainRequest{
|
request := certificate.ObtainRequest{
|
||||||
|
@ -453,7 +453,7 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain,
|
||||||
|
|
||||||
cert, err := client.Certificate.Obtain(request)
|
cert, err := client.Certificate.Obtain(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to generate a certificate for the domains %v: %v", uncheckedDomains, err)
|
return nil, fmt.Errorf("unable to generate a certificate for the domains %v: %w", uncheckedDomains, err)
|
||||||
}
|
}
|
||||||
if cert == nil {
|
if cert == nil {
|
||||||
return nil, fmt.Errorf("domains %v do not generate a certificate", uncheckedDomains)
|
return nil, fmt.Errorf("domains %v do not generate a certificate", uncheckedDomains)
|
||||||
|
@ -498,7 +498,7 @@ func (p *Provider) addCertificateForDomain(domain types.Domain, certificate []by
|
||||||
|
|
||||||
// deleteUnnecessaryDomains deletes from the configuration :
|
// deleteUnnecessaryDomains deletes from the configuration :
|
||||||
// - Duplicated domains
|
// - Duplicated domains
|
||||||
// - Domains which are checked by wildcard domain
|
// - Domains which are checked by wildcard domain.
|
||||||
func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []types.Domain {
|
func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []types.Domain {
|
||||||
var newDomains []types.Domain
|
var newDomains []types.Domain
|
||||||
|
|
||||||
|
@ -657,7 +657,7 @@ func (p *Provider) renewCertificates(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get provided certificate which check a domains list (Main and SANs)
|
// Get provided certificate which check a domains list (Main and SANs)
|
||||||
// from static and dynamic provided certificates
|
// from static and dynamic provided certificates.
|
||||||
func (p *Provider) getUncheckedDomains(ctx context.Context, domainsToCheck []string, tlsStore string) []string {
|
func (p *Provider) getUncheckedDomains(ctx context.Context, domainsToCheck []string, tlsStore string) []string {
|
||||||
p.resolvingDomainsMutex.RLock()
|
p.resolvingDomainsMutex.RLock()
|
||||||
defer p.resolvingDomainsMutex.RUnlock()
|
defer p.resolvingDomainsMutex.RUnlock()
|
||||||
|
@ -716,7 +716,7 @@ func getX509Certificate(ctx context.Context, cert *Certificate) (*x509.Certifica
|
||||||
return crt, err
|
return crt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// getValidDomains checks if given domain is allowed to generate a ACME certificate and return it
|
// getValidDomains checks if given domain is allowed to generate a ACME certificate and return it.
|
||||||
func (p *Provider) getValidDomains(ctx context.Context, domain types.Domain) ([]string, error) {
|
func (p *Provider) getValidDomains(ctx context.Context, domain types.Domain) ([]string, error) {
|
||||||
domains := domain.ToStrArray()
|
domains := domain.ToStrArray()
|
||||||
if len(domains) == 0 {
|
if len(domains) == 0 {
|
||||||
|
|
|
@ -94,12 +94,12 @@ func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the provider
|
// Init the provider.
|
||||||
func (p ProviderAggregator) Init() error {
|
func (p ProviderAggregator) Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide calls the provide method of every providers
|
// Provide calls the provide method of every providers.
|
||||||
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||||
if p.fileProvider != nil {
|
if p.fileProvider != nil {
|
||||||
launchProvider(configurationChan, pool, p.fileProvider)
|
launchProvider(configurationChan, pool, p.fileProvider)
|
||||||
|
|
|
@ -18,7 +18,7 @@ type constraintLabelFunc func(map[string]string) bool
|
||||||
// The expression must match any logical boolean combination of:
|
// The expression must match any logical boolean combination of:
|
||||||
// - `Label(labelName, labelValue)`
|
// - `Label(labelName, labelValue)`
|
||||||
// - `LabelRegex(labelName, regexValue)`
|
// - `LabelRegex(labelName, regexValue)`
|
||||||
// - `MarathonConstraint(field:operator:value)`
|
// - `MarathonConstraint(field:operator:value)`.
|
||||||
func MatchLabels(labels map[string]string, expr string) (bool, error) {
|
func MatchLabels(labels map[string]string, expr string) (bool, error) {
|
||||||
if expr == "" {
|
if expr == "" {
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
|
@ -12,7 +12,7 @@ type constraintTagFunc func([]string) bool
|
||||||
// MatchTags reports whether the expression matches with the given tags.
|
// MatchTags reports whether the expression matches with the given tags.
|
||||||
// The expression must match any logical boolean combination of:
|
// The expression must match any logical boolean combination of:
|
||||||
// - `Tag(tagValue)`
|
// - `Tag(tagValue)`
|
||||||
// - `TagRegex(regexValue)`
|
// - `TagRegex(regexValue)`.
|
||||||
func MatchTags(tags []string, expr string) (bool, error) {
|
func MatchTags(tags []string, expr string) (bool, error) {
|
||||||
if expr == "" {
|
if expr == "" {
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (p *Provider) SetDefaults() {
|
||||||
func (p *Provider) Init() error {
|
func (p *Provider) Init() error {
|
||||||
defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, nil)
|
defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while parsing default rule: %v", err)
|
return fmt.Errorf("error while parsing default rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.defaultRuleTpl = defaultRuleTpl
|
p.defaultRuleTpl = defaultRuleTpl
|
||||||
|
@ -107,7 +107,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||||
|
|
||||||
p.client, err = createClient(p.Endpoint)
|
p.client, err = createClient(p.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error create consul client, %v", err)
|
return fmt.Errorf("error create consul client, %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Duration(p.RefreshInterval))
|
ticker := time.NewTicker(time.Duration(p.RefreshInterval))
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (p *Provider) SetDefaults() {
|
||||||
func (p *Provider) Init() error {
|
func (p *Provider) Init() error {
|
||||||
defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, nil)
|
defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while parsing default rule: %v", err)
|
return fmt.Errorf("error while parsing default rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.defaultRuleTpl = defaultRuleTpl
|
p.defaultRuleTpl = defaultRuleTpl
|
||||||
|
|
|
@ -11,7 +11,8 @@ const (
|
||||||
labelDockerComposeService = "com.docker.compose.service"
|
labelDockerComposeService = "com.docker.compose.service"
|
||||||
)
|
)
|
||||||
|
|
||||||
// configuration Contains information from the labels that are globals (not related to the dynamic configuration) or specific to the provider.
|
// configuration Contains information from the labels that are globals (not related to the dynamic configuration)
|
||||||
|
// or specific to the provider.
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
Docker specificConfiguration
|
Docker specificConfiguration
|
||||||
|
@ -38,8 +39,8 @@ func (p *Provider) getConfiguration(container dockerData) (configuration, error)
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getStringMultipleStrict get multiple string values associated to several labels
|
// getStringMultipleStrict get multiple string values associated to several labels.
|
||||||
// Fail if one label is missing
|
// Fail if one label is missing.
|
||||||
func getStringMultipleStrict(labels map[string]string, labelNames ...string) (map[string]string, error) {
|
func getStringMultipleStrict(labels map[string]string, labelNames ...string) (map[string]string, error) {
|
||||||
foundLabels := map[string]string{}
|
foundLabels := map[string]string{}
|
||||||
for _, name := range labelNames {
|
for _, name := range labelNames {
|
||||||
|
@ -53,7 +54,7 @@ func getStringMultipleStrict(labels map[string]string, labelNames ...string) (ma
|
||||||
return foundLabels, nil
|
return foundLabels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getStringValue get string value associated to a label
|
// getStringValue get string value associated to a label.
|
||||||
func getStringValue(labels map[string]string, labelName string, defaultValue string) string {
|
func getStringValue(labels map[string]string, labelName string, defaultValue string) string {
|
||||||
if value, ok := labels[labelName]; ok && len(value) > 0 {
|
if value, ok := labels[labelName]; ok && len(value) > 0 {
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (p *Provider) SetDefaults() {
|
||||||
p.Filename = ""
|
p.Filename = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the provider
|
// Init the provider.
|
||||||
func (p *Provider) Init() error {
|
func (p *Provider) Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildConfiguration loads configuration either from file or a directory specified by 'Filename'/'Directory'
|
// BuildConfiguration loads configuration either from file or a directory
|
||||||
// and returns a 'Configuration' object
|
// specified by 'Filename'/'Directory' and returns a 'Configuration' object.
|
||||||
func (p *Provider) BuildConfiguration() (*dynamic.Configuration, error) {
|
func (p *Provider) BuildConfiguration() (*dynamic.Configuration, error) {
|
||||||
ctx := log.With(context.Background(), log.Str(log.ProviderName, providerName))
|
ctx := log.With(context.Background(), log.Str(log.ProviderName, providerName))
|
||||||
|
|
||||||
|
@ -94,12 +94,12 @@ func (p *Provider) BuildConfiguration() (*dynamic.Configuration, error) {
|
||||||
func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationChan chan<- dynamic.Message, callback func(chan<- dynamic.Message, fsnotify.Event)) error {
|
func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationChan chan<- dynamic.Message, callback func(chan<- dynamic.Message, fsnotify.Event)) error {
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating file watcher: %s", err)
|
return fmt.Errorf("error creating file watcher: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = watcher.Add(directory)
|
err = watcher.Add(directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error adding file watcher: %s", err)
|
return fmt.Errorf("error adding file watcher: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process events
|
// Process events
|
||||||
|
@ -201,7 +201,7 @@ func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguratio
|
||||||
func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *dynamic.Configuration) (*dynamic.Configuration, error) {
|
func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *dynamic.Configuration) (*dynamic.Configuration, error) {
|
||||||
fileList, err := ioutil.ReadDir(directory)
|
fileList, err := ioutil.ReadDir(directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return configuration, fmt.Errorf("unable to read directory %s: %v", directory, err)
|
return configuration, fmt.Errorf("unable to read directory %s: %w", directory, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if configuration == nil {
|
if configuration == nil {
|
||||||
|
@ -234,7 +234,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||||
if item.IsDir() {
|
if item.IsDir() {
|
||||||
configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration)
|
configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return configuration, fmt.Errorf("unable to load content configuration from subdirectory %s: %v", item, err)
|
return configuration, fmt.Errorf("unable to load content configuration from subdirectory %s: %w", item, err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||||
var c *dynamic.Configuration
|
var c *dynamic.Configuration
|
||||||
c, err = p.loadFileConfig(ctx, filepath.Join(directory, item.Name()), true)
|
c, err = p.loadFileConfig(ctx, filepath.Join(directory, item.Name()), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return configuration, fmt.Errorf("%s: %v", filepath.Join(directory, item.Name()), err)
|
return configuration, fmt.Errorf("%s: %w", filepath.Join(directory, item.Name()), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, conf := range c.HTTP.Routers {
|
for name, conf := range c.HTTP.Routers {
|
||||||
|
@ -354,7 +354,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||||
func (p *Provider) CreateConfiguration(ctx context.Context, filename string, funcMap template.FuncMap, templateObjects interface{}) (*dynamic.Configuration, error) {
|
func (p *Provider) CreateConfiguration(ctx context.Context, filename string, funcMap template.FuncMap, templateObjects interface{}) (*dynamic.Configuration, error) {
|
||||||
tmplContent, err := readFile(filename)
|
tmplContent, err := readFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading configuration file: %s - %s", filename, err)
|
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultFuncMap = sprig.TxtFuncMap()
|
var defaultFuncMap = sprig.TxtFuncMap()
|
||||||
|
@ -391,7 +391,7 @@ func (p *Provider) CreateConfiguration(ctx context.Context, filename string, fun
|
||||||
func (p *Provider) DecodeConfiguration(filename string) (*dynamic.Configuration, error) {
|
func (p *Provider) DecodeConfiguration(filename string) (*dynamic.Configuration, error) {
|
||||||
content, err := readFile(filename)
|
content, err := readFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading configuration file: %s - %s", filename, err)
|
return nil, fmt.Errorf("error reading configuration file: %s - %w", filename, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.decodeConfiguration(filename, content)
|
return p.decodeConfiguration(filename, content)
|
||||||
|
|
|
@ -280,7 +280,7 @@ func createProvider(t *testing.T, test ProvideTestCase, watch bool) (*Provider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createTempDir Helper
|
// createTempDir Helper.
|
||||||
func createTempDir(t *testing.T, dir string) string {
|
func createTempDir(t *testing.T, dir string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ func newClientImpl(csKube *kubernetes.Clientset, csCrd *versioned.Clientset) *cl
|
||||||
func newInClusterClient(endpoint string) (*clientWrapper, error) {
|
func newInClusterClient(endpoint string) (*clientWrapper, error) {
|
||||||
config, err := rest.InClusterConfig()
|
config, err := rest.InClusterConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create in-cluster configuration: %v", err)
|
return nil, fmt.Errorf("failed to create in-cluster configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if endpoint != "" {
|
if endpoint != "" {
|
||||||
|
@ -135,7 +135,7 @@ func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrappe
|
||||||
if caFilePath != "" {
|
if caFilePath != "" {
|
||||||
caData, err := ioutil.ReadFile(caFilePath)
|
caData, err := ioutil.ReadFile(caFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read CA file %s: %v", caFilePath, err)
|
return nil, fmt.Errorf("failed to read CA file %s: %w", caFilePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.TLSClientConfig = rest.TLSClientConfig{CAData: caData}
|
config.TLSClientConfig = rest.TLSClientConfig{CAData: caData}
|
||||||
|
|
|
@ -325,7 +325,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alp
|
||||||
if len(auth.TLS.CASecret) > 0 {
|
if len(auth.TLS.CASecret) > 0 {
|
||||||
caSecret, err := loadCASecret(namespace, auth.TLS.CASecret, k8sClient)
|
caSecret, err := loadCASecret(namespace, auth.TLS.CASecret, k8sClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load auth ca secret: %v", err)
|
return nil, fmt.Errorf("failed to load auth ca secret: %w", err)
|
||||||
}
|
}
|
||||||
forwardAuth.TLS.CA = caSecret
|
forwardAuth.TLS.CA = caSecret
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alp
|
||||||
if len(auth.TLS.CertSecret) > 0 {
|
if len(auth.TLS.CertSecret) > 0 {
|
||||||
authSecretCert, authSecretKey, err := loadAuthTLSSecret(namespace, auth.TLS.CertSecret, k8sClient)
|
authSecretCert, authSecretKey, err := loadAuthTLSSecret(namespace, auth.TLS.CertSecret, k8sClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load auth secret: %v", err)
|
return nil, fmt.Errorf("failed to load auth secret: %w", err)
|
||||||
}
|
}
|
||||||
forwardAuth.TLS.Cert = authSecretCert
|
forwardAuth.TLS.Cert = authSecretCert
|
||||||
forwardAuth.TLS.Key = authSecretKey
|
forwardAuth.TLS.Key = authSecretKey
|
||||||
|
@ -345,7 +345,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alp
|
||||||
func loadCASecret(namespace, secretName string, k8sClient Client) (string, error) {
|
func loadCASecret(namespace, secretName string, k8sClient Client) (string, error) {
|
||||||
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
|
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to fetch secret '%s/%s': %v", namespace, secretName, err)
|
return "", fmt.Errorf("failed to fetch secret '%s/%s': %w", namespace, secretName, err)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
|
return "", fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
|
||||||
|
@ -366,7 +366,7 @@ func loadCASecret(namespace, secretName string, k8sClient Client) (string, error
|
||||||
func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string, string, error) {
|
func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string, string, error) {
|
||||||
secret, exists, err := k8sClient.GetSecret(namespace, secretName)
|
secret, exists, err := k8sClient.GetSecret(namespace, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err)
|
return "", "", fmt.Errorf("failed to fetch secret '%s/%s': %w", namespace, secretName, err)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
return "", "", fmt.Errorf("secret '%s/%s' does not exist", namespace, secretName)
|
return "", "", fmt.Errorf("secret '%s/%s' does not exist", namespace, secretName)
|
||||||
|
@ -424,7 +424,7 @@ func getAuthCredentials(k8sClient Client, authSecret, namespace string) ([]strin
|
||||||
|
|
||||||
auth, err := loadAuthCredentials(namespace, authSecret, k8sClient)
|
auth, err := loadAuthCredentials(namespace, authSecret, k8sClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load auth credentials: %v", err)
|
return nil, fmt.Errorf("failed to load auth credentials: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return auth, nil
|
return auth, nil
|
||||||
|
@ -433,7 +433,7 @@ func getAuthCredentials(k8sClient Client, authSecret, namespace string) ([]strin
|
||||||
func loadAuthCredentials(namespace, secretName string, k8sClient Client) ([]string, error) {
|
func loadAuthCredentials(namespace, secretName string, k8sClient Client) ([]string, error) {
|
||||||
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
|
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch secret '%s/%s': %v", namespace, secretName, err)
|
return nil, fmt.Errorf("failed to fetch secret '%s/%s': %w", namespace, secretName, err)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
|
return nil, fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
|
||||||
|
@ -459,7 +459,7 @@ func loadAuthCredentials(namespace, secretName string, k8sClient Client) ([]stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return nil, fmt.Errorf("error reading secret for %s/%s: %v", namespace, secretName, err)
|
return nil, fmt.Errorf("error reading secret for %s/%s: %w", namespace, secretName, err)
|
||||||
}
|
}
|
||||||
if len(credentials) == 0 {
|
if len(credentials) == 0 {
|
||||||
return nil, fmt.Errorf("secret '%s/%s' does not contain any credentials", namespace, secretName)
|
return nil, fmt.Errorf("secret '%s/%s' does not contain any credentials", namespace, secretName)
|
||||||
|
@ -641,7 +641,7 @@ func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bo
|
||||||
func getTLS(k8sClient Client, secretName, namespace string) (*tls.CertAndStores, error) {
|
func getTLS(k8sClient Client, secretName, namespace string) (*tls.CertAndStores, error) {
|
||||||
secret, exists, err := k8sClient.GetSecret(namespace, secretName)
|
secret, exists, err := k8sClient.GetSecret(namespace, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch secret %s/%s: %v", namespace, secretName, err)
|
return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, fmt.Errorf("secret %s/%s does not exist", namespace, secretName)
|
return nil, fmt.Errorf("secret %s/%s does not exist", namespace, secretName)
|
||||||
|
|
|
@ -55,7 +55,7 @@ type ErrorPage struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Chain holds a chain of middlewares
|
// Chain holds a chain of middlewares.
|
||||||
type Chain struct {
|
type Chain struct {
|
||||||
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ type TLSOption struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// TLSOptionSpec configures TLS for an entry point
|
// TLSOptionSpec configures TLS for an entry point.
|
||||||
type TLSOptionSpec struct {
|
type TLSOptionSpec struct {
|
||||||
MinVersion string `json:"minVersion,omitempty"`
|
MinVersion string `json:"minVersion,omitempty"`
|
||||||
MaxVersion string `json:"maxVersion,omitempty"`
|
MaxVersion string `json:"maxVersion,omitempty"`
|
||||||
|
|
|
@ -64,7 +64,7 @@ type clientWrapper struct {
|
||||||
func newInClusterClient(endpoint string) (*clientWrapper, error) {
|
func newInClusterClient(endpoint string) (*clientWrapper, error) {
|
||||||
config, err := rest.InClusterConfig()
|
config, err := rest.InClusterConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create in-cluster configuration: %s", err)
|
return nil, fmt.Errorf("failed to create in-cluster configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if endpoint != "" {
|
if endpoint != "" {
|
||||||
|
@ -98,7 +98,7 @@ func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrappe
|
||||||
if caFilePath != "" {
|
if caFilePath != "" {
|
||||||
caData, err := ioutil.ReadFile(caFilePath)
|
caData, err := ioutil.ReadFile(caFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read CA file %s: %s", caFilePath, err)
|
return nil, fmt.Errorf("failed to read CA file %s: %w", caFilePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.TLSClientConfig = rest.TLSClientConfig{CAData: caData}
|
config.TLSClientConfig = rest.TLSClientConfig{CAData: caData}
|
||||||
|
@ -215,7 +215,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1beta1.Ingress, ip,
|
||||||
|
|
||||||
ing, err := c.factories[c.lookupNamespace(src.Namespace)].Networking().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name)
|
ing, err := c.factories[c.lookupNamespace(src.Namespace)].Networking().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get ingress %s/%s: %v", src.Namespace, src.Name, err)
|
return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ing.Status.LoadBalancer.Ingress) > 0 {
|
if len(ing.Status.LoadBalancer.Ingress) > 0 {
|
||||||
|
@ -231,7 +231,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1beta1.Ingress, ip,
|
||||||
|
|
||||||
_, err = c.clientset.NetworkingV1beta1().Ingresses(ingCopy.Namespace).UpdateStatus(ingCopy)
|
_, err = c.clientset.NetworkingV1beta1().Ingresses(ingCopy.Namespace).UpdateStatus(ingCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update ingress status %s/%s: %v", src.Namespace, src.Name, err)
|
return fmt.Errorf("failed to update ingress status %s/%s: %w", src.Namespace, src.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Updated status on ingress %s/%s", src.Namespace, src.Name)
|
log.Infof("Updated status on ingress %s/%s", src.Namespace, src.Name)
|
||||||
|
@ -241,7 +241,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1beta1.Ingress, ip,
|
||||||
func (c *clientWrapper) updateIngressStatusOld(src *networkingv1beta1.Ingress, ip, hostname string) error {
|
func (c *clientWrapper) updateIngressStatusOld(src *networkingv1beta1.Ingress, ip, hostname string) error {
|
||||||
ing, err := c.factories[c.lookupNamespace(src.Namespace)].Extensions().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name)
|
ing, err := c.factories[c.lookupNamespace(src.Namespace)].Extensions().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get ingress %s/%s: %v", src.Namespace, src.Name, err)
|
return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ing.Status.LoadBalancer.Ingress) > 0 {
|
if len(ing.Status.LoadBalancer.Ingress) > 0 {
|
||||||
|
@ -257,7 +257,7 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1beta1.Ingress, i
|
||||||
|
|
||||||
_, err = c.clientset.ExtensionsV1beta1().Ingresses(ingCopy.Namespace).UpdateStatus(ingCopy)
|
_, err = c.clientset.ExtensionsV1beta1().Ingresses(ingCopy.Namespace).UpdateStatus(ingCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update ingress status %s/%s: %v", src.Namespace, src.Name, err)
|
return fmt.Errorf("failed to update ingress status %s/%s: %w", src.Namespace, src.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Updated status on ingress %s/%s", src.Namespace, src.Name)
|
log.Infof("Updated status on ingress %s/%s", src.Namespace, src.Name)
|
||||||
|
|
|
@ -46,7 +46,7 @@ type Provider struct {
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointIngress holds the endpoint information for the Kubernetes provider
|
// EndpointIngress holds the endpoint information for the Kubernetes provider.
|
||||||
type EndpointIngress struct {
|
type EndpointIngress struct {
|
||||||
IP string `description:"IP used for Kubernetes Ingress endpoints." json:"ip,omitempty" toml:"ip,omitempty" yaml:"ip,omitempty"`
|
IP string `description:"IP used for Kubernetes Ingress endpoints." json:"ip,omitempty" toml:"ip,omitempty" yaml:"ip,omitempty"`
|
||||||
Hostname string `description:"Hostname used for Kubernetes Ingress endpoints." json:"hostname,omitempty" toml:"hostname,omitempty" yaml:"hostname,omitempty"`
|
Hostname string `description:"Hostname used for Kubernetes Ingress endpoints." json:"hostname,omitempty" toml:"hostname,omitempty" yaml:"hostname,omitempty"`
|
||||||
|
@ -306,7 +306,7 @@ func (p *Provider) updateIngressStatus(ing *v1beta1.Ingress, k8sClient Client) e
|
||||||
|
|
||||||
service, exists, err := k8sClient.GetService(serviceNamespace, serviceName)
|
service, exists, err := k8sClient.GetService(serviceNamespace, serviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot get service %s, received error: %s", p.IngressEndpoint.PublishedService, err)
|
return fmt.Errorf("cannot get service %s, received error: %w", p.IngressEndpoint.PublishedService, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists && service.Status.LoadBalancer.Ingress == nil {
|
if exists && service.Status.LoadBalancer.Ingress == nil {
|
||||||
|
@ -346,7 +346,7 @@ func getCertificates(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Cl
|
||||||
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
||||||
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to fetch secret %s/%s: %v", ingress.Namespace, t.SecretName, err)
|
return fmt.Errorf("failed to fetch secret %s/%s: %w", ingress.Namespace, t.SecretName, err)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue