Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/nodes/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var _ = Describe("Raw node data", func() {
Expect(err).To(HaveOccurred())
Expect(err).To(
BeUnwrappableErrorWith(
HaveLen(4),
HaveLen(5),
HaveEach(MatchError(ContainSubstring("error retrieving node data")))),
)
Expect(len(data)).To(BeNumerically("==", 0))
Expand All @@ -79,7 +79,7 @@ var _ = Describe("Raw node data", func() {
}

nodes := getReadyNodes(mockNcs.cache)
Expect(len(nodes)).To(BeNumerically("==", 4))
Expect(len(nodes)).To(BeNumerically("==", 5))
// Note: Nodes.jsonl isn't in any order
Expect(nodes[0].ObjectMeta.Name).Should(Equal("nodename4"))
})
Expand Down
3 changes: 2 additions & 1 deletion pkg/nodes/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"math"
"net"
"net/http"
"strconv"
"time"
Expand Down Expand Up @@ -92,7 +93,7 @@ type directNode struct {
}

func (d directNode) formatEndpoint(s string) string {
return fmt.Sprintf("https://%s:%v/%s", d.ip, d.port, s)
return fmt.Sprintf("https://%s/%s", net.JoinHostPort(d.ip, strconv.FormatInt(d.port, 10)), s)
}

// setupDirectNodeAPI retrieves node stats directly from the node api
Expand Down
165 changes: 165 additions & 0 deletions pkg/nodes/request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package nodes

import (
"net/url"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("directNode formatEndpoint", func() {
Context("IPv4 addresses", func() {
It("should format IPv4 address correctly", func() {
node := directNode{
ip: "10.128.15.239",
port: 10250,
}
endpoint := node.formatEndpoint("stats/summary")
Expect(endpoint).To(Equal("https://10.128.15.239:10250/stats/summary"))

// Verify URL is parseable
parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Scheme).To(Equal("https"))
Expect(parsedURL.Host).To(Equal("10.128.15.239:10250"))
Expect(parsedURL.Path).To(Equal("/stats/summary"))
})

It("should handle different ports", func() {
node := directNode{
ip: "192.168.1.1",
port: 443,
}
endpoint := node.formatEndpoint("metrics")
Expect(endpoint).To(Equal("https://192.168.1.1:443/metrics"))

parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Host).To(Equal("192.168.1.1:443"))
})
})

Context("IPv6 addresses", func() {
It("should wrap IPv6 address in brackets", func() {
node := directNode{
ip: "2a05:d014:1314:704::a282",
port: 10250,
}
endpoint := node.formatEndpoint("stats/summary")
Expect(endpoint).To(Equal("https://[2a05:d014:1314:704::a282]:10250/stats/summary"))

// Verify URL is parseable
parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Scheme).To(Equal("https"))
Expect(parsedURL.Host).To(Equal("[2a05:d014:1314:704::a282]:10250"))
Expect(parsedURL.Path).To(Equal("/stats/summary"))
})

It("should handle IPv6 loopback address", func() {
node := directNode{
ip: "::1",
port: 10250,
}
endpoint := node.formatEndpoint("stats/summary")
Expect(endpoint).To(Equal("https://[::1]:10250/stats/summary"))

parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Host).To(Equal("[::1]:10250"))
})

It("should handle private IPv6 address", func() {
node := directNode{
ip: "fd00::1",
port: 443,
}
endpoint := node.formatEndpoint("metrics")
Expect(endpoint).To(Equal("https://[fd00::1]:443/metrics"))

parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Host).To(Equal("[fd00::1]:443"))
})

It("should handle full IPv6 address", func() {
node := directNode{
ip: "2001:db8:85a3:0:0:8a2e:370:7334",
port: 8080,
}
endpoint := node.formatEndpoint("api/v1/health")
Expect(endpoint).To(Equal("https://[2001:db8:85a3:0:0:8a2e:370:7334]:8080/api/v1/health"))

parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Scheme).To(Equal("https"))
Expect(parsedURL.Host).To(Equal("[2001:db8:85a3:0:0:8a2e:370:7334]:8080"))
Expect(parsedURL.Path).To(Equal("/api/v1/health"))
})

It("should handle compressed IPv6 address", func() {
node := directNode{
ip: "2001:db8::1",
port: 10250,
}
endpoint := node.formatEndpoint("stats/summary")
Expect(endpoint).To(Equal("https://[2001:db8::1]:10250/stats/summary"))

parsedURL, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
Expect(parsedURL.Host).To(Equal("[2001:db8::1]:10250"))
})
})

Context("Edge cases", func() {
It("should handle empty path", func() {
node := directNode{
ip: "10.0.0.1",
port: 443,
}
endpoint := node.formatEndpoint("")
Expect(endpoint).To(Equal("https://10.0.0.1:443/"))

_, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
})

It("should handle path with leading slash", func() {
node := directNode{
ip: "192.168.1.1",
port: 8080,
}
endpoint := node.formatEndpoint("/api/v1/nodes")
Expect(endpoint).To(Equal("https://192.168.1.1:8080//api/v1/nodes"))

_, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
})

It("should handle different port values", func() {
node := directNode{
ip: "10.0.0.1",
port: 1,
}
endpoint := node.formatEndpoint("test")
Expect(endpoint).To(Equal("https://10.0.0.1:1/test"))

_, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
})

It("should handle large port numbers", func() {
node := directNode{
ip: "10.0.0.1",
port: 65535,
}
endpoint := node.formatEndpoint("test")
Expect(endpoint).To(Equal("https://10.0.0.1:65535/test"))

_, err := url.Parse(endpoint)
Expect(err).ToNot(HaveOccurred())
})
})
})

// Made with Bob
Loading
Loading