Merge pull request #90797 from fedepaol/sctpconnectporter

Add SCTP support to agnhost connect / porter commands.
This commit is contained in:
Kubernetes Prow Robot 2020-06-23 07:05:41 -07:00 committed by GitHub
commit 0072d8ae23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 132 additions and 36 deletions

View File

@ -88,7 +88,7 @@ Usage:
### connect ### connect
Tries to open a TCP connection to the given host and port. On error it Tries to open a TCP or SCTP connection to the given host and port. On error it
prints an error message prefixed with a specific fixed string that prints an error message prefixed with a specific fixed string that
test cases can check for: test cases can check for:
@ -105,9 +105,11 @@ output than to check the exit code.)
Usage: Usage:
```console ```console
kubectl exec test-agnost -- /agnost connect [--timeout=<duration>] <host>:<port> kubectl exec test-agnhost -- /agnhost connect [--timeout=<duration>] [--protocol=<protocol>] <host>:<port>
``` ```
The optional `--protocol` parameter can be set to `sctp` to test SCTP
connections. The default value is `tcp`.
### crd-conversion-webhook ### crd-conversion-webhook
@ -543,10 +545,10 @@ Usage:
### porter ### porter
Serves requested data on ports specified in ENV variables. For example, if the environment Serves requested data on ports specified in environment variables of the form `SERVE_{PORT,TLS_PORT,SCTP_PORT}_[NNNN]`. eg:
variable `SERVE_PORT_9001` is set, then the subcommand will start serving on the port 9001. - `SERVE_PORT_9001` - serve TCP connections on port 9001
Additionally, if the environment variable `SERVE_TLS_PORT_9002` is set, then the subcommand - `SERVE_TLS_PORT_9002` - serve TLS-encrypted TCP connections on port 9002
will start a TLS server on that port. - `SERVE_SCTP_PORT_9003` - serve SCTP connections on port 9003
The included `localhost.crt` is a PEM-encoded TLS cert with SAN IPs `127.0.0.1` and `[::1]`, The included `localhost.crt` is a PEM-encoded TLS cert with SAN IPs `127.0.0.1` and `[::1]`,
expiring in January 2084, generated from `src/crypto/tls`: expiring in January 2084, generated from `src/crypto/tls`:

View File

@ -9,7 +9,10 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["connect.go"], srcs = ["connect.go"],
importpath = "k8s.io/kubernetes/test/images/agnhost/connect", importpath = "k8s.io/kubernetes/test/images/agnhost/connect",
deps = ["//vendor/github.com/spf13/cobra:go_default_library"], deps = [
"//vendor/github.com/ishidawataru/sctp:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
],
) )
filegroup( filegroup(

View File

@ -23,14 +23,15 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/ishidawataru/sctp"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// CmdConnect is used by agnhost Cobra. // CmdConnect is used by agnhost Cobra.
var CmdConnect = &cobra.Command{ var CmdConnect = &cobra.Command{
Use: "connect [host:port]", Use: "connect [host:port]",
Short: "Attempts a TCP connection and returns useful errors", Short: "Attempts a TCP or SCTP connection and returns useful errors",
Long: `Tries to open a TCP connection to the given host and port. On error it prints an error message prefixed with a specific fixed string that test cases can check for: Long: `Tries to open a TCP or SCTP connection to the given host and port. On error it prints an error message prefixed with a specific fixed string that test cases can check for:
* UNKNOWN - Generic/unknown (non-network) error (eg, bad arguments) * UNKNOWN - Generic/unknown (non-network) error (eg, bad arguments)
* TIMEOUT - The connection attempt timed out * TIMEOUT - The connection attempt timed out
@ -42,14 +43,27 @@ var CmdConnect = &cobra.Command{
} }
var timeout time.Duration var timeout time.Duration
var protocol string
func init() { func init() {
CmdConnect.Flags().DurationVar(&timeout, "timeout", time.Duration(0), "Maximum time before returning an error") CmdConnect.Flags().DurationVar(&timeout, "timeout", time.Duration(0), "Maximum time before returning an error")
CmdConnect.Flags().StringVar(&protocol, "protocol", "tcp", "The protocol to use to perform the connection, can be tcp or sctp")
} }
func main(cmd *cobra.Command, args []string) { func main(cmd *cobra.Command, args []string) {
dest := args[0] dest := args[0]
switch protocol {
case "", "tcp":
connectTCP(dest, timeout)
case "sctp":
connectSCTP(dest, timeout)
default:
fmt.Fprint(os.Stderr, "Unsupported protocol\n", protocol)
os.Exit(1)
}
}
func connectTCP(dest string, timeout time.Duration) {
// Redundantly parse and resolve the destination so we can return the correct // Redundantly parse and resolve the destination so we can return the correct
// errors if there's a problem. // errors if there's a problem.
if _, _, err := net.SplitHostPort(dest); err != nil { if _, _, err := net.SplitHostPort(dest); err != nil {
@ -81,3 +95,33 @@ func main(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "OTHER: %v\n", err) fmt.Fprintf(os.Stderr, "OTHER: %v\n", err)
os.Exit(1) os.Exit(1)
} }
func connectSCTP(dest string, timeout time.Duration) {
addr, err := sctp.ResolveSCTPAddr("sctp", dest)
if err != nil {
fmt.Fprintf(os.Stderr, "DNS: %v\n", err)
os.Exit(1)
}
timeoutCh := time.After(timeout)
errCh := make(chan (error))
go func() {
conn, err := sctp.DialSCTP("sctp", nil, addr)
if err == nil {
conn.Close()
}
errCh <- err
}()
select {
case err := <-errCh:
if err != nil {
fmt.Fprintf(os.Stderr, "OTHER: %v\n", err)
os.Exit(1)
}
case <-timeoutCh:
fmt.Fprint(os.Stderr, "TIMEOUT\n")
os.Exit(1)
}
}

View File

@ -9,7 +9,10 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["porter.go"], srcs = ["porter.go"],
importpath = "k8s.io/kubernetes/test/images/agnhost/porter", importpath = "k8s.io/kubernetes/test/images/agnhost/porter",
deps = ["//vendor/github.com/spf13/cobra:go_default_library"], deps = [
"//vendor/github.com/ishidawataru/sctp:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
],
) )
filegroup( filegroup(

View File

@ -29,19 +29,24 @@ import (
"os" "os"
"strings" "strings"
"github.com/ishidawataru/sctp"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const prefix = "SERVE_PORT_" const tcpPrefix = "SERVE_PORT_"
const sctpPrefix = "SERVE_SCTP_PORT_"
const tlsPrefix = "SERVE_TLS_PORT_" const tlsPrefix = "SERVE_TLS_PORT_"
// CmdPorter is used by agnhost Cobra. // CmdPorter is used by agnhost Cobra.
var CmdPorter = &cobra.Command{ var CmdPorter = &cobra.Command{
Use: "porter", Use: "porter",
Short: "Serves requested data on ports specified in ENV variables", Short: "Serves requested data on ports specified in ENV variables",
Long: `Serves requested data on ports specified in ENV variables. For example, if the environment variable "SERVE_PORT_9001" is set, then the subcommand will start serving on the port 9001. Long: `Serves requested data on ports specified in environment variables of the form SERVE_{PORT,TLS_PORT,SCTP_PORT}_[NNNN].
Additionally, if the environment variable "SERVE_TLS_PORT_9002" is set, then the subcommand will start a TLS server on that port. eg:
* SERVE_PORT_9001 - serve TCP connections on port 9001
* SERVE_TLS_PORT_9002 - serve TLS-encrypted TCP connections on port 9002
* SERVE_SCTP_PORT_9003 - serve SCTP connections on port 9003
The included "localhost.crt" is a PEM-encoded TLS cert with SAN IPs "127.0.0.1" and "[::1]", expiring in January 2084, generated from "src/crypto/tls". The included "localhost.crt" is a PEM-encoded TLS cert with SAN IPs "127.0.0.1" and "[::1]", expiring in January 2084, generated from "src/crypto/tls".
@ -58,11 +63,15 @@ func main(cmd *cobra.Command, args []string) {
parts := strings.SplitN(vk, "=", 2) parts := strings.SplitN(vk, "=", 2)
key := parts[0] key := parts[0]
value := parts[1] value := parts[1]
if strings.HasPrefix(key, prefix) {
port := strings.TrimPrefix(key, prefix) switch {
case strings.HasPrefix(key, tcpPrefix):
port := strings.TrimPrefix(key, tcpPrefix)
go servePort(port, value) go servePort(port, value)
} case strings.HasPrefix(key, sctpPrefix):
if strings.HasPrefix(key, tlsPrefix) { port := strings.TrimPrefix(key, sctpPrefix)
go serveSCTPPort(port, value)
case strings.HasPrefix(key, tlsPrefix):
port := strings.TrimPrefix(key, tlsPrefix) port := strings.TrimPrefix(key, tlsPrefix)
go serveTLSPort(port, value) go serveTLSPort(port, value)
} }
@ -98,3 +107,38 @@ func serveTLSPort(port, value string) {
} }
log.Printf("tls server on port %q with certFile=%q, keyFile=%q failed: %v", port, certFile, keyFile, s.ListenAndServeTLS(certFile, keyFile)) log.Printf("tls server on port %q with certFile=%q, keyFile=%q failed: %v", port, certFile, keyFile, s.ListenAndServeTLS(certFile, keyFile))
} }
func serveSCTPPort(port, value string) {
serverAddress, err := sctp.ResolveSCTPAddr("sctp", "0.0.0.0:"+port)
if err != nil {
log.Fatal("Sctp: failed to resolve address. error:", err)
}
listener, err := sctp.ListenSCTP("sctp", serverAddress)
if err != nil {
log.Fatal("Failed to listen SCTP. error:", err)
}
log.Printf("Started SCTP server")
defer listener.Close()
defer func() {
log.Printf("SCTP server exited")
}()
for {
conn, err := listener.AcceptSCTP()
if err != nil {
log.Fatal("Failed to accept SCTP. error:", err)
}
go func(conn *sctp.SCTPConn) {
defer conn.Close()
log.Println("Sending response")
_, err = conn.Write([]byte(value))
if err != nil {
log.Println("Failed to send response", err)
return
}
log.Println("Response sent")
}(conn)
}
}

View File

@ -1,8 +1,8 @@
linux/amd64=REGISTRY/agnhost:2.19-linux-amd64 linux/amd64=REGISTRY/agnhost:2.20-linux-amd64
linux/arm=REGISTRY/agnhost:2.19-linux-arm linux/arm=REGISTRY/agnhost:2.20-linux-arm
linux/arm64=REGISTRY/agnhost:2.19-linux-arm64 linux/arm64=REGISTRY/agnhost:2.20-linux-arm64
linux/ppc64le=REGISTRY/agnhost:2.19-linux-ppc64le linux/ppc64le=REGISTRY/agnhost:2.20-linux-ppc64le
linux/s390x=REGISTRY/agnhost:2.19-linux-s390x linux/s390x=REGISTRY/agnhost:2.20-linux-s390x
windows/amd64/1809=REGISTRY/agnhost:2.19-windows-amd64-1809 windows/amd64/1809=REGISTRY/agnhost:2.20-windows-amd64-1809
windows/amd64/1903=REGISTRY/agnhost:2.19-windows-amd64-1903 windows/amd64/1903=REGISTRY/agnhost:2.20-windows-amd64-1903
windows/amd64/1909=REGISTRY/agnhost:2.19-windows-amd64-1909 windows/amd64/1909=REGISTRY/agnhost:2.20-windows-amd64-1909

View File

@ -1 +1 @@
1.2 1.3

View File

@ -1,8 +1,8 @@
linux/amd64=REGISTRY/agnhost:2.19-linux-amd64 linux/amd64=REGISTRY/agnhost:2.20-linux-amd64
linux/arm=REGISTRY/agnhost:2.19-linux-arm linux/arm=REGISTRY/agnhost:2.20-linux-arm
linux/arm64=REGISTRY/agnhost:2.19-linux-arm64 linux/arm64=REGISTRY/agnhost:2.20-linux-arm64
linux/ppc64le=REGISTRY/agnhost:2.19-linux-ppc64le linux/ppc64le=REGISTRY/agnhost:2.20-linux-ppc64le
linux/s390x=REGISTRY/agnhost:2.19-linux-s390x linux/s390x=REGISTRY/agnhost:2.20-linux-s390x
windows/amd64/1809=REGISTRY/agnhost:2.19-windows-amd64-1809 windows/amd64/1809=REGISTRY/agnhost:2.20-windows-amd64-1809
windows/amd64/1903=REGISTRY/agnhost:2.19-windows-amd64-1903 windows/amd64/1903=REGISTRY/agnhost:2.20-windows-amd64-1903
windows/amd64/1909=REGISTRY/agnhost:2.19-windows-amd64-1909 windows/amd64/1909=REGISTRY/agnhost:2.20-windows-amd64-1909

View File

@ -1 +1 @@
1.2 1.3