Skip to content

Commit 594ea24

Browse files
committed
Harden URL construction and add IPv6 support
1 parent 929f72e commit 594ea24

4 files changed

Lines changed: 139 additions & 2 deletions

File tree

kubelet-to-gcm/monitor/controller/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"io"
2222
"io/ioutil"
23+
"net"
2324
"net/http"
2425
"net/url"
2526
"strings"
@@ -81,7 +82,7 @@ type Client struct {
8182
// NewClient generates a client to hit the given controller.
8283
func NewClient(host string, port uint, client *http.Client) (*Client, error) {
8384
// Parse our URL upfront, so we can fail fast.
84-
urlStr := fmt.Sprintf("http://%s:%d/metrics", host, port)
85+
urlStr := fmt.Sprintf("http://%s/metrics", net.JoinHostPort(host, fmt.Sprint(port)))
8586
metricsURL, err := url.Parse(urlStr)
8687
if err != nil {
8788
return nil, err
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
Copyright 2017 Google Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controller
18+
19+
import (
20+
"net/http"
21+
"testing"
22+
)
23+
24+
func TestNewClient(t *testing.T) {
25+
testCases := []struct {
26+
name string
27+
host string
28+
port uint
29+
expectedURL string
30+
}{
31+
{
32+
name: "IPv4",
33+
host: "127.0.0.1",
34+
port: 10250,
35+
expectedURL: "http://127.0.0.1:10250/metrics",
36+
},
37+
{
38+
name: "IPv6",
39+
host: "2001:db8::1",
40+
port: 10250,
41+
expectedURL: "http://[2001:db8::1]:10250/metrics",
42+
},
43+
{
44+
name: "Hostname",
45+
host: "localhost",
46+
port: 8080,
47+
expectedURL: "http://localhost:8080/metrics",
48+
},
49+
}
50+
51+
for _, tc := range testCases {
52+
t.Run(tc.name, func(t *testing.T) {
53+
c, err := NewClient(tc.host, tc.port, http.DefaultClient)
54+
if err != nil {
55+
t.Fatalf("NewClient failed: %v", err)
56+
}
57+
if c.metricsURL.String() != tc.expectedURL {
58+
t.Errorf("Expected URL %q, got %q", tc.expectedURL, c.metricsURL.String())
59+
}
60+
})
61+
}
62+
}

kubelet-to-gcm/monitor/kubelet/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"io/ioutil"
23+
"net"
2324
"net/http"
2425
"net/url"
2526

@@ -40,7 +41,7 @@ func NewClient(host string, port uint, client *http.Client, useAuthPort bool) (*
4041
if useAuthPort {
4142
protocol = "https"
4243
}
43-
urlStr := fmt.Sprintf("%s://%s:%d/stats/summary", protocol, host, port)
44+
urlStr := fmt.Sprintf("%s://%s/stats/summary", protocol, net.JoinHostPort(host, fmt.Sprint(port)))
4445
summaryURL, err := url.Parse(urlStr)
4546
if err != nil {
4647
return nil, err
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
Copyright 2017 Google Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kubelet
18+
19+
import (
20+
"net/http"
21+
"testing"
22+
)
23+
24+
func TestNewClient(t *testing.T) {
25+
testCases := []struct {
26+
name string
27+
host string
28+
port uint
29+
useAuthPort bool
30+
expectedURL string
31+
}{
32+
{
33+
name: "IPv4 HTTP",
34+
host: "127.0.0.1",
35+
port: 10255,
36+
useAuthPort: false,
37+
expectedURL: "http://127.0.0.1:10255/stats/summary",
38+
},
39+
{
40+
name: "IPv4 HTTPS",
41+
host: "127.0.0.1",
42+
port: 10250,
43+
useAuthPort: true,
44+
expectedURL: "https://127.0.0.1:10250/stats/summary",
45+
},
46+
{
47+
name: "IPv6 HTTP",
48+
host: "2001:db8::1",
49+
port: 10255,
50+
useAuthPort: false,
51+
expectedURL: "http://[2001:db8::1]:10255/stats/summary",
52+
},
53+
{
54+
name: "IPv6 HTTPS",
55+
host: "2001:db8::1",
56+
port: 10250,
57+
useAuthPort: true,
58+
expectedURL: "https://[2001:db8::1]:10250/stats/summary",
59+
},
60+
}
61+
62+
for _, tc := range testCases {
63+
t.Run(tc.name, func(t *testing.T) {
64+
c, err := NewClient(tc.host, tc.port, http.DefaultClient, tc.useAuthPort)
65+
if err != nil {
66+
t.Fatalf("NewClient failed: %v", err)
67+
}
68+
if c.summaryURL.String() != tc.expectedURL {
69+
t.Errorf("Expected URL %q, got %q", tc.expectedURL, c.summaryURL.String())
70+
}
71+
})
72+
}
73+
}

0 commit comments

Comments
 (0)