1
0
Fork 0

Merge current branch v2.4 into master

This commit is contained in:
Jean-Baptiste Doumenjou 2021-03-09 11:32:01 +01:00
commit 702e301990
100 changed files with 561 additions and 557 deletions

View file

@ -40,7 +40,7 @@ func Do(baseConfig interface{}, indent bool) (string, error) {
}
func doOnJSON(input string) string {
mailExp := regexp.MustCompile(`\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3}"`)
mailExp := regexp.MustCompile(`\w[-.\w]*\w@\w[-.\w]*\w\.\w{2,3}"`)
return xurls.Relaxed().ReplaceAllString(mailExp.ReplaceAllString(input, maskLarge+"\""), maskLarge)
}

View file

@ -2,7 +2,6 @@ package anonymize
import (
"flag"
"io/ioutil"
"os"
"strings"
"testing"
@ -462,14 +461,14 @@ func TestDo_dynamicConfiguration(t *testing.T) {
},
}
expectedConfiguration, err := ioutil.ReadFile("./testdata/anonymized-dynamic-config.json")
expectedConfiguration, err := os.ReadFile("./testdata/anonymized-dynamic-config.json")
require.NoError(t, err)
cleanJSON, err := Do(config, true)
require.NoError(t, err)
if *updateExpected {
require.NoError(t, ioutil.WriteFile("testdata/anonymized-dynamic-config.json", []byte(cleanJSON), 0666))
require.NoError(t, os.WriteFile("testdata/anonymized-dynamic-config.json", []byte(cleanJSON), 0666))
}
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
@ -965,14 +964,14 @@ func TestDo_staticConfiguration(t *testing.T) {
},
}
expectedConfiguration, err := ioutil.ReadFile("./testdata/anonymized-static-config.json")
expectedConfiguration, err := os.ReadFile("./testdata/anonymized-static-config.json")
require.NoError(t, err)
cleanJSON, err := Do(config, true)
require.NoError(t, err)
if *updateExpected {
require.NoError(t, ioutil.WriteFile("testdata/anonymized-static-config.json", []byte(cleanJSON), 0666))
require.NoError(t, os.WriteFile("testdata/anonymized-static-config.json", []byte(cleanJSON), 0666))
}
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")

View file

@ -1,7 +1,7 @@
package anonymize
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -9,12 +9,12 @@ import (
)
func Test_doOnJSON(t *testing.T) {
baseConfiguration, err := ioutil.ReadFile("./testdata/example.json")
baseConfiguration, err := os.ReadFile("./testdata/example.json")
require.NoError(t, err)
anomConfiguration := doOnJSON(string(baseConfiguration))
expectedConfiguration, err := ioutil.ReadFile("./testdata/expected.json")
expectedConfiguration, err := os.ReadFile("./testdata/expected.json")
require.NoError(t, err)
assert.JSONEq(t, string(expectedConfiguration), anomConfiguration)

View file

@ -3,9 +3,10 @@ package api
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"strconv"
"testing"
@ -212,7 +213,7 @@ func TestHandler_EntryPoints(t *testing.T) {
}
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -226,11 +227,11 @@ func TestHandler_EntryPoints(t *testing.T) {
newJSON, err := json.MarshalIndent(results, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.jsonFile, newJSON, 0o644)
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.jsonFile)
data, err := os.ReadFile(test.expected.jsonFile)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})

View file

@ -4,9 +4,10 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"strconv"
"testing"
@ -826,7 +827,7 @@ func TestHandler_HTTP(t *testing.T) {
}
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -840,11 +841,11 @@ func TestHandler_HTTP(t *testing.T) {
newJSON, err := json.MarshalIndent(results, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.jsonFile, newJSON, 0o644)
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.jsonFile)
data, err := os.ReadFile(test.expected.jsonFile)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})

View file

@ -2,9 +2,10 @@ package api
import (
"encoding/json"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -263,7 +264,7 @@ func TestHandler_Overview(t *testing.T) {
}
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -277,11 +278,11 @@ func TestHandler_Overview(t *testing.T) {
newJSON, err := json.MarshalIndent(results, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.jsonFile, newJSON, 0o644)
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.jsonFile)
data, err := os.ReadFile(test.expected.jsonFile)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})

View file

@ -3,9 +3,10 @@ package api
import (
"context"
"encoding/json"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -534,7 +535,7 @@ func TestHandler_TCP(t *testing.T) {
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -548,11 +549,11 @@ func TestHandler_TCP(t *testing.T) {
newJSON, err := json.MarshalIndent(results, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.jsonFile, newJSON, 0o644)
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.jsonFile)
data, err := os.ReadFile(test.expected.jsonFile)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})

View file

@ -3,9 +3,10 @@ package api
import (
"encoding/json"
"flag"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -144,7 +145,7 @@ func TestHandler_RawData(t *testing.T) {
assert.Equal(t, test.expected.statusCode, resp.StatusCode)
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -161,11 +162,11 @@ func TestHandler_RawData(t *testing.T) {
newJSON, err := json.MarshalIndent(rtRepr, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.json, newJSON, 0o644)
err = os.WriteFile(test.expected.json, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.json)
data, err := os.ReadFile(test.expected.json)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})
@ -267,7 +268,7 @@ func TestHandler_GetMiddleware(t *testing.T) {
return
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()

View file

@ -3,9 +3,10 @@ package api
import (
"context"
"encoding/json"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -511,7 +512,7 @@ func TestHandler_UDP(t *testing.T) {
assert.Equal(t, resp.Header.Get("Content-Type"), "application/json")
contents, err := ioutil.ReadAll(resp.Body)
contents, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
@ -525,11 +526,11 @@ func TestHandler_UDP(t *testing.T) {
newJSON, err := json.MarshalIndent(results, "", "\t")
require.NoError(t, err)
err = ioutil.WriteFile(test.expected.jsonFile, newJSON, 0o644)
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
require.NoError(t, err)
}
data, err := ioutil.ReadFile(test.expected.jsonFile)
data, err := os.ReadFile(test.expected.jsonFile)
require.NoError(t, err)
assert.JSONEq(t, string(data), string(contents))
})

View file

@ -1,7 +1,6 @@
package cli
import (
"io/ioutil"
"os"
"strings"
@ -56,7 +55,7 @@ func (f *FileLoader) Load(args []string, cmd *cli.Command) (bool, error) {
logger := log.WithoutContext()
logger.Printf("Configuration loaded from file: %s", configFile)
content, _ := ioutil.ReadFile(configFile)
content, _ := os.ReadFile(configFile)
logger.Debug(string(content))
return true, nil
@ -79,7 +78,7 @@ func loadConfigFiles(configFile string, element interface{}) (string, error) {
return "", nil
}
if err = file.Decode(filePath, element); err != nil {
if err := file.Decode(filePath, element); err != nil {
return "", err
}
return filePath, nil

View file

@ -4,7 +4,6 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"time"
@ -446,7 +445,7 @@ func (c *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
if c.CA != "" {
var ca []byte
if _, errCA := os.Stat(c.CA); errCA == nil {
ca, err = ioutil.ReadFile(c.CA)
ca, err = os.ReadFile(c.CA)
if err != nil {
return nil, fmt.Errorf("failed to read CA. %w", err)
}

View file

@ -24,9 +24,21 @@ func TestJobBackOff(t *testing.T) {
exp.MinJobInterval = testMinJobInterval
exp.Reset()
expectedResults := []time.Duration{500, 500, 500, 1000, 2000, 4000, 5000, 5000, 500, 1000, 2000, 4000, 5000, 5000}
for i, d := range expectedResults {
expectedResults[i] = d * time.Millisecond
expectedResults := []time.Duration{
500 * time.Millisecond,
500 * time.Millisecond,
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
5 * time.Second,
5 * time.Second,
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
5 * time.Second,
5 * time.Second,
}
for i, expected := range expectedResults {

View file

@ -3,7 +3,7 @@ package metrics
import (
"context"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"regexp"
@ -79,7 +79,7 @@ func TestInfluxDB(t *testing.T) {
func TestInfluxDBHTTP(t *testing.T) {
c := make(chan *string)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "can't read body "+err.Error(), http.StatusBadRequest)
return

View file

@ -30,7 +30,7 @@ func TestScalableHistogram(t *testing.T) {
measuredDuration, err := time.ParseDuration(extractedDurationString[0] + "ms")
assert.NoError(t, err)
assert.InDelta(t, 500*time.Millisecond, measuredDuration, float64(1*time.Millisecond))
assert.InDelta(t, 500*time.Millisecond, measuredDuration, float64(15*time.Millisecond))
}
func TestNewMultiRegistry(t *testing.T) {

View file

@ -402,7 +402,7 @@ func newCollector(metricName string, labels stdprometheus.Labels, c stdprometheu
// collector wraps a Collector object from the Prometheus client library.
// It adds information on how many generations this metric should be present
// in the /metrics output, relatived to the time it was last tracked.
// in the /metrics output, relative to the time it was last tracked.
type collector struct {
id string
labels stdprometheus.Labels

View file

@ -4,7 +4,6 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@ -42,9 +41,7 @@ var (
)
func TestLogRotation(t *testing.T) {
tempDir := createTempDir(t, "traefik_")
fileName := filepath.Join(tempDir, "traefik.log")
fileName := filepath.Join(t.TempDir(), "traefik.log")
rotatedFileName := fileName + ".rotated"
config := &types.AccessLog{FilePath: fileName, Format: CommonFormat}
@ -100,7 +97,7 @@ func TestLogRotation(t *testing.T) {
func lineCount(t *testing.T, fileName string) int {
t.Helper()
fileContents, err := ioutil.ReadFile(fileName)
fileContents, err := os.ReadFile(fileName)
if err != nil {
t.Fatalf("Error reading from file %s: %s", fileName, err)
}
@ -117,8 +114,6 @@ func lineCount(t *testing.T, fileName string) int {
}
func TestLoggerHeaderFields(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat)
expectedValue := "expectedValue"
testCases := []struct {
@ -172,7 +167,7 @@ func TestLoggerHeaderFields(t *testing.T) {
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
logFile, err := ioutil.TempFile(tmpDir, "*.log")
logFile, err := os.CreateTemp(t.TempDir(), "*.log")
require.NoError(t, err)
config := &types.AccessLog{
@ -202,7 +197,7 @@ func TestLoggerHeaderFields(t *testing.T) {
writer.WriteHeader(http.StatusOK)
}))
logData, err := ioutil.ReadFile(logFile.Name())
logData, err := os.ReadFile(logFile.Name())
require.NoError(t, err)
if test.expected == types.AccessLogDrop {
@ -215,13 +210,11 @@ func TestLoggerHeaderFields(t *testing.T) {
}
func TestLoggerCLF(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat}
doLogging(t, config)
logData, err := ioutil.ReadFile(logFilePath)
logData, err := os.ReadFile(logFilePath)
require.NoError(t, err)
expectedLog := ` TestHost - TestUser [13/Apr/2016:07:14:19 -0700] "POST testpath HTTP/0.0" 123 12 "testReferer" "testUserAgent" 1 "testRouter" "http://127.0.0.1/testService" 1ms`
@ -229,13 +222,11 @@ func TestLoggerCLF(t *testing.T) {
}
func TestAsyncLoggerCLF(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024}
doLogging(t, config)
logData, err := ioutil.ReadFile(logFilePath)
logData, err := os.ReadFile(logFilePath)
require.NoError(t, err)
expectedLog := ` TestHost - TestUser [13/Apr/2016:07:14:19 -0700] "POST testpath HTTP/0.0" 123 12 "testReferer" "testUserAgent" 1 "testRouter" "http://127.0.0.1/testService" 1ms`
@ -452,9 +443,7 @@ func TestLoggerJSON(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
tmpDir := createTempDir(t, JSONFormat)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
test.config.FilePath = logFilePath
if test.tls {
@ -463,7 +452,7 @@ func TestLoggerJSON(t *testing.T) {
doLogging(t, test.config)
}
logData, err := ioutil.ReadFile(logFilePath)
logData, err := os.ReadFile(logFilePath)
require.NoError(t, err)
jsonData := make(map[string]interface{})
@ -677,7 +666,7 @@ func TestNewLogHandlerOutputStdout(t *testing.T) {
doLogging(t, test.config)
written, err := ioutil.ReadFile(file.Name())
written, err := os.ReadFile(file.Name())
require.NoError(t, err, "unable to read captured stdout from file")
assertValidLogData(t, test.expectedLog, written)
})
@ -713,16 +702,16 @@ func assertValidLogData(t *testing.T, expected string, logData []byte) {
assert.Equal(t, resultExpected[OriginContentSize], result[OriginContentSize], formatErrMessage)
assert.Equal(t, resultExpected[RequestRefererHeader], result[RequestRefererHeader], formatErrMessage)
assert.Equal(t, resultExpected[RequestUserAgentHeader], result[RequestUserAgentHeader], formatErrMessage)
assert.Regexp(t, regexp.MustCompile("[0-9]*"), result[RequestCount], formatErrMessage)
assert.Regexp(t, regexp.MustCompile(`\d*`), result[RequestCount], formatErrMessage)
assert.Equal(t, resultExpected[RouterName], result[RouterName], formatErrMessage)
assert.Equal(t, resultExpected[ServiceURL], result[ServiceURL], formatErrMessage)
assert.Regexp(t, regexp.MustCompile("[0-9]*ms"), result[Duration], formatErrMessage)
assert.Regexp(t, regexp.MustCompile(`\d*ms`), result[Duration], formatErrMessage)
}
func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
t.Helper()
file, err := ioutil.TempFile("", "testlogger")
file, err := os.CreateTemp("", "testlogger")
require.NoError(t, err, "failed to create temp file")
original := os.Stdout
@ -736,17 +725,6 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
return file, restoreStdout
}
func createTempDir(t *testing.T, prefix string) string {
t.Helper()
tmpDir, err := ioutil.TempDir("", prefix)
require.NoError(t, err, "failed to create temp dir")
t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
return tmpDir
}
func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
t.Helper()

View file

@ -1,7 +1,7 @@
package auth
import (
"io/ioutil"
"os"
"strings"
)
@ -46,7 +46,7 @@ func loadUsers(fileName string, appendUsers []string) ([]string, error) {
}
func getLinesFromFile(filename string) ([]string, error) {
dat, err := ioutil.ReadFile(filename)
dat, err := os.ReadFile(filename)
if err != nil {
return nil, err
}

View file

@ -3,7 +3,7 @@ package auth
import (
"context"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
@ -66,7 +66,7 @@ func TestBasicAuthSuccess(t *testing.T) {
assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal")
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
defer res.Body.Close()
@ -97,7 +97,7 @@ func TestBasicAuthUserHeader(t *testing.T) {
assert.Equal(t, http.StatusOK, res.StatusCode)
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
defer res.Body.Close()
@ -128,7 +128,7 @@ func TestBasicAuthHeaderRemoved(t *testing.T) {
assert.Equal(t, http.StatusOK, res.StatusCode)
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -159,7 +159,7 @@ func TestBasicAuthHeaderPresent(t *testing.T) {
assert.Equal(t, http.StatusOK, res.StatusCode)
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -215,9 +215,8 @@ func TestBasicAuthUsersFromFile(t *testing.T) {
t.Parallel()
// Creates the temporary configuration file with the users
usersFile, err := ioutil.TempFile("", "auth-users")
usersFile, err := os.CreateTemp(t.TempDir(), "auth-users")
require.NoError(t, err)
defer os.Remove(usersFile.Name())
_, err = usersFile.Write([]byte(test.userFileContent))
require.NoError(t, err)
@ -250,7 +249,7 @@ func TestBasicAuthUsersFromFile(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode, "Cannot authenticate user "+userName)
var body []byte
body, err = ioutil.ReadAll(res.Body)
body, err = io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -270,7 +269,7 @@ func TestBasicAuthUsersFromFile(t *testing.T) {
require.Equal(t, `Basic realm="`+test.realm+`"`, res.Header.Get("WWW-Authenticate"))
}
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)

View file

@ -3,7 +3,7 @@ package auth
import (
"context"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"os"
@ -93,9 +93,8 @@ func TestDigestAuthUsersFromFile(t *testing.T) {
t.Parallel()
// Creates the temporary configuration file with the users
usersFile, err := ioutil.TempFile("", "auth-users")
usersFile, err := os.CreateTemp(t.TempDir(), "auth-users")
require.NoError(t, err)
defer os.Remove(usersFile.Name())
_, err = usersFile.Write([]byte(test.userFileContent))
require.NoError(t, err)
@ -127,7 +126,7 @@ func TestDigestAuthUsersFromFile(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode, "Cannot authenticate user "+userName)
var body []byte
body, err = ioutil.ReadAll(res.Body)
body, err = io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -145,7 +144,7 @@ func TestDigestAuthUsersFromFile(t *testing.T) {
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
var body []byte
body, err = ioutil.ReadAll(res.Body)
body, err = io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)

View file

@ -4,7 +4,7 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"io"
"net"
"net/http"
"regexp"
@ -126,7 +126,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return
}
body, readError := ioutil.ReadAll(forwardResponse.Body)
body, readError := io.ReadAll(forwardResponse.Body)
if readError != nil {
logMessage := fmt.Sprintf("Error reading body %s. Cause: %s", fa.address, readError)
logger.Debug(logMessage)

View file

@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
@ -44,7 +43,7 @@ func TestForwardAuthFail(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, http.StatusForbidden, res.StatusCode)
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -92,7 +91,7 @@ func TestForwardAuthSuccess(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, http.StatusOK, res.StatusCode)
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -134,7 +133,7 @@ func TestForwardAuthRedirect(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "http://example.com/redirect-test", location.String())
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -187,7 +186,7 @@ func TestForwardAuthRemoveHopByHopHeaders(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "http://example.com/redirect-test", location.String(), "they should be equal")
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
assert.NotEmpty(t, string(body), "there should be something in the body")
}
@ -238,7 +237,7 @@ func TestForwardAuthFailResponseHeaders(t *testing.T) {
assert.Equal(t, value, res.Header[key])
}
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
require.NoError(t, err)
err = res.Body.Close()
require.NoError(t, err)
@ -489,5 +488,5 @@ type mockBackend struct {
}
func (b *mockBackend) Setup(componentName string) (opentracing.Tracer, io.Closer, error) {
return b.Tracer, ioutil.NopCloser(nil), nil
return b.Tracer, io.NopCloser(nil), nil
}

View file

@ -2,7 +2,7 @@ package compress
import (
"context"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@ -205,7 +205,7 @@ func TestIntegrationShouldNotCompress(t *testing.T) {
assert.Equal(t, gzipValue, resp.Header.Get(contentEncodingHeader))
assert.Equal(t, acceptEncodingHeader, resp.Header.Get(varyHeader))
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
assert.EqualValues(t, fakeCompressedBody, body)
})
@ -287,7 +287,7 @@ func TestIntegrationShouldCompress(t *testing.T) {
assert.Equal(t, gzipValue, resp.Header.Get(contentEncodingHeader))
assert.Equal(t, acceptEncodingHeader, resp.Header.Get(varyHeader))
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
if assert.ObjectsAreEqualValues(body, fakeBody) {
assert.Fail(t, "expected a compressed body", "got %v", body)

View file

@ -92,39 +92,42 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// check the recorder code against the configured http status code ranges
code := catcher.getCode()
for _, block := range c.httpCodeRanges {
if code >= block[0] && code <= block[1] {
logger.Debugf("Caught HTTP Status Code %d, returning error page", code)
if code < block[0] || code > block[1] {
continue
}
var query string
if len(c.backendQuery) > 0 {
query = "/" + strings.TrimPrefix(c.backendQuery, "/")
query = strings.ReplaceAll(query, "{status}", strconv.Itoa(code))
}
logger.Debugf("Caught HTTP Status Code %d, returning error page", code)
pageReq, err := newRequest(backendURL + query)
if err != nil {
logger.Error(err)
rw.WriteHeader(code)
_, err = fmt.Fprint(rw, http.StatusText(code))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
return
}
var query string
if len(c.backendQuery) > 0 {
query = "/" + strings.TrimPrefix(c.backendQuery, "/")
query = strings.ReplaceAll(query, "{status}", strconv.Itoa(code))
}
recorderErrorPage := newResponseRecorder(ctx, rw)
utils.CopyHeaders(pageReq.Header, req.Header)
c.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context()))
utils.CopyHeaders(rw.Header(), recorderErrorPage.Header())
pageReq, err := newRequest(backendURL + query)
if err != nil {
logger.Error(err)
rw.WriteHeader(code)
if _, err = rw.Write(recorderErrorPage.GetBody().Bytes()); err != nil {
logger.Error(err)
_, err = fmt.Fprint(rw, http.StatusText(code))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
return
}
recorderErrorPage := newResponseRecorder(ctx, rw)
utils.CopyHeaders(pageReq.Header, req.Header)
c.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context()))
utils.CopyHeaders(rw.Header(), recorderErrorPage.Header())
rw.WriteHeader(code)
if _, err = rw.Write(recorderErrorPage.GetBody().Bytes()); err != nil {
logger.Error(err)
}
return
}
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
@ -279,10 +280,12 @@ func TestRateLimit(t *testing.T) {
// actual default value
burst = 1
}
period := time.Duration(test.config.Period)
if period == 0 {
period = time.Second
}
if test.config.Average == 0 {
if reqCount < 75*test.incomingLoad/100 {
t.Fatalf("we (arbitrarily) expect at least 75%% of the requests to go through with no rate limiting, and yet only %d/%d went through", reqCount, test.incomingLoad)
@ -297,14 +300,18 @@ func TestRateLimit(t *testing.T) {
// we take into account the configured burst,
// because it also helps absorbing non-bursty traffic.
rate := float64(test.config.Average) / float64(period)
wantCount := int(int64(rate*float64(test.loadDuration)) + burst)
// Allow for a 2% leeway
maxCount := wantCount * 102 / 100
// With very high CPU loads,
// we can expect some extra delay in addition to the rate limiting we already do,
// so we allow for some extra leeway there.
// Feel free to adjust wrt to the load on e.g. the CI.
minCount := wantCount * 95 / 100
minCount := computeMinCount(wantCount)
if reqCount < minCount {
t.Fatalf("rate was slower than expected: %d requests (wanted > %d) in %v", reqCount, minCount, elapsed)
}
@ -314,3 +321,11 @@ func TestRateLimit(t *testing.T) {
})
}
}
func computeMinCount(wantCount int) int {
if os.Getenv("CI") != "" {
return wantCount * 60 / 100
}
return wantCount * 95 / 100
}

View file

@ -4,7 +4,7 @@ import (
"bufio"
"context"
"fmt"
"io/ioutil"
"io"
"math"
"net"
"net/http"
@ -73,12 +73,12 @@ func (r *retry) GetTracingInformation() (string, ext.SpanKindEnum) {
}
func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// if we might make multiple attempts, swap the body for an ioutil.NopCloser
// if we might make multiple attempts, swap the body for an io.NopCloser
// cf https://github.com/traefik/traefik/issues/1008
if r.attempts > 1 {
body := req.Body
defer body.Close()
req.Body = ioutil.NopCloser(body)
req.Body = io.NopCloser(body)
}
attempts := 1

View file

@ -3,10 +3,10 @@ package retry
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/http/httptrace"
"strconv"
"strings"
"testing"
"time"
@ -16,10 +16,7 @@ import (
"github.com/stretchr/testify/require"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/middlewares/emptybackendhandler"
"github.com/traefik/traefik/v2/pkg/testhelpers"
"github.com/vulcand/oxy/forward"
"github.com/vulcand/oxy/roundrobin"
)
func TestRetry(t *testing.T) {
@ -32,14 +29,14 @@ func TestRetry(t *testing.T) {
}{
{
desc: "no retry on success",
config: dynamic.Retry{Attempts: 1},
config: dynamic.Retry{Attempts: 5},
wantRetryAttempts: 0,
wantResponseStatus: http.StatusOK,
amountFaultyEndpoints: 0,
},
{
desc: "no retry on success with backoff",
config: dynamic.Retry{Attempts: 1, InitialInterval: ptypes.Duration(time.Microsecond * 50)},
config: dynamic.Retry{Attempts: 5, InitialInterval: ptypes.Duration(time.Microsecond * 50)},
wantRetryAttempts: 0,
wantResponseStatus: http.StatusOK,
amountFaultyEndpoints: 0,
@ -102,42 +99,28 @@ func TestRetry(t *testing.T) {
},
}
backendServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusOK)
_, err := rw.Write([]byte("OK"))
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
}))
forwarder, err := forward.New()
require.NoError(t, err)
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
loadBalancer, err := roundrobin.New(forwarder)
require.NoError(t, err)
retryAttemps := 0
next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
retryAttemps++
// out of range port
basePort := 1133444
for i := 0; i < test.amountFaultyEndpoints; i++ {
// 192.0.2.0 is a non-routable IP for testing purposes.
// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928
// We only use the port specification here because the URL is used as identifier
// in the load balancer and using the exact same URL would not add a new server.
err = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i)))
require.NoError(t, err)
}
if retryAttemps > test.amountFaultyEndpoints {
// calls WroteHeaders on httptrace.
_ = r.Write(io.Discard)
// add the functioning server to the end of the load balancer list
err = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
require.NoError(t, err)
rw.WriteHeader(http.StatusOK)
return
}
rw.WriteHeader(http.StatusBadGateway)
})
retryListener := &countingRetryListener{}
retry, err := New(context.Background(), loadBalancer, test.config, retryListener, "traefikTest")
retry, err := New(context.Background(), next, test.config, retryListener, "traefikTest")
require.NoError(t, err)
recorder := httptest.NewRecorder()
@ -152,15 +135,9 @@ func TestRetry(t *testing.T) {
}
func TestRetryEmptyServerList(t *testing.T) {
forwarder, err := forward.New()
require.NoError(t, err)
loadBalancer, err := roundrobin.New(forwarder)
require.NoError(t, err)
// The EmptyBackend middleware ensures that there is a 503
// response status set when there is no backend server in the pool.
next := emptybackendhandler.New(loadBalancer)
next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusServiceUnavailable)
})
retryListener := &countingRetryListener{}
retry, err := New(context.Background(), next, dynamic.Retry{Attempts: 3}, retryListener, "traefikTest")
@ -293,47 +270,29 @@ func TestRetryWebsocket(t *testing.T) {
},
}
forwarder, err := forward.New()
if err != nil {
t.Fatalf("Error creating forwarder: %v", err)
}
backendServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
upgrader := websocket.Upgrader{}
_, err := upgrader.Upgrade(rw, req, nil)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
}))
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
loadBalancer, err := roundrobin.New(forwarder)
if err != nil {
t.Fatalf("Error creating load balancer: %v", err)
}
retryAttemps := 0
next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
retryAttemps++
// out of range port
basePort := 1133444
for i := 0; i < test.amountFaultyEndpoints; i++ {
// 192.0.2.0 is a non-routable IP for testing purposes.
// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928
// We only use the port specification here because the URL is used as identifier
// in the load balancer and using the exact same URL would not add a new server.
_ = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i)))
}
if retryAttemps > test.amountFaultyEndpoints {
upgrader := websocket.Upgrader{}
_, err := upgrader.Upgrade(rw, r, nil)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
return
}
// add the functioning server to the end of the load balancer list
err = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
if err != nil {
t.Fatalf("Fail to upsert server: %v", err)
}
rw.WriteHeader(http.StatusBadGateway)
})
retryListener := &countingRetryListener{}
retryH, err := New(context.Background(), loadBalancer, dynamic.Retry{Attempts: test.maxRequestAttempts}, retryListener, "traefikTest")
retryH, err := New(context.Background(), next, dynamic.Retry{Attempts: test.maxRequestAttempts}, retryListener, "traefikTest")
require.NoError(t, err)
retryServer := httptest.NewServer(retryH)

View file

@ -27,12 +27,12 @@ func (n MockTracer) Extract(format, carrier interface{}) (opentracing.SpanContex
return nil, opentracing.ErrSpanContextNotFound
}
// MockSpanContext.
// MockSpanContext a span context mock.
type MockSpanContext struct{}
func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
// MockSpan.
// MockSpan a span mock.
type MockSpan struct {
OpName string
Tags map[string]interface{}

View file

@ -6,7 +6,7 @@ import (
"encoding/json"
"fmt"
"hash/fnv"
"io/ioutil"
"io"
"net/http"
"time"
@ -153,7 +153,7 @@ func (c *client) createUUID() (string, error) {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed read response body: %w", err)
}
@ -236,7 +236,7 @@ func (c *client) sendDataRetryable(ctx context.Context, req *http.Request) error
defer func() { _ = resp.Body.Close() }()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %w", err)
}

View file

@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
@ -68,7 +67,7 @@ func NewClient(opts ClientOptions) (*Client, error) {
return nil, err
}
goPath, err := ioutil.TempDir(sourcesRootPath, "gop-*")
goPath, err := os.MkdirTemp(sourcesRootPath, "gop-*")
if err != nil {
return nil, fmt.Errorf("failed to create GoPath: %w", err)
}
@ -197,7 +196,7 @@ func (c *Client) Download(ctx context.Context, pName, pVersion string) (string,
return hash, nil
}
data, _ := ioutil.ReadAll(resp.Body)
data, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("error: %d: %s", resp.StatusCode, string(data))
}
@ -353,7 +352,7 @@ func (c *Client) WriteState(plugins map[string]Descriptor) error {
return err
}
return ioutil.WriteFile(c.stateFile, mp, 0o600)
return os.WriteFile(c.stateFile, mp, 0o600)
}
// ResetAll resets all plugins related directories.

View file

@ -63,27 +63,24 @@ func (c *ChallengeTLSALPN) Present(domain, _, keyAuth string) error {
timer := time.NewTimer(c.Timeout)
var errC error
select {
case t := <-timer.C:
timer.Stop()
close(c.chans[string(certPEMBlock)])
c.muChans.Lock()
c.cleanChan(string(certPEMBlock))
c.muChans.Unlock()
err = c.CleanUp(domain, "", keyAuth)
if err != nil {
logger.Errorf("Failed to clean up TLS challenge: %v", err)
}
errC = fmt.Errorf("timeout %s", t)
return fmt.Errorf("timeout %s", t)
case <-ch:
// noop
return nil
}
c.muChans.Lock()
delete(c.chans, string(certPEMBlock))
c.muChans.Unlock()
return errC
}
// CleanUp cleans the challenges when certificate is obtained.
@ -115,16 +112,23 @@ func (c *ChallengeTLSALPN) Provide(configurationChan chan<- dynamic.Message, _ *
// ListenConfiguration sets a new Configuration into the configurationChan.
func (c *ChallengeTLSALPN) ListenConfiguration(conf dynamic.Configuration) {
c.muChans.Lock()
for _, certificate := range conf.TLS.Certificates {
if !containsACMETLS1(certificate.Stores) {
continue
}
c.muChans.Lock()
if _, ok := c.chans[certificate.CertFile.String()]; ok {
close(c.chans[certificate.CertFile.String()])
}
c.muChans.Unlock()
c.cleanChan(certificate.CertFile.String())
}
c.muChans.Unlock()
}
func (c *ChallengeTLSALPN) cleanChan(key string) {
if _, ok := c.chans[key]; ok {
close(c.chans[key])
delete(c.chans, key)
}
}

View file

@ -2,7 +2,7 @@ package acme
import (
"encoding/json"
"io/ioutil"
"io"
"os"
"sync"
@ -60,7 +60,7 @@ func (s *LocalStore) get(resolverName string) (*StoredData, error) {
}
defer f.Close()
file, err := ioutil.ReadAll(f)
file, err := io.ReadAll(f)
if err != nil {
return nil, err
}
@ -108,7 +108,7 @@ func (s *LocalStore) listenSaveAction() {
logger.Error(err)
}
err = ioutil.WriteFile(s.filename, data, 0o600)
err = os.WriteFile(s.filename, data, 0o600)
if err != nil {
logger.Error(err)
}

View file

@ -2,7 +2,7 @@ package acme
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
@ -23,7 +23,7 @@ func TestLocalStore_GetAccount(t *testing.T) {
}
}`, email)
err := ioutil.WriteFile(acmeFile, []byte(filePayload), 0o600)
err := os.WriteFile(acmeFile, []byte(filePayload), 0o600)
require.NoError(t, err)
testCases := []struct {
@ -68,7 +68,7 @@ func TestLocalStore_SaveAccount(t *testing.T) {
time.Sleep(100 * time.Millisecond)
file, err := ioutil.ReadFile(acmeFile)
file, err := os.ReadFile(acmeFile)
require.NoError(t, err)
expected := `{

View file

@ -119,10 +119,6 @@ func (p ProviderAggregator) Init() error {
// Provide calls the provide method of every providers.
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
if p.internalProvider != nil {
launchProvider(configurationChan, pool, p.internalProvider)
}
if p.fileProvider != nil {
launchProvider(configurationChan, pool, p.fileProvider)
}
@ -134,6 +130,12 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
})
}
// internal provider must be the last because we use it to know if all the providers are loaded.
// ConfigurationWatcher will wait for this requiredProvider before applying configurations.
if p.internalProvider != nil {
launchProvider(configurationChan, pool, p.internalProvider)
}
return nil
}

View file

@ -32,12 +32,11 @@ func TestProviderAggregator_Provide(t *testing.T) {
errCh <- aggregator.Provide(cfgCh, pool)
}()
// Make sure the internal provider is always called first, followed by the file provider.
requireReceivedMessageFromProviders(t, cfgCh, []string{"internal"})
// Make sure the file provider is always called first.
requireReceivedMessageFromProviders(t, cfgCh, []string{"file"})
// Check if all providers have been called, the order doesn't matter.
requireReceivedMessageFromProviders(t, cfgCh, []string{"salad", "tomato", "onion"})
requireReceivedMessageFromProviders(t, cfgCh, []string{"salad", "tomato", "onion", "internal"})
require.NoError(t, <-errCh)
}
@ -52,7 +51,8 @@ func requireReceivedMessageFromProviders(t *testing.T, cfgCh <-chan dynamic.Mess
for range names {
select {
case <-time.After(10 * time.Millisecond):
case <-time.After(100 * time.Millisecond):
require.Fail(t, "Timeout while waiting for configuration.")
case msg = <-cfgCh:
receivedMessagesFrom = append(receivedMessagesFrom, msg.ProviderName)
}

View file

@ -5,7 +5,6 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -197,7 +196,7 @@ func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguratio
}
func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *dynamic.Configuration) (*dynamic.Configuration, error) {
fileList, err := ioutil.ReadDir(directory)
fileList, err := os.ReadDir(directory)
if err != nil {
return configuration, fmt.Errorf("unable to read directory %s: %w", directory, err)
}
@ -436,7 +435,7 @@ func (p *Provider) decodeConfiguration(filePath, content string) (*dynamic.Confi
func readFile(filename string) (string, error) {
if len(filename) > 0 {
buf, err := ioutil.ReadFile(filename)
buf, err := os.ReadFile(filename)
if err != nil {
return "", err
}

View file

@ -3,7 +3,6 @@ package file
import (
"context"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@ -27,13 +26,12 @@ type ProvideTestCase struct {
}
func TestTLSContent(t *testing.T) {
tempDir := createTempDir(t, "testdir")
defer os.RemoveAll(tempDir)
tempDir := t.TempDir()
fileTLS, err := createTempFile("./fixtures/toml/tls_file.cert", tempDir)
require.NoError(t, err)
fileConfig, err := ioutil.TempFile(tempDir, "temp*.toml")
fileConfig, err := os.CreateTemp(tempDir, "temp*.toml")
require.NoError(t, err)
content := `
@ -245,7 +243,7 @@ func getTestCases() []ProvideTestCase {
func createProvider(t *testing.T, test ProvideTestCase, watch bool) *Provider {
t.Helper()
tempDir := createTempDir(t, "testdir")
tempDir := t.TempDir()
provider := &Provider{}
provider.Watch = true
@ -265,7 +263,7 @@ func createProvider(t *testing.T, test ProvideTestCase, watch bool) *Provider {
var file *os.File
if watch {
var err error
file, err = ioutil.TempFile(tempDir, "temp*"+filepath.Ext(test.filePath))
file, err = os.CreateTemp(tempDir, "temp*"+filepath.Ext(test.filePath))
require.NoError(t, err)
} else {
var err error
@ -283,17 +281,6 @@ func createProvider(t *testing.T, test ProvideTestCase, watch bool) *Provider {
return provider
}
// createTempDir Helper.
func createTempDir(t *testing.T, dir string) string {
t.Helper()
d, err := ioutil.TempDir("", dir)
if err != nil {
t.Fatal(err)
}
return d
}
func copyFile(srcPath, dstPath string) error {
dst, err := os.OpenFile(dstPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666)
if err != nil {
@ -312,7 +299,7 @@ func copyFile(srcPath, dstPath string) error {
}
func createTempFile(srcPath, tempDir string) (*os.File, error) {
file, err := ioutil.TempFile(tempDir, "temp*"+filepath.Ext(srcPath))
file, err := os.CreateTemp(tempDir, "temp*"+filepath.Ext(srcPath))
if err != nil {
return nil, err
}

View file

@ -4,7 +4,7 @@ import (
"context"
"fmt"
"hash/fnv"
"io/ioutil"
"io"
"net/http"
"time"
@ -139,7 +139,7 @@ func (p *Provider) fetchConfigurationData() ([]byte, error) {
return nil, fmt.Errorf("received non-ok response code: %d", res.StatusCode)
}
return ioutil.ReadAll(res.Body)
return io.ReadAll(res.Body)
}
// decodeConfiguration decodes and returns the dynamic configuration from the given data.

View file

@ -3,7 +3,6 @@ package crd
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@ -147,7 +146,7 @@ func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrappe
}
if caFilePath != "" {
caData, err := ioutil.ReadFile(caFilePath)
caData, err := os.ReadFile(caFilePath)
if err != nil {
return nil, fmt.Errorf("failed to read CA file %s: %w", caFilePath, err)
}

View file

@ -2,7 +2,7 @@ package crd
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
@ -46,7 +46,7 @@ func newClientMock(paths ...string) clientMock {
var c clientMock
for _, path := range paths {
yamlContent, err := ioutil.ReadFile(filepath.FromSlash("./fixtures/" + path))
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
if err != nil {
panic(err)
}

View file

@ -2,7 +2,7 @@ package crd
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
@ -4537,7 +4537,7 @@ func TestCrossNamespace(t *testing.T) {
var k8sObjects []runtime.Object
var crdObjects []runtime.Object
for _, path := range test.paths {
yamlContent, err := ioutil.ReadFile(filepath.FromSlash("./fixtures/" + path))
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
if err != nil {
panic(err)
}

View file

@ -4,7 +4,7 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"time"
"github.com/traefik/traefik/v2/pkg/log"
@ -138,7 +138,7 @@ func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrappe
}
if caFilePath != "" {
caData, err := ioutil.ReadFile(caFilePath)
caData, err := os.ReadFile(caFilePath)
if err != nil {
return nil, fmt.Errorf("failed to read CA file %s: %w", caFilePath, err)
}

View file

@ -2,7 +2,7 @@ package gateway
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s"
@ -43,7 +43,7 @@ func newClientMock(paths ...string) clientMock {
var c clientMock
for _, path := range paths {
yamlContent, err := ioutil.ReadFile(filepath.FromSlash("./fixtures/" + path))
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
if err != nil {
panic(err)
}

View file

@ -550,23 +550,24 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha1.ListenerStatus)
gatewayStatus.Listeners = listenerStatuses
// update "Scheduled" status with "ResourcesAvailable" reason
gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{
Type: string(v1alpha1.GatewayConditionScheduled),
Status: metav1.ConditionTrue,
Reason: "ResourcesAvailable",
Message: "Resources available",
LastTransitionTime: metav1.Now(),
})
// update "Ready" status with "ListenersValid" reason
gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{
Type: string(v1alpha1.GatewayConditionReady),
Status: metav1.ConditionTrue,
Reason: "ListenersValid",
Message: "Listeners valid",
LastTransitionTime: metav1.Now(),
})
gatewayStatus.Conditions = append(gatewayStatus.Conditions,
// update "Scheduled" status with "ResourcesAvailable" reason
metav1.Condition{
Type: string(v1alpha1.GatewayConditionScheduled),
Status: metav1.ConditionTrue,
Reason: "ResourcesAvailable",
Message: "Resources available",
LastTransitionTime: metav1.Now(),
},
// update "Ready" status with "ListenersValid" reason
metav1.Condition{
Type: string(v1alpha1.GatewayConditionReady),
Status: metav1.ConditionTrue,
Reason: "ListenersValid",
Message: "Listeners valid",
LastTransitionTime: metav1.Now(),
},
)
return gatewayStatus, nil
}

View file

@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@ -112,7 +111,7 @@ func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrappe
}
if caFilePath != "" {
caData, err := ioutil.ReadFile(caFilePath)
caData, err := os.ReadFile(caFilePath)
if err != nil {
return nil, fmt.Errorf("failed to read CA file %s: %w", caFilePath, err)
}
@ -341,7 +340,7 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1beta1.Ingress, i
}
// isLoadBalancerIngressEquals returns true if the given slices are equal, false otherwise.
func isLoadBalancerIngressEquals(aSlice []corev1.LoadBalancerIngress, bSlice []corev1.LoadBalancerIngress) bool {
func isLoadBalancerIngressEquals(aSlice, bSlice []corev1.LoadBalancerIngress) bool {
if len(aSlice) != len(bSlice) {
return false
}

View file

@ -2,7 +2,7 @@ package ingress
import (
"fmt"
"io/ioutil"
"os"
"github.com/hashicorp/go-version"
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s"
@ -36,7 +36,7 @@ func newClientMock(serverVersion string, paths ...string) clientMock {
c.serverVersion = version.Must(version.NewVersion(serverVersion))
for _, path := range paths {
yamlContent, err := ioutil.ReadFile(path)
yamlContent, err := os.ReadFile(path)
if err != nil {
panic(err)
}

View file

@ -4,7 +4,7 @@ import (
"context"
"encoding/json"
"flag"
"io/ioutil"
"os"
"path/filepath"
"testing"
@ -271,11 +271,11 @@ func Test_createConfiguration(t *testing.T) {
newJSON, err := json.MarshalIndent(cfg, "", " ")
require.NoError(t, err)
err = ioutil.WriteFile(filename, newJSON, 0o644)
err = os.WriteFile(filename, newJSON, 0o644)
require.NoError(t, err)
}
expectedJSON, err := ioutil.ReadFile(filename)
expectedJSON, err := os.ReadFile(filename)
require.NoError(t, err)
actualJSON, err := json.MarshalIndent(cfg, "", " ")

View file

@ -28,6 +28,7 @@ type ConfigurationWatcher struct {
configurationValidatedChan chan dynamic.Message
providerConfigUpdateMap map[string]chan dynamic.Message
requiredProvider string
configurationListeners []func(dynamic.Configuration)
routinesPool *safe.Pool
@ -39,6 +40,7 @@ func NewConfigurationWatcher(
pvd provider.Provider,
providersThrottleDuration time.Duration,
defaultEntryPoints []string,
requiredProvider string,
) *ConfigurationWatcher {
watcher := &ConfigurationWatcher{
provider: pvd,
@ -48,6 +50,7 @@ func NewConfigurationWatcher(
providersThrottleDuration: providersThrottleDuration,
routinesPool: routinesPool,
defaultEntryPoints: defaultEntryPoints,
requiredProvider: requiredProvider,
}
currentConfigurations := make(dynamic.Configurations)
@ -146,8 +149,11 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
conf := mergeConfiguration(newConfigurations, c.defaultEntryPoints)
conf = applyModel(conf)
for _, listener := range c.configurationListeners {
listener(conf)
// We wait for first configuration of the require provider before applying configurations.
if _, ok := newConfigurations[c.requiredProvider]; c.requiredProvider == "" || ok {
for _, listener := range c.configurationListeners {
listener(conf)
}
}
}

View file

@ -55,7 +55,7 @@ func TestNewConfigurationWatcher(t *testing.T) {
}},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{}, "")
run := make(chan struct{})
@ -112,7 +112,7 @@ func TestListenProvidersThrottleProviderConfigReload(t *testing.T) {
})
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{}, "")
publishedConfigCount := 0
watcher.AddListener(func(_ dynamic.Configuration) {
@ -136,7 +136,7 @@ func TestListenProvidersSkipsEmptyConfigs(t *testing.T) {
messages: []dynamic.Message{{ProviderName: "mock"}},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{}, "")
watcher.AddListener(func(_ dynamic.Configuration) {
t.Error("An empty configuration was published but it should not")
})
@ -162,7 +162,7 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
messages: []dynamic.Message{message, message},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{}, "")
alreadyCalled := false
watcher.AddListener(func(_ dynamic.Configuration) {
@ -205,7 +205,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond, []string{"defaultEP"})
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond, []string{"defaultEP"}, "")
var lastConfig dynamic.Configuration
watcher.AddListener(func(conf dynamic.Configuration) {
@ -216,7 +216,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
defer watcher.Stop()
// give some time so that the configuration can be processed
time.Sleep(40 * time.Millisecond)
time.Sleep(100 * time.Millisecond)
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
@ -260,7 +260,7 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{"defaultEP"})
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{"defaultEP"}, "")
var publishedProviderConfig dynamic.Configuration
@ -327,7 +327,7 @@ func TestPublishConfigUpdatedByProvider(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{}, "")
publishedConfigCount := 0
watcher.AddListener(func(configuration dynamic.Configuration) {
@ -375,7 +375,7 @@ func TestPublishConfigUpdatedByConfigWatcherListener(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{})
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{}, "")
publishedConfigCount := 0
watcher.AddListener(func(configuration dynamic.Configuration) {

View file

@ -2,7 +2,7 @@ package router
import (
"context"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"strings"
@ -827,7 +827,7 @@ func BenchmarkRouterServe(b *testing.B) {
res := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("")),
Body: io.NopCloser(strings.NewReader("")),
}
routersConfig := map[string]*dynamic.Router{
@ -879,7 +879,7 @@ func BenchmarkRouterServe(b *testing.B) {
func BenchmarkService(b *testing.B) {
res := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("")),
Body: io.NopCloser(strings.NewReader("")),
}
serviceConfig := map[string]*dynamic.Service{

View file

@ -362,11 +362,11 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
return nil, err
}
if err = tc.SetKeepAlive(true); err != nil {
if err := tc.SetKeepAlive(true); err != nil {
return nil, err
}
if err = tc.SetKeepAlivePeriod(3 * time.Minute); err != nil {
if err := tc.SetKeepAlivePeriod(3 * time.Minute); err != nil {
// Some systems, such as OpenBSD, have no user-settable per-socket TCP
// keepalive options.
if !errors.Is(err, syscall.ENOPROTOOPT) {

View file

@ -48,7 +48,7 @@ func TestShutdownTCP(t *testing.T) {
for {
_, err := http.ReadRequest(bufio.NewReader(conn))
if errors.Is(err, io.EOF) || (err != nil && strings.HasSuffix(err.Error(), "use of closed network connection")) {
if errors.Is(err, io.EOF) || (err != nil && errors.Is(err, net.ErrClosed)) {
return
}
require.NoError(t, err)
@ -70,6 +70,8 @@ func testShutdown(t *testing.T, router *tcp.Router) {
epConfig.LifeCycle.RequestAcceptGraceTimeout = 0
epConfig.LifeCycle.GraceTimeOut = ptypes.Duration(5 * time.Second)
epConfig.RespondingTimeouts.ReadTimeout = ptypes.Duration(5 * time.Second)
epConfig.RespondingTimeouts.WriteTimeout = ptypes.Duration(5 * time.Second)
entryPoint, err := NewTCPEntryPoint(context.Background(), &static.EntryPoint{
// We explicitly use an IPV4 address because on Alpine, with an IPV6 address
@ -97,6 +99,11 @@ func testShutdown(t *testing.T, router *tcp.Router) {
err = request.Write(conn)
require.NoError(t, err)
reader := bufio.NewReader(conn)
// Wait for first byte in response.
_, err = reader.Peek(1)
require.NoError(t, err)
go entryPoint.Shutdown(context.Background())
// Make sure that new connections are not permitted anymore.
@ -123,7 +130,7 @@ func testShutdown(t *testing.T, router *tcp.Router) {
// And make sure that the connection we had opened before shutting things down is still operational
resp, err := http.ReadResponse(bufio.NewReader(conn), request)
resp, err := http.ReadResponse(reader, request)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
@ -133,22 +140,17 @@ func startEntrypoint(entryPoint *TCPEntryPoint, router *tcp.Router) (net.Conn, e
entryPoint.SwitchRouter(router)
var conn net.Conn
var err error
var epStarted bool
for i := 0; i < 10; i++ {
conn, err = net.Dial("tcp", entryPoint.listener.Addr().String())
conn, err := net.Dial("tcp", entryPoint.listener.Addr().String())
if err != nil {
time.Sleep(100 * time.Millisecond)
continue
}
epStarted = true
break
return conn, err
}
if !epStarted {
return nil, errors.New("entry point never started")
}
return conn, err
return nil, errors.New("entry point never started")
}
func TestReadTimeoutWithoutFirstByte(t *testing.T) {

View file

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"sync"
@ -88,7 +87,7 @@ func (m *Mirroring) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
if errors.Is(err, errBodyTooLarge) {
req.Body = ioutil.NopCloser(io.MultiReader(bytes.NewReader(bytesRead), req.Body))
req.Body = io.NopCloser(io.MultiReader(bytes.NewReader(bytesRead), req.Body))
m.handler.ServeHTTP(rw, req)
logger.Debugf("no mirroring, request body larger than allowed size")
return
@ -147,8 +146,8 @@ func (b blackHoleResponseWriter) Header() http.Header {
return http.Header{}
}
func (b blackHoleResponseWriter) Write(bytes []byte) (int, error) {
return len(bytes), nil
func (b blackHoleResponseWriter) Write(data []byte) (int, error) {
return len(data), nil
}
func (b blackHoleResponseWriter) WriteHeader(statusCode int) {}
@ -182,7 +181,7 @@ func newReusableRequest(req *http.Request, maxBodySize int64) (*reusableRequest,
// unbounded body size
if maxBodySize < 0 {
body, err := ioutil.ReadAll(req.Body)
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, nil, err
}
@ -217,7 +216,7 @@ func (rr reusableRequest) clone(ctx context.Context) *http.Request {
req := rr.req.Clone(ctx)
if rr.body != nil {
req.Body = ioutil.NopCloser(bytes.NewReader(rr.body))
req.Body = io.NopCloser(bytes.NewReader(rr.body))
}
return req

View file

@ -3,7 +3,7 @@ package mirror
import (
"bytes"
"context"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"sync/atomic"
@ -148,7 +148,7 @@ func TestMirroringWithBody(t *testing.T) {
handler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
assert.NotNil(t, r.Body)
bb, err := ioutil.ReadAll(r.Body)
bb, err := io.ReadAll(r.Body)
assert.NoError(t, err)
assert.Equal(t, body, bb)
rw.WriteHeader(http.StatusOK)
@ -159,7 +159,7 @@ func TestMirroringWithBody(t *testing.T) {
for i := 0; i < numMirrors; i++ {
err := mirror.AddMirror(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
assert.NotNil(t, r.Body)
bb, err := ioutil.ReadAll(r.Body)
bb, err := io.ReadAll(r.Body)
assert.NoError(t, err)
assert.Equal(t, body, bb)
atomic.AddInt32(&countMirror, 1)
@ -213,13 +213,13 @@ func TestCloneRequest(t *testing.T) {
// first call
cloned := rr.clone(ctx)
body, err := ioutil.ReadAll(cloned.Body)
body, err := io.ReadAll(cloned.Body)
assert.NoError(t, err)
assert.Equal(t, bb, body)
// second call
cloned = rr.clone(ctx)
body, err = ioutil.ReadAll(cloned.Body)
body, err = io.ReadAll(cloned.Body)
assert.NoError(t, err)
assert.Equal(t, bb, body)
})

View file

@ -24,6 +24,19 @@ type stickyCookie struct {
httpOnly bool
}
// Balancer is a WeightedRoundRobin load balancer based on Earliest Deadline First (EDF).
// (https://en.wikipedia.org/wiki/Earliest_deadline_first_scheduling)
// Each pick from the schedule has the earliest deadline entry selected.
// Entries have deadlines set at currentDeadline + 1 / weight,
// providing weighted round robin behavior with floating point weights and an O(log n) pick time.
type Balancer struct {
stickyCookie *stickyCookie
mutex sync.RWMutex
handlers []*namedHandler
curDeadline float64
}
// New creates a new load balancer.
func New(sticky *dynamic.Sticky) *Balancer {
balancer := &Balancer{}
@ -68,19 +81,6 @@ func (b *Balancer) Pop() interface{} {
return h
}
// Balancer is a WeightedRoundRobin load balancer based on Earliest Deadline First (EDF).
// (https://en.wikipedia.org/wiki/Earliest_deadline_first_scheduling)
// Each pick from the schedule has the earliest deadline entry selected.
// Entries have deadlines set at currentDeadline + 1 / weight,
// providing weighted round robin behavior with floating point weights and an O(log n) pick time.
type Balancer struct {
stickyCookie *stickyCookie
mutex sync.RWMutex
handlers []*namedHandler
curDeadline float64
}
func (b *Balancer) nextServer() (*namedHandler, error) {
b.mutex.Lock()
defer b.mutex.Unlock()

View file

@ -1,7 +1,7 @@
package service
import (
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"strings"
@ -21,7 +21,7 @@ func (t *staticTransport) RoundTrip(r *http.Request) (*http.Response, error) {
func BenchmarkProxy(b *testing.B) {
res := &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader("")),
Body: io.NopCloser(strings.NewReader("")),
}
w := httptest.NewRecorder()

View file

@ -123,6 +123,8 @@ func createRoundTripper(cfg *dynamic.ServersTransport) (http.RoundTripper, error
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
ReadBufferSize: 64 * 1024,
WriteBufferSize: 64 * 1024,
}
transport.RegisterProtocol("h2c", &h2cTransportWrapper{

View file

@ -4,7 +4,6 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
@ -90,7 +89,7 @@ func (f FileOrContent) Read() ([]byte, error) {
var content []byte
if f.IsPath() {
var err error
content, err = ioutil.ReadFile(f.String())
content, err = os.ReadFile(f.String())
if err != nil {
return nil, err
}

View file

@ -5,7 +5,6 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"github.com/traefik/traefik/v2/pkg/log"
@ -34,7 +33,7 @@ func (clientTLS *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, e
var ca []byte
if _, errCA := os.Stat(clientTLS.CA); errCA == nil {
var err error
ca, err = ioutil.ReadFile(clientTLS.CA)
ca, err = os.ReadFile(clientTLS.CA)
if err != nil {
return nil, fmt.Errorf("failed to read CA. %w", err)
}