Sanitize URLs for bucket fetch error messages.
Co-authored-by: Jagpreet Singh Tamber <jagpreetstamber@gmail.com> Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
parent
9a0f9af295
commit
5854dbee73
|
@ -728,7 +728,7 @@ func fetchEtagIndex(ctx context.Context, provider BucketProvider, obj *bucketv1.
|
||||||
path := filepath.Join(tempDir, sourceignore.IgnoreFile)
|
path := filepath.Join(tempDir, sourceignore.IgnoreFile)
|
||||||
if _, err := provider.FGetObject(ctxTimeout, obj.Spec.BucketName, sourceignore.IgnoreFile, path); err != nil {
|
if _, err := provider.FGetObject(ctxTimeout, obj.Spec.BucketName, sourceignore.IgnoreFile, path); err != nil {
|
||||||
if !provider.ObjectIsNotFound(err) {
|
if !provider.ObjectIsNotFound(err) {
|
||||||
return err
|
return fmt.Errorf("failed to get Etag for '%s' object: %w", sourceignore.IgnoreFile, serror.SanitizeError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ps, err := sourceignore.ReadIgnoreFile(path, nil)
|
ps, err := sourceignore.ReadIgnoreFile(path, nil)
|
||||||
|
@ -792,7 +792,7 @@ func fetchIndexFiles(ctx context.Context, provider BucketProvider, obj *bucketv1
|
||||||
index.Delete(k)
|
index.Delete(k)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to get '%s' object: %w", k, err)
|
return fmt.Errorf("failed to get '%s' object: %w", k, serror.SanitizeError(err))
|
||||||
}
|
}
|
||||||
if t != etag {
|
if t != etag {
|
||||||
index.Add(k, etag)
|
index.Add(k, etag)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package error
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SanitizedError struct {
|
||||||
|
err string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e SanitizedError) Error() string {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SanitizeError extracts all URLs from the error message
|
||||||
|
// and replaces them with the URL without the query string.
|
||||||
|
func SanitizeError(err error) SanitizedError {
|
||||||
|
errorMessage := err.Error()
|
||||||
|
for _, u := range extractURLs(errorMessage) {
|
||||||
|
urlWithoutQueryString, err := removeQueryString(u)
|
||||||
|
if err == nil {
|
||||||
|
re, err := regexp.Compile(fmt.Sprintf("%s*", regexp.QuoteMeta(u)))
|
||||||
|
if err == nil {
|
||||||
|
errorMessage = re.ReplaceAllString(errorMessage, urlWithoutQueryString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SanitizedError{errorMessage}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeQueryString takes a URL string as input and returns the URL without the query string.
|
||||||
|
func removeQueryString(urlStr string) (string, error) {
|
||||||
|
// Parse the URL.
|
||||||
|
u, err := url.Parse(urlStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebuild the URL without the query string.
|
||||||
|
u.RawQuery = ""
|
||||||
|
return u.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractURLs takes a log message as input and returns the URLs found.
|
||||||
|
func extractURLs(logMessage string) []string {
|
||||||
|
// Define a regular expression to match a URL.
|
||||||
|
// This is a simple pattern and might need to be adjusted depending on the log message format.
|
||||||
|
urlRegex := regexp.MustCompile(`https?://[^\s]+`)
|
||||||
|
|
||||||
|
// Find the first match in the log message.
|
||||||
|
matches := urlRegex.FindAllString(logMessage, -1)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package error
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_extractURLs(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
logMessage string
|
||||||
|
wantUrls []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Log Contains single URL",
|
||||||
|
logMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml?se=2024-05-01T16%3A28%3A26Z&sig=Signature&sp=rl&sr=c&st=2024-02-01T16%3A28%3A26Z&sv=2022-11-02\": dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
wantUrls: []string{"https://blobstorage.blob.core.windows.net/container/index.yaml?se=2024-05-01T16%3A28%3A26Z&sig=Signature&sp=rl&sr=c&st=2024-02-01T16%3A28%3A26Z&sv=2022-11-02\":"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Log Contains multiple URL",
|
||||||
|
logMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml?abc=es https://blobstorage1.blob.core.windows.net/container/index.yaml?abc=no : dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
wantUrls: []string{
|
||||||
|
"https://blobstorage.blob.core.windows.net/container/index.yaml?abc=es",
|
||||||
|
"https://blobstorage1.blob.core.windows.net/container/index.yaml?abc=no",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Log Contains No URL",
|
||||||
|
logMessage: "Log message without URL",
|
||||||
|
wantUrls: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
g := NewWithT(t)
|
||||||
|
|
||||||
|
urls := extractURLs(tt.logMessage)
|
||||||
|
|
||||||
|
g.Expect(len(urls)).To(Equal(len(tt.wantUrls)))
|
||||||
|
for i := range tt.wantUrls {
|
||||||
|
g.Expect(urls[i]).To(Equal(tt.wantUrls[i]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_removeQueryString(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
urlStr string
|
||||||
|
wantUrl string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "URL with query string",
|
||||||
|
urlStr: "https://blobstorage.blob.core.windows.net/container/index.yaml?se=2024-05-01T16%3A28%3A26Z&sig=Signature&sp=rl&sr=c&st=2024-02-01T16%3A28%3A26Z&sv=2022-11-02",
|
||||||
|
wantUrl: "https://blobstorage.blob.core.windows.net/container/index.yaml",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URL without query string",
|
||||||
|
urlStr: "https://blobstorage.blob.core.windows.net/container/index.yaml",
|
||||||
|
wantUrl: "https://blobstorage.blob.core.windows.net/container/index.yaml",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URL with query string and port",
|
||||||
|
urlStr: "https://blobstorage.blob.core.windows.net:443/container/index.yaml?se=2024-05-01T16%3A28%3A26Z&sig=Signature&sp=rl&sr=c&st=2024-02-01T16%3A28%3A26Z&sv=2022-11-02",
|
||||||
|
wantUrl: "https://blobstorage.blob.core.windows.net:443/container/index.yaml",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid URL",
|
||||||
|
urlStr: "NoUrl",
|
||||||
|
wantUrl: "NoUrl",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
g := NewWithT(t)
|
||||||
|
|
||||||
|
urlWithoutQueryString, err := removeQueryString(tt.urlStr)
|
||||||
|
|
||||||
|
g.Expect(err).To(BeNil())
|
||||||
|
g.Expect(urlWithoutQueryString).To(Equal(tt.wantUrl))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_SanitizeError(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
errMessage string
|
||||||
|
wantErrMessage string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Log message with URL with query string",
|
||||||
|
errMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml?se=2024-05-01T16%3A28%3A26Z&sig=Signature&sp=rl&sr=c&st=2024-02-01T16%3A28%3A26Z&sv=2022-11-02\": dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
wantErrMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Log message without URL",
|
||||||
|
errMessage: "Log message contains no URL",
|
||||||
|
wantErrMessage: "Log message contains no URL",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "Log message with multiple Urls",
|
||||||
|
errMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml?abc=es https://blobstorage1.blob.core.windows.net/container/index.yaml?abc=no dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
wantErrMessage: "Get \"https://blobstorage.blob.core.windows.net/container/index.yaml https://blobstorage1.blob.core.windows.net/container/index.yaml dial tcp 20.60.53.129:443: connect: connection refused",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
g := NewWithT(t)
|
||||||
|
|
||||||
|
err := SanitizeError(errors.New(tt.errMessage))
|
||||||
|
g.Expect(err.Error()).To(Equal(tt.wantErrMessage))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue