-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test template-validator certificate rotation
The test checks the TLS certificate returned by the template validator webhook server. The port-forwarding code was mostly inspired by the implementation in kubectl. Signed-off-by: Andrej Krejcir <[email protected]>
- Loading branch information
1 parent
e123f86
commit 518d02e
Showing
29 changed files
with
4,901 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package tests | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"net" | ||
"net/http" | ||
"strconv" | ||
"sync/atomic" | ||
|
||
. "github.com/onsi/ginkgo" | ||
core "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/util/httpstream" | ||
"k8s.io/client-go/rest" | ||
"k8s.io/client-go/tools/portforward" | ||
"k8s.io/client-go/transport/spdy" | ||
) | ||
|
||
type PortForwarder interface { | ||
Connect(pod *core.Pod, remotePort uint16) (net.Conn, error) | ||
} | ||
|
||
type portForwarderImpl struct { | ||
config *rest.Config | ||
client rest.Interface | ||
requestId int32 | ||
} | ||
|
||
var _ PortForwarder = &portForwarderImpl{} | ||
|
||
func (p *portForwarderImpl) Connect(pod *core.Pod, remotePort uint16) (net.Conn, error) { | ||
streamConnection, err := p.createStreamConnection(pod) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
requestId := atomic.AddInt32(&p.requestId, 1) | ||
|
||
// Error stream is needed, otherwise port-forwarding will not work | ||
headers := http.Header{} | ||
headers.Set(core.StreamType, core.StreamTypeError) | ||
headers.Set(core.PortHeader, fmt.Sprintf("%d", remotePort)) | ||
headers.Set(core.PortForwardRequestIDHeader, strconv.Itoa(int(requestId))) | ||
errorStream, err := streamConnection.CreateStream(headers) | ||
if err != nil { | ||
streamConnection.Close() | ||
return nil, err | ||
} | ||
// We will not write to error stream | ||
errorStream.Close() | ||
|
||
headers.Set(core.StreamType, core.StreamTypeData) | ||
dataStream, err := streamConnection.CreateStream(headers) | ||
if err != nil { | ||
streamConnection.Close() | ||
return nil, err | ||
} | ||
|
||
pipeIn, pipeOut := net.Pipe() | ||
// Read data from pod | ||
go func() { | ||
defer pipeIn.Close() | ||
_, err := io.Copy(pipeIn, dataStream) | ||
if err != nil { | ||
fmt.Fprintf(GinkgoWriter, "Error reading from port-forwarding: %v", err) | ||
return | ||
} | ||
}() | ||
|
||
// Send data to pod | ||
go func() { | ||
defer streamConnection.Close() | ||
defer dataStream.Close() | ||
_, err := io.Copy(dataStream, pipeIn) | ||
if err != nil { | ||
fmt.Fprintf(GinkgoWriter, "Error writing to port-forwarding: %v", err) | ||
return | ||
} | ||
}() | ||
|
||
return pipeOut, nil | ||
} | ||
|
||
func (p *portForwarderImpl) createStreamConnection(pod *core.Pod) (httpstream.Connection, error) { | ||
transport, upgrader, err := spdy.RoundTripperFor(p.config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
req := p.client.Post(). | ||
Resource("pods"). | ||
Namespace(pod.Namespace). | ||
Name(pod.Name). | ||
SubResource("portforward") | ||
|
||
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", req.URL()) | ||
streamConn, _, err := dialer.Dial(portforward.PortForwardProtocolV1Name) | ||
return streamConn, err | ||
} | ||
|
||
func NewPortForwarder(config *rest.Config, client rest.Interface) PortForwarder { | ||
return &portForwarderImpl{ | ||
config: config, | ||
client: client, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.