Commit fedc68f7 authored by Brad Davidson's avatar Brad Davidson Committed by Brad Davidson

Update Kubernetes to v1.20.10-k3s1

parent 82f7488a
...@@ -37,34 +37,34 @@ replace ( ...@@ -37,34 +37,34 @@ replace (
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
google.golang.org/grpc => google.golang.org/grpc v1.27.1 google.golang.org/grpc => google.golang.org/grpc v1.27.1
gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2 gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2
k8s.io/api => github.com/k3s-io/kubernetes/staging/src/k8s.io/api v1.20.9-k3s1 k8s.io/api => github.com/k3s-io/kubernetes/staging/src/k8s.io/api v1.20.10-k3s1
k8s.io/apiextensions-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.20.9-k3s1 k8s.io/apiextensions-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.20.10-k3s1
k8s.io/apimachinery => github.com/k3s-io/kubernetes/staging/src/k8s.io/apimachinery v1.20.9-k3s1 k8s.io/apimachinery => github.com/k3s-io/kubernetes/staging/src/k8s.io/apimachinery v1.20.10-k3s1
k8s.io/apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiserver v1.20.9-k3s1 k8s.io/apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiserver v1.20.10-k3s1
k8s.io/cli-runtime => github.com/k3s-io/kubernetes/staging/src/k8s.io/cli-runtime v1.20.9-k3s1 k8s.io/cli-runtime => github.com/k3s-io/kubernetes/staging/src/k8s.io/cli-runtime v1.20.10-k3s1
k8s.io/client-go => github.com/k3s-io/kubernetes/staging/src/k8s.io/client-go v1.20.9-k3s1 k8s.io/client-go => github.com/k3s-io/kubernetes/staging/src/k8s.io/client-go v1.20.10-k3s1
k8s.io/cloud-provider => github.com/k3s-io/kubernetes/staging/src/k8s.io/cloud-provider v1.20.9-k3s1 k8s.io/cloud-provider => github.com/k3s-io/kubernetes/staging/src/k8s.io/cloud-provider v1.20.10-k3s1
k8s.io/cluster-bootstrap => github.com/k3s-io/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.20.9-k3s1 k8s.io/cluster-bootstrap => github.com/k3s-io/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.20.10-k3s1
k8s.io/code-generator => github.com/k3s-io/kubernetes/staging/src/k8s.io/code-generator v1.20.9-k3s1 k8s.io/code-generator => github.com/k3s-io/kubernetes/staging/src/k8s.io/code-generator v1.20.10-k3s1
k8s.io/component-base => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-base v1.20.9-k3s1 k8s.io/component-base => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-base v1.20.10-k3s1
k8s.io/component-helpers => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-helpers v1.20.9-k3s1 k8s.io/component-helpers => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-helpers v1.20.10-k3s1
k8s.io/controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/controller-manager v1.20.9-k3s1 k8s.io/controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/controller-manager v1.20.10-k3s1
k8s.io/cri-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/cri-api v1.20.9-k3s1 k8s.io/cri-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/cri-api v1.20.10-k3s1
k8s.io/csi-translation-lib => github.com/k3s-io/kubernetes/staging/src/k8s.io/csi-translation-lib v1.20.9-k3s1 k8s.io/csi-translation-lib => github.com/k3s-io/kubernetes/staging/src/k8s.io/csi-translation-lib v1.20.10-k3s1
k8s.io/kube-aggregator => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-aggregator v1.20.9-k3s1 k8s.io/kube-aggregator => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-aggregator v1.20.10-k3s1
k8s.io/kube-controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-controller-manager v1.20.9-k3s1 k8s.io/kube-controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-controller-manager v1.20.10-k3s1
k8s.io/kube-proxy => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-proxy v1.20.9-k3s1 k8s.io/kube-proxy => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-proxy v1.20.10-k3s1
k8s.io/kube-scheduler => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-scheduler v1.20.9-k3s1 k8s.io/kube-scheduler => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-scheduler v1.20.10-k3s1
k8s.io/kubectl => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubectl v1.20.9-k3s1 k8s.io/kubectl => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubectl v1.20.10-k3s1
k8s.io/kubelet => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubelet v1.20.9-k3s1 k8s.io/kubelet => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubelet v1.20.10-k3s1
k8s.io/kubernetes => github.com/k3s-io/kubernetes v1.20.9-k3s1 k8s.io/kubernetes => github.com/k3s-io/kubernetes v1.20.10-k3s1
k8s.io/legacy-cloud-providers => github.com/k3s-io/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.20.9-k3s1 k8s.io/legacy-cloud-providers => github.com/k3s-io/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.20.10-k3s1
k8s.io/metrics => github.com/k3s-io/kubernetes/staging/src/k8s.io/metrics v1.20.9-k3s1 k8s.io/metrics => github.com/k3s-io/kubernetes/staging/src/k8s.io/metrics v1.20.10-k3s1
k8s.io/mount-utils => github.com/k3s-io/kubernetes/staging/src/k8s.io/mount-utils v1.20.9-k3s1 k8s.io/mount-utils => github.com/k3s-io/kubernetes/staging/src/k8s.io/mount-utils v1.20.10-k3s1
k8s.io/node-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/node-api v1.20.9-k3s1 k8s.io/node-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/node-api v1.20.10-k3s1
k8s.io/sample-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-apiserver v1.20.9-k3s1 k8s.io/sample-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-apiserver v1.20.10-k3s1
k8s.io/sample-cli-plugin => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.20.9-k3s1 k8s.io/sample-cli-plugin => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.20.10-k3s1
k8s.io/sample-controller => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-controller v1.20.9-k3s1 k8s.io/sample-controller => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-controller v1.20.10-k3s1
mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34 mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
) )
...@@ -130,7 +130,7 @@ require ( ...@@ -130,7 +130,7 @@ require (
k8s.io/cri-api v1.20.0 k8s.io/cri-api v1.20.0
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/kubectl v1.20.5 k8s.io/kubectl v1.20.5
k8s.io/kubernetes v1.20.9 k8s.io/kubernetes v1.20.10
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 k8s.io/utils v0.0.0-20201110183641-67b214c5f920
sigs.k8s.io/yaml v1.2.0 sigs.k8s.io/yaml v1.2.0
) )
...@@ -335,7 +335,7 @@ func RecordRequestAbort(req *http.Request, requestInfo *request.RequestInfo) { ...@@ -335,7 +335,7 @@ func RecordRequestAbort(req *http.Request, requestInfo *request.RequestInfo) {
} }
scope := CleanScope(requestInfo) scope := CleanScope(requestInfo)
reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), req) reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), "", req)
resource := requestInfo.Resource resource := requestInfo.Resource
subresource := requestInfo.Subresource subresource := requestInfo.Subresource
group := requestInfo.APIGroup group := requestInfo.APIGroup
...@@ -358,7 +358,7 @@ func RecordRequestTermination(req *http.Request, requestInfo *request.RequestInf ...@@ -358,7 +358,7 @@ func RecordRequestTermination(req *http.Request, requestInfo *request.RequestInf
// InstrumentRouteFunc which is registered in installer.go with predefined // InstrumentRouteFunc which is registered in installer.go with predefined
// list of verbs (different than those translated to RequestInfo). // list of verbs (different than those translated to RequestInfo).
// However, we need to tweak it e.g. to differentiate GET from LIST. // However, we need to tweak it e.g. to differentiate GET from LIST.
reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), req) reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), "", req)
if requestInfo.IsResourceRequest { if requestInfo.IsResourceRequest {
requestTerminationsTotal.WithLabelValues(reportedVerb, requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component, codeToString(code)).Inc() requestTerminationsTotal.WithLabelValues(reportedVerb, requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component, codeToString(code)).Inc()
...@@ -380,7 +380,7 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp ...@@ -380,7 +380,7 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp
// InstrumentRouteFunc which is registered in installer.go with predefined // InstrumentRouteFunc which is registered in installer.go with predefined
// list of verbs (different than those translated to RequestInfo). // list of verbs (different than those translated to RequestInfo).
// However, we need to tweak it e.g. to differentiate GET from LIST. // However, we need to tweak it e.g. to differentiate GET from LIST.
reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), req) reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), "", req)
if requestInfo.IsResourceRequest { if requestInfo.IsResourceRequest {
g = longRunningRequestGauge.WithLabelValues(reportedVerb, requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component) g = longRunningRequestGauge.WithLabelValues(reportedVerb, requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component)
...@@ -399,7 +399,7 @@ func MonitorRequest(req *http.Request, verb, group, version, resource, subresour ...@@ -399,7 +399,7 @@ func MonitorRequest(req *http.Request, verb, group, version, resource, subresour
// InstrumentRouteFunc which is registered in installer.go with predefined // InstrumentRouteFunc which is registered in installer.go with predefined
// list of verbs (different than those translated to RequestInfo). // list of verbs (different than those translated to RequestInfo).
// However, we need to tweak it e.g. to differentiate GET from LIST. // However, we need to tweak it e.g. to differentiate GET from LIST.
reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), req) reportedVerb := cleanVerb(canonicalVerb(strings.ToUpper(req.Method), scope), verb, req)
dryRun := cleanDryRun(req.URL) dryRun := cleanDryRun(req.URL)
elapsedSeconds := elapsed.Seconds() elapsedSeconds := elapsed.Seconds()
...@@ -517,8 +517,15 @@ func canonicalVerb(verb string, scope string) string { ...@@ -517,8 +517,15 @@ func canonicalVerb(verb string, scope string) string {
} }
} }
func cleanVerb(verb string, request *http.Request) string { func cleanVerb(verb, suggestedVerb string, request *http.Request) string {
reportedVerb := verb reportedVerb := verb
// CanonicalVerb (being an input for this function) doesn't handle correctly the
// deprecated path pattern for watch of:
// GET /api/{version}/watch/{resource}
// We correct it manually based on the pass verb from the installer.
if suggestedVerb == "WATCH" || suggestedVerb == "WATCHLIST" {
reportedVerb = "WATCH"
}
if verb == "LIST" { if verb == "LIST" {
// see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool // see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool
if values := request.URL.Query()["watch"]; len(values) > 0 { if values := request.URL.Query()["watch"]; len(values) > 0 {
......
...@@ -31,8 +31,8 @@ type decoratedWatcher struct { ...@@ -31,8 +31,8 @@ type decoratedWatcher struct {
resultCh chan watch.Event resultCh chan watch.Event
} }
func newDecoratedWatcher(w watch.Interface, decorator ObjectFunc) *decoratedWatcher { func newDecoratedWatcher(ctx context.Context, w watch.Interface, decorator ObjectFunc) *decoratedWatcher {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(ctx)
d := &decoratedWatcher{ d := &decoratedWatcher{
w: w, w: w,
decorator: decorator, decorator: decorator,
...@@ -43,14 +43,18 @@ func newDecoratedWatcher(w watch.Interface, decorator ObjectFunc) *decoratedWatc ...@@ -43,14 +43,18 @@ func newDecoratedWatcher(w watch.Interface, decorator ObjectFunc) *decoratedWatc
return d return d
} }
// run decorates watch events from the underlying watcher until its result channel
// is closed or the passed in context is done.
// When run() returns, decoratedWatcher#resultCh is closed.
func (d *decoratedWatcher) run(ctx context.Context) { func (d *decoratedWatcher) run(ctx context.Context) {
var recv, send watch.Event var recv, send watch.Event
var ok bool var ok bool
defer close(d.resultCh)
for { for {
select { select {
case recv, ok = <-d.w.ResultChan(): case recv, ok = <-d.w.ResultChan():
// The underlying channel may be closed after timeout.
if !ok { if !ok {
// The underlying channel was closed, cancel our context
d.cancel() d.cancel()
return return
} }
...@@ -67,20 +71,24 @@ func (d *decoratedWatcher) run(ctx context.Context) { ...@@ -67,20 +71,24 @@ func (d *decoratedWatcher) run(ctx context.Context) {
} }
select { select {
case d.resultCh <- send: case d.resultCh <- send:
if send.Type == watch.Error { // propagated event successfully
d.cancel()
}
case <-ctx.Done(): case <-ctx.Done():
// context timed out or was cancelled, stop the underlying watcher
d.w.Stop()
return
} }
case <-ctx.Done(): case <-ctx.Done():
// context timed out or was cancelled, stop the underlying watcher
d.w.Stop() d.w.Stop()
close(d.resultCh)
return return
} }
} }
} }
func (d *decoratedWatcher) Stop() { func (d *decoratedWatcher) Stop() {
// stop the underlying watcher
d.w.Stop()
// cancel our context
d.cancel() d.cancel()
} }
......
...@@ -1136,7 +1136,7 @@ func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate ...@@ -1136,7 +1136,7 @@ func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate
return nil, err return nil, err
} }
if e.Decorator != nil { if e.Decorator != nil {
return newDecoratedWatcher(w, e.Decorator), nil return newDecoratedWatcher(ctx, w, e.Decorator), nil
} }
return w, nil return w, nil
} }
...@@ -1149,7 +1149,7 @@ func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate ...@@ -1149,7 +1149,7 @@ func (e *Store) WatchPredicate(ctx context.Context, p storage.SelectionPredicate
return nil, err return nil, err
} }
if e.Decorator != nil { if e.Decorator != nil {
return newDecoratedWatcher(w, e.Decorator), nil return newDecoratedWatcher(ctx, w, e.Decorator), nil
} }
return w, nil return w, nil
} }
......
...@@ -134,7 +134,7 @@ func tunnelHTTPConnect(proxyConn net.Conn, proxyAddress, addr string) (net.Conn, ...@@ -134,7 +134,7 @@ func tunnelHTTPConnect(proxyConn net.Conn, proxyAddress, addr string) (net.Conn,
type proxier interface { type proxier interface {
// proxy returns a connection to addr. // proxy returns a connection to addr.
proxy(addr string) (net.Conn, error) proxy(ctx context.Context, addr string) (net.Conn, error)
} }
var _ proxier = &httpConnectProxier{} var _ proxier = &httpConnectProxier{}
...@@ -144,7 +144,7 @@ type httpConnectProxier struct { ...@@ -144,7 +144,7 @@ type httpConnectProxier struct {
proxyAddress string proxyAddress string
} }
func (t *httpConnectProxier) proxy(addr string) (net.Conn, error) { func (t *httpConnectProxier) proxy(ctx context.Context, addr string) (net.Conn, error) {
return tunnelHTTPConnect(t.conn, t.proxyAddress, addr) return tunnelHTTPConnect(t.conn, t.proxyAddress, addr)
} }
...@@ -154,8 +154,8 @@ type grpcProxier struct { ...@@ -154,8 +154,8 @@ type grpcProxier struct {
tunnel client.Tunnel tunnel client.Tunnel
} }
func (g *grpcProxier) proxy(addr string) (net.Conn, error) { func (g *grpcProxier) proxy(ctx context.Context, addr string) (net.Conn, error) {
return g.tunnel.Dial("tcp", addr) return g.tunnel.DialContext(ctx, "tcp", addr)
} }
type proxyServerConnector interface { type proxyServerConnector interface {
...@@ -203,7 +203,8 @@ func (u *udsGRPCConnector) connect() (proxier, error) { ...@@ -203,7 +203,8 @@ func (u *udsGRPCConnector) connect() (proxier, error) {
return c, err return c, err
}) })
tunnel, err := client.CreateSingleUseGrpcTunnel(udsName, dialOption, grpc.WithInsecure()) ctx := context.TODO()
tunnel, err := client.CreateSingleUseGrpcTunnel(ctx, udsName, dialOption, grpc.WithInsecure())
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -234,7 +235,7 @@ func (d *dialerCreator) createDialer() utilnet.DialFunc { ...@@ -234,7 +235,7 @@ func (d *dialerCreator) createDialer() utilnet.DialFunc {
egressmetrics.Metrics.ObserveDialFailure(d.options.protocol, d.options.transport, egressmetrics.StageConnect) egressmetrics.Metrics.ObserveDialFailure(d.options.protocol, d.options.transport, egressmetrics.StageConnect)
return nil, err return nil, err
} }
conn, err := proxier.proxy(addr) conn, err := proxier.proxy(ctx, addr)
if err != nil { if err != nil {
egressmetrics.Metrics.ObserveDialFailure(d.options.protocol, d.options.transport, egressmetrics.StageProxy) egressmetrics.Metrics.ObserveDialFailure(d.options.protocol, d.options.transport, egressmetrics.StageProxy)
return nil, err return nil, err
......
...@@ -301,12 +301,22 @@ func (s *store) GuaranteedUpdate( ...@@ -301,12 +301,22 @@ func (s *store) GuaranteedUpdate(
} }
// It's possible we were working with stale data // It's possible we were working with stale data
// Remember the revision of the potentially stale data and the resulting update error
cachedRev := origState.rev
cachedUpdateErr := err
// Actually fetch // Actually fetch
origState, err = getCurrentState() origState, err = getCurrentState()
if err != nil { if err != nil {
return err return err
} }
mustCheckData = false mustCheckData = false
// it turns out our cached data was not stale, return the error
if cachedRev == origState.rev {
return cachedUpdateErr
}
// Retry // Retry
continue continue
} }
......
...@@ -3,8 +3,8 @@ package version ...@@ -3,8 +3,8 @@ package version
var ( var (
gitMajor = "1" gitMajor = "1"
gitMinor = "20" gitMinor = "20"
gitVersion = "v1.20.9-k3s1" gitVersion = "v1.20.10-k3s1"
gitCommit = "d30af26bd94ad3b90ba23bb51c962cfa46e15db7" gitCommit = "2750cc2faa1fe333ca159610b4e51f377447ba40"
gitTreeState = "clean" gitTreeState = "clean"
buildDate = "2021-07-15T23:42:22Z" buildDate = "2021-08-12T22:29:42Z"
) )
...@@ -670,8 +670,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ ...@@ -670,8 +670,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19 h1:0jaDAAxtqIrrqas4vtTqxct4xS5kHfRNycTRLTyJmVM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 h1:fmRfl9WJ4ApJn7LxNuED4m0t18qivVQOxP6aAYG9J6c=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
......
...@@ -3,8 +3,8 @@ package version ...@@ -3,8 +3,8 @@ package version
var ( var (
gitMajor = "1" gitMajor = "1"
gitMinor = "20" gitMinor = "20"
gitVersion = "v1.20.9-k3s1" gitVersion = "v1.20.10-k3s1"
gitCommit = "d30af26bd94ad3b90ba23bb51c962cfa46e15db7" gitCommit = "2750cc2faa1fe333ca159610b4e51f377447ba40"
gitTreeState = "clean" gitTreeState = "clean"
buildDate = "2021-07-15T23:42:22Z" buildDate = "2021-08-12T22:29:42Z"
) )
...@@ -104,11 +104,7 @@ func (ccc *CSRCleanerController) worker() { ...@@ -104,11 +104,7 @@ func (ccc *CSRCleanerController) worker() {
} }
func (ccc *CSRCleanerController) handle(csr *capi.CertificateSigningRequest) error { func (ccc *CSRCleanerController) handle(csr *capi.CertificateSigningRequest) error {
isIssuedExpired, err := isIssuedExpired(csr) if isIssuedPastDeadline(csr) || isDeniedPastDeadline(csr) || isFailedPastDeadline(csr) || isPendingPastDeadline(csr) || isIssuedExpired(csr) {
if err != nil {
return err
}
if isIssuedPastDeadline(csr) || isDeniedPastDeadline(csr) || isFailedPastDeadline(csr) || isPendingPastDeadline(csr) || isIssuedExpired {
if err := ccc.csrClient.Delete(context.TODO(), csr.Name, metav1.DeleteOptions{}); err != nil { if err := ccc.csrClient.Delete(context.TODO(), csr.Name, metav1.DeleteOptions{}); err != nil {
return fmt.Errorf("unable to delete CSR %q: %v", csr.Name, err) return fmt.Errorf("unable to delete CSR %q: %v", csr.Name, err)
} }
...@@ -118,18 +114,14 @@ func (ccc *CSRCleanerController) handle(csr *capi.CertificateSigningRequest) err ...@@ -118,18 +114,14 @@ func (ccc *CSRCleanerController) handle(csr *capi.CertificateSigningRequest) err
// isIssuedExpired checks if the CSR has been issued a certificate and if the // isIssuedExpired checks if the CSR has been issued a certificate and if the
// expiration of the certificate (the NotAfter value) has passed. // expiration of the certificate (the NotAfter value) has passed.
func isIssuedExpired(csr *capi.CertificateSigningRequest) (bool, error) { func isIssuedExpired(csr *capi.CertificateSigningRequest) bool {
isExpired, err := isExpired(csr)
if err != nil {
return false, err
}
for _, c := range csr.Status.Conditions { for _, c := range csr.Status.Conditions {
if c.Type == capi.CertificateApproved && isIssued(csr) && isExpired { if c.Type == capi.CertificateApproved && isIssued(csr) && isExpired(csr) {
klog.Infof("Cleaning CSR %q as the associated certificate is expired.", csr.Name) klog.Infof("Cleaning CSR %q as the associated certificate is expired.", csr.Name)
return true, nil return true
} }
} }
return false, nil return false
} }
// isPendingPastDeadline checks if the certificate has a Pending status and the // isPendingPastDeadline checks if the certificate has a Pending status and the
...@@ -198,20 +190,20 @@ func isIssued(csr *capi.CertificateSigningRequest) bool { ...@@ -198,20 +190,20 @@ func isIssued(csr *capi.CertificateSigningRequest) bool {
// isExpired checks if the CSR has a certificate and the date in the `NotAfter` // isExpired checks if the CSR has a certificate and the date in the `NotAfter`
// field has gone by. // field has gone by.
func isExpired(csr *capi.CertificateSigningRequest) (bool, error) { func isExpired(csr *capi.CertificateSigningRequest) bool {
if len(csr.Status.Certificate) == 0 { if len(csr.Status.Certificate) == 0 {
return false, nil return false
} }
block, _ := pem.Decode(csr.Status.Certificate) block, _ := pem.Decode(csr.Status.Certificate)
if block == nil { if block == nil {
return false, fmt.Errorf("expected the certificate associated with the CSR to be PEM encoded") return false
} }
certs, err := x509.ParseCertificates(block.Bytes) certs, err := x509.ParseCertificates(block.Bytes)
if err != nil { if err != nil {
return false, fmt.Errorf("unable to parse certificate data: %v", err) return false
} }
if len(certs) == 0 { if len(certs) == 0 {
return false, fmt.Errorf("no certificates found") return false
} }
return time.Now().After(certs[0].NotAfter), nil return time.Now().After(certs[0].NotAfter)
} }
...@@ -18,6 +18,8 @@ package kubelet ...@@ -18,6 +18,8 @@ package kubelet
import ( import (
"fmt" "fmt"
"io/ioutil"
"path/filepath"
"syscall" "syscall"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
...@@ -90,6 +92,57 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, o ...@@ -90,6 +92,57 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, o
return physicalMounter, nil return physicalMounter, nil
} }
// removeOrphanedPodVolumeDirs attempts to remove the pod volumes directory and
// its subdirectories. There should be no files left under normal conditions
// when this is called, so it effectively does a recursive rmdir instead of
// RemoveAll to ensure it only removes directories and not regular files.
func (kl *Kubelet) removeOrphanedPodVolumeDirs(uid types.UID) []error {
orphanVolumeErrors := []error{}
// If there are still volume directories, attempt to rmdir them
volumePaths, err := kl.getPodVolumePathListFromDisk(uid)
if err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred during reading volume dir from disk", uid, err))
return orphanVolumeErrors
}
if len(volumePaths) > 0 {
for _, volumePath := range volumePaths {
if err := syscall.Rmdir(volumePath); err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() volume at path %v: %v", uid, volumePath, err))
} else {
klog.Warningf("Cleaned up orphaned volume from pod %q at %s", uid, volumePath)
}
}
}
// If there are any volume-subpaths, attempt to rmdir them
subpathVolumePaths, err := kl.getPodVolumeSubpathListFromDisk(uid)
if err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred during reading of volume-subpaths dir from disk", uid, err))
return orphanVolumeErrors
}
if len(subpathVolumePaths) > 0 {
for _, subpathVolumePath := range subpathVolumePaths {
if err := syscall.Rmdir(subpathVolumePath); err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() subpath at path %v: %v", uid, subpathVolumePath, err))
} else {
klog.Warningf("Cleaned up orphaned volume subpath from pod %q at %s", uid, subpathVolumePath)
}
}
}
// Remove any remaining subdirectories along with the volumes directory itself.
// Fail if any regular files are encountered.
podVolDir := kl.getPodVolumesDir(uid)
if err := removeall.RemoveDirsOneFilesystem(kl.mounter, podVolDir); err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred when trying to remove the volumes dir", uid, err))
} else {
klog.Warningf("Cleaned up orphaned pod volumes dir from pod %q at %s", uid, podVolDir)
}
return orphanVolumeErrors
}
// cleanupOrphanedPodDirs removes the volumes of pods that should not be // cleanupOrphanedPodDirs removes the volumes of pods that should not be
// running and that have no containers running. Note that we roll up logs here since it runs in the main loop. // running and that have no containers running. Note that we roll up logs here since it runs in the main loop.
func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecontainer.Pod) error { func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecontainer.Pod) error {
...@@ -122,55 +175,48 @@ func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecon ...@@ -122,55 +175,48 @@ func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecon
continue continue
} }
allVolumesCleanedUp := true // Attempt to remove the pod volumes directory and its subdirs
podVolumeErrors := kl.removeOrphanedPodVolumeDirs(uid)
// If there are still volume directories, attempt to rmdir them if len(podVolumeErrors) > 0 {
volumePaths, err := kl.getPodVolumePathListFromDisk(uid) orphanVolumeErrors = append(orphanVolumeErrors, podVolumeErrors...)
if err != nil { // Not all volumes were removed, so don't clean up the pod directory yet. It is likely
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred during reading volume dir from disk", uid, err)) // that there are still mountpoints or files left which could cause removal of the pod
// directory to fail below.
// Errors for all removal operations have already been recorded, so don't add another
// one here.
continue continue
} }
if len(volumePaths) > 0 {
for _, volumePath := range volumePaths {
if err := syscall.Rmdir(volumePath); err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() volume at path %v: %v", uid, volumePath, err))
allVolumesCleanedUp = false
} else {
klog.Warningf("Cleaned up orphaned volume from pod %q at %s", uid, volumePath)
}
}
}
// If there are any volume-subpaths, attempt to rmdir them // Call RemoveAllOneFilesystem for remaining subdirs under the pod directory
subpathVolumePaths, err := kl.getPodVolumeSubpathListFromDisk(uid) podDir := kl.getPodDir(uid)
podSubdirs, err := ioutil.ReadDir(podDir)
if err != nil { if err != nil {
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred during reading of volume-subpaths dir from disk", uid, err)) klog.Errorf("Could not read directory %q; err: %v", podDir, err)
orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred during reading the pod dir from disk", uid, err))
continue continue
} }
if len(subpathVolumePaths) > 0 { for _, podSubdir := range podSubdirs {
for _, subpathVolumePath := range subpathVolumePaths { podSubdirName := podSubdir.Name()
if err := syscall.Rmdir(subpathVolumePath); err != nil { podSubdirPath := filepath.Join(podDir, podSubdirName)
orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() subpath at path %v: %v", uid, subpathVolumePath, err)) // Never attempt RemoveAllOneFilesystem on the volumes directory,
allVolumesCleanedUp = false // as this could lead to data loss in some situations. The volumes
} else { // directory should have been removed by removeOrphanedPodVolumeDirs.
klog.Warningf("Cleaned up orphaned volume subpath from pod %q at %s", uid, subpathVolumePath) if podSubdirName == "volumes" {
} err := fmt.Errorf("volumes subdir was found after it was removed")
klog.Errorf("Orphaned pod %q found, but failed to remove volumes subdir %q; err: %v", uid, podSubdirPath, err)
continue
} }
if err := removeall.RemoveAllOneFilesystem(kl.mounter, podSubdirPath); err != nil {
klog.Errorf("Failed to remove orphaned pod %q subdir %q; err: %v", uid, podSubdirPath, err)
orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred when trying to remove subdir %q", uid, err, podSubdirPath))
} }
if !allVolumesCleanedUp {
// Not all volumes were removed, so don't clean up the pod directory yet. It is likely
// that there are still mountpoints left which could stall RemoveAllOneFilesystem which
// would otherwise be called below.
// Errors for all removal operations have already been recorded, so don't add another
// one here.
continue
} }
// Rmdir the pod dir, which should be empty if everything above was successful
klog.V(3).Infof("Orphaned pod %q found, removing", uid) klog.V(3).Infof("Orphaned pod %q found, removing", uid)
if err := removeall.RemoveAllOneFilesystem(kl.mounter, kl.getPodDir(uid)); err != nil { if err := syscall.Rmdir(podDir); err != nil {
klog.Errorf("Failed to remove orphaned pod %q dir; err: %v", uid, err) klog.Errorf("Failed to remove orphaned pod %q dir; err: %v", uid, err)
orphanRemovalErrors = append(orphanRemovalErrors, err) orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error %v occurred when trying to remove the pod directory", uid, err))
} }
} }
......
...@@ -139,6 +139,7 @@ func (c *Configurator) create() (*Scheduler, error) { ...@@ -139,6 +139,7 @@ func (c *Configurator) create() (*Scheduler, error) {
frameworkruntime.WithRunAllFilters(c.alwaysCheckAllPredicates), frameworkruntime.WithRunAllFilters(c.alwaysCheckAllPredicates),
frameworkruntime.WithPodNominator(nominator), frameworkruntime.WithPodNominator(nominator),
frameworkruntime.WithCaptureProfile(frameworkruntime.CaptureProfile(c.frameworkCapturer)), frameworkruntime.WithCaptureProfile(frameworkruntime.CaptureProfile(c.frameworkCapturer)),
frameworkruntime.WithExtenders(extenders),
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("initializing profiles: %v", err) return nil, fmt.Errorf("initializing profiles: %v", err)
......
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- sig-storage-approvers
reviewers:
- sig-storage-reviewers
labels:
- sig/storage
...@@ -25,16 +25,16 @@ import ( ...@@ -25,16 +25,16 @@ import (
"k8s.io/mount-utils" "k8s.io/mount-utils"
) )
// RemoveAllOneFilesystem removes path and any children it contains. // RemoveAllOneFilesystemCommon removes the path and any children it contains,
// It removes everything it can but returns the first error // using the provided remove function. It removes everything it can but returns
// it encounters. If the path does not exist, RemoveAll // the first error it encounters. If the path does not exist, RemoveAll
// returns nil (no error). // returns nil (no error).
// It makes sure it does not cross mount boundary, i.e. it does *not* remove // It makes sure it does not cross mount boundary, i.e. it does *not* remove
// files from another filesystems. Like 'rm -rf --one-file-system'. // files from another filesystems. Like 'rm -rf --one-file-system'.
// It is copied from RemoveAll() sources, with IsLikelyNotMountPoint // It is copied from RemoveAll() sources, with IsLikelyNotMountPoint
func RemoveAllOneFilesystem(mounter mount.Interface, path string) error { func RemoveAllOneFilesystemCommon(mounter mount.Interface, path string, remove func(string) error) error {
// Simple case: if Remove works, we're done. // Simple case: if Remove works, we're done.
err := os.Remove(path) err := remove(path)
if err == nil || os.IsNotExist(err) { if err == nil || os.IsNotExist(err) {
return nil return nil
} }
...@@ -48,7 +48,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error { ...@@ -48,7 +48,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
return serr return serr
} }
if !dir.IsDir() { if !dir.IsDir() {
// Not a directory; return the error from Remove. // Not a directory; return the error from remove.
return err return err
} }
...@@ -76,7 +76,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error { ...@@ -76,7 +76,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
for { for {
names, err1 := fd.Readdirnames(100) names, err1 := fd.Readdirnames(100)
for _, name := range names { for _, name := range names {
err1 := RemoveAllOneFilesystem(mounter, path+string(os.PathSeparator)+name) err1 := RemoveAllOneFilesystemCommon(mounter, path+string(os.PathSeparator)+name, remove)
if err == nil { if err == nil {
err = err1 err = err1
} }
...@@ -97,7 +97,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error { ...@@ -97,7 +97,7 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
fd.Close() fd.Close()
// Remove directory. // Remove directory.
err1 := os.Remove(path) err1 := remove(path)
if err1 == nil || os.IsNotExist(err1) { if err1 == nil || os.IsNotExist(err1) {
return nil return nil
} }
...@@ -106,3 +106,23 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error { ...@@ -106,3 +106,23 @@ func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
} }
return err return err
} }
// RemoveAllOneFilesystem removes the path and any children it contains, using
// the os.Remove function. It makes sure it does not cross mount boundaries,
// i.e. it returns an error rather than remove files from another filesystem.
// It removes everything it can but returns the first error it encounters.
// If the path does not exist, it returns nil (no error).
func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
return RemoveAllOneFilesystemCommon(mounter, path, os.Remove)
}
// RemoveDirsOneFilesystem removes the path and any empty subdirectories it
// contains, using the syscall.Rmdir function. Unlike RemoveAllOneFilesystem,
// RemoveDirsOneFilesystem will remove only directories and returns an error if
// it encounters any files in the directory tree. It makes sure it does not
// cross mount boundaries, i.e. it returns an error rather than remove dirs
// from another filesystem. It removes everything it can but returns the first
// error it encounters. If the path does not exist, it returns nil (no error).
func RemoveDirsOneFilesystem(mounter mount.Interface, path string) error {
return RemoveAllOneFilesystemCommon(mounter, path, syscall.Rmdir)
}
...@@ -1262,13 +1262,6 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service, ...@@ -1262,13 +1262,6 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
// construct FrontendIPConfigurationPropertiesFormat // construct FrontendIPConfigurationPropertiesFormat
var fipConfigurationProperties *network.FrontendIPConfigurationPropertiesFormat var fipConfigurationProperties *network.FrontendIPConfigurationPropertiesFormat
if isInternal { if isInternal {
// azure does not support ILB for IPv6 yet.
// TODO: remove this check when ILB supports IPv6 *and* the SDK
// have been rev'ed to 2019* version
if utilnet.IsIPv6String(service.Spec.ClusterIP) {
return nil, fmt.Errorf("ensure(%s): lb(%s) - internal load balancers does not support IPv6", serviceName, lbName)
}
subnetName := subnet(service) subnetName := subnet(service)
if subnetName == nil { if subnetName == nil {
subnetName = &az.SubnetName subnetName = &az.SubnetName
...@@ -1286,6 +1279,10 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service, ...@@ -1286,6 +1279,10 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
Subnet: &subnet, Subnet: &subnet,
} }
if utilnet.IsIPv6String(service.Spec.ClusterIP) {
configProperties.PrivateIPAddressVersion = network.IPv6
}
loadBalancerIP := service.Spec.LoadBalancerIP loadBalancerIP := service.Spec.LoadBalancerIP
if loadBalancerIP != "" { if loadBalancerIP != "" {
configProperties.PrivateIPAllocationMethod = network.Static configProperties.PrivateIPAllocationMethod = network.Static
......
...@@ -1034,6 +1034,11 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend ...@@ -1034,6 +1034,11 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend
} }
func getAvailabilitySetNameByID(asID string) (string, error) { func getAvailabilitySetNameByID(asID string) (string, error) {
// for standalone VM
if asID == "" {
return "", nil
}
matches := vmasIDRE.FindStringSubmatch(asID) matches := vmasIDRE.FindStringSubmatch(asID)
if len(matches) != 2 { if len(matches) != 2 {
return "", fmt.Errorf("getAvailabilitySetNameByID: failed to parse the VMAS ID %s", asID) return "", fmt.Errorf("getAvailabilitySetNameByID: failed to parse the VMAS ID %s", asID)
......
...@@ -1378,10 +1378,19 @@ func (ss *scaleSet) ensureBackendPoolDeletedFromNode(nodeName, backendPoolID str ...@@ -1378,10 +1378,19 @@ func (ss *scaleSet) ensureBackendPoolDeletedFromNode(nodeName, backendPoolID str
func (ss *scaleSet) GetNodeNameByIPConfigurationID(ipConfigurationID string) (string, string, error) { func (ss *scaleSet) GetNodeNameByIPConfigurationID(ipConfigurationID string) (string, string, error) {
matches := vmssIPConfigurationRE.FindStringSubmatch(ipConfigurationID) matches := vmssIPConfigurationRE.FindStringSubmatch(ipConfigurationID)
if len(matches) != 4 { if len(matches) != 4 {
klog.V(4).Infof("Can not extract scale set name from ipConfigurationID (%s), assuming it is managed by availability set", ipConfigurationID) if ss.DisableAvailabilitySetNodes {
return "", "", ErrorNotVmssInstance return "", "", ErrorNotVmssInstance
} }
klog.V(4).Infof("Can not extract scale set name from ipConfigurationID (%s), assuming it is managed by availability set", ipConfigurationID)
name, rg, err := ss.availabilitySet.GetNodeNameByIPConfigurationID(ipConfigurationID)
if err != nil {
klog.Errorf("GetNodeNameByIPConfigurationID: failed to invoke availabilitySet.GetNodeNameByIPConfigurationID: %s", err.Error())
return "", "", err
}
return name, rg, nil
}
resourceGroup := matches[1] resourceGroup := matches[1]
scaleSetName := matches[2] scaleSetName := matches[2]
instanceID := matches[3] instanceID := matches[3]
......
...@@ -35,7 +35,7 @@ import ( ...@@ -35,7 +35,7 @@ import (
type Tunnel interface { type Tunnel interface {
// Dial connects to the address on the named network, similar to // Dial connects to the address on the named network, similar to
// what net.Dial does. The only supported protocol is tcp. // what net.Dial does. The only supported protocol is tcp.
Dial(protocol, address string) (net.Conn, error) DialContext(ctx context.Context, protocol, address string) (net.Conn, error)
} }
type dialResult struct { type dialResult struct {
...@@ -66,15 +66,15 @@ var _ clientConn = &grpc.ClientConn{} ...@@ -66,15 +66,15 @@ var _ clientConn = &grpc.ClientConn{}
// gRPC based proxy service. // gRPC based proxy service.
// Currently, a single tunnel supports a single connection, and the tunnel is closed when the connection is terminated // Currently, a single tunnel supports a single connection, and the tunnel is closed when the connection is terminated
// The Dial() method of the returned tunnel should only be called once // The Dial() method of the returned tunnel should only be called once
func CreateSingleUseGrpcTunnel(address string, opts ...grpc.DialOption) (Tunnel, error) { func CreateSingleUseGrpcTunnel(ctx context.Context, address string, opts ...grpc.DialOption) (Tunnel, error) {
c, err := grpc.Dial(address, opts...) c, err := grpc.DialContext(ctx, address, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
grpcClient := client.NewProxyServiceClient(c) grpcClient := client.NewProxyServiceClient(c)
stream, err := grpcClient.Proxy(context.Background()) stream, err := grpcClient.Proxy(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -175,7 +175,7 @@ func (t *grpcTunnel) serve(c clientConn) { ...@@ -175,7 +175,7 @@ func (t *grpcTunnel) serve(c clientConn) {
// Dial connects to the address on the named network, similar to // Dial connects to the address on the named network, similar to
// what net.Dial does. The only supported protocol is tcp. // what net.Dial does. The only supported protocol is tcp.
func (t *grpcTunnel) Dial(protocol, address string) (net.Conn, error) { func (t *grpcTunnel) DialContext(ctx context.Context, protocol, address string) (net.Conn, error) {
if protocol != "tcp" { if protocol != "tcp" {
return nil, errors.New("protocol not supported") return nil, errors.New("protocol not supported")
} }
...@@ -224,7 +224,9 @@ func (t *grpcTunnel) Dial(protocol, address string) (net.Conn, error) { ...@@ -224,7 +224,9 @@ func (t *grpcTunnel) Dial(protocol, address string) (net.Conn, error) {
t.conns[res.connid] = c t.conns[res.connid] = c
t.connsLock.Unlock() t.connsLock.Unlock()
case <-time.After(30 * time.Second): case <-time.After(30 * time.Second):
return nil, errors.New("dial timeout") return nil, errors.New("dial timeout, backstop")
case <-ctx.Done():
return nil, errors.New("dial timeout, context")
} }
return c, nil return c, nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment