Skip to content

Commit

Permalink
common/sanitize + relevant updates
Browse files Browse the repository at this point in the history
  • Loading branch information
peterbourgon committed Sep 17, 2015
1 parent 5b8afd5 commit b57965c
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 63 deletions.
39 changes: 39 additions & 0 deletions common/sanitize/sanitize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package sanitize

import (
"fmt"
"log"
"net"
"net/url"
"strings"
)

// URL returns a function that sanitizes a URL string. It lets underspecified
// strings to be converted to usable URLs via some default arguments.
func URL(scheme string, port int, path string) func(string) string {
if scheme == "" {
scheme = "http://"
}
return func(s string) string {
if s == "" {
return s // can't do much here
}
if !strings.HasPrefix(s, "http") {
s = scheme + s
}
u, err := url.Parse(s)
if err != nil {
log.Printf("%q: %v", s, err)
return s // oh well
}
if port > 0 {
if _, _, err = net.SplitHostPort(u.Host); err != nil {
u.Host += fmt.Sprintf(":%d", port)
}
}
if path != "" && u.Path != path {
u.Path = path
}
return u.String()
}
}
34 changes: 34 additions & 0 deletions common/sanitize/sanitize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package sanitize_test

import (
"testing"

"github.com/weaveworks/scope/common/sanitize"
)

func TestSanitizeURL(t *testing.T) {
for _, input := range []struct {
scheme string
port int
path string
input string
want string
}{
{"", 0, "", "", ""},
{"", 0, "", "foo", "http://foo"},
{"", 80, "", "foo", "http://foo:80"},
{"", 0, "some/path", "foo", "http://foo/some/path"},
{"", 0, "/some/path", "foo", "http://foo/some/path"},
{"https://", 0, "", "foo", "https://foo"},
{"https://", 80, "", "foo", "https://foo:80"},
{"https://", 0, "some/path", "foo", "https://foo/some/path"},
{"https://", 0, "", "http://foo", "http://foo"}, // specified scheme beats default...
{"", 9999, "", "foo:80", "http://foo:80"}, // specified port beats default...
{"", 0, "/bar", "foo/baz", "http://foo/bar"}, // ...but default path beats specified!
} {
if want, have := input.want, sanitize.URL(input.scheme, input.port, input.path)(input.input); want != have {
t.Errorf("sanitize.URL(%q, %d, %q)(%q): want %q, have %q", input.scheme, input.port, input.path, input.input, want, have)
continue
}
}
}
2 changes: 1 addition & 1 deletion experimental/demoprobe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func main() {
)
flag.Parse()

publisher, err := xfer.NewHTTPPublisher(*publish, "demoprobe", "demoprobe")
_, publisher, err := xfer.NewHTTPPublisher(*publish, "demoprobe", "demoprobe")
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion experimental/fixprobe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func main() {
}
f.Close()

publisher, err := xfer.NewHTTPPublisher(*publish, "fixprobe", "fixprobe")
_, publisher, err := xfer.NewHTTPPublisher(*publish, "fixprobe", "fixprobe")
if err != nil {
log.Fatal(err)
}
Expand Down
7 changes: 2 additions & 5 deletions probe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func main() {
}

publisherFactory := func(target string) (xfer.Publisher, error) {
publisher, err := xfer.NewHTTPPublisher(target, *token, probeID)
_, publisher, err := xfer.NewHTTPPublisher(target, *token, probeID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -139,10 +139,7 @@ func main() {
}

if *weaveRouterAddr != "" {
weave, err := overlay.NewWeave(hostID, *weaveRouterAddr)
if err != nil {
log.Fatalf("failed to start Weave tagger: %v", err)
}
weave := overlay.NewWeave(hostID, *weaveRouterAddr)
tickers = append(tickers, weave)
taggers = append(taggers, weave)
reporters = append(reporters, weave)
Expand Down
36 changes: 5 additions & 31 deletions probe/overlay/weave.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"net/url"
"regexp"
"strings"
"sync"

"github.com/weaveworks/scope/common/sanitize"

"github.com/weaveworks/scope/common/exec"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/report"
Expand Down Expand Up @@ -68,15 +68,11 @@ type weaveStatus struct {

// NewWeave returns a new Weave tagger based on the Weave router at
// address. The address should be an IP or FQDN, no port.
func NewWeave(hostID, weaveRouterAddress string) (*Weave, error) {
s, err := sanitize("http://", 6784, "/report")(weaveRouterAddress)
if err != nil {
return nil, err
}
func NewWeave(hostID, weaveRouterAddress string) *Weave {
return &Weave{
url: s,
url: sanitize.URL("http://", 6784, "/report")(weaveRouterAddress),
hostID: hostID,
}, nil
}
}

// Tick implements Ticker
Expand Down Expand Up @@ -202,25 +198,3 @@ func (w *Weave) Report() (report.Report, error) {
}
return r, nil
}

func sanitize(scheme string, port int, path string) func(string) (string, error) {
return func(s string) (string, error) {
if s == "" {
return "", fmt.Errorf("no host")
}
if !strings.HasPrefix(s, "http") {
s = scheme + s
}
u, err := url.Parse(s)
if err != nil {
return "", err
}
if _, _, err = net.SplitHostPort(u.Host); err != nil {
u.Host += fmt.Sprintf(":%d", port)
}
if u.Path != path {
u.Path = path
}
return u.String(), nil
}
}
6 changes: 1 addition & 5 deletions probe/overlay/weave_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ func TestWeaveTaggerOverlayTopology(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(mockWeaveRouter))
defer s.Close()

w, err := overlay.NewWeave(mockHostID, s.URL)
if err != nil {
t.Fatal(err)
}

w := overlay.NewWeave(mockHostID, s.URL)
w.Tick()

{
Expand Down
41 changes: 22 additions & 19 deletions xfer/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package xfer

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"strings"
"sync"
"time"

"github.com/weaveworks/scope/common/sanitize"
)

const (
Expand All @@ -17,17 +19,17 @@ const (
)

// Publisher is something which can send a buffered set of data somewhere,
// probably to a collector.
// probably to a remote collector.
type Publisher interface {
Publish(*bytes.Buffer) error
Stop()
}

// HTTPPublisher publishes reports by POST to a fixed endpoint.
type HTTPPublisher struct {
url string
token string
id string
url string
token string
probeID string
}

// ScopeProbeIDHeader is the header we use to carry the probe's unique ID. The
Expand All @@ -37,21 +39,23 @@ type HTTPPublisher struct {
const ScopeProbeIDHeader = "X-Scope-Probe-ID"

// NewHTTPPublisher returns an HTTPPublisher ready for use.
func NewHTTPPublisher(target, token, id string) (*HTTPPublisher, error) {
if !strings.HasPrefix(target, "http") {
target = "http://" + target
}
u, err := url.Parse(target)
func NewHTTPPublisher(target, token, probeID string) (string, *HTTPPublisher, error) {
targetAPI := sanitize.URL("http://", 0, "/api")(target)
resp, err := http.Get(targetAPI)
if err != nil {
return nil, err
return "", nil, err
}
if u.Path == "" {
u.Path = "/api/report"
defer resp.Body.Close()
var apiResponse struct {
ID string `json:"id"`
}
return &HTTPPublisher{
url: u.String(),
token: token,
id: id,
if err := json.NewDecoder(resp.Body).Decode(&apiResponse); err != nil {
return "", nil, err
}
return apiResponse.ID, &HTTPPublisher{
url: sanitize.URL("http://", 0, "/api/report")(target),
token: token,
probeID: probeID,
}, nil
}

Expand All @@ -65,9 +69,8 @@ func (p HTTPPublisher) Publish(buf *bytes.Buffer) error {
if err != nil {
return err
}

req.Header.Set("Authorization", AuthorizationHeader(p.token))
req.Header.Set(ScopeProbeIDHeader, p.id)
req.Header.Set(ScopeProbeIDHeader, p.probeID)
req.Header.Set("Content-Encoding", "gzip")
// req.Header.Set("Content-Type", "application/binary") // TODO: we should use http.DetectContentType(..) on the gob'ed

Expand Down
8 changes: 7 additions & 1 deletion xfer/publisher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"compress/gzip"
"encoding/gob"
"encoding/json"
"net/http"
"net/http/httptest"
"reflect"
Expand All @@ -27,6 +28,11 @@ func TestHTTPPublisher(t *testing.T) {
)

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api" {
json.NewEncoder(w).Encode(map[string]string{"id": "irrelevant"})
return
}

if want, have := xfer.AuthorizationHeader(token), r.Header.Get("Authorization"); want != have {
t.Errorf("want %q, have %q", want, have)
}
Expand Down Expand Up @@ -61,7 +67,7 @@ func TestHTTPPublisher(t *testing.T) {
s := httptest.NewServer(handlers.CompressHandler(handler))
defer s.Close()

p, err := xfer.NewHTTPPublisher(s.URL, token, id)
_, p, err := xfer.NewHTTPPublisher(s.URL, token, id)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit b57965c

Please sign in to comment.