Skip to content

Commit 445bcde

Browse files
committed
ci: improve sysdig client test coverage
1 parent baede82 commit 445bcde

1 file changed

Lines changed: 140 additions & 17 deletions

File tree

internal/infra/sysdig/client_test.go

Lines changed: 140 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@ import (
1212
"github.com/sysdiglabs/sysdig-mcp-server/internal/infra/sysdig"
1313
)
1414

15+
func permissionsHandler(captureHeaders func(http.Header)) http.Handler {
16+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17+
if captureHeaders != nil {
18+
captureHeaders(r.Header)
19+
}
20+
if r.URL.Path == "/api/users/me/permissions" {
21+
w.Header().Set("Content-Type", "application/json")
22+
w.WriteHeader(http.StatusOK)
23+
_, _ = w.Write([]byte(`{"permissions":[]}`))
24+
return
25+
}
26+
w.WriteHeader(http.StatusNotFound)
27+
})
28+
}
29+
1530
var _ = Describe("Client TLS", func() {
1631
var ts *httptest.Server
1732

1833
BeforeEach(func() {
19-
// Start a TLS server with a self-signed certificate
20-
ts = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21-
if r.URL.Path == "/api/users/me/permissions" {
22-
w.Header().Set("Content-Type", "application/json")
23-
w.WriteHeader(http.StatusOK)
24-
_, _ = w.Write([]byte(`{"permissions":[]}`))
25-
return
26-
}
27-
w.WriteHeader(http.StatusNotFound)
28-
}))
29-
// Redirect server logs to GinkgoWriter to avoid noise in test output
34+
ts = httptest.NewTLSServer(permissionsHandler(nil))
3035
ts.Config.ErrorLog = log.New(GinkgoWriter, "", 0)
3136
})
3237

@@ -35,35 +40,153 @@ var _ = Describe("Client TLS", func() {
3540
})
3641

3742
It("should fail request with self-signed cert by default", func() {
38-
// Create client pointing to the TLS server without custom transport
3943
client, err := sysdig.NewSysdigClient(
4044
sysdig.WithFixedHostAndToken(ts.URL, "dummy-token"),
4145
)
4246
Expect(err).NotTo(HaveOccurred())
4347

44-
// Attempt request
4548
_, err = client.GetMyPermissionsWithResponse(context.Background())
4649
Expect(err).To(HaveOccurred())
47-
// Verification that it failed due to certificate issues
4850
Expect(err.Error()).To(Or(ContainSubstring("certificate"), ContainSubstring("unknown authority")))
4951
})
5052

5153
It("should succeed request when using custom HTTP client with InsecureSkipVerify", func() {
52-
// Create custom HTTP client that skips verification
5354
transport := http.DefaultTransport.(*http.Transport).Clone()
5455
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
5556
httpClient := &http.Client{Transport: transport}
5657

57-
// Create client using the custom HTTP client
5858
client, err := sysdig.NewSysdigClient(
5959
sysdig.WithFixedHostAndToken(ts.URL, "dummy-token"),
6060
sysdig.WithHTTPClient(httpClient),
6161
)
6262
Expect(err).NotTo(HaveOccurred())
6363

64-
// Attempt request
6564
resp, err := client.GetMyPermissionsWithResponse(context.Background())
6665
Expect(err).NotTo(HaveOccurred())
6766
Expect(resp.HTTPResponse.StatusCode).To(Equal(http.StatusOK))
6867
})
6968
})
69+
70+
var _ = Describe("Context helpers", func() {
71+
It("roundtrips token through context", func() {
72+
ctx := sysdig.WrapContextWithToken(context.Background(), "my-token")
73+
Expect(sysdig.GetTokenFromContext(ctx)).To(Equal("my-token"))
74+
})
75+
76+
It("roundtrips host through context", func() {
77+
ctx := sysdig.WrapContextWithHost(context.Background(), "https://example.com")
78+
Expect(sysdig.GetHostFromContext(ctx)).To(Equal("https://example.com"))
79+
})
80+
81+
It("panics when token is missing from context", func() {
82+
Expect(func() {
83+
sysdig.GetTokenFromContext(context.Background())
84+
}).To(Panic())
85+
})
86+
87+
It("panics when host is missing from context", func() {
88+
Expect(func() {
89+
sysdig.GetHostFromContext(context.Background())
90+
}).To(Panic())
91+
})
92+
})
93+
94+
var _ = Describe("Client authentication", func() {
95+
var ts *httptest.Server
96+
var lastHeaders http.Header
97+
98+
BeforeEach(func() {
99+
ts = httptest.NewServer(permissionsHandler(func(h http.Header) {
100+
lastHeaders = h.Clone()
101+
}))
102+
})
103+
104+
AfterEach(func() {
105+
ts.Close()
106+
})
107+
108+
Describe("WithHostAndTokenFromContext", func() {
109+
It("authenticates using context values", func() {
110+
client, err := sysdig.NewSysdigClient(sysdig.WithHostAndTokenFromContext())
111+
Expect(err).NotTo(HaveOccurred())
112+
113+
ctx := sysdig.WrapContextWithHost(context.Background(), ts.URL)
114+
ctx = sysdig.WrapContextWithToken(ctx, "ctx-token")
115+
116+
resp, err := client.GetMyPermissionsWithResponse(ctx)
117+
Expect(err).NotTo(HaveOccurred())
118+
Expect(resp.HTTPResponse.StatusCode).To(Equal(http.StatusOK))
119+
Expect(lastHeaders.Get("Authorization")).To(Equal("Bearer ctx-token"))
120+
})
121+
122+
It("fails when token is missing from context", func() {
123+
client, err := sysdig.NewSysdigClient(sysdig.WithHostAndTokenFromContext())
124+
Expect(err).NotTo(HaveOccurred())
125+
126+
ctx := sysdig.WrapContextWithHost(context.Background(), ts.URL)
127+
128+
_, err = client.GetMyPermissionsWithResponse(ctx)
129+
Expect(err).To(MatchError(ContainSubstring("authorization token not present")))
130+
})
131+
})
132+
133+
Describe("WithFallbackAuthentication", func() {
134+
It("uses first auth when it succeeds", func() {
135+
client, err := sysdig.NewSysdigClient(
136+
sysdig.WithFallbackAuthentication(
137+
sysdig.WithFixedHostAndToken(ts.URL, "primary-token"),
138+
sysdig.WithFixedHostAndToken(ts.URL, "fallback-token"),
139+
),
140+
)
141+
Expect(err).NotTo(HaveOccurred())
142+
143+
resp, err := client.GetMyPermissionsWithResponse(context.Background())
144+
Expect(err).NotTo(HaveOccurred())
145+
Expect(resp.HTTPResponse.StatusCode).To(Equal(http.StatusOK))
146+
Expect(lastHeaders.Get("Authorization")).To(Equal("Bearer primary-token"))
147+
})
148+
149+
It("falls back to second auth when first fails", func() {
150+
client, err := sysdig.NewSysdigClient(
151+
sysdig.WithFallbackAuthentication(
152+
sysdig.WithHostAndTokenFromContext(),
153+
sysdig.WithFixedHostAndToken(ts.URL, "fallback-token"),
154+
),
155+
)
156+
Expect(err).NotTo(HaveOccurred())
157+
158+
resp, err := client.GetMyPermissionsWithResponse(context.Background())
159+
Expect(err).NotTo(HaveOccurred())
160+
Expect(resp.HTTPResponse.StatusCode).To(Equal(http.StatusOK))
161+
Expect(lastHeaders.Get("Authorization")).To(Equal("Bearer fallback-token"))
162+
})
163+
164+
It("fails when all auth methods fail", func() {
165+
client, err := sysdig.NewSysdigClient(
166+
sysdig.WithFallbackAuthentication(
167+
sysdig.WithHostAndTokenFromContext(),
168+
sysdig.WithHostAndTokenFromContext(),
169+
),
170+
)
171+
Expect(err).NotTo(HaveOccurred())
172+
173+
_, err = client.GetMyPermissionsWithResponse(context.Background())
174+
Expect(err).To(MatchError(ContainSubstring("unable to authenticate")))
175+
})
176+
})
177+
178+
Describe("WithVersion", func() {
179+
It("sends User-Agent header with version", func() {
180+
client, err := sysdig.NewSysdigClient(
181+
sysdig.WithFixedHostAndToken(ts.URL, "tok"),
182+
sysdig.WithVersion("2.0.0"),
183+
)
184+
Expect(err).NotTo(HaveOccurred())
185+
186+
resp, err := client.GetMyPermissionsWithResponse(context.Background())
187+
Expect(err).NotTo(HaveOccurred())
188+
Expect(resp.HTTPResponse.StatusCode).To(Equal(http.StatusOK))
189+
Expect(lastHeaders.Get("User-Agent")).To(Equal("sysdig-mcp-server/2.0.0"))
190+
})
191+
})
192+
})

0 commit comments

Comments
 (0)