Skip to content

Commit 1ea418d

Browse files
authored
fix(metricproviders): Check and handle invalid server URL. Fixed argoproj#1444 (argoproj#1534)
fix(metricproviders): Check and handle invalid server URL. Fixed argoproj#1444 (argoproj#1534) Signed-off-by: Noam Gal <[email protected]>
1 parent 4c08f7e commit 1ea418d

File tree

3 files changed

+61
-41
lines changed

3 files changed

+61
-41
lines changed

USERS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Organizations below are **officially** using Argo Rollouts. Please send a PR wit
66
1. [Ambassador Labs](https://www.getambassador.io)
77
1. [Ant Group](https://www.antgroup.com/)
88
1. [Bucketplace](https://www.bucketplace.co.kr/)
9+
1. [Codefresh](https://codefresh.io/)
910
1. [Databricks](https://github.com/databricks)
1011
1. [Devtron Labs](https://github.com/devtron-labs/devtron)
1112
1. [Intuit](https://www.intuit.com/)

metricproviders/datadog/datadog.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ func (p *Provider) Run(run *v1alpha1.AnalysisRun, metric v1alpha1.Metric) v1alph
7070
endpoint = p.config.Address + "/api/v1/query"
7171
}
7272

73-
url, _ := url.Parse(endpoint)
73+
url, err := url.Parse(endpoint)
74+
if err != nil {
75+
return metricutil.MarkMeasurementError(measurement, err)
76+
}
7477

7578
now := unixNow()
7679
var interval int64 = 300

metricproviders/datadog/datadog_test.go

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func TestRunSuite(t *testing.T) {
2727

2828
// Test Cases
2929
var tests = []struct {
30+
serverURL string
3031
webServerStatus int
3132
webServerResponse string
3233
metric v1alpha1.Metric
@@ -172,62 +173,77 @@ func TestRunSuite(t *testing.T) {
172173
expectedErrorMessage: "Could not parse JSON body: json: cannot unmarshal string into Go struct field datadogResponse.Series of type []struct { Pointlist [][]float64 \"json:\\\"pointlist\\\"\" }",
173174
useEnvVarForKeys: false,
174175
},
176+
177+
// Error if server address is faulty
178+
{
179+
serverURL: "://wrong.schema",
180+
metric: v1alpha1.Metric{},
181+
expectedPhase: v1alpha1.AnalysisPhaseError,
182+
expectedErrorMessage: "parse \"://wrong.schema/api/v1/query\": missing protocol scheme",
183+
useEnvVarForKeys: false,
184+
},
175185
}
176186

177187
// Run
178188

179189
for _, test := range tests {
180-
// Server setup with response
181-
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
190+
serverURL := test.serverURL
182191

183-
//Check query variables
184-
actualQuery := req.URL.Query().Get("query")
185-
actualFrom := req.URL.Query().Get("from")
186-
actualTo := req.URL.Query().Get("to")
192+
if serverURL == "" {
193+
// Server setup with response
194+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
187195

188-
if actualQuery != "avg:kubernetes.cpu.user.total{*}" {
189-
t.Errorf("\nquery expected avg:kubernetes.cpu.user.total{*} but got %s", actualQuery)
190-
}
196+
//Check query variables
197+
actualQuery := req.URL.Query().Get("query")
198+
actualFrom := req.URL.Query().Get("from")
199+
actualTo := req.URL.Query().Get("to")
191200

192-
if from, err := strconv.ParseInt(actualFrom, 10, 64); err == nil && from != unixNow()-test.expectedIntervalSeconds {
193-
t.Errorf("\nfrom %d expected be equal to %d", from, unixNow()-test.expectedIntervalSeconds)
194-
} else if err != nil {
195-
t.Errorf("\nfailed to parse from: %v", err)
196-
}
201+
if actualQuery != "avg:kubernetes.cpu.user.total{*}" {
202+
t.Errorf("\nquery expected avg:kubernetes.cpu.user.total{*} but got %s", actualQuery)
203+
}
197204

198-
if to, err := strconv.ParseInt(actualTo, 10, 64); err == nil && to != unixNow() {
199-
t.Errorf("\nto %d was expected be equal to %d", to, unixNow())
200-
} else if err != nil {
201-
t.Errorf("\nfailed to parse to: %v", err)
202-
}
205+
if from, err := strconv.ParseInt(actualFrom, 10, 64); err == nil && from != unixNow()-test.expectedIntervalSeconds {
206+
t.Errorf("\nfrom %d expected be equal to %d", from, unixNow()-test.expectedIntervalSeconds)
207+
} else if err != nil {
208+
t.Errorf("\nfailed to parse from: %v", err)
209+
}
203210

204-
//Check headers
205-
if req.Header.Get("Content-Type") != "application/json" {
206-
t.Errorf("\nContent-Type header expected to be application/json but got %s", req.Header.Get("Content-Type"))
207-
}
208-
if req.Header.Get("DD-API-KEY") != expectedApiKey {
209-
t.Errorf("\nDD-API-KEY header expected %s but got %s", expectedApiKey, req.Header.Get("DD-API-KEY"))
210-
}
211-
if req.Header.Get("DD-APPLICATION-KEY") != expectedAppKey {
212-
t.Errorf("\nDD-APPLICATION-KEY header expected %s but got %s", expectedAppKey, req.Header.Get("DD-APPLICATION-KEY"))
213-
}
211+
if to, err := strconv.ParseInt(actualTo, 10, 64); err == nil && to != unixNow() {
212+
t.Errorf("\nto %d was expected be equal to %d", to, unixNow())
213+
} else if err != nil {
214+
t.Errorf("\nfailed to parse to: %v", err)
215+
}
214216

215-
// Return mock response
216-
if test.webServerStatus < 200 || test.webServerStatus >= 300 {
217-
http.Error(rw, test.webServerResponse, test.webServerStatus)
218-
} else {
219-
rw.Header().Set("Content-Type", "application/json")
220-
io.WriteString(rw, test.webServerResponse)
221-
}
222-
}))
223-
defer server.Close()
217+
//Check headers
218+
if req.Header.Get("Content-Type") != "application/json" {
219+
t.Errorf("\nContent-Type header expected to be application/json but got %s", req.Header.Get("Content-Type"))
220+
}
221+
if req.Header.Get("DD-API-KEY") != expectedApiKey {
222+
t.Errorf("\nDD-API-KEY header expected %s but got %s", expectedApiKey, req.Header.Get("DD-API-KEY"))
223+
}
224+
if req.Header.Get("DD-APPLICATION-KEY") != expectedAppKey {
225+
t.Errorf("\nDD-APPLICATION-KEY header expected %s but got %s", expectedAppKey, req.Header.Get("DD-APPLICATION-KEY"))
226+
}
227+
228+
// Return mock response
229+
if test.webServerStatus < 200 || test.webServerStatus >= 300 {
230+
http.Error(rw, test.webServerResponse, test.webServerStatus)
231+
} else {
232+
rw.Header().Set("Content-Type", "application/json")
233+
io.WriteString(rw, test.webServerResponse)
234+
}
235+
}))
236+
defer server.Close()
237+
238+
serverURL = server.URL
239+
}
224240

225241
tokenSecret := &corev1.Secret{
226242
ObjectMeta: metav1.ObjectMeta{
227243
Name: DatadogTokensSecretName,
228244
},
229245
Data: map[string][]byte{
230-
"address": []byte(server.URL),
246+
"address": []byte(serverURL),
231247
"api-key": []byte(expectedApiKey),
232248
"app-key": []byte(expectedAppKey),
233249
},
@@ -236,7 +252,7 @@ func TestRunSuite(t *testing.T) {
236252
if test.useEnvVarForKeys {
237253
os.Setenv("DD_API_KEY", expectedApiKey)
238254
os.Setenv("DD_APP_KEY", expectedAppKey)
239-
os.Setenv("DD_ADDRESS", server.URL)
255+
os.Setenv("DD_ADDRESS", serverURL)
240256
} else {
241257
os.Unsetenv("DD_API_KEY")
242258
os.Unsetenv("DD_APP_KEY")

0 commit comments

Comments
 (0)