mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-24 20:28:02 +08:00
vendor: update buildkit to v0.19.0-rc1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
18
vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
generated
vendored
18
vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
generated
vendored
@@ -147,7 +147,6 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
|
||||
|
||||
// RawMessage#Unmarshal appends to data - we reset the slice down to 0 and will either see
|
||||
// data written to data, or be larger than data and a different array.
|
||||
n := len(data)
|
||||
m := json.RawMessage(data[:0])
|
||||
if err := r.decoder.Decode(&m); err != nil {
|
||||
return 0, err
|
||||
@@ -156,12 +155,19 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
|
||||
// If capacity of data is less than length of the message, decoder will allocate a new slice
|
||||
// and set m to it, which means we need to copy the partial result back into data and preserve
|
||||
// the remaining result for subsequent reads.
|
||||
if len(m) > n {
|
||||
//nolint:staticcheck // SA4006,SA4010 underlying array of data is modified here.
|
||||
data = append(data[0:0], m[:n]...)
|
||||
r.remaining = m[n:]
|
||||
return n, io.ErrShortBuffer
|
||||
if len(m) > cap(data) {
|
||||
copy(data, m)
|
||||
r.remaining = m[len(data):]
|
||||
return len(data), io.ErrShortBuffer
|
||||
}
|
||||
|
||||
if len(m) > len(data) {
|
||||
// The bytes beyond len(data) were stored in data's underlying array, which we do
|
||||
// not own after this function returns.
|
||||
r.remaining = append([]byte(nil), m[len(data):]...)
|
||||
return len(data), io.ErrShortBuffer
|
||||
}
|
||||
|
||||
return len(m), nil
|
||||
}
|
||||
|
||||
|
9
vendor/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go
generated
vendored
9
vendor/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go
generated
vendored
@@ -116,6 +116,15 @@ func IsUpgradeFailure(err error) bool {
|
||||
return errors.As(err, &upgradeErr)
|
||||
}
|
||||
|
||||
// isHTTPSProxyError returns true if error is Gorilla/Websockets HTTPS Proxy dial error;
|
||||
// false otherwise (see https://github.com/kubernetes/kubernetes/issues/126134).
|
||||
func IsHTTPSProxyError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(err.Error(), "proxy: unknown scheme: https")
|
||||
}
|
||||
|
||||
// IsUpgradeRequest returns true if the given request is a connection upgrade request
|
||||
func IsUpgradeRequest(req *http.Request) bool {
|
||||
for _, h := range req.Header[http.CanonicalHeaderKey(HeaderConnection)] {
|
||||
|
452
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go
generated
vendored
Normal file
452
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go
generated
vendored
Normal file
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package wsstream
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||
"k8s.io/apimachinery/pkg/util/portforward"
|
||||
"k8s.io/apimachinery/pkg/util/remotecommand"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const WebSocketProtocolHeader = "Sec-Websocket-Protocol"
|
||||
|
||||
// The Websocket subprotocol "channel.k8s.io" prepends each binary message with a byte indicating
|
||||
// the channel number (zero indexed) the message was sent on. Messages in both directions should
|
||||
// prefix their messages with this channel byte. When used for remote execution, the channel numbers
|
||||
// are by convention defined to match the POSIX file-descriptors assigned to STDIN, STDOUT, and STDERR
|
||||
// (0, 1, and 2). No other conversion is performed on the raw subprotocol - writes are sent as they
|
||||
// are received by the server.
|
||||
//
|
||||
// Example client session:
|
||||
//
|
||||
// CONNECT http://server.com with subprotocol "channel.k8s.io"
|
||||
// WRITE []byte{0, 102, 111, 111, 10} # send "foo\n" on channel 0 (STDIN)
|
||||
// READ []byte{1, 10} # receive "\n" on channel 1 (STDOUT)
|
||||
// CLOSE
|
||||
const ChannelWebSocketProtocol = "channel.k8s.io"
|
||||
|
||||
// The Websocket subprotocol "base64.channel.k8s.io" base64 encodes each message with a character
|
||||
// indicating the channel number (zero indexed) the message was sent on. Messages in both directions
|
||||
// should prefix their messages with this channel char. When used for remote execution, the channel
|
||||
// numbers are by convention defined to match the POSIX file-descriptors assigned to STDIN, STDOUT,
|
||||
// and STDERR ('0', '1', and '2'). The data received on the server is base64 decoded (and must be
|
||||
// be valid) and data written by the server to the client is base64 encoded.
|
||||
//
|
||||
// Example client session:
|
||||
//
|
||||
// CONNECT http://server.com with subprotocol "base64.channel.k8s.io"
|
||||
// WRITE []byte{48, 90, 109, 57, 118, 67, 103, 111, 61} # send "foo\n" (base64: "Zm9vCgo=") on channel '0' (STDIN)
|
||||
// READ []byte{49, 67, 103, 61, 61} # receive "\n" (base64: "Cg==") on channel '1' (STDOUT)
|
||||
// CLOSE
|
||||
const Base64ChannelWebSocketProtocol = "base64.channel.k8s.io"
|
||||
|
||||
type codecType int
|
||||
|
||||
const (
|
||||
rawCodec codecType = iota
|
||||
base64Codec
|
||||
)
|
||||
|
||||
type ChannelType int
|
||||
|
||||
const (
|
||||
IgnoreChannel ChannelType = iota
|
||||
ReadChannel
|
||||
WriteChannel
|
||||
ReadWriteChannel
|
||||
)
|
||||
|
||||
// IsWebSocketRequest returns true if the incoming request contains connection upgrade headers
|
||||
// for WebSockets.
|
||||
func IsWebSocketRequest(req *http.Request) bool {
|
||||
if !strings.EqualFold(req.Header.Get("Upgrade"), "websocket") {
|
||||
return false
|
||||
}
|
||||
return httpstream.IsUpgradeRequest(req)
|
||||
}
|
||||
|
||||
// IsWebSocketRequestWithStreamCloseProtocol returns true if the request contains headers
|
||||
// identifying that it is requesting a websocket upgrade with a remotecommand protocol
|
||||
// version that supports the "CLOSE" signal; false otherwise.
|
||||
func IsWebSocketRequestWithStreamCloseProtocol(req *http.Request) bool {
|
||||
if !IsWebSocketRequest(req) {
|
||||
return false
|
||||
}
|
||||
requestedProtocols := strings.TrimSpace(req.Header.Get(WebSocketProtocolHeader))
|
||||
for _, requestedProtocol := range strings.Split(requestedProtocols, ",") {
|
||||
if protocolSupportsStreamClose(strings.TrimSpace(requestedProtocol)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IsWebSocketRequestWithTunnelingProtocol returns true if the request contains headers
|
||||
// identifying that it is requesting a websocket upgrade with a tunneling protocol;
|
||||
// false otherwise.
|
||||
func IsWebSocketRequestWithTunnelingProtocol(req *http.Request) bool {
|
||||
if !IsWebSocketRequest(req) {
|
||||
return false
|
||||
}
|
||||
requestedProtocols := strings.TrimSpace(req.Header.Get(WebSocketProtocolHeader))
|
||||
for _, requestedProtocol := range strings.Split(requestedProtocols, ",") {
|
||||
if protocolSupportsWebsocketTunneling(strings.TrimSpace(requestedProtocol)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IgnoreReceives reads from a WebSocket until it is closed, then returns. If timeout is set, the
|
||||
// read and write deadlines are pushed every time a new message is received.
|
||||
func IgnoreReceives(ws *websocket.Conn, timeout time.Duration) {
|
||||
defer runtime.HandleCrash()
|
||||
var data []byte
|
||||
for {
|
||||
resetTimeout(ws, timeout)
|
||||
if err := websocket.Message.Receive(ws, &data); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handshake ensures the provided user protocol matches one of the allowed protocols. It returns
|
||||
// no error if no protocol is specified.
|
||||
func handshake(config *websocket.Config, req *http.Request, allowed []string) error {
|
||||
protocols := config.Protocol
|
||||
if len(protocols) == 0 {
|
||||
protocols = []string{""}
|
||||
}
|
||||
|
||||
for _, protocol := range protocols {
|
||||
for _, allow := range allowed {
|
||||
if allow == protocol {
|
||||
config.Protocol = []string{protocol}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("requested protocol(s) are not supported: %v; supports %v", config.Protocol, allowed)
|
||||
}
|
||||
|
||||
// ChannelProtocolConfig describes a websocket subprotocol with channels.
|
||||
type ChannelProtocolConfig struct {
|
||||
Binary bool
|
||||
Channels []ChannelType
|
||||
}
|
||||
|
||||
// NewDefaultChannelProtocols returns a channel protocol map with the
|
||||
// subprotocols "", "channel.k8s.io", "base64.channel.k8s.io" and the given
|
||||
// channels.
|
||||
func NewDefaultChannelProtocols(channels []ChannelType) map[string]ChannelProtocolConfig {
|
||||
return map[string]ChannelProtocolConfig{
|
||||
"": {Binary: true, Channels: channels},
|
||||
ChannelWebSocketProtocol: {Binary: true, Channels: channels},
|
||||
Base64ChannelWebSocketProtocol: {Binary: false, Channels: channels},
|
||||
}
|
||||
}
|
||||
|
||||
// Conn supports sending multiple binary channels over a websocket connection.
|
||||
type Conn struct {
|
||||
protocols map[string]ChannelProtocolConfig
|
||||
selectedProtocol string
|
||||
channels []*websocketChannel
|
||||
codec codecType
|
||||
ready chan struct{}
|
||||
ws *websocket.Conn
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// NewConn creates a WebSocket connection that supports a set of channels. Channels begin each
|
||||
// web socket message with a single byte indicating the channel number (0-N). 255 is reserved for
|
||||
// future use. The channel types for each channel are passed as an array, supporting the different
|
||||
// duplex modes. Read and Write refer to whether the channel can be used as a Reader or Writer.
|
||||
//
|
||||
// The protocols parameter maps subprotocol names to ChannelProtocols. The empty string subprotocol
|
||||
// name is used if websocket.Config.Protocol is empty.
|
||||
func NewConn(protocols map[string]ChannelProtocolConfig) *Conn {
|
||||
return &Conn{
|
||||
ready: make(chan struct{}),
|
||||
protocols: protocols,
|
||||
}
|
||||
}
|
||||
|
||||
// SetIdleTimeout sets the interval for both reads and writes before timeout. If not specified,
|
||||
// there is no timeout on the connection.
|
||||
func (conn *Conn) SetIdleTimeout(duration time.Duration) {
|
||||
conn.timeout = duration
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets a timeout on writing to the websocket connection. The
|
||||
// passed "duration" identifies how far into the future the write must complete
|
||||
// by before the timeout fires.
|
||||
func (conn *Conn) SetWriteDeadline(duration time.Duration) {
|
||||
conn.ws.SetWriteDeadline(time.Now().Add(duration)) //nolint:errcheck
|
||||
}
|
||||
|
||||
// Open the connection and create channels for reading and writing. It returns
|
||||
// the selected subprotocol, a slice of channels and an error.
|
||||
func (conn *Conn) Open(w http.ResponseWriter, req *http.Request) (string, []io.ReadWriteCloser, error) {
|
||||
// serveHTTPComplete is channel that is closed/selected when "websocket#ServeHTTP" finishes.
|
||||
serveHTTPComplete := make(chan struct{})
|
||||
// Ensure panic in spawned goroutine is propagated into the parent goroutine.
|
||||
panicChan := make(chan any, 1)
|
||||
go func() {
|
||||
// If websocket server returns, propagate panic if necessary. Otherwise,
|
||||
// signal HTTPServe finished by closing "serveHTTPComplete".
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
panicChan <- p
|
||||
} else {
|
||||
close(serveHTTPComplete)
|
||||
}
|
||||
}()
|
||||
websocket.Server{Handshake: conn.handshake, Handler: conn.handle}.ServeHTTP(w, req)
|
||||
}()
|
||||
|
||||
// In normal circumstances, "websocket.Server#ServeHTTP" calls "initialize" which closes
|
||||
// "conn.ready" and then blocks until serving is complete.
|
||||
select {
|
||||
case <-conn.ready:
|
||||
klog.V(8).Infof("websocket server initialized--serving")
|
||||
case <-serveHTTPComplete:
|
||||
// websocket server returned before completing initialization; cleanup and return error.
|
||||
conn.closeNonThreadSafe() //nolint:errcheck
|
||||
return "", nil, fmt.Errorf("websocket server finished before becoming ready")
|
||||
case p := <-panicChan:
|
||||
panic(p)
|
||||
}
|
||||
|
||||
rwc := make([]io.ReadWriteCloser, len(conn.channels))
|
||||
for i := range conn.channels {
|
||||
rwc[i] = conn.channels[i]
|
||||
}
|
||||
return conn.selectedProtocol, rwc, nil
|
||||
}
|
||||
|
||||
func (conn *Conn) initialize(ws *websocket.Conn) {
|
||||
negotiated := ws.Config().Protocol
|
||||
conn.selectedProtocol = negotiated[0]
|
||||
p := conn.protocols[conn.selectedProtocol]
|
||||
if p.Binary {
|
||||
conn.codec = rawCodec
|
||||
} else {
|
||||
conn.codec = base64Codec
|
||||
}
|
||||
conn.ws = ws
|
||||
conn.channels = make([]*websocketChannel, len(p.Channels))
|
||||
for i, t := range p.Channels {
|
||||
switch t {
|
||||
case ReadChannel:
|
||||
conn.channels[i] = newWebsocketChannel(conn, byte(i), true, false)
|
||||
case WriteChannel:
|
||||
conn.channels[i] = newWebsocketChannel(conn, byte(i), false, true)
|
||||
case ReadWriteChannel:
|
||||
conn.channels[i] = newWebsocketChannel(conn, byte(i), true, true)
|
||||
case IgnoreChannel:
|
||||
conn.channels[i] = newWebsocketChannel(conn, byte(i), false, false)
|
||||
}
|
||||
}
|
||||
|
||||
close(conn.ready)
|
||||
}
|
||||
|
||||
func (conn *Conn) handshake(config *websocket.Config, req *http.Request) error {
|
||||
supportedProtocols := make([]string, 0, len(conn.protocols))
|
||||
for p := range conn.protocols {
|
||||
supportedProtocols = append(supportedProtocols, p)
|
||||
}
|
||||
return handshake(config, req, supportedProtocols)
|
||||
}
|
||||
|
||||
func (conn *Conn) resetTimeout() {
|
||||
if conn.timeout > 0 {
|
||||
conn.ws.SetDeadline(time.Now().Add(conn.timeout))
|
||||
}
|
||||
}
|
||||
|
||||
// closeNonThreadSafe cleans up by closing streams and the websocket
|
||||
// connection *without* waiting for the "ready" channel.
|
||||
func (conn *Conn) closeNonThreadSafe() error {
|
||||
for _, s := range conn.channels {
|
||||
s.Close()
|
||||
}
|
||||
var err error
|
||||
if conn.ws != nil {
|
||||
err = conn.ws.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Close is only valid after Open has been called
|
||||
func (conn *Conn) Close() error {
|
||||
<-conn.ready
|
||||
return conn.closeNonThreadSafe()
|
||||
}
|
||||
|
||||
// protocolSupportsStreamClose returns true if the passed protocol
|
||||
// supports the stream close signal (currently only V5 remotecommand);
|
||||
// false otherwise.
|
||||
func protocolSupportsStreamClose(protocol string) bool {
|
||||
return protocol == remotecommand.StreamProtocolV5Name
|
||||
}
|
||||
|
||||
// protocolSupportsWebsocketTunneling returns true if the passed protocol
|
||||
// is a tunneled Kubernetes spdy protocol; false otherwise.
|
||||
func protocolSupportsWebsocketTunneling(protocol string) bool {
|
||||
return strings.HasPrefix(protocol, portforward.WebsocketsSPDYTunnelingPrefix) && strings.HasSuffix(protocol, portforward.KubernetesSuffix)
|
||||
}
|
||||
|
||||
// handle implements a websocket handler.
|
||||
func (conn *Conn) handle(ws *websocket.Conn) {
|
||||
conn.initialize(ws)
|
||||
defer conn.Close()
|
||||
supportsStreamClose := protocolSupportsStreamClose(conn.selectedProtocol)
|
||||
|
||||
for {
|
||||
conn.resetTimeout()
|
||||
var data []byte
|
||||
if err := websocket.Message.Receive(ws, &data); err != nil {
|
||||
if err != io.EOF {
|
||||
klog.Errorf("Error on socket receive: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
if len(data) == 0 {
|
||||
continue
|
||||
}
|
||||
if supportsStreamClose && data[0] == remotecommand.StreamClose {
|
||||
if len(data) != 2 {
|
||||
klog.Errorf("Single channel byte should follow stream close signal. Got %d bytes", len(data)-1)
|
||||
break
|
||||
} else {
|
||||
channel := data[1]
|
||||
if int(channel) >= len(conn.channels) {
|
||||
klog.Errorf("Close is targeted for a channel %d that is not valid, possible protocol error", channel)
|
||||
break
|
||||
}
|
||||
klog.V(4).Infof("Received half-close signal from client; close %d stream", channel)
|
||||
conn.channels[channel].Close() // After first Close, other closes are noop.
|
||||
}
|
||||
continue
|
||||
}
|
||||
channel := data[0]
|
||||
if conn.codec == base64Codec {
|
||||
channel = channel - '0'
|
||||
}
|
||||
data = data[1:]
|
||||
if int(channel) >= len(conn.channels) {
|
||||
klog.V(6).Infof("Frame is targeted for a reader %d that is not valid, possible protocol error", channel)
|
||||
continue
|
||||
}
|
||||
if _, err := conn.channels[channel].DataFromSocket(data); err != nil {
|
||||
klog.Errorf("Unable to write frame (%d bytes) to %d: %v", len(data), channel, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write multiplexes the specified channel onto the websocket
|
||||
func (conn *Conn) write(num byte, data []byte) (int, error) {
|
||||
conn.resetTimeout()
|
||||
switch conn.codec {
|
||||
case rawCodec:
|
||||
frame := make([]byte, len(data)+1)
|
||||
frame[0] = num
|
||||
copy(frame[1:], data)
|
||||
if err := websocket.Message.Send(conn.ws, frame); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case base64Codec:
|
||||
frame := string('0'+num) + base64.StdEncoding.EncodeToString(data)
|
||||
if err := websocket.Message.Send(conn.ws, frame); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
// websocketChannel represents a channel in a connection
|
||||
type websocketChannel struct {
|
||||
conn *Conn
|
||||
num byte
|
||||
r io.Reader
|
||||
w io.WriteCloser
|
||||
|
||||
read, write bool
|
||||
}
|
||||
|
||||
// newWebsocketChannel creates a pipe for writing to a websocket. Do not write to this pipe
|
||||
// prior to the connection being opened. It may be no, half, or full duplex depending on
|
||||
// read and write.
|
||||
func newWebsocketChannel(conn *Conn, num byte, read, write bool) *websocketChannel {
|
||||
r, w := io.Pipe()
|
||||
return &websocketChannel{conn, num, r, w, read, write}
|
||||
}
|
||||
|
||||
func (p *websocketChannel) Write(data []byte) (int, error) {
|
||||
if !p.write {
|
||||
return len(data), nil
|
||||
}
|
||||
return p.conn.write(p.num, data)
|
||||
}
|
||||
|
||||
// DataFromSocket is invoked by the connection receiver to move data from the connection
|
||||
// into a specific channel.
|
||||
func (p *websocketChannel) DataFromSocket(data []byte) (int, error) {
|
||||
if !p.read {
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
switch p.conn.codec {
|
||||
case rawCodec:
|
||||
return p.w.Write(data)
|
||||
case base64Codec:
|
||||
dst := make([]byte, len(data))
|
||||
n, err := base64.StdEncoding.Decode(dst, data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return p.w.Write(dst[:n])
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *websocketChannel) Read(data []byte) (int, error) {
|
||||
if !p.read {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return p.r.Read(data)
|
||||
}
|
||||
|
||||
func (p *websocketChannel) Close() error {
|
||||
return p.w.Close()
|
||||
}
|
69
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/doc.go
generated
vendored
Normal file
69
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/doc.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Package wsstream contains utilities for streaming content over WebSockets.
|
||||
// The Conn type allows callers to multiplex multiple read/write channels over
|
||||
// a single websocket.
|
||||
//
|
||||
// "channel.k8s.io"
|
||||
//
|
||||
// The Websocket RemoteCommand subprotocol "channel.k8s.io" prepends each binary message with a
|
||||
// byte indicating the channel number (zero indexed) the message was sent on. Messages in both
|
||||
// directions should prefix their messages with this channel byte. Used for remote execution,
|
||||
// the channel numbers are by convention defined to match the POSIX file-descriptors assigned
|
||||
// to STDIN, STDOUT, and STDERR (0, 1, and 2). No other conversion is performed on the raw
|
||||
// subprotocol - writes are sent as they are received by the server.
|
||||
//
|
||||
// Example client session:
|
||||
//
|
||||
// CONNECT http://server.com with subprotocol "channel.k8s.io"
|
||||
// WRITE []byte{0, 102, 111, 111, 10} # send "foo\n" on channel 0 (STDIN)
|
||||
// READ []byte{1, 10} # receive "\n" on channel 1 (STDOUT)
|
||||
// CLOSE
|
||||
//
|
||||
// "v2.channel.k8s.io"
|
||||
//
|
||||
// The second Websocket subprotocol version "v2.channel.k8s.io" is the same as version 1,
|
||||
// but it is the first "versioned" subprotocol.
|
||||
//
|
||||
// "v3.channel.k8s.io"
|
||||
//
|
||||
// The third version of the Websocket RemoteCommand subprotocol adds another channel
|
||||
// for terminal resizing events. This channel is prepended with the byte '3', and it
|
||||
// transmits two window sizes (encoding TerminalSize struct) with integers in the range
|
||||
// (0,65536].
|
||||
//
|
||||
// "v4.channel.k8s.io"
|
||||
//
|
||||
// The fourth version of the Websocket RemoteCommand subprotocol adds a channel for
|
||||
// errors. This channel returns structured errors containing process exit codes. The
|
||||
// error is "apierrors.StatusError{}".
|
||||
//
|
||||
// "v5.channel.k8s.io"
|
||||
//
|
||||
// The fifth version of the Websocket RemoteCommand subprotocol adds a CLOSE signal,
|
||||
// which is sent as the first byte of the message. The second byte is the channel
|
||||
// id. This CLOSE signal is handled by the websocket server by closing the stream,
|
||||
// allowing the other streams to complete transmission if necessary, and gracefully
|
||||
// shutdown the connection.
|
||||
//
|
||||
// Example client session:
|
||||
//
|
||||
// CONNECT http://server.com with subprotocol "v5.channel.k8s.io"
|
||||
// WRITE []byte{0, 102, 111, 111, 10} # send "foo\n" on channel 0 (STDIN)
|
||||
// WRITE []byte{255, 0} # send CLOSE signal (STDIN)
|
||||
// CLOSE
|
||||
package wsstream // import "k8s.io/apimachinery/pkg/util/httpstream/wsstream"
|
177
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/stream.go
generated
vendored
Normal file
177
vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/stream.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package wsstream
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
// The WebSocket subprotocol "binary.k8s.io" will only send messages to the
|
||||
// client and ignore messages sent to the server. The received messages are
|
||||
// the exact bytes written to the stream. Zero byte messages are possible.
|
||||
const binaryWebSocketProtocol = "binary.k8s.io"
|
||||
|
||||
// The WebSocket subprotocol "base64.binary.k8s.io" will only send messages to the
|
||||
// client and ignore messages sent to the server. The received messages are
|
||||
// a base64 version of the bytes written to the stream. Zero byte messages are
|
||||
// possible.
|
||||
const base64BinaryWebSocketProtocol = "base64.binary.k8s.io"
|
||||
|
||||
// ReaderProtocolConfig describes a websocket subprotocol with one stream.
|
||||
type ReaderProtocolConfig struct {
|
||||
Binary bool
|
||||
}
|
||||
|
||||
// NewDefaultReaderProtocols returns a stream protocol map with the
|
||||
// subprotocols "", "channel.k8s.io", "base64.channel.k8s.io".
|
||||
func NewDefaultReaderProtocols() map[string]ReaderProtocolConfig {
|
||||
return map[string]ReaderProtocolConfig{
|
||||
"": {Binary: true},
|
||||
binaryWebSocketProtocol: {Binary: true},
|
||||
base64BinaryWebSocketProtocol: {Binary: false},
|
||||
}
|
||||
}
|
||||
|
||||
// Reader supports returning an arbitrary byte stream over a websocket channel.
|
||||
type Reader struct {
|
||||
err chan error
|
||||
r io.Reader
|
||||
ping bool
|
||||
timeout time.Duration
|
||||
protocols map[string]ReaderProtocolConfig
|
||||
selectedProtocol string
|
||||
|
||||
handleCrash func(additionalHandlers ...func(interface{})) // overridable for testing
|
||||
}
|
||||
|
||||
// NewReader creates a WebSocket pipe that will copy the contents of r to a provided
|
||||
// WebSocket connection. If ping is true, a zero length message will be sent to the client
|
||||
// before the stream begins reading.
|
||||
//
|
||||
// The protocols parameter maps subprotocol names to StreamProtocols. The empty string
|
||||
// subprotocol name is used if websocket.Config.Protocol is empty.
|
||||
func NewReader(r io.Reader, ping bool, protocols map[string]ReaderProtocolConfig) *Reader {
|
||||
return &Reader{
|
||||
r: r,
|
||||
err: make(chan error),
|
||||
ping: ping,
|
||||
protocols: protocols,
|
||||
handleCrash: runtime.HandleCrash,
|
||||
}
|
||||
}
|
||||
|
||||
// SetIdleTimeout sets the interval for both reads and writes before timeout. If not specified,
|
||||
// there is no timeout on the reader.
|
||||
func (r *Reader) SetIdleTimeout(duration time.Duration) {
|
||||
r.timeout = duration
|
||||
}
|
||||
|
||||
func (r *Reader) handshake(config *websocket.Config, req *http.Request) error {
|
||||
supportedProtocols := make([]string, 0, len(r.protocols))
|
||||
for p := range r.protocols {
|
||||
supportedProtocols = append(supportedProtocols, p)
|
||||
}
|
||||
return handshake(config, req, supportedProtocols)
|
||||
}
|
||||
|
||||
// Copy the reader to the response. The created WebSocket is closed after this
|
||||
// method completes.
|
||||
func (r *Reader) Copy(w http.ResponseWriter, req *http.Request) error {
|
||||
go func() {
|
||||
defer r.handleCrash()
|
||||
websocket.Server{Handshake: r.handshake, Handler: r.handle}.ServeHTTP(w, req)
|
||||
}()
|
||||
return <-r.err
|
||||
}
|
||||
|
||||
// handle implements a WebSocket handler.
|
||||
func (r *Reader) handle(ws *websocket.Conn) {
|
||||
// Close the connection when the client requests it, or when we finish streaming, whichever happens first
|
||||
closeConnOnce := &sync.Once{}
|
||||
closeConn := func() {
|
||||
closeConnOnce.Do(func() {
|
||||
ws.Close()
|
||||
})
|
||||
}
|
||||
|
||||
negotiated := ws.Config().Protocol
|
||||
r.selectedProtocol = negotiated[0]
|
||||
defer close(r.err)
|
||||
defer closeConn()
|
||||
|
||||
go func() {
|
||||
defer runtime.HandleCrash()
|
||||
// This blocks until the connection is closed.
|
||||
// Client should not send anything.
|
||||
IgnoreReceives(ws, r.timeout)
|
||||
// Once the client closes, we should also close
|
||||
closeConn()
|
||||
}()
|
||||
|
||||
r.err <- messageCopy(ws, r.r, !r.protocols[r.selectedProtocol].Binary, r.ping, r.timeout)
|
||||
}
|
||||
|
||||
func resetTimeout(ws *websocket.Conn, timeout time.Duration) {
|
||||
if timeout > 0 {
|
||||
ws.SetDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
}
|
||||
|
||||
func messageCopy(ws *websocket.Conn, r io.Reader, base64Encode, ping bool, timeout time.Duration) error {
|
||||
buf := make([]byte, 2048)
|
||||
if ping {
|
||||
resetTimeout(ws, timeout)
|
||||
if base64Encode {
|
||||
if err := websocket.Message.Send(ws, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := websocket.Message.Send(ws, []byte{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for {
|
||||
resetTimeout(ws, timeout)
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if n > 0 {
|
||||
if base64Encode {
|
||||
if err := websocket.Message.Send(ws, base64.StdEncoding.EncodeToString(buf[:n])); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := websocket.Message.Send(ws, buf[:n]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go
generated
vendored
47
vendor/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go
generated
vendored
@@ -15,7 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto
|
||||
// source: k8s.io/apimachinery/pkg/util/intstr/generated.proto
|
||||
|
||||
package intstr
|
||||
|
||||
@@ -43,7 +43,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
func (m *IntOrString) Reset() { *m = IntOrString{} }
|
||||
func (*IntOrString) ProtoMessage() {}
|
||||
func (*IntOrString) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_94e046ae3ce6121c, []int{0}
|
||||
return fileDescriptor_771bacc35a5ec189, []int{0}
|
||||
}
|
||||
func (m *IntOrString) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -73,30 +73,29 @@ func init() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto", fileDescriptor_94e046ae3ce6121c)
|
||||
proto.RegisterFile("k8s.io/apimachinery/pkg/util/intstr/generated.proto", fileDescriptor_771bacc35a5ec189)
|
||||
}
|
||||
|
||||
var fileDescriptor_94e046ae3ce6121c = []byte{
|
||||
// 292 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xb1, 0x4a, 0x03, 0x31,
|
||||
0x1c, 0xc6, 0x13, 0x5b, 0x8b, 0x9e, 0xe0, 0x50, 0x1c, 0x8a, 0x43, 0x7a, 0x58, 0x90, 0x5b, 0x4c,
|
||||
0x56, 0x71, 0xec, 0x56, 0x10, 0x84, 0x56, 0x1c, 0xdc, 0xee, 0xda, 0x98, 0x86, 0x6b, 0x93, 0x90,
|
||||
0xfb, 0x9f, 0x70, 0x5b, 0x1f, 0x41, 0x37, 0x47, 0x1f, 0xe7, 0xc6, 0x8e, 0x1d, 0xa4, 0x78, 0xf1,
|
||||
0x2d, 0x9c, 0xe4, 0x72, 0x07, 0x3a, 0x3a, 0x25, 0xdf, 0xf7, 0xfd, 0x7e, 0x19, 0x12, 0xdc, 0xa6,
|
||||
0xd7, 0x19, 0x95, 0x9a, 0xa5, 0x79, 0xc2, 0xad, 0xe2, 0xc0, 0x33, 0xf6, 0xcc, 0xd5, 0x42, 0x5b,
|
||||
0xd6, 0x0e, 0xb1, 0x91, 0xeb, 0x78, 0xbe, 0x94, 0x8a, 0xdb, 0x82, 0x99, 0x54, 0xb0, 0x1c, 0xe4,
|
||||
0x8a, 0x49, 0x05, 0x19, 0x58, 0x26, 0xb8, 0xe2, 0x36, 0x06, 0xbe, 0xa0, 0xc6, 0x6a, 0xd0, 0xfd,
|
||||
0x51, 0x23, 0xd1, 0xbf, 0x12, 0x35, 0xa9, 0xa0, 0xb5, 0x44, 0x1b, 0xe9, 0xfc, 0x4a, 0x48, 0x58,
|
||||
0xe6, 0x09, 0x9d, 0xeb, 0x35, 0x13, 0x5a, 0x68, 0xe6, 0xdd, 0x24, 0x7f, 0xf2, 0xc9, 0x07, 0x7f,
|
||||
0x6b, 0xde, 0xbc, 0x78, 0xc5, 0xc1, 0xc9, 0x44, 0xc1, 0x9d, 0x9d, 0x81, 0x95, 0x4a, 0xf4, 0xa3,
|
||||
0xa0, 0x0b, 0x85, 0xe1, 0x03, 0x1c, 0xe2, 0xa8, 0x33, 0x3e, 0x2b, 0xf7, 0x43, 0xe4, 0xf6, 0xc3,
|
||||
0xee, 0x7d, 0x61, 0xf8, 0x77, 0x7b, 0x4e, 0x3d, 0xd1, 0xbf, 0x0c, 0x7a, 0x52, 0xc1, 0x43, 0xbc,
|
||||
0x1a, 0x1c, 0x84, 0x38, 0x3a, 0x1c, 0x9f, 0xb6, 0x6c, 0x6f, 0xe2, 0xdb, 0x69, 0xbb, 0xd6, 0x5c,
|
||||
0x06, 0xb6, 0xe6, 0x3a, 0x21, 0x8e, 0x8e, 0x7f, 0xb9, 0x99, 0x6f, 0xa7, 0xed, 0x7a, 0x73, 0xf4,
|
||||
0xf6, 0x3e, 0x44, 0x9b, 0x8f, 0x10, 0x8d, 0x27, 0x65, 0x45, 0xd0, 0xb6, 0x22, 0x68, 0x57, 0x11,
|
||||
0xb4, 0x71, 0x04, 0x97, 0x8e, 0xe0, 0xad, 0x23, 0x78, 0xe7, 0x08, 0xfe, 0x74, 0x04, 0xbf, 0x7c,
|
||||
0x11, 0xf4, 0x38, 0xfa, 0xc7, 0x17, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0xdc, 0xc4, 0xf0, 0xa0,
|
||||
0x81, 0x01, 0x00, 0x00,
|
||||
var fileDescriptor_771bacc35a5ec189 = []byte{
|
||||
// 277 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0xce, 0xb6, 0x28, 0xd6,
|
||||
0xcb, 0xcc, 0xd7, 0x4f, 0x2c, 0xc8, 0xcc, 0x4d, 0x4c, 0xce, 0xc8, 0xcc, 0x4b, 0x2d, 0xaa, 0xd4,
|
||||
0x2f, 0xc8, 0x4e, 0xd7, 0x2f, 0x2d, 0xc9, 0xcc, 0xd1, 0xcf, 0xcc, 0x2b, 0x29, 0x2e, 0x29, 0xd2,
|
||||
0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
|
||||
0x52, 0x86, 0x68, 0xd2, 0x43, 0xd6, 0xa4, 0x57, 0x90, 0x9d, 0xae, 0x07, 0xd2, 0xa4, 0x07, 0xd1,
|
||||
0x24, 0xa5, 0x9b, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, 0x9e, 0x9f,
|
||||
0x9e, 0xaf, 0x0f, 0xd6, 0x9b, 0x54, 0x9a, 0x06, 0xe6, 0x81, 0x39, 0x60, 0x16, 0xc4, 0x4c, 0xa5,
|
||||
0x89, 0x8c, 0x5c, 0xdc, 0x9e, 0x79, 0x25, 0xfe, 0x45, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x42,
|
||||
0x1a, 0x5c, 0x2c, 0x25, 0x95, 0x05, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x4e, 0x22, 0x27,
|
||||
0xee, 0xc9, 0x33, 0x3c, 0xba, 0x27, 0xcf, 0x12, 0x52, 0x59, 0x90, 0xfa, 0x0b, 0x4a, 0x07, 0x81,
|
||||
0x55, 0x08, 0xa9, 0x71, 0xb1, 0x65, 0xe6, 0x95, 0x84, 0x25, 0xe6, 0x48, 0x30, 0x29, 0x30, 0x6a,
|
||||
0xb0, 0x3a, 0xf1, 0x41, 0xd5, 0xb2, 0x79, 0x82, 0x45, 0x83, 0xa0, 0xb2, 0x20, 0x75, 0xc5, 0x25,
|
||||
0x45, 0x20, 0x75, 0xcc, 0x0a, 0x8c, 0x1a, 0x9c, 0x08, 0x75, 0xc1, 0x60, 0xd1, 0x20, 0xa8, 0xac,
|
||||
0x15, 0xc7, 0x8c, 0x05, 0xf2, 0x0c, 0x0d, 0x77, 0x14, 0x18, 0x9c, 0x3c, 0x4f, 0x3c, 0x94, 0x63,
|
||||
0xb8, 0xf0, 0x50, 0x8e, 0xe1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9,
|
||||
0x31, 0x5e, 0x78, 0x24, 0xc7, 0x78, 0xe3, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e,
|
||||
0xcb, 0x31, 0x44, 0x29, 0x13, 0x11, 0x84, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x63, 0xa1, 0x0b,
|
||||
0x1e, 0x68, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *IntOrString) Marshal() (dAtA []byte, err error) {
|
||||
|
26
vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go
generated
vendored
26
vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go
generated
vendored
@@ -25,6 +25,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@@ -92,6 +93,20 @@ func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
|
||||
return json.Unmarshal(value, &intstr.IntVal)
|
||||
}
|
||||
|
||||
func (intstr *IntOrString) UnmarshalCBOR(value []byte) error {
|
||||
if err := cbor.Unmarshal(value, &intstr.StrVal); err == nil {
|
||||
intstr.Type = String
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := cbor.Unmarshal(value, &intstr.IntVal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intstr.Type = Int
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string value, or the Itoa of the int value.
|
||||
func (intstr *IntOrString) String() string {
|
||||
if intstr == nil {
|
||||
@@ -126,6 +141,17 @@ func (intstr IntOrString) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (intstr IntOrString) MarshalCBOR() ([]byte, error) {
|
||||
switch intstr.Type {
|
||||
case Int:
|
||||
return cbor.Marshal(intstr.IntVal)
|
||||
case String:
|
||||
return cbor.Marshal(intstr.StrVal)
|
||||
default:
|
||||
return nil, fmt.Errorf("impossible IntOrString.Type")
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
|
2
vendor/k8s.io/apimachinery/pkg/util/managedfields/node.yaml
generated
vendored
2
vendor/k8s.io/apimachinery/pkg/util/managedfields/node.yaml
generated
vendored
@@ -120,7 +120,7 @@ status:
|
||||
type: PIDPressure
|
||||
- lastHeartbeatTime: "2019-09-20T19:32:50Z"
|
||||
lastTransitionTime: "2019-07-09T16:17:49Z"
|
||||
message: kubelet is posting ready status. AppArmor enabled
|
||||
message: kubelet is posting ready status
|
||||
reason: KubeletReady
|
||||
status: "True"
|
||||
type: Ready
|
||||
|
24
vendor/k8s.io/apimachinery/pkg/util/portforward/constants.go
generated
vendored
Normal file
24
vendor/k8s.io/apimachinery/pkg/util/portforward/constants.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package portforward
|
||||
|
||||
const (
|
||||
PortForwardV1Name = "portforward.k8s.io"
|
||||
WebsocketsSPDYTunnelingPrefix = "SPDY/3.1+"
|
||||
KubernetesSuffix = ".k8s.io"
|
||||
WebsocketsSPDYTunnelingPortForwardV1 = WebsocketsSPDYTunnelingPrefix + PortForwardV1Name
|
||||
)
|
6
vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
generated
vendored
6
vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
generated
vendored
@@ -36,6 +36,7 @@ import (
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
|
||||
"github.com/mxk/go-flowrate/flowrate"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@@ -336,6 +337,7 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
|
||||
clone.Host = h.Location.Host
|
||||
}
|
||||
clone.URL = &location
|
||||
klog.V(6).Infof("UpgradeAwareProxy: dialing for SPDY upgrade with headers: %v", clone.Header)
|
||||
backendConn, err = h.DialForUpgrade(clone)
|
||||
if err != nil {
|
||||
klog.V(6).Infof("Proxy connection error: %v", err)
|
||||
@@ -370,13 +372,13 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
|
||||
// hijacking should be the last step in the upgrade.
|
||||
requestHijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
klog.V(6).Infof("Unable to hijack response writer: %T", w)
|
||||
klog.Errorf("Unable to hijack response writer: %T", w)
|
||||
h.Responder.Error(w, req, fmt.Errorf("request connection cannot be hijacked: %T", w))
|
||||
return true
|
||||
}
|
||||
requestHijackedConn, _, err := requestHijacker.Hijack()
|
||||
if err != nil {
|
||||
klog.V(6).Infof("Unable to hijack response: %v", err)
|
||||
klog.Errorf("Unable to hijack response: %v", err)
|
||||
h.Responder.Error(w, req, fmt.Errorf("error hijacking connection: %v", err))
|
||||
return true
|
||||
}
|
||||
|
135
vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
generated
vendored
135
vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
@@ -35,7 +36,7 @@ var (
|
||||
)
|
||||
|
||||
// PanicHandlers is a list of functions which will be invoked when a panic happens.
|
||||
var PanicHandlers = []func(interface{}){logPanic}
|
||||
var PanicHandlers = []func(context.Context, interface{}){logPanic}
|
||||
|
||||
// HandleCrash simply catches a crash and logs an error. Meant to be called via
|
||||
// defer. Additional context-specific handlers can be provided, and will be
|
||||
@@ -43,23 +44,54 @@ var PanicHandlers = []func(interface{}){logPanic}
|
||||
// handlers and logging the panic message.
|
||||
//
|
||||
// E.g., you can provide one or more additional handlers for something like shutting down go routines gracefully.
|
||||
//
|
||||
// TODO(pohly): logcheck:context // HandleCrashWithContext should be used instead of HandleCrash in code which supports contextual logging.
|
||||
func HandleCrash(additionalHandlers ...func(interface{})) {
|
||||
if r := recover(); r != nil {
|
||||
for _, fn := range PanicHandlers {
|
||||
fn(r)
|
||||
}
|
||||
for _, fn := range additionalHandlers {
|
||||
fn(r)
|
||||
}
|
||||
if ReallyCrash {
|
||||
// Actually proceed to panic.
|
||||
panic(r)
|
||||
additionalHandlersWithContext := make([]func(context.Context, interface{}), len(additionalHandlers))
|
||||
for i, handler := range additionalHandlers {
|
||||
handler := handler // capture loop variable
|
||||
additionalHandlersWithContext[i] = func(_ context.Context, r interface{}) {
|
||||
handler(r)
|
||||
}
|
||||
}
|
||||
|
||||
handleCrash(context.Background(), r, additionalHandlersWithContext...)
|
||||
}
|
||||
}
|
||||
|
||||
// HandleCrashWithContext simply catches a crash and logs an error. Meant to be called via
|
||||
// defer. Additional context-specific handlers can be provided, and will be
|
||||
// called in case of panic. HandleCrash actually crashes, after calling the
|
||||
// handlers and logging the panic message.
|
||||
//
|
||||
// E.g., you can provide one or more additional handlers for something like shutting down go routines gracefully.
|
||||
//
|
||||
// The context is used to determine how to log.
|
||||
func HandleCrashWithContext(ctx context.Context, additionalHandlers ...func(context.Context, interface{})) {
|
||||
if r := recover(); r != nil {
|
||||
handleCrash(ctx, r, additionalHandlers...)
|
||||
}
|
||||
}
|
||||
|
||||
// handleCrash is the common implementation of HandleCrash and HandleCrash.
|
||||
// Having those call a common implementation ensures that the stack depth
|
||||
// is the same regardless through which path the handlers get invoked.
|
||||
func handleCrash(ctx context.Context, r any, additionalHandlers ...func(context.Context, interface{})) {
|
||||
for _, fn := range PanicHandlers {
|
||||
fn(ctx, r)
|
||||
}
|
||||
for _, fn := range additionalHandlers {
|
||||
fn(ctx, r)
|
||||
}
|
||||
if ReallyCrash {
|
||||
// Actually proceed to panic.
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
|
||||
// logPanic logs the caller tree when a panic occurs (except in the special case of http.ErrAbortHandler).
|
||||
func logPanic(r interface{}) {
|
||||
func logPanic(ctx context.Context, r interface{}) {
|
||||
if r == http.ErrAbortHandler {
|
||||
// honor the http.ErrAbortHandler sentinel panic value:
|
||||
// ErrAbortHandler is a sentinel panic value to abort a handler.
|
||||
@@ -73,10 +105,20 @@ func logPanic(r interface{}) {
|
||||
const size = 64 << 10
|
||||
stacktrace := make([]byte, size)
|
||||
stacktrace = stacktrace[:runtime.Stack(stacktrace, false)]
|
||||
|
||||
// We don't really know how many call frames to skip because the Go
|
||||
// panic handler is between us and the code where the panic occurred.
|
||||
// If it's one function (as in Go 1.21), then skipping four levels
|
||||
// gets us to the function which called the `defer HandleCrashWithontext(...)`.
|
||||
logger := klog.FromContext(ctx).WithCallDepth(4)
|
||||
|
||||
// For backwards compatibility, conversion to string
|
||||
// is handled here instead of defering to the logging
|
||||
// backend.
|
||||
if _, ok := r.(string); ok {
|
||||
klog.Errorf("Observed a panic: %s\n%s", r, stacktrace)
|
||||
logger.Error(nil, "Observed a panic", "panic", r, "stacktrace", string(stacktrace))
|
||||
} else {
|
||||
klog.Errorf("Observed a panic: %#v (%v)\n%s", r, r, stacktrace)
|
||||
logger.Error(nil, "Observed a panic", "panic", fmt.Sprintf("%v", r), "panicGoValue", fmt.Sprintf("%#v", r), "stacktrace", string(stacktrace))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,35 +126,76 @@ func logPanic(r interface{}) {
|
||||
// error occurs.
|
||||
// TODO(lavalamp): for testability, this and the below HandleError function
|
||||
// should be packaged up into a testable and reusable object.
|
||||
var ErrorHandlers = []func(error){
|
||||
var ErrorHandlers = []ErrorHandler{
|
||||
logError,
|
||||
(&rudimentaryErrorBackoff{
|
||||
lastErrorTime: time.Now(),
|
||||
// 1ms was the number folks were able to stomach as a global rate limit.
|
||||
// If you need to log errors more than 1000 times a second you
|
||||
// should probably consider fixing your code instead. :)
|
||||
minPeriod: time.Millisecond,
|
||||
}).OnError,
|
||||
func(_ context.Context, _ error, _ string, _ ...interface{}) {
|
||||
(&rudimentaryErrorBackoff{
|
||||
lastErrorTime: time.Now(),
|
||||
// 1ms was the number folks were able to stomach as a global rate limit.
|
||||
// If you need to log errors more than 1000 times a second you
|
||||
// should probably consider fixing your code instead. :)
|
||||
minPeriod: time.Millisecond,
|
||||
}).OnError()
|
||||
},
|
||||
}
|
||||
|
||||
type ErrorHandler func(ctx context.Context, err error, msg string, keysAndValues ...interface{})
|
||||
|
||||
// HandlerError is a method to invoke when a non-user facing piece of code cannot
|
||||
// return an error and needs to indicate it has been ignored. Invoking this method
|
||||
// is preferable to logging the error - the default behavior is to log but the
|
||||
// errors may be sent to a remote server for analysis.
|
||||
//
|
||||
// TODO(pohly): logcheck:context // HandleErrorWithContext should be used instead of HandleError in code which supports contextual logging.
|
||||
func HandleError(err error) {
|
||||
// this is sometimes called with a nil error. We probably shouldn't fail and should do nothing instead
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
handleError(context.Background(), err, "Unhandled Error")
|
||||
}
|
||||
|
||||
// HandlerErrorWithContext is a method to invoke when a non-user facing piece of code cannot
|
||||
// return an error and needs to indicate it has been ignored. Invoking this method
|
||||
// is preferable to logging the error - the default behavior is to log but the
|
||||
// errors may be sent to a remote server for analysis. The context is used to
|
||||
// determine how to log the error.
|
||||
//
|
||||
// If contextual logging is enabled, the default log output is equivalent to
|
||||
//
|
||||
// logr.FromContext(ctx).WithName("UnhandledError").Error(err, msg, keysAndValues...)
|
||||
//
|
||||
// Without contextual logging, it is equivalent to:
|
||||
//
|
||||
// klog.ErrorS(err, msg, keysAndValues...)
|
||||
//
|
||||
// In contrast to HandleError, passing nil for the error is still going to
|
||||
// trigger a log entry. Don't construct a new error or wrap an error
|
||||
// with fmt.Errorf. Instead, add additional information via the mssage
|
||||
// and key/value pairs.
|
||||
//
|
||||
// This variant should be used instead of HandleError because it supports
|
||||
// structured, contextual logging.
|
||||
func HandleErrorWithContext(ctx context.Context, err error, msg string, keysAndValues ...interface{}) {
|
||||
handleError(ctx, err, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// handleError is the common implementation of HandleError and HandleErrorWithContext.
|
||||
// Using this common implementation ensures that the stack depth
|
||||
// is the same regardless through which path the handlers get invoked.
|
||||
func handleError(ctx context.Context, err error, msg string, keysAndValues ...interface{}) {
|
||||
for _, fn := range ErrorHandlers {
|
||||
fn(err)
|
||||
fn(ctx, err, msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
|
||||
// logError prints an error with the call stack of the location it was reported
|
||||
func logError(err error) {
|
||||
klog.ErrorDepth(2, err)
|
||||
// logError prints an error with the call stack of the location it was reported.
|
||||
// It expects to be called as <caller> -> HandleError[WithContext] -> handleError -> logError.
|
||||
func logError(ctx context.Context, err error, msg string, keysAndValues ...interface{}) {
|
||||
logger := klog.FromContext(ctx).WithCallDepth(3)
|
||||
logger = klog.LoggerWithName(logger, "UnhandledError")
|
||||
logger.Error(err, msg, keysAndValues...) //nolint:logcheck // logcheck complains about unknown key/value pairs.
|
||||
}
|
||||
|
||||
type rudimentaryErrorBackoff struct {
|
||||
@@ -125,7 +208,7 @@ type rudimentaryErrorBackoff struct {
|
||||
|
||||
// OnError will block if it is called more often than the embedded period time.
|
||||
// This will prevent overly tight hot error loops.
|
||||
func (r *rudimentaryErrorBackoff) OnError(error) {
|
||||
func (r *rudimentaryErrorBackoff) OnError() {
|
||||
now := time.Now() // start the timer before acquiring the lock
|
||||
r.lastErrorTimeLock.Lock()
|
||||
d := now.Sub(r.lastErrorTime)
|
||||
|
2
vendor/k8s.io/apimachinery/pkg/util/sets/doc.go
generated
vendored
2
vendor/k8s.io/apimachinery/pkg/util/sets/doc.go
generated
vendored
@@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package sets has generic set and specified sets. Generic set will
|
||||
// replace specified ones over time. And specific ones are deprecated.
|
||||
package sets
|
||||
package sets // import "k8s.io/apimachinery/pkg/util/sets"
|
||||
|
53
vendor/k8s.io/apimachinery/pkg/util/sets/ordered.go
generated
vendored
53
vendor/k8s.io/apimachinery/pkg/util/sets/ordered.go
generated
vendored
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package sets
|
||||
|
||||
// ordered is a constraint that permits any ordered type: any type
|
||||
// that supports the operators < <= >= >.
|
||||
// If future releases of Go add new ordered types,
|
||||
// this constraint will be modified to include them.
|
||||
type ordered interface {
|
||||
integer | float | ~string
|
||||
}
|
||||
|
||||
// integer is a constraint that permits any integer type.
|
||||
// If future releases of Go add new predeclared integer types,
|
||||
// this constraint will be modified to include them.
|
||||
type integer interface {
|
||||
signed | unsigned
|
||||
}
|
||||
|
||||
// float is a constraint that permits any floating-point type.
|
||||
// If future releases of Go add new predeclared floating-point types,
|
||||
// this constraint will be modified to include them.
|
||||
type float interface {
|
||||
~float32 | ~float64
|
||||
}
|
||||
|
||||
// signed is a constraint that permits any signed integer type.
|
||||
// If future releases of Go add new predeclared signed integer types,
|
||||
// this constraint will be modified to include them.
|
||||
type signed interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64
|
||||
}
|
||||
|
||||
// unsigned is a constraint that permits any unsigned integer type.
|
||||
// If future releases of Go add new predeclared unsigned integer types,
|
||||
// this constraint will be modified to include them.
|
||||
type unsigned interface {
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||
}
|
17
vendor/k8s.io/apimachinery/pkg/util/sets/set.go
generated
vendored
17
vendor/k8s.io/apimachinery/pkg/util/sets/set.go
generated
vendored
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package sets
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,7 @@ func New[T comparable](items ...T) Set[T] {
|
||||
// KeySet creates a Set from a keys of a map[comparable](? extends interface{}).
|
||||
// If the value passed in is not actually a map, this will panic.
|
||||
func KeySet[T comparable, V any](theMap map[T]V) Set[T] {
|
||||
ret := Set[T]{}
|
||||
ret := make(Set[T], len(theMap))
|
||||
for keyValue := range theMap {
|
||||
ret.Insert(keyValue)
|
||||
}
|
||||
@@ -67,14 +68,8 @@ func (s Set[T]) Delete(items ...T) Set[T] {
|
||||
// Clear empties the set.
|
||||
// It is preferable to replace the set with a newly constructed set,
|
||||
// but not all callers can do that (when there are other references to the map).
|
||||
// In some cases the set *won't* be fully cleared, e.g. a Set[float32] containing NaN
|
||||
// can't be cleared because NaN can't be removed.
|
||||
// For sets containing items of a type that is reflexive for ==,
|
||||
// this is optimized to a single call to runtime.mapclear().
|
||||
func (s Set[T]) Clear() Set[T] {
|
||||
for key := range s {
|
||||
delete(s, key)
|
||||
}
|
||||
clear(s)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -193,7 +188,7 @@ func (s1 Set[T]) Equal(s2 Set[T]) bool {
|
||||
return len(s1) == len(s2) && s1.IsSuperset(s2)
|
||||
}
|
||||
|
||||
type sortableSliceOfGeneric[T ordered] []T
|
||||
type sortableSliceOfGeneric[T cmp.Ordered] []T
|
||||
|
||||
func (g sortableSliceOfGeneric[T]) Len() int { return len(g) }
|
||||
func (g sortableSliceOfGeneric[T]) Less(i, j int) bool { return less[T](g[i], g[j]) }
|
||||
@@ -203,7 +198,7 @@ func (g sortableSliceOfGeneric[T]) Swap(i, j int) { g[i], g[j] = g[j], g[i]
|
||||
//
|
||||
// This is a separate function and not a method because not all types supported
|
||||
// by Generic are ordered and only those can be sorted.
|
||||
func List[T ordered](s Set[T]) []T {
|
||||
func List[T cmp.Ordered](s Set[T]) []T {
|
||||
res := make(sortableSliceOfGeneric[T], 0, len(s))
|
||||
for key := range s {
|
||||
res = append(res, key)
|
||||
@@ -236,6 +231,6 @@ func (s Set[T]) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func less[T ordered](lhs, rhs T) bool {
|
||||
func less[T cmp.Ordered](lhs, rhs T) bool {
|
||||
return lhs < rhs
|
||||
}
|
||||
|
11
vendor/k8s.io/apimachinery/pkg/util/validation/OWNERS
generated
vendored
Normal file
11
vendor/k8s.io/apimachinery/pkg/util/validation/OWNERS
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
# Disable inheritance as this is an api owners file
|
||||
options:
|
||||
no_parent_owners: true
|
||||
approvers:
|
||||
- api-approvers
|
||||
reviewers:
|
||||
- api-reviewers
|
||||
labels:
|
||||
- kind/api-change
|
56
vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
generated
vendored
56
vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
generated
vendored
@@ -19,10 +19,9 @@ package validation
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
netutils "k8s.io/utils/net"
|
||||
@@ -352,11 +351,12 @@ func IsValidPortName(port string) []string {
|
||||
}
|
||||
|
||||
// IsValidIP tests that the argument is a valid IP address.
|
||||
func IsValidIP(value string) []string {
|
||||
func IsValidIP(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
if netutils.ParseIPSloppy(value) == nil {
|
||||
return []string{"must be a valid IP address, (e.g. 10.9.8.7 or 2001:db8::ffff)"}
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IP address, (e.g. 10.9.8.7 or 2001:db8::ffff)"))
|
||||
}
|
||||
return nil
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidIPv4Address tests that the argument is a valid IPv4 address.
|
||||
@@ -379,6 +379,16 @@ func IsValidIPv6Address(fldPath *field.Path, value string) field.ErrorList {
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidCIDR tests that the argument is a valid CIDR value.
|
||||
func IsValidCIDR(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
_, _, err := netutils.ParseCIDRSloppy(value)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid CIDR value, (e.g. 10.9.8.0/24 or 2001:db8::/64)"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
const percentFmt string = "[0-9]+%"
|
||||
const percentErrMsg string = "a valid percent string must be a numeric string followed by an ending '%'"
|
||||
|
||||
@@ -409,6 +419,9 @@ func IsHTTPHeaderName(value string) []string {
|
||||
const envVarNameFmt = "[-._a-zA-Z][-._a-zA-Z0-9]*"
|
||||
const envVarNameFmtErrMsg string = "a valid environment variable name must consist of alphabetic characters, digits, '_', '-', or '.', and must not start with a digit"
|
||||
|
||||
// TODO(hirazawaui): Rename this when the RelaxedEnvironmentVariableValidation gate is removed.
|
||||
const relaxedEnvVarNameFmtErrMsg string = "a valid environment variable name must consist only of printable ASCII characters other than '='"
|
||||
|
||||
var envVarNameRegexp = regexp.MustCompile("^" + envVarNameFmt + "$")
|
||||
|
||||
// IsEnvVarName tests if a string is a valid environment variable name.
|
||||
@@ -422,6 +435,24 @@ func IsEnvVarName(value string) []string {
|
||||
return errs
|
||||
}
|
||||
|
||||
// IsRelaxedEnvVarName tests if a string is a valid environment variable name.
|
||||
func IsRelaxedEnvVarName(value string) []string {
|
||||
var errs []string
|
||||
|
||||
if len(value) == 0 {
|
||||
errs = append(errs, "environment variable name "+EmptyError())
|
||||
}
|
||||
|
||||
for _, r := range value {
|
||||
if r > unicode.MaxASCII || !unicode.IsPrint(r) || r == '=' {
|
||||
errs = append(errs, relaxedEnvVarNameFmtErrMsg)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
const configMapKeyFmt = `[-._a-zA-Z0-9]+`
|
||||
const configMapKeyErrMsg string = "a valid config key must consist of alphanumeric characters, '-', '_' or '.'"
|
||||
|
||||
@@ -493,18 +524,3 @@ func hasChDirPrefix(value string) []string {
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// IsValidSocketAddr checks that string represents a valid socket address
|
||||
// as defined in RFC 789. (e.g 0.0.0.0:10254 or [::]:10254))
|
||||
func IsValidSocketAddr(value string) []string {
|
||||
var errs []string
|
||||
ip, port, err := net.SplitHostPort(value)
|
||||
if err != nil {
|
||||
errs = append(errs, "must be a valid socket address format, (e.g. 0.0.0.0:10254 or [::]:10254)")
|
||||
return errs
|
||||
}
|
||||
portInt, _ := strconv.Atoi(port)
|
||||
errs = append(errs, IsValidPortNum(portInt)...)
|
||||
errs = append(errs, IsValidIP(ip)...)
|
||||
return errs
|
||||
}
|
||||
|
Reference in New Issue
Block a user