Skip to content

Commit 08c3fcf

Browse files
Gracefully handle unreachable URIs in loadSupportBundleSpecsFromURIs (#1383)
* gracefully handle unreachable URIs in loadSupportBundleSpecsFromURIs * let caller decide how to handle the error * fix klog import * Add a test to ensure failing to load uri does not error --------- Co-authored-by: Evans Mungai <[email protected]>
1 parent 1d2c119 commit 08c3fcf

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

cmd/troubleshoot/cli/run.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,21 +232,29 @@ the %s Admin Console to begin analysis.`
232232
return nil
233233
}
234234

235+
// loadSupportBundleSpecsFromURIs loads support bundle specs from URIs
235236
func loadSupportBundleSpecsFromURIs(ctx context.Context, kinds *loader.TroubleshootKinds) (*loader.TroubleshootKinds, error) {
236237
remoteRawSpecs := []string{}
237238
for _, s := range kinds.SupportBundlesV1Beta2 {
238239
if s.Spec.Uri != "" && util.IsURL(s.Spec.Uri) {
239240
// We are using LoadSupportBundleSpec function here since it handles prompting
240241
// users to accept insecure connections
241242
// There is an opportunity to refactor this code in favour of the Loader APIs
243+
// TODO: Pass ctx to LoadSupportBundleSpec
242244
rawSpec, err := supportbundle.LoadSupportBundleSpec(s.Spec.Uri)
243245
if err != nil {
244-
return nil, errors.Wrapf(err, "failed to load support bundle from URI %q", s.Spec.Uri)
246+
// In the event a spec can't be loaded, we'll just skip it and print a warning
247+
klog.Warningf("unable to load support bundle from URI: %q: %v", s.Spec.Uri, err)
248+
continue
245249
}
246250
remoteRawSpecs = append(remoteRawSpecs, string(rawSpec))
247251
}
248252
}
249253

254+
if len(remoteRawSpecs) == 0 {
255+
return kinds, nil
256+
}
257+
250258
return loader.LoadSpecs(ctx, loader.LoadOptions{
251259
RawSpecs: remoteRawSpecs,
252260
})
@@ -264,9 +272,10 @@ func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface)
264272
if !viper.GetBool("no-uri") {
265273
moreKinds, err := loadSupportBundleSpecsFromURIs(ctx, kinds)
266274
if err != nil {
267-
return nil, nil, err
275+
klog.Warningf("unable to load support bundles from URIs: %v", err)
276+
} else {
277+
kinds.Add(moreKinds)
268278
}
269-
kinds.Add(moreKinds)
270279
}
271280

272281
// Check if we have any collectors to run in the troubleshoot specs

cmd/troubleshoot/cli/run_test.go

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,29 @@ import (
44
"context"
55
"net/http"
66
"net/http/httptest"
7+
"strings"
78
"testing"
9+
"time"
810

11+
"github.com/replicatedhq/troubleshoot/pkg/httputil"
912
"github.com/replicatedhq/troubleshoot/pkg/loader"
1013
"github.com/stretchr/testify/assert"
1114
"github.com/stretchr/testify/require"
1215
)
1316

17+
var orig = `
18+
apiVersion: troubleshoot.sh/v1beta2
19+
kind: SupportBundle
20+
metadata:
21+
name: sb-1
22+
spec:
23+
uri: $MY_URI
24+
collectors:
25+
- configMap:
26+
name: kube-root-ca.crt
27+
namespace: default
28+
`
29+
1430
func Test_loadSupportBundleSpecsFromURIs(t *testing.T) {
1531
// Run a webserver to serve the spec
1632
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -25,18 +41,7 @@ spec:
2541
}))
2642
defer srv.Close()
2743

28-
orig := `
29-
apiVersion: troubleshoot.sh/v1beta2
30-
kind: SupportBundle
31-
metadata:
32-
name: sb-1
33-
spec:
34-
uri: ` + srv.URL + `
35-
collectors:
36-
- configMap:
37-
name: kube-root-ca.crt
38-
namespace: default
39-
`
44+
orig := strings.ReplaceAll(orig, "$MY_URI", srv.URL)
4045

4146
ctx := context.Background()
4247
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{RawSpec: orig})
@@ -49,3 +54,30 @@ spec:
4954
require.Len(t, moreKinds.SupportBundlesV1Beta2, 1)
5055
assert.NotNil(t, moreKinds.SupportBundlesV1Beta2[0].Spec.Collectors[0].ClusterInfo)
5156
}
57+
58+
func Test_loadSupportBundleSpecsFromURIs_TimeoutError(t *testing.T) {
59+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
60+
time.Sleep(2 * time.Second) // this will cause a timeout
61+
}))
62+
defer srv.Close()
63+
ctx := context.Background()
64+
65+
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
66+
RawSpec: strings.ReplaceAll(orig, "$MY_URI", srv.URL),
67+
})
68+
require.NoError(t, err)
69+
70+
// Set the timeout on the http client to 10ms
71+
// supportbundle.LoadSupportBundleSpec does not yet use the context
72+
before := httputil.GetHttpClient().Timeout
73+
httputil.GetHttpClient().Timeout = 10 * time.Millisecond
74+
defer func() {
75+
// Reinstate the original timeout. Its a global var so we need to reset it
76+
httputil.GetHttpClient().Timeout = before
77+
}()
78+
79+
kindsAfter, err := loadSupportBundleSpecsFromURIs(ctx, kinds)
80+
require.NoError(t, err)
81+
82+
assert.Equal(t, kinds, kindsAfter)
83+
}

0 commit comments

Comments
 (0)