[mqtt] Implements mqtt publish tooling
This commit is contained in:
112
vendor/github.com/testcontainers/testcontainers-go/wait/host_port.go
generated
vendored
Normal file
112
vendor/github.com/testcontainers/testcontainers-go/wait/host_port.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package wait
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// Implement interface
|
||||
var _ Strategy = (*HostPortStrategy)(nil)
|
||||
|
||||
type HostPortStrategy struct {
|
||||
Port nat.Port
|
||||
// all WaitStrategies should have a startupTimeout to avoid waiting infinitely
|
||||
startupTimeout time.Duration
|
||||
}
|
||||
|
||||
// NewHostPortStrategy constructs a default host port strategy
|
||||
func NewHostPortStrategy(port nat.Port) *HostPortStrategy {
|
||||
return &HostPortStrategy{
|
||||
Port: port,
|
||||
startupTimeout: defaultStartupTimeout(),
|
||||
}
|
||||
}
|
||||
|
||||
// fluent builders for each property
|
||||
// since go has neither covariance nor generics, the return type must be the type of the concrete implementation
|
||||
// this is true for all properties, even the "shared" ones like startupTimeout
|
||||
|
||||
// ForListeningPort is a helper similar to those in Wait.java
|
||||
// https://github.com/testcontainers/testcontainers-java/blob/1d85a3834bd937f80aad3a4cec249c027f31aeb4/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java
|
||||
func ForListeningPort(port nat.Port) *HostPortStrategy {
|
||||
return NewHostPortStrategy(port)
|
||||
}
|
||||
|
||||
func (hp *HostPortStrategy) WithStartupTimeout(startupTimeout time.Duration) *HostPortStrategy {
|
||||
hp.startupTimeout = startupTimeout
|
||||
return hp
|
||||
}
|
||||
|
||||
// WaitUntilReady implements Strategy.WaitUntilReady
|
||||
func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) {
|
||||
// limit context to startupTimeout
|
||||
ctx, cancelContext := context.WithTimeout(ctx, hp.startupTimeout)
|
||||
defer cancelContext()
|
||||
|
||||
ipAddress, err := target.Host(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
port, err := target.MappedPort(ctx, hp.Port)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
proto := port.Proto()
|
||||
portNumber := port.Int()
|
||||
portString := strconv.Itoa(portNumber)
|
||||
|
||||
//external check
|
||||
dialer := net.Dialer{}
|
||||
address := net.JoinHostPort(ipAddress, portString)
|
||||
for {
|
||||
conn, err := dialer.DialContext(ctx, proto, address)
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
if v, ok := err.(*net.OpError); ok {
|
||||
if v2, ok := (v.Err).(*os.SyscallError); ok {
|
||||
if v2.Err == syscall.ECONNREFUSED {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
//internal check
|
||||
command := buildInternalCheckCommand(hp.Port.Int())
|
||||
for {
|
||||
exitCode, err := target.Exec(ctx, []string{"/bin/bash", "-c", command})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "host port waiting failed")
|
||||
}
|
||||
|
||||
if exitCode == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildInternalCheckCommand(internalPort int) string {
|
||||
command := `(
|
||||
cat /proc/net/tcp{,6} | awk '{print $2}' | grep -i :%x ||
|
||||
nc -vz -w 1 localhost %d ||
|
||||
/bin/bash -c '</dev/tcp/localhost/%d'
|
||||
)
|
||||
`
|
||||
return "true && " + fmt.Sprintf(command, internalPort, internalPort, internalPort)
|
||||
}
|
147
vendor/github.com/testcontainers/testcontainers-go/wait/http.go
generated
vendored
Normal file
147
vendor/github.com/testcontainers/testcontainers-go/wait/http.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
package wait
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// Implement interface
|
||||
var _ Strategy = (*HTTPStrategy)(nil)
|
||||
|
||||
type HTTPStrategy struct {
|
||||
// all Strategies should have a startupTimeout to avoid waiting infinitely
|
||||
startupTimeout time.Duration
|
||||
|
||||
// additional properties
|
||||
Port nat.Port
|
||||
Path string
|
||||
StatusCodeMatcher func(status int) bool
|
||||
UseTLS bool
|
||||
AllowInsecure bool
|
||||
}
|
||||
|
||||
// NewHTTPStrategy constructs a HTTP strategy waiting on port 80 and status code 200
|
||||
func NewHTTPStrategy(path string) *HTTPStrategy {
|
||||
return &HTTPStrategy{
|
||||
startupTimeout: defaultStartupTimeout(),
|
||||
Port: "80/tcp",
|
||||
Path: path,
|
||||
StatusCodeMatcher: defaultStatusCodeMatcher,
|
||||
UseTLS: false,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func defaultStatusCodeMatcher(status int) bool {
|
||||
return status == http.StatusOK
|
||||
}
|
||||
|
||||
// fluent builders for each property
|
||||
// since go has neither covariance nor generics, the return type must be the type of the concrete implementation
|
||||
// this is true for all properties, even the "shared" ones like startupTimeout
|
||||
|
||||
func (ws *HTTPStrategy) WithStartupTimeout(startupTimeout time.Duration) *HTTPStrategy {
|
||||
ws.startupTimeout = startupTimeout
|
||||
return ws
|
||||
}
|
||||
|
||||
func (ws *HTTPStrategy) WithPort(port nat.Port) *HTTPStrategy {
|
||||
ws.Port = port
|
||||
return ws
|
||||
}
|
||||
|
||||
func (ws *HTTPStrategy) WithStatusCodeMatcher(statusCodeMatcher func(status int) bool) *HTTPStrategy {
|
||||
ws.StatusCodeMatcher = statusCodeMatcher
|
||||
return ws
|
||||
}
|
||||
|
||||
func (ws *HTTPStrategy) WithTLS(useTLS bool) *HTTPStrategy {
|
||||
ws.UseTLS = useTLS
|
||||
return ws
|
||||
}
|
||||
|
||||
func (ws *HTTPStrategy) WithAllowInsecure(allowInsecure bool) *HTTPStrategy {
|
||||
ws.AllowInsecure = allowInsecure
|
||||
return ws
|
||||
}
|
||||
|
||||
// ForHTTP is a convenience method similar to Wait.java
|
||||
// https://github.com/testcontainers/testcontainers-java/blob/1d85a3834bd937f80aad3a4cec249c027f31aeb4/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java
|
||||
func ForHTTP(path string) *HTTPStrategy {
|
||||
return NewHTTPStrategy(path)
|
||||
}
|
||||
|
||||
// WaitUntilReady implements Strategy.WaitUntilReady
|
||||
func (ws *HTTPStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) {
|
||||
// limit context to startupTimeout
|
||||
ctx, cancelContext := context.WithTimeout(ctx, ws.startupTimeout)
|
||||
defer cancelContext()
|
||||
|
||||
ipAddress, err := target.Host(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
port, err := target.MappedPort(ctx, ws.Port)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if port.Proto() != "tcp" {
|
||||
return errors.New("Cannot use HTTP client on non-TCP ports")
|
||||
}
|
||||
|
||||
portNumber := port.Int()
|
||||
portString := strconv.Itoa(portNumber)
|
||||
|
||||
address := net.JoinHostPort(ipAddress, portString)
|
||||
|
||||
var proto string
|
||||
if ws.UseTLS {
|
||||
proto = "https"
|
||||
} else {
|
||||
proto = "http"
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s://%s%s", proto, address, ws.Path)
|
||||
|
||||
tripper := http.DefaultTransport
|
||||
|
||||
if ws.AllowInsecure {
|
||||
tripper.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
|
||||
client := http.Client{Timeout: ws.startupTimeout, Transport: tripper}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
Retry:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
break Retry
|
||||
default:
|
||||
resp, err := client.Do(req)
|
||||
if err != nil || !ws.StatusCodeMatcher(resp.StatusCode) {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
break Retry
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
104
vendor/github.com/testcontainers/testcontainers-go/wait/log.go
generated
vendored
Normal file
104
vendor/github.com/testcontainers/testcontainers-go/wait/log.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
package wait
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Implement interface
|
||||
var _ Strategy = (*LogStrategy)(nil)
|
||||
|
||||
// LogStrategy will wait until a given log entry shows up in the docker logs
|
||||
type LogStrategy struct {
|
||||
// all Strategies should have a startupTimeout to avoid waiting infinitely
|
||||
startupTimeout time.Duration
|
||||
|
||||
// additional properties
|
||||
Log string
|
||||
PollInterval time.Duration
|
||||
Occurrence int
|
||||
}
|
||||
|
||||
// NewLogStrategy constructs a HTTP strategy waiting on port 80 and status code 200
|
||||
func NewLogStrategy(log string) *LogStrategy {
|
||||
return &LogStrategy{
|
||||
startupTimeout: defaultStartupTimeout(),
|
||||
Log: log,
|
||||
PollInterval: 100 * time.Millisecond,
|
||||
Occurrence: 1,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fluent builders for each property
|
||||
// since go has neither covariance nor generics, the return type must be the type of the concrete implementation
|
||||
// this is true for all properties, even the "shared" ones like startupTimeout
|
||||
|
||||
// WithStartupTimeout can be used to change the default startup timeout
|
||||
func (ws *LogStrategy) WithStartupTimeout(startupTimeout time.Duration) *LogStrategy {
|
||||
ws.startupTimeout = startupTimeout
|
||||
return ws
|
||||
}
|
||||
|
||||
// WithPollInterval can be used to override the default polling interval of 100 milliseconds
|
||||
func (ws *LogStrategy) WithPollInterval(pollInterval time.Duration) *LogStrategy {
|
||||
ws.PollInterval = pollInterval
|
||||
return ws
|
||||
}
|
||||
|
||||
func (ws *LogStrategy) WithOccurrence(o int) *LogStrategy {
|
||||
// the number of occurence needs to be positive
|
||||
if o <= 0 {
|
||||
o = 1
|
||||
}
|
||||
ws.Occurrence = o
|
||||
return ws
|
||||
}
|
||||
|
||||
// ForLog is the default construction for the fluid interface.
|
||||
//
|
||||
// For Example:
|
||||
// wait.
|
||||
// ForLog("some text").
|
||||
// WithPollInterval(1 * time.Second)
|
||||
func ForLog(log string) *LogStrategy {
|
||||
return NewLogStrategy(log)
|
||||
}
|
||||
|
||||
// WaitUntilReady implements Strategy.WaitUntilReady
|
||||
func (ws *LogStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) {
|
||||
// limit context to startupTimeout
|
||||
ctx, cancelContext := context.WithTimeout(ctx, ws.startupTimeout)
|
||||
defer cancelContext()
|
||||
currentOccurence := 0
|
||||
|
||||
LOOP:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
reader, err := target.Logs(ctx)
|
||||
|
||||
if err != nil {
|
||||
time.Sleep(ws.PollInterval)
|
||||
continue
|
||||
}
|
||||
b, err := ioutil.ReadAll(reader)
|
||||
logs := string(b)
|
||||
if strings.Contains(logs, ws.Log) {
|
||||
currentOccurence++
|
||||
if ws.Occurrence == 0 || currentOccurence >= ws.Occurrence-1 {
|
||||
break LOOP
|
||||
}
|
||||
} else {
|
||||
time.Sleep(ws.PollInterval)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
47
vendor/github.com/testcontainers/testcontainers-go/wait/multi.go
generated
vendored
Normal file
47
vendor/github.com/testcontainers/testcontainers-go/wait/multi.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package wait
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Implement interface
|
||||
var _ Strategy = (*MultiStrategy)(nil)
|
||||
|
||||
type MultiStrategy struct {
|
||||
// all Strategies should have a startupTimeout to avoid waiting infinitely
|
||||
startupTimeout time.Duration
|
||||
|
||||
// additional properties
|
||||
Strategies []Strategy
|
||||
}
|
||||
|
||||
func (ms *MultiStrategy) WithStartupTimeout(startupTimeout time.Duration) *MultiStrategy {
|
||||
ms.startupTimeout = startupTimeout
|
||||
return ms
|
||||
}
|
||||
|
||||
func ForAll(strategies ...Strategy) *MultiStrategy {
|
||||
return &MultiStrategy{
|
||||
startupTimeout: defaultStartupTimeout(),
|
||||
Strategies: strategies,
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *MultiStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) {
|
||||
ctx, cancelContext := context.WithTimeout(ctx, ms.startupTimeout)
|
||||
defer cancelContext()
|
||||
|
||||
if len(ms.Strategies) == 0 {
|
||||
return fmt.Errorf("no wait strategy supplied")
|
||||
}
|
||||
|
||||
for _, strategy := range ms.Strategies {
|
||||
err := strategy.WaitUntilReady(ctx, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
24
vendor/github.com/testcontainers/testcontainers-go/wait/wait.go
generated
vendored
Normal file
24
vendor/github.com/testcontainers/testcontainers-go/wait/wait.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
package wait
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
type Strategy interface {
|
||||
WaitUntilReady(context.Context, StrategyTarget) error
|
||||
}
|
||||
|
||||
type StrategyTarget interface {
|
||||
Host(context.Context) (string, error)
|
||||
MappedPort(context.Context, nat.Port) (nat.Port, error)
|
||||
Logs(context.Context) (io.ReadCloser, error)
|
||||
Exec(ctx context.Context, cmd []string) (int, error)
|
||||
}
|
||||
|
||||
func defaultStartupTimeout() time.Duration {
|
||||
return 60 * time.Second
|
||||
}
|
Reference in New Issue
Block a user