From 96eab1202717e073782ec399a4e0820cae15b1bb Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 17 Aug 2017 17:19:06 -0700 Subject: Updating server dependancies. (#7246) --- vendor/gopkg.in/gomail.v2/.travis.yml | 1 - vendor/gopkg.in/gomail.v2/README.md | 43 +++-- vendor/gopkg.in/gomail.v2/auth.go | 52 ++++-- vendor/gopkg.in/gomail.v2/auth_test.go | 88 +++++++-- vendor/gopkg.in/gomail.v2/example_test.go | 14 +- vendor/gopkg.in/gomail.v2/message.go | 96 ++++------ vendor/gopkg.in/gomail.v2/message_test.go | 177 +++--------------- vendor/gopkg.in/gomail.v2/mime.go | 6 +- vendor/gopkg.in/gomail.v2/mime_go14.go | 13 +- vendor/gopkg.in/gomail.v2/send.go | 11 +- vendor/gopkg.in/gomail.v2/smtp.go | 125 +++++-------- vendor/gopkg.in/gomail.v2/smtp_test.go | 118 ++++-------- vendor/gopkg.in/gomail.v2/writeto.go | 96 ++-------- vendor/gopkg.in/olivere/elastic.v5/client.go | 9 +- vendor/gopkg.in/olivere/elastic.v5/client_test.go | 16 +- vendor/gopkg.in/olivere/elastic.v5/retry_test.go | 6 +- vendor/gopkg.in/olivere/elastic.v5/run-es-5.5.1.sh | 1 + .../olivere/elastic.v5/search_aggs_bucket_terms.go | 110 ++++++----- .../elastic.v5/search_aggs_bucket_terms_test.go | 51 +++++ vendor/gopkg.in/yaml.v2/LICENSE | 208 ++++++++++++++++++++- vendor/gopkg.in/yaml.v2/README.md | 2 + vendor/gopkg.in/yaml.v2/decode_test.go | 10 +- vendor/gopkg.in/yaml.v2/example_embedded_test.go | 41 ++++ vendor/gopkg.in/yaml.v2/scannerc.go | 9 +- 24 files changed, 714 insertions(+), 589 deletions(-) create mode 100755 vendor/gopkg.in/olivere/elastic.v5/run-es-5.5.1.sh create mode 100644 vendor/gopkg.in/yaml.v2/example_embedded_test.go (limited to 'vendor/gopkg.in') diff --git a/vendor/gopkg.in/gomail.v2/.travis.yml b/vendor/gopkg.in/gomail.v2/.travis.yml index 48915e737..24edf22cc 100644 --- a/vendor/gopkg.in/gomail.v2/.travis.yml +++ b/vendor/gopkg.in/gomail.v2/.travis.yml @@ -5,5 +5,4 @@ go: - 1.3 - 1.4 - 1.5 - - 1.6 - tip diff --git a/vendor/gopkg.in/gomail.v2/README.md b/vendor/gopkg.in/gomail.v2/README.md index b3be9e146..18cb88130 100644 --- a/vendor/gopkg.in/gomail.v2/README.md +++ b/vendor/gopkg.in/gomail.v2/README.md @@ -6,12 +6,8 @@ Gomail is a simple and efficient package to send emails. It is well tested and documented. -Gomail can only send emails using an SMTP server. But the API is flexible and it -is easy to implement other methods for sending emails using a local Postfix, an -API, etc. - It is versioned using [gopkg.in](https://gopkg.in) so I promise -there will never be backward incompatible changes within each version. +they will never be backward incompatible changes within each version. It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. @@ -25,6 +21,7 @@ Gomail supports: - Automatic encoding of special characters - SSL and TLS - Sending multiple emails with the same SMTP connection +- Any method to send emails: SMTP, postfix (not included but easily doable), etc ## Documentation @@ -51,20 +48,8 @@ considered valid by the client running Gomail. As a quick workaround you can bypass the verification of the server's certificate chain and host name by using `SetTLSConfig`: - package main - - import ( - "crypto/tls" - - "gopkg.in/gomail.v2" - ) - - func main() { - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") - d.TLSConfig = &tls.Config{InsecureSkipVerify: true} - - // Send emails using d. - } + d := gomail.NewPlainDialer("smtp.example.com", "user", "123456", 587) + d.TLSConfig = &tls.Config{InsecureSkipVerify: true} Note, however, that this is insecure and should not be used in production. @@ -90,3 +75,23 @@ See [CHANGELOG.md](CHANGELOG.md). You can ask questions on the [Gomail thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion) in the Go mailing-list. + + +## Support + +If you want to support the development of Gomail, I gladly accept donations. + +I will give 100% of the money I receive to +[Enfants, Espoir Du Monde](http://www.eedm.fr/). +EEDM is a French NGO which helps children in Bangladesh, Cameroun, Haiti, India +and Madagascar. + +All its members are volunteers so its operating costs are only +1.9%. So your money will directly helps children of these countries. + +As an added bonus, your donations will also tip me by lowering my taxes :smile: + +I will send an email with the receipt of the donation to EEDM annually to all +donors. + +[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PYQKC7VFVXCFG) diff --git a/vendor/gopkg.in/gomail.v2/auth.go b/vendor/gopkg.in/gomail.v2/auth.go index d28b83ab7..4bcdd0620 100644 --- a/vendor/gopkg.in/gomail.v2/auth.go +++ b/vendor/gopkg.in/gomail.v2/auth.go @@ -7,33 +7,51 @@ import ( "net/smtp" ) -// loginAuth is an smtp.Auth that implements the LOGIN authentication mechanism. -type loginAuth struct { +// plainAuth is an smtp.Auth that implements the PLAIN authentication mechanism. +// It fallbacks to the LOGIN mechanism if it is the only mechanism advertised +// by the server. +type plainAuth struct { username string password string host string + login bool } -func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { - if !server.TLS { - advertised := false - for _, mechanism := range server.Auth { - if mechanism == "LOGIN" { - advertised = true - break - } - } - if !advertised { - return "", nil, errors.New("gomail: unencrypted connection") - } - } +func (a *plainAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { if server.Name != a.host { return "", nil, errors.New("gomail: wrong host name") } - return "LOGIN", nil, nil + + var plain, login bool + for _, a := range server.Auth { + switch a { + case "PLAIN": + plain = true + case "LOGIN": + login = true + } + } + + if !server.TLS && !plain && !login { + return "", nil, errors.New("gomail: unencrypted connection") + } + + if !plain && login { + a.login = true + return "LOGIN", nil, nil + } + + return "PLAIN", []byte("\x00" + a.username + "\x00" + a.password), nil } -func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { +func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) { + if !a.login { + if more { + return nil, errors.New("gomail: unexpected server challenge") + } + return nil, nil + } + if !more { return nil, nil } diff --git a/vendor/gopkg.in/gomail.v2/auth_test.go b/vendor/gopkg.in/gomail.v2/auth_test.go index 428ef3467..20b477214 100644 --- a/vendor/gopkg.in/gomail.v2/auth_test.go +++ b/vendor/gopkg.in/gomail.v2/auth_test.go @@ -11,51 +11,103 @@ const ( testHost = "smtp.example.com" ) -type authTest struct { +var testAuth = &plainAuth{ + username: testUser, + password: testPwd, + host: testHost, +} + +type plainAuthTest struct { auths []string challenges []string tls bool + wantProto string wantData []string wantError bool } func TestNoAdvertisement(t *testing.T) { - testLoginAuth(t, &authTest{ - auths: []string{}, - tls: false, - wantError: true, + testPlainAuth(t, &plainAuthTest{ + auths: []string{}, + challenges: []string{"Username:", "Password:"}, + tls: false, + wantProto: "PLAIN", + wantError: true, }) } func TestNoAdvertisementTLS(t *testing.T) { - testLoginAuth(t, &authTest{ + testPlainAuth(t, &plainAuthTest{ auths: []string{}, challenges: []string{"Username:", "Password:"}, tls: true, - wantData: []string{"", testUser, testPwd}, + wantProto: "PLAIN", + wantData: []string{"\x00" + testUser + "\x00" + testPwd}, }) } -func TestLogin(t *testing.T) { - testLoginAuth(t, &authTest{ +func TestPlain(t *testing.T) { + testPlainAuth(t, &plainAuthTest{ + auths: []string{"PLAIN"}, + challenges: []string{"Username:", "Password:"}, + tls: false, + wantProto: "PLAIN", + wantData: []string{"\x00" + testUser + "\x00" + testPwd}, + }) +} + +func TestPlainTLS(t *testing.T) { + testPlainAuth(t, &plainAuthTest{ + auths: []string{"PLAIN"}, + challenges: []string{"Username:", "Password:"}, + tls: true, + wantProto: "PLAIN", + wantData: []string{"\x00" + testUser + "\x00" + testPwd}, + }) +} + +func TestPlainAndLogin(t *testing.T) { + testPlainAuth(t, &plainAuthTest{ auths: []string{"PLAIN", "LOGIN"}, challenges: []string{"Username:", "Password:"}, tls: false, + wantProto: "PLAIN", + wantData: []string{"\x00" + testUser + "\x00" + testPwd}, + }) +} + +func TestPlainAndLoginTLS(t *testing.T) { + testPlainAuth(t, &plainAuthTest{ + auths: []string{"PLAIN", "LOGIN"}, + challenges: []string{"Username:", "Password:"}, + tls: true, + wantProto: "PLAIN", + wantData: []string{"\x00" + testUser + "\x00" + testPwd}, + }) +} + +func TestLogin(t *testing.T) { + testPlainAuth(t, &plainAuthTest{ + auths: []string{"LOGIN"}, + challenges: []string{"Username:", "Password:"}, + tls: false, + wantProto: "LOGIN", wantData: []string{"", testUser, testPwd}, }) } func TestLoginTLS(t *testing.T) { - testLoginAuth(t, &authTest{ + testPlainAuth(t, &plainAuthTest{ auths: []string{"LOGIN"}, challenges: []string{"Username:", "Password:"}, tls: true, + wantProto: "LOGIN", wantData: []string{"", testUser, testPwd}, }) } -func testLoginAuth(t *testing.T, test *authTest) { - auth := &loginAuth{ +func testPlainAuth(t *testing.T, test *plainAuthTest) { + auth := &plainAuth{ username: testUser, password: testPwd, host: testHost, @@ -67,13 +119,13 @@ func testLoginAuth(t *testing.T, test *authTest) { } proto, toServer, err := auth.Start(server) if err != nil && !test.wantError { - t.Fatalf("loginAuth.Start(): %v", err) + t.Fatalf("plainAuth.Start(): %v", err) } if err != nil && test.wantError { return } - if proto != "LOGIN" { - t.Errorf("invalid protocol, got %q, want LOGIN", proto) + if proto != test.wantProto { + t.Errorf("invalid protocol, got %q, want %q", proto, test.wantProto) } i := 0 @@ -82,6 +134,10 @@ func testLoginAuth(t *testing.T, test *authTest) { t.Errorf("Invalid response, got %q, want %q", got, test.wantData[i]) } + if proto == "PLAIN" { + return + } + for _, challenge := range test.challenges { i++ if i >= len(test.wantData) { @@ -90,7 +146,7 @@ func testLoginAuth(t *testing.T, test *authTest) { toServer, err = auth.Next([]byte(challenge), true) if err != nil { - t.Fatalf("loginAuth.Auth(): %v", err) + t.Fatalf("plainAuth.Auth(): %v", err) } got = string(toServer) if got != test.wantData[i] { diff --git a/vendor/gopkg.in/gomail.v2/example_test.go b/vendor/gopkg.in/gomail.v2/example_test.go index 90008abe8..8d9c6c293 100644 --- a/vendor/gopkg.in/gomail.v2/example_test.go +++ b/vendor/gopkg.in/gomail.v2/example_test.go @@ -19,7 +19,7 @@ func Example() { m.SetBody("text/html", "Hello Bob and Cora!") m.Attach("/home/Alex/lolcat.jpg") - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456") // Send the email to Bob, Cora and Dan. if err := d.DialAndSend(m); err != nil { @@ -32,7 +32,7 @@ func Example_daemon() { ch := make(chan *gomail.Message) go func() { - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456") var s gomail.SendCloser var err error @@ -79,7 +79,7 @@ func Example_newsletter() { Address string } - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456") s, err := d.Dial() if err != nil { panic(err) @@ -151,10 +151,6 @@ func ExampleSetHeader() { m.Attach("foo.jpg", gomail.SetHeader(h)) } -func ExampleRename() { - m.Attach("/tmp/0000146.jpg", gomail.Rename("picture.jpg")) -} - func ExampleMessage_AddAlternative() { m.SetBody("text/plain", "Hello!") m.AddAlternative("text/html", "

Hello!

") @@ -217,7 +213,3 @@ func ExampleSetCharset() { func ExampleSetEncoding() { m = gomail.NewMessage(gomail.SetEncoding(gomail.Base64)) } - -func ExampleSetPartEncoding() { - m.SetBody("text/plain", "Hello!", gomail.SetPartEncoding(gomail.Unencoded)) -} diff --git a/vendor/gopkg.in/gomail.v2/message.go b/vendor/gopkg.in/gomail.v2/message.go index 4bffb1e7f..2f75368bd 100644 --- a/vendor/gopkg.in/gomail.v2/message.go +++ b/vendor/gopkg.in/gomail.v2/message.go @@ -11,7 +11,7 @@ import ( // Message represents an email. type Message struct { header header - parts []*part + parts []part attachments []*file embedded []*file charset string @@ -23,9 +23,8 @@ type Message struct { type header map[string][]string type part struct { - contentType string - copier func(io.Writer) error - encoding Encoding + header header + copier func(io.Writer) error } // NewMessage creates a new message. It uses UTF-8 and quoted-printable encoding @@ -127,10 +126,6 @@ func (m *Message) SetAddressHeader(field, address, name string) { // FormatAddress formats an address and a name as a valid RFC 5322 address. func (m *Message) FormatAddress(address, name string) string { - if name == "" { - return address - } - enc := m.encodeString(name) if enc == name { m.buf.WriteByte('"') @@ -182,60 +177,53 @@ func (m *Message) GetHeader(field string) []string { return m.header[field] } -// SetBody sets the body of the message. It replaces any content previously set -// by SetBody, AddAlternative or AddAlternativeWriter. -func (m *Message) SetBody(contentType, body string, settings ...PartSetting) { - m.parts = []*part{m.newPart(contentType, newCopier(body), settings)} +// SetBody sets the body of the message. +func (m *Message) SetBody(contentType, body string) { + m.parts = []part{ + { + header: m.getPartHeader(contentType), + copier: func(w io.Writer) error { + _, err := io.WriteString(w, body) + return err + }, + }, + } } // AddAlternative adds an alternative part to the message. // // It is commonly used to send HTML emails that default to the plain text -// version for backward compatibility. AddAlternative appends the new part to -// the end of the message. So the plain text part should be added before the -// HTML part. See http://en.wikipedia.org/wiki/MIME#Alternative -func (m *Message) AddAlternative(contentType, body string, settings ...PartSetting) { - m.AddAlternativeWriter(contentType, newCopier(body), settings...) -} - -func newCopier(s string) func(io.Writer) error { - return func(w io.Writer) error { - _, err := io.WriteString(w, s) - return err - } +// version for backward compatibility. +// +// More info: http://en.wikipedia.org/wiki/MIME#Alternative +func (m *Message) AddAlternative(contentType, body string) { + m.parts = append(m.parts, + part{ + header: m.getPartHeader(contentType), + copier: func(w io.Writer) error { + _, err := io.WriteString(w, body) + return err + }, + }, + ) } // AddAlternativeWriter adds an alternative part to the message. It can be // useful with the text/template or html/template packages. -func (m *Message) AddAlternativeWriter(contentType string, f func(io.Writer) error, settings ...PartSetting) { - m.parts = append(m.parts, m.newPart(contentType, f, settings)) -} - -func (m *Message) newPart(contentType string, f func(io.Writer) error, settings []PartSetting) *part { - p := &part{ - contentType: contentType, - copier: f, - encoding: m.encoding, - } - - for _, s := range settings { - s(p) +func (m *Message) AddAlternativeWriter(contentType string, f func(io.Writer) error) { + m.parts = []part{ + { + header: m.getPartHeader(contentType), + copier: f, + }, } - - return p } -// A PartSetting can be used as an argument in Message.SetBody, -// Message.AddAlternative or Message.AddAlternativeWriter to configure the part -// added to a message. -type PartSetting func(*part) - -// SetPartEncoding sets the encoding of the part added to the message. By -// default, parts use the same encoding than the message. -func SetPartEncoding(e Encoding) PartSetting { - return PartSetting(func(p *part) { - p.encoding = e - }) +func (m *Message) getPartHeader(contentType string) header { + return map[string][]string{ + "Content-Type": {contentType + "; charset=" + m.charset}, + "Content-Transfer-Encoding": {string(m.encoding)}, + } } type file struct { @@ -264,14 +252,6 @@ func SetHeader(h map[string][]string) FileSetting { } } -// Rename is a file setting to set the name of the attachment if the name is -// different than the filename on disk. -func Rename(name string) FileSetting { - return func(f *file) { - f.Name = name - } -} - // SetCopyFunc is a file setting to replace the function that runs when the // message is sent. It should copy the content of the file to the io.Writer. // diff --git a/vendor/gopkg.in/gomail.v2/message_test.go b/vendor/gopkg.in/gomail.v2/message_test.go index acceff2a6..fdd9ff9bd 100644 --- a/vendor/gopkg.in/gomail.v2/message_test.go +++ b/vendor/gopkg.in/gomail.v2/message_test.go @@ -63,6 +63,29 @@ func TestMessage(t *testing.T) { testMessage(t, m, 0, want) } +func TestBodyWriter(t *testing.T) { + m := NewMessage() + m.SetHeader("From", "from@example.com") + m.SetHeader("To", "to@example.com") + m.AddAlternativeWriter("text/plain", func(w io.Writer) error { + _, err := w.Write([]byte("Test message")) + return err + }) + + want := &message{ + from: "from@example.com", + to: []string{"to@example.com"}, + content: "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Content-Type: text/plain; charset=UTF-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Test message", + } + + testMessage(t, m, 0, want) +} + func TestCustomMessage(t *testing.T) { m := NewMessage(SetCharset("ISO-8859-1"), SetEncoding(Base64)) m.SetHeaders(map[string][]string{ @@ -150,8 +173,7 @@ func TestAlternative(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/alternative;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/alternative; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + @@ -169,74 +191,6 @@ func TestAlternative(t *testing.T) { testMessage(t, m, 1, want) } -func TestPartSetting(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain; format=flowed", "¡Hola, señor!", SetPartEncoding(Unencoded)) - m.AddAlternative("text/html", "¡Hola, señor!") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/alternative;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; format=flowed; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: 8bit\r\n" + - "\r\n" + - "¡Hola, señor!\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/html; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestBodyWriter(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.AddAlternativeWriter("text/plain", func(w io.Writer) error { - _, err := w.Write([]byte("Test message")) - return err - }) - m.AddAlternativeWriter("text/html", func(w io.Writer) error { - _, err := w.Write([]byte("Test HTML")) - return err - }) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/alternative;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test message\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/html; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test HTML\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - func TestAttachmentOnly(t *testing.T) { m := NewMessage() m.SetHeader("From", "from@example.com") @@ -270,8 +224,7 @@ func TestAttachment(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/mixed;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + @@ -290,40 +243,6 @@ func TestAttachment(t *testing.T) { testMessage(t, m, 1, want) } -func TestRename(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "Test") - name, copy := mockCopyFile("/tmp/test.pdf") - rename := Rename("another.pdf") - m.Attach(name, copy, rename) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/mixed;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/pdf; name=\"another.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"another.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - func TestAttachmentsOnly(t *testing.T) { m := NewMessage() m.SetHeader("From", "from@example.com") @@ -336,8 +255,7 @@ func TestAttachmentsOnly(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/mixed;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + @@ -370,8 +288,7 @@ func TestAttachments(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/mixed;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + @@ -409,8 +326,7 @@ func TestEmbedded(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/related;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/related; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + @@ -451,16 +367,13 @@ func TestFullMessage(t *testing.T) { to: []string{"to@example.com"}, content: "From: from@example.com\r\n" + "To: to@example.com\r\n" + - "Content-Type: multipart/mixed;\r\n" + - " boundary=_BOUNDARY_1_\r\n" + + "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + "\r\n" + "--_BOUNDARY_1_\r\n" + - "Content-Type: multipart/related;\r\n" + - " boundary=_BOUNDARY_2_\r\n" + + "Content-Type: multipart/related; boundary=_BOUNDARY_2_\r\n" + "\r\n" + "--_BOUNDARY_2_\r\n" + - "Content-Type: multipart/alternative;\r\n" + - " boundary=_BOUNDARY_3_\r\n" + + "Content-Type: multipart/alternative; boundary=_BOUNDARY_3_\r\n" + "\r\n" + "--_BOUNDARY_3_\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + @@ -564,34 +477,6 @@ func TestBase64LineLength(t *testing.T) { testMessage(t, m, 0, want) } -func TestEmptyName(t *testing.T) { - m := NewMessage() - m.SetAddressHeader("From", "from@example.com", "") - - want := &message{ - from: "from@example.com", - content: "From: from@example.com\r\n", - } - - testMessage(t, m, 0, want) -} - -func TestEmptyHeader(t *testing.T) { - m := NewMessage() - m.SetHeaders(map[string][]string{ - "From": {"from@example.com"}, - "X-Empty": nil, - }) - - want := &message{ - from: "from@example.com", - content: "From: from@example.com\r\n" + - "X-Empty:\r\n", - } - - testMessage(t, m, 0, want) -} - func testMessage(t *testing.T, m *Message, bCount int, want *message) { err := Send(stubSendMail(t, bCount, want), m) if err != nil { diff --git a/vendor/gopkg.in/gomail.v2/mime.go b/vendor/gopkg.in/gomail.v2/mime.go index 194d4a769..51cba724b 100644 --- a/vendor/gopkg.in/gomail.v2/mime.go +++ b/vendor/gopkg.in/gomail.v2/mime.go @@ -5,7 +5,6 @@ package gomail import ( "mime" "mime/quotedprintable" - "strings" ) var newQPWriter = quotedprintable.NewWriter @@ -15,7 +14,6 @@ type mimeEncoder struct { } var ( - bEncoding = mimeEncoder{mime.BEncoding} - qEncoding = mimeEncoder{mime.QEncoding} - lastIndexByte = strings.LastIndexByte + bEncoding = mimeEncoder{mime.BEncoding} + qEncoding = mimeEncoder{mime.QEncoding} ) diff --git a/vendor/gopkg.in/gomail.v2/mime_go14.go b/vendor/gopkg.in/gomail.v2/mime_go14.go index 3dc26aa2a..246e2e5e5 100644 --- a/vendor/gopkg.in/gomail.v2/mime_go14.go +++ b/vendor/gopkg.in/gomail.v2/mime_go14.go @@ -11,15 +11,6 @@ type mimeEncoder struct { } var ( - bEncoding = mimeEncoder{quotedprintable.BEncoding} - qEncoding = mimeEncoder{quotedprintable.QEncoding} - lastIndexByte = func(s string, c byte) int { - for i := len(s) - 1; i >= 0; i-- { - - if s[i] == c { - return i - } - } - return -1 - } + bEncoding = mimeEncoder{quotedprintable.BEncoding} + qEncoding = mimeEncoder{quotedprintable.QEncoding} ) diff --git a/vendor/gopkg.in/gomail.v2/send.go b/vendor/gopkg.in/gomail.v2/send.go index 9115ebe72..3e6726509 100644 --- a/vendor/gopkg.in/gomail.v2/send.go +++ b/vendor/gopkg.in/gomail.v2/send.go @@ -20,7 +20,7 @@ type SendCloser interface { Close() error } -// A SendFunc is a function that sends emails to the given addresses. +// A SendFunc is a function that sends emails to the given adresses. // // The SendFunc type is an adapter to allow the use of ordinary functions as // email senders. If f is a function with the appropriate signature, SendFunc(f) @@ -108,9 +108,10 @@ func addAddress(list []string, addr string) []string { } func parseAddress(field string) (string, error) { - addr, err := mail.ParseAddress(field) - if err != nil { - return "", fmt.Errorf("gomail: invalid address %q: %v", field, err) + a, err := mail.ParseAddress(field) + if a == nil { + return "", err } - return addr.Address, nil + + return a.Address, err } diff --git a/vendor/gopkg.in/gomail.v2/smtp.go b/vendor/gopkg.in/gomail.v2/smtp.go index 2aa49c8b6..cf773a102 100644 --- a/vendor/gopkg.in/gomail.v2/smtp.go +++ b/vendor/gopkg.in/gomail.v2/smtp.go @@ -6,8 +6,6 @@ import ( "io" "net" "net/smtp" - "strings" - "time" ) // A Dialer is a dialer to an SMTP server. @@ -16,10 +14,6 @@ type Dialer struct { Host string // Port represents the port of the SMTP server. Port int - // Username is the username to use to authenticate to the SMTP server. - Username string - // Password is the password to use to authenticate to the SMTP server. - Password string // Auth represents the authentication mechanism used to authenticate to the // SMTP server. Auth smtp.Auth @@ -30,94 +24,83 @@ type Dialer struct { // TSLConfig represents the TLS configuration used for the TLS (when the // STARTTLS extension is used) or SSL connection. TLSConfig *tls.Config - // LocalName is the hostname sent to the SMTP server with the HELO command. - // By default, "localhost" is sent. - LocalName string } -// NewDialer returns a new SMTP Dialer. The given parameters are used to connect -// to the SMTP server. -func NewDialer(host string, port int, username, password string) *Dialer { - return &Dialer{ - Host: host, - Port: port, - Username: username, - Password: password, - SSL: port == 465, - } -} - -// NewPlainDialer returns a new SMTP Dialer. The given parameters are used to -// connect to the SMTP server. +// NewPlainDialer returns a Dialer. The given parameters are used to connect to +// the SMTP server via a PLAIN authentication mechanism. // -// Deprecated: Use NewDialer instead. +// It fallbacks to the LOGIN mechanism if it is the only mechanism advertised by +// the server. func NewPlainDialer(host string, port int, username, password string) *Dialer { - return NewDialer(host, port, username, password) + return &Dialer{ + Host: host, + Port: port, + Auth: &plainAuth{ + username: username, + password: password, + host: host, + }, + SSL: port == 465, + } } // Dial dials and authenticates to an SMTP server. The returned SendCloser // should be closed when done using it. func (d *Dialer) Dial() (SendCloser, error) { - conn, err := netDialTimeout("tcp", addr(d.Host, d.Port), 10*time.Second) + c, err := d.dial() if err != nil { return nil, err } + if d.Auth != nil { + if ok, _ := c.Extension("AUTH"); ok { + if err = c.Auth(d.Auth); err != nil { + c.Close() + return nil, err + } + } + } + + return &smtpSender{c}, nil +} + +func (d *Dialer) dial() (smtpClient, error) { if d.SSL { - conn = tlsClient(conn, d.tlsConfig()) + return d.sslDial() } + return d.starttlsDial() +} - c, err := smtpNewClient(conn, d.Host) +func (d *Dialer) starttlsDial() (smtpClient, error) { + c, err := smtpDial(addr(d.Host, d.Port)) if err != nil { return nil, err } - if d.LocalName != "" { - if err := c.Hello(d.LocalName); err != nil { + if ok, _ := c.Extension("STARTTLS"); ok { + if err := c.StartTLS(d.tlsConfig()); err != nil { + c.Close() return nil, err } } - if !d.SSL { - if ok, _ := c.Extension("STARTTLS"); ok { - if err := c.StartTLS(d.tlsConfig()); err != nil { - c.Close() - return nil, err - } - } - } - - if d.Auth == nil && d.Username != "" { - if ok, auths := c.Extension("AUTH"); ok { - if strings.Contains(auths, "CRAM-MD5") { - d.Auth = smtp.CRAMMD5Auth(d.Username, d.Password) - } else if strings.Contains(auths, "LOGIN") && - !strings.Contains(auths, "PLAIN") { - d.Auth = &loginAuth{ - username: d.Username, - password: d.Password, - host: d.Host, - } - } else { - d.Auth = smtp.PlainAuth("", d.Username, d.Password, d.Host) - } - } - } + return c, nil +} - if d.Auth != nil { - if err = c.Auth(d.Auth); err != nil { - c.Close() - return nil, err - } +func (d *Dialer) sslDial() (smtpClient, error) { + conn, err := tlsDial("tcp", addr(d.Host, d.Port), d.tlsConfig()) + if err != nil { + return nil, err } - return &smtpSender{c, d}, nil + return newClient(conn, d.Host) } func (d *Dialer) tlsConfig() *tls.Config { if d.TLSConfig == nil { return &tls.Config{ServerName: d.Host} } + return d.TLSConfig } @@ -139,21 +122,10 @@ func (d *Dialer) DialAndSend(m ...*Message) error { type smtpSender struct { smtpClient - d *Dialer } func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { if err := c.Mail(from); err != nil { - if err == io.EOF { - // This is probably due to a timeout, so reconnect and try again. - sc, derr := c.d.Dial() - if derr == nil { - if s, ok := sc.(*smtpSender); ok { - *c = *s - return c.Send(from, to, msg) - } - } - } return err } @@ -182,15 +154,16 @@ func (c *smtpSender) Close() error { // Stubbed out for tests. var ( - netDialTimeout = net.DialTimeout - tlsClient = tls.Client - smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { + smtpDial = func(addr string) (smtpClient, error) { + return smtp.Dial(addr) + } + tlsDial = tls.Dial + newClient = func(conn net.Conn, host string) (smtpClient, error) { return smtp.NewClient(conn, host) } ) type smtpClient interface { - Hello(string) error Extension(string) (bool, string) StartTLS(*tls.Config) error Auth(smtp.Auth) error diff --git a/vendor/gopkg.in/gomail.v2/smtp_test.go b/vendor/gopkg.in/gomail.v2/smtp_test.go index b6f91555b..c8503489b 100644 --- a/vendor/gopkg.in/gomail.v2/smtp_test.go +++ b/vendor/gopkg.in/gomail.v2/smtp_test.go @@ -8,7 +8,6 @@ import ( "net/smtp" "reflect" "testing" - "time" ) const ( @@ -17,14 +16,12 @@ const ( ) var ( - testConn = &net.TCPConn{} testTLSConn = &tls.Conn{} testConfig = &tls.Config{InsecureSkipVerify: true} - testAuth = smtp.PlainAuth("", testUser, testPwd, testHost) ) func TestDialer(t *testing.T) { - d := NewDialer(testHost, testPort, "user", "pwd") + d := NewPlainDialer(testHost, testPort, "user", "pwd") testSendMail(t, d, []string{ "Extension STARTTLS", "StartTLS", @@ -42,7 +39,7 @@ func TestDialer(t *testing.T) { } func TestDialerSSL(t *testing.T) { - d := NewDialer(testHost, testSSLPort, "user", "pwd") + d := NewPlainDialer(testHost, testSSLPort, "user", "pwd") testSendMail(t, d, []string{ "Extension AUTH", "Auth", @@ -58,11 +55,9 @@ func TestDialerSSL(t *testing.T) { } func TestDialerConfig(t *testing.T) { - d := NewDialer(testHost, testPort, "user", "pwd") - d.LocalName = "test" + d := NewPlainDialer(testHost, testPort, "user", "pwd") d.TLSConfig = testConfig testSendMail(t, d, []string{ - "Hello test", "Extension STARTTLS", "StartTLS", "Extension AUTH", @@ -79,11 +74,9 @@ func TestDialerConfig(t *testing.T) { } func TestDialerSSLConfig(t *testing.T) { - d := NewDialer(testHost, testSSLPort, "user", "pwd") - d.LocalName = "test" + d := NewPlainDialer(testHost, testSSLPort, "user", "pwd") d.TLSConfig = testConfig testSendMail(t, d, []string{ - "Hello test", "Extension AUTH", "Auth", "Mail " + testFrom, @@ -116,40 +109,13 @@ func TestDialerNoAuth(t *testing.T) { }) } -func TestDialerTimeout(t *testing.T) { - d := &Dialer{ - Host: testHost, - Port: testPort, - } - testSendMailTimeout(t, d, []string{ - "Extension STARTTLS", - "StartTLS", - "Mail " + testFrom, - "Extension STARTTLS", - "StartTLS", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - type mockClient struct { - t *testing.T - i int - want []string - addr string - config *tls.Config - timeout bool -} - -func (c *mockClient) Hello(localName string) error { - c.do("Hello " + localName) - return nil + t *testing.T + i int + want []string + addr string + auth smtp.Auth + config *tls.Config } func (c *mockClient) Extension(ext string) (bool, string) { @@ -164,19 +130,13 @@ func (c *mockClient) StartTLS(config *tls.Config) error { } func (c *mockClient) Auth(a smtp.Auth) error { - if !reflect.DeepEqual(a, testAuth) { - c.t.Errorf("Invalid auth, got %#v, want %#v", a, testAuth) - } + assertAuth(c.t, a, c.auth) c.do("Auth") return nil } func (c *mockClient) Mail(from string) error { c.do("Mail " + from) - if c.timeout { - c.timeout = false - return io.EOF - } return nil } @@ -232,42 +192,32 @@ func (w *mockWriter) Close() error { } func testSendMail(t *testing.T, d *Dialer, want []string) { - doTestSendMail(t, d, want, false) -} - -func testSendMailTimeout(t *testing.T, d *Dialer, want []string) { - doTestSendMail(t, d, want, true) -} - -func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { testClient := &mockClient{ - t: t, - want: want, - addr: addr(d.Host, d.Port), - config: d.TLSConfig, - timeout: timeout, + t: t, + want: want, + addr: addr(d.Host, d.Port), + auth: testAuth, + config: d.TLSConfig, } - netDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { - if network != "tcp" { - t.Errorf("Invalid network, got %q, want tcp", network) - } - if address != testClient.addr { - t.Errorf("Invalid address, got %q, want %q", - address, testClient.addr) - } - return testConn, nil + smtpDial = func(addr string) (smtpClient, error) { + assertAddr(t, addr, testClient.addr) + return testClient, nil } - tlsClient = func(conn net.Conn, config *tls.Config) *tls.Conn { - if conn != testConn { - t.Errorf("Invalid conn, got %#v, want %#v", conn, testConn) + tlsDial = func(network, addr string, config *tls.Config) (*tls.Conn, error) { + if network != "tcp" { + t.Errorf("Invalid network, got %q, want tcp", network) } + assertAddr(t, addr, testClient.addr) assertConfig(t, config, testClient.config) - return testTLSConn + return testTLSConn, nil } - smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { + newClient = func(conn net.Conn, host string) (smtpClient, error) { + if conn != testTLSConn { + t.Error("Invalid TLS connection used") + } if host != testHost { t.Errorf("Invalid host, got %q, want %q", host, testHost) } @@ -279,6 +229,18 @@ func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { } } +func assertAuth(t *testing.T, got, want smtp.Auth) { + if !reflect.DeepEqual(got, want) { + t.Errorf("Invalid auth, got %#v, want %#v", got, want) + } +} + +func assertAddr(t *testing.T, got, want string) { + if got != want { + t.Errorf("Invalid addr, got %q, want %q", got, want) + } +} + func assertConfig(t *testing.T, got, want *tls.Config) { if want == nil { want = &tls.Config{ServerName: testHost} diff --git a/vendor/gopkg.in/gomail.v2/writeto.go b/vendor/gopkg.in/gomail.v2/writeto.go index 9fb6b86e8..57a1dd7f1 100644 --- a/vendor/gopkg.in/gomail.v2/writeto.go +++ b/vendor/gopkg.in/gomail.v2/writeto.go @@ -7,7 +7,6 @@ import ( "mime" "mime/multipart" "path/filepath" - "strings" "time" ) @@ -39,7 +38,8 @@ func (w *messageWriter) writeMessage(m *Message) { w.openMultipart("alternative") } for _, part := range m.parts { - w.writePart(part, m.charset) + w.writeHeaders(part.header) + w.writeBody(part.copier, m.encoding) } if m.hasAlternativePart() { w.closeMultipart() @@ -79,7 +79,7 @@ type messageWriter struct { func (w *messageWriter) openMultipart(mimeType string) { mw := multipart.NewWriter(w) - contentType := "multipart/" + mimeType + ";\r\n boundary=" + mw.Boundary() + contentType := "multipart/" + mimeType + "; boundary=" + mw.Boundary() w.writers[w.depth] = mw if w.depth == 0 { @@ -104,14 +104,6 @@ func (w *messageWriter) closeMultipart() { } } -func (w *messageWriter) writePart(p *part, charset string) { - w.writeHeaders(map[string][]string{ - "Content-Type": {p.contentType + "; charset=" + charset}, - "Content-Transfer-Encoding": {string(p.encoding)}, - }) - w.writeBody(p.copier, p.encoding) -} - func (w *messageWriter) addFiles(files []*file, isAttachment bool) { for _, f := range files { if _, ok := f.Header["Content-Type"]; !ok { @@ -162,80 +154,24 @@ func (w *messageWriter) writeString(s string) { w.n += int64(n) } -func (w *messageWriter) writeHeader(k string, v ...string) { - w.writeString(k) - if len(v) == 0 { - w.writeString(":\r\n") - return - } - w.writeString(": ") - - // Max header line length is 78 characters in RFC 5322 and 76 characters - // in RFC 2047. So for the sake of simplicity we use the 76 characters - // limit. - charsLeft := 76 - len(k) - len(": ") - - for i, s := range v { - // If the line is already too long, insert a newline right away. - if charsLeft < 1 { - if i == 0 { - w.writeString("\r\n ") - } else { - w.writeString(",\r\n ") - } - charsLeft = 75 - } else if i != 0 { - w.writeString(", ") - charsLeft -= 2 - } - - // While the header content is too long, fold it by inserting a newline. - for len(s) > charsLeft { - s = w.writeLine(s, charsLeft) - charsLeft = 75 +func (w *messageWriter) writeStrings(a []string, sep string) { + if len(a) > 0 { + w.writeString(a[0]) + if len(a) == 1 { + return } + } + for _, s := range a[1:] { + w.writeString(sep) w.writeString(s) - if i := lastIndexByte(s, '\n'); i != -1 { - charsLeft = 75 - (len(s) - i - 1) - } else { - charsLeft -= len(s) - } } - w.writeString("\r\n") } -func (w *messageWriter) writeLine(s string, charsLeft int) string { - // If there is already a newline before the limit. Write the line. - if i := strings.IndexByte(s, '\n'); i != -1 && i < charsLeft { - w.writeString(s[:i+1]) - return s[i+1:] - } - - for i := charsLeft - 1; i >= 0; i-- { - if s[i] == ' ' { - w.writeString(s[:i]) - w.writeString("\r\n ") - return s[i+1:] - } - } - - // We could not insert a newline cleanly so look for a space or a newline - // even if it is after the limit. - for i := 75; i < len(s); i++ { - if s[i] == ' ' { - w.writeString(s[:i]) - w.writeString("\r\n ") - return s[i+1:] - } - if s[i] == '\n' { - w.writeString(s[:i+1]) - return s[i+1:] - } - } - - // Too bad, no space or newline in the whole string. Just write everything. - w.writeString(s) - return "" +func (w *messageWriter) writeHeader(k string, v ...string) { + w.writeString(k) + w.writeString(": ") + w.writeStrings(v, ", ") + w.writeString("\r\n") } func (w *messageWriter) writeHeaders(h map[string][]string) { diff --git a/vendor/gopkg.in/olivere/elastic.v5/client.go b/vendor/gopkg.in/olivere/elastic.v5/client.go index 13be369bd..e517a7fa8 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/client.go +++ b/vendor/gopkg.in/olivere/elastic.v5/client.go @@ -26,7 +26,7 @@ import ( const ( // Version is the current version of Elastic. - Version = "5.0.43" + Version = "5.0.45" // DefaultURL is the default endpoint of Elasticsearch on the local machine. // It is used e.g. when initializing a new Client without a specific URL. @@ -1257,6 +1257,13 @@ func (c *Client) PerformRequest(ctx context.Context, method, path string, params // Proceed, but don't mark the node as dead return nil, err } + if ue, ok := err.(*url.Error); ok { + // This happens e.g. on redirect errors, see https://golang.org/src/net/http/client_test.go#L329 + if ue.Err == context.Canceled || ue.Err == context.DeadlineExceeded { + // Proceed, but don't mark the node as dead + return nil, err + } + } if err != nil { n++ wait, ok, rerr := c.retrier.Retry(ctx, n, (*http.Request)(req), res, err) diff --git a/vendor/gopkg.in/olivere/elastic.v5/client_test.go b/vendor/gopkg.in/olivere/elastic.v5/client_test.go index 1441f1791..6caf7b797 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/client_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/client_test.go @@ -16,6 +16,7 @@ import ( "reflect" "regexp" "strings" + "sync" "testing" "time" @@ -294,6 +295,7 @@ func TestClientHealthcheckTimeoutLeak(t *testing.T) { // leaks via leaktest. mux := http.NewServeMux() + var reqDoneMu sync.Mutex var reqDone bool mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { cn, ok := w.(http.CloseNotifier) @@ -301,7 +303,9 @@ func TestClientHealthcheckTimeoutLeak(t *testing.T) { t.Fatalf("Writer is not CloseNotifier, but %v", reflect.TypeOf(w).Name()) } <-cn.CloseNotify() + reqDoneMu.Lock() reqDone = true + reqDoneMu.Unlock() }) lis, err := net.Listen("tcp", "127.0.0.1:0") @@ -346,9 +350,12 @@ func TestClientHealthcheckTimeoutLeak(t *testing.T) { } <-time.After(time.Second) + reqDoneMu.Lock() if !reqDone { + reqDoneMu.Unlock() t.Fatal("Request wasn't canceled or stopped") } + reqDoneMu.Unlock() } // -- NewSimpleClient -- @@ -552,6 +559,7 @@ func TestClientSniffTimeoutLeak(t *testing.T) { // leaks via leaktest. mux := http.NewServeMux() + var reqDoneMu sync.Mutex var reqDone bool mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { cn, ok := w.(http.CloseNotifier) @@ -559,7 +567,9 @@ func TestClientSniffTimeoutLeak(t *testing.T) { t.Fatalf("Writer is not CloseNotifier, but %v", reflect.TypeOf(w).Name()) } <-cn.CloseNotify() + reqDoneMu.Lock() reqDone = true + reqDoneMu.Unlock() }) lis, err := net.Listen("tcp", "127.0.0.1:0") @@ -605,9 +615,12 @@ func TestClientSniffTimeoutLeak(t *testing.T) { } <-time.After(time.Second) + reqDoneMu.Lock() if !reqDone { + reqDoneMu.Unlock() t.Fatal("Request wasn't canceled or stopped") } + reqDoneMu.Unlock() } func TestClientExtractHostname(t *testing.T) { @@ -1195,7 +1208,8 @@ func TestPerformRequestWithTimeout(t *testing.T) { res *Response err error } - ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() resc := make(chan result, 1) go func() { diff --git a/vendor/gopkg.in/olivere/elastic.v5/retry_test.go b/vendor/gopkg.in/olivere/elastic.v5/retry_test.go index 14ebbb835..804313095 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/retry_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/retry_test.go @@ -21,14 +21,14 @@ func TestRetry(t *testing.T) { // This function is successfull on "successOn" calls. f := func() error { i++ - t.Logf("function is called %d. time\n", i) + // t.Logf("function is called %d. time\n", i) if i == successOn { - t.Log("OK") + // t.Log("OK") return nil } - t.Log("error") + // t.Log("error") return errors.New("error") } diff --git a/vendor/gopkg.in/olivere/elastic.v5/run-es-5.5.1.sh b/vendor/gopkg.in/olivere/elastic.v5/run-es-5.5.1.sh new file mode 100755 index 000000000..343a605ba --- /dev/null +++ b/vendor/gopkg.in/olivere/elastic.v5/run-es-5.5.1.sh @@ -0,0 +1 @@ +docker run --rm --privileged=true -p 9200:9200 -p 9300:9300 -v "$PWD/etc:/usr/share/elasticsearch/config" -e ES_JAVA_OPTS='-Xms1g -Xmx1g' elasticsearch:5.5.1 elasticsearch diff --git a/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms.go b/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms.go index 5497aa6e9..6bcc322d0 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms.go +++ b/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms.go @@ -20,15 +20,10 @@ type TermsAggregation struct { minDocCount *int shardMinDocCount *int valueType string - includePattern string - includeFlags *int - excludePattern string - excludeFlags *int + includeExclude *TermsAggregationIncludeExclude executionHint string collectionMode string showTermDocCountError *bool - includeTerms []string - excludeTerms []string order []TermsOrder } @@ -91,24 +86,50 @@ func (a *TermsAggregation) ShardMinDocCount(shardMinDocCount int) *TermsAggregat } func (a *TermsAggregation) Include(regexp string) *TermsAggregation { - a.includePattern = regexp + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.Include = regexp return a } -func (a *TermsAggregation) IncludeWithFlags(regexp string, flags int) *TermsAggregation { - a.includePattern = regexp - a.includeFlags = &flags +func (a *TermsAggregation) IncludeValues(values ...interface{}) *TermsAggregation { + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...) return a } func (a *TermsAggregation) Exclude(regexp string) *TermsAggregation { - a.excludePattern = regexp + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.Exclude = regexp + return a +} + +func (a *TermsAggregation) ExcludeValues(values ...interface{}) *TermsAggregation { + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...) + return a +} + +func (a *TermsAggregation) Partition(p int) *TermsAggregation { + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.Partition = p return a } -func (a *TermsAggregation) ExcludeWithFlags(regexp string, flags int) *TermsAggregation { - a.excludePattern = regexp - a.excludeFlags = &flags +func (a *TermsAggregation) NumPartitions(n int) *TermsAggregation { + if a.includeExclude == nil { + a.includeExclude = &TermsAggregationIncludeExclude{} + } + a.includeExclude.NumPartitions = n return a } @@ -207,16 +228,6 @@ func (a *TermsAggregation) ShowTermDocCountError(showTermDocCountError bool) *Te return a } -func (a *TermsAggregation) IncludeTerms(terms ...string) *TermsAggregation { - a.includeTerms = append(a.includeTerms, terms...) - return a -} - -func (a *TermsAggregation) ExcludeTerms(terms ...string) *TermsAggregation { - a.excludeTerms = append(a.excludeTerms, terms...) - return a -} - func (a *TermsAggregation) Source() (interface{}, error) { // Example: // { @@ -283,32 +294,27 @@ func (a *TermsAggregation) Source() (interface{}, error) { } opts["order"] = orderSlice } - if len(a.includeTerms) > 0 { - opts["include"] = a.includeTerms - } - if a.includePattern != "" { - if a.includeFlags == nil || *a.includeFlags == 0 { - opts["include"] = a.includePattern - } else { - p := make(map[string]interface{}) - p["pattern"] = a.includePattern - p["flags"] = *a.includeFlags - opts["include"] = p + // Include/Exclude + if ie := a.includeExclude; ie != nil { + // Include + if ie.Include != "" { + opts["include"] = ie.Include + } else if len(ie.IncludeValues) > 0 { + opts["include"] = ie.IncludeValues + } else if ie.NumPartitions > 0 { + inc := make(map[string]interface{}) + inc["partition"] = ie.Partition + inc["num_partitions"] = ie.NumPartitions + opts["include"] = inc } - } - if len(a.excludeTerms) > 0 { - opts["exclude"] = a.excludeTerms - } - if a.excludePattern != "" { - if a.excludeFlags == nil || *a.excludeFlags == 0 { - opts["exclude"] = a.excludePattern - } else { - p := make(map[string]interface{}) - p["pattern"] = a.excludePattern - p["flags"] = *a.excludeFlags - opts["exclude"] = p + // Exclude + if ie.Exclude != "" { + opts["exclude"] = ie.Exclude + } else if len(ie.ExcludeValues) > 0 { + opts["exclude"] = ie.ExcludeValues } } + if a.executionHint != "" { opts["execution_hint"] = a.executionHint } @@ -334,6 +340,16 @@ func (a *TermsAggregation) Source() (interface{}, error) { return source, nil } +// TermsAggregationIncludeExclude allows for include/exclude in a TermsAggregation. +type TermsAggregationIncludeExclude struct { + Include string + Exclude string + IncludeValues []interface{} + ExcludeValues []interface{} + Partition int + NumPartitions int +} + // TermsOrder specifies a single order field for a terms aggregation. type TermsOrder struct { Field string diff --git a/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms_test.go b/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms_test.go index 6b5c1bb8a..351cbf63b 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/search_aggs_bucket_terms_test.go @@ -102,3 +102,54 @@ func TestTermsAggregationWithMissing(t *testing.T) { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } } + +func TestTermsAggregationWithIncludeExclude(t *testing.T) { + agg := NewTermsAggregation().Field("tags").Include(".*sport.*").Exclude("water_.*") + src, err := agg.Source() + if err != nil { + t.Fatal(err) + } + data, err := json.Marshal(src) + if err != nil { + t.Fatalf("marshaling to JSON failed: %v", err) + } + got := string(data) + expected := `{"terms":{"exclude":"water_.*","field":"tags","include":".*sport.*"}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestTermsAggregationWithIncludeExcludeValues(t *testing.T) { + agg := NewTermsAggregation().Field("make").IncludeValues("mazda", "honda").ExcludeValues("rover", "jensen") + src, err := agg.Source() + if err != nil { + t.Fatal(err) + } + data, err := json.Marshal(src) + if err != nil { + t.Fatalf("marshaling to JSON failed: %v", err) + } + got := string(data) + expected := `{"terms":{"exclude":["rover","jensen"],"field":"make","include":["mazda","honda"]}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestTermsAggregationWithPartitions(t *testing.T) { + agg := NewTermsAggregation().Field("account_id").Partition(0).NumPartitions(20) + src, err := agg.Source() + if err != nil { + t.Fatal(err) + } + data, err := json.Marshal(src) + if err != nil { + t.Fatalf("marshaling to JSON failed: %v", err) + } + got := string(data) + expected := `{"terms":{"field":"account_id","include":{"num_partitions":20,"partition":0}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} diff --git a/vendor/gopkg.in/yaml.v2/LICENSE b/vendor/gopkg.in/yaml.v2/LICENSE index 866d74a7a..8dada3eda 100644 --- a/vendor/gopkg.in/yaml.v2/LICENSE +++ b/vendor/gopkg.in/yaml.v2/LICENSE @@ -1,13 +1,201 @@ -Copyright 2011-2016 Canonical Ltd. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v2/README.md index 1884de6a7..7a512d67c 100644 --- a/vendor/gopkg.in/yaml.v2/README.md +++ b/vendor/gopkg.in/yaml.v2/README.md @@ -48,6 +48,8 @@ The yaml package is licensed under the Apache License 2.0. Please see the LICENS Example ------- +Some more examples can be found in the "examples" folder. + ```Go package main diff --git a/vendor/gopkg.in/yaml.v2/decode_test.go b/vendor/gopkg.in/yaml.v2/decode_test.go index 3d0807a07..713b1ee9c 100644 --- a/vendor/gopkg.in/yaml.v2/decode_test.go +++ b/vendor/gopkg.in/yaml.v2/decode_test.go @@ -405,6 +405,12 @@ var unmarshalTests = []struct { map[string]interface{}{"v": 1}, }, + // Non-specific tag (Issue #75) + { + "v: ! test", + map[string]interface{}{"v": "test"}, + }, + // Anchors and aliases. { "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", @@ -604,7 +610,8 @@ type inlineC struct { } func (s *S) TestUnmarshal(c *C) { - for _, item := range unmarshalTests { + for i, item := range unmarshalTests { + c.Logf("test %d: %q", i, item.data) t := reflect.ValueOf(item.value).Type() var value interface{} switch t.Kind() { @@ -648,6 +655,7 @@ var unmarshalErrorTests = []struct { {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, + {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, } func (s *S) TestUnmarshalErrors(c *C) { diff --git a/vendor/gopkg.in/yaml.v2/example_embedded_test.go b/vendor/gopkg.in/yaml.v2/example_embedded_test.go new file mode 100644 index 000000000..c8b241d54 --- /dev/null +++ b/vendor/gopkg.in/yaml.v2/example_embedded_test.go @@ -0,0 +1,41 @@ +package yaml_test + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v2" +) + +// An example showing how to unmarshal embedded +// structs from YAML. + +type StructA struct { + A string `yaml:"a"` +} + +type StructB struct { + // Embedded structs are not treated as embedded in YAML by default. To do that, + // add the ",inline" annotation below + StructA `yaml:",inline"` + B string `yaml:"b"` +} + +var data = ` +a: a string from struct A +b: a string from struct B +` + +func ExampleUnmarshal_embedded() { + var b StructB + + err := yaml.Unmarshal([]byte(data), &b) + if err != nil { + log.Fatal("cannot unmarshal data: %v", err) + } + fmt.Println(b.A) + fmt.Println(b.B) + // Output: + // a string from struct A + // a string from struct B +} diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go index 2c9d5111f..074484455 100644 --- a/vendor/gopkg.in/yaml.v2/scannerc.go +++ b/vendor/gopkg.in/yaml.v2/scannerc.go @@ -611,7 +611,7 @@ func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, co if directive { context = "while parsing a %TAG directive" } - return yaml_parser_set_scanner_error(parser, context, context_mark, "did not find URI escaped octet") + return yaml_parser_set_scanner_error(parser, context, context_mark, problem) } func trace(args ...interface{}) func() { @@ -1944,7 +1944,7 @@ func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_ma } else { // It's either the '!' tag or not really a tag handle. If it's a %TAG // directive, it's an error. If it's a tag token, it must be a part of URI. - if directive && !(s[0] == '!' && s[1] == 0) { + if directive && string(s) != "!" { yaml_parser_set_scanner_tag_error(parser, directive, start_mark, "did not find expected '!'") return false @@ -1959,6 +1959,7 @@ func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_ma func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { //size_t length = head ? strlen((char *)head) : 0 var s []byte + hasTag := len(head) > 0 // Copy the head if needed. // @@ -2000,10 +2001,10 @@ func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { return false } + hasTag = true } - // Check if the tag is non-empty. - if len(s) == 0 { + if !hasTag { yaml_parser_set_scanner_tag_error(parser, directive, start_mark, "did not find expected tag URI") return false -- cgit v1.2.3-1-g7c22