rebase: upgrade snapshot v1beta1 api and clientset to v1 version

At present e2e snapshot code make use of snapshot v1beta1 api and client
This patch address the same and snapshot api clientset/apis are updated
to v1 version.

Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
Humble Chirammal 2021-06-23 14:22:11 +05:30 committed by mergify[bot]
parent 0749315d7e
commit 5aca04d540
58 changed files with 1561 additions and 1285 deletions

4
go.mod
View File

@ -14,7 +14,7 @@ require (
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a
github.com/kubernetes-csi/csi-lib-utils v0.9.1 github.com/kubernetes-csi/csi-lib-utils v0.9.1
github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.1.0
github.com/libopenstorage/secrets v0.0.0-20201006135900-af310b01fe47 github.com/libopenstorage/secrets v0.0.0-20201006135900-af310b01fe47
github.com/onsi/ginkgo v1.16.4 github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.13.0 github.com/onsi/gomega v1.13.0
@ -39,7 +39,7 @@ replace (
github.com/golang/protobuf => github.com/golang/protobuf v1.4.3 github.com/golang/protobuf => github.com/golang/protobuf v1.4.3
github.com/hashicorp/vault/api => github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a github.com/hashicorp/vault/api => github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a
github.com/hashicorp/vault/sdk => github.com/hashicorp/vault/sdk v0.1.14-0.20201116234512-b4d4137dfe8b github.com/hashicorp/vault/sdk => github.com/hashicorp/vault/sdk v0.1.14-0.20201116234512-b4d4137dfe8b
github.com/kubernetes-csi/external-snapshotter/v2 => github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1-0.20200504125226-859696c419ff google.golang.org/grpc => google.golang.org/grpc v1.35.0
k8s.io/api => k8s.io/api v0.20.6 k8s.io/api => k8s.io/api v0.20.6
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.6 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.6
k8s.io/apimachinery => k8s.io/apimachinery v0.20.6 k8s.io/apimachinery => k8s.io/apimachinery v0.20.6

374
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
version = 1
test_patterns = [
"*_test.go"
]
[[analyzers]]
name = "go"
enabled = true
[analyzers.meta]
import_path = "github.com/imdario/mergo"

View File

@ -4,6 +4,4 @@ install:
- go get golang.org/x/tools/cmd/cover - go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
script: script:
- go test -race -v ./...
after_script:
- $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN - $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN

View File

@ -13,7 +13,6 @@ It is ready for production use. [It is used in several projects by Docker, Googl
[![Build Status][1]][2] [![Build Status][1]][2]
[![Coverage Status][7]][8] [![Coverage Status][7]][8]
[![Sourcegraph][9]][10] [![Sourcegraph][9]][10]
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield)
[1]: https://travis-ci.org/imdario/mergo.png [1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo [2]: https://travis-ci.org/imdario/mergo
@ -28,7 +27,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl
### Latest release ### Latest release
[Release v0.3.7](https://github.com/imdario/mergo/releases/tag/v0.3.7). [Release v0.3.6](https://github.com/imdario/mergo/releases/tag/v0.3.6).
### Important note ### Important note
@ -218,21 +217,6 @@ If I can help you, you have an idea or you are using Mergo in your projects, don
Written by [Dario Castañé](http://dario.im). Written by [Dario Castañé](http://dario.im).
## Top Contributors
[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)
## License ## License
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large)

View File

@ -72,7 +72,6 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
case reflect.Struct: case reflect.Struct:
srcMap := src.Interface().(map[string]interface{}) srcMap := src.Interface().(map[string]interface{})
for key := range srcMap { for key := range srcMap {
config.overwriteWithEmptyValue = true
srcValue := srcMap[key] srcValue := srcMap[key]
fieldName := changeInitialCase(key, unicode.ToUpper) fieldName := changeInitialCase(key, unicode.ToUpper)
dstElement := dst.FieldByName(fieldName) dstElement := dst.FieldByName(fieldName)
@ -99,11 +98,11 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
continue continue
} }
if srcKind == dstKind { if srcKind == dstKind {
if _, err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return return
} }
} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface { } else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
if _, err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return return
} }
} else if srcKind == reflect.Map { } else if srcKind == reflect.Map {
@ -157,8 +156,7 @@ func _map(dst, src interface{}, opts ...func(*Config)) error {
// To be friction-less, we redirect equal-type arguments // To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything. // to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() { if vSrc.Kind() == vDst.Kind() {
_, err := deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
return err
} }
switch vSrc.Kind() { switch vSrc.Kind() {
case reflect.Struct: case reflect.Struct:

View File

@ -11,39 +11,24 @@ package mergo
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"unsafe"
) )
func hasExportedField(dst reflect.Value) (exported bool) { func hasExportedField(dst reflect.Value) (exported bool) {
for i, n := 0, dst.NumField(); i < n; i++ { for i, n := 0, dst.NumField(); i < n; i++ {
field := dst.Type().Field(i) field := dst.Type().Field(i)
if isExportedComponent(&field) { if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
return true exported = exported || hasExportedField(dst.Field(i))
} else {
exported = exported || len(field.PkgPath) == 0
} }
} }
return return
} }
func isExportedComponent(field *reflect.StructField) bool {
name := field.Name
pkgPath := field.PkgPath
if len(pkgPath) > 0 {
return false
}
c := name[0]
if 'a' <= c && c <= 'z' || c == '_' {
return false
}
return true
}
type Config struct { type Config struct {
Overwrite bool Overwrite bool
AppendSlice bool AppendSlice bool
TypeCheck bool Transformers Transformers
Transformers Transformers
overwriteWithEmptyValue bool
overwriteSliceWithEmptyValue bool
} }
type Transformers interface { type Transformers interface {
@ -53,17 +38,12 @@ type Transformers interface {
// Traverses recursively both values, assigning src's fields values to dst. // Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows // The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types. // short circuiting on recursive types.
func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (dst reflect.Value, err error) { func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
dst = dstIn
overwrite := config.Overwrite overwrite := config.Overwrite
typeCheck := config.TypeCheck
overwriteWithEmptySrc := config.overwriteWithEmptyValue
overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
if !src.IsValid() { if !src.IsValid() {
return return
} }
if dst.CanAddr() { if dst.CanAddr() {
addr := dst.UnsafeAddr() addr := dst.UnsafeAddr()
h := 17 * addr h := 17 * addr
@ -71,7 +51,7 @@ func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int,
typ := dst.Type() typ := dst.Type()
for p := seen; p != nil; p = p.next { for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ { if p.ptr == addr && p.typ == typ {
return dst, nil return nil
} }
} }
// Remember, remember... // Remember, remember...
@ -85,170 +65,136 @@ func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int,
} }
} }
if dst.IsValid() && src.IsValid() && src.Type() != dst.Type() {
err = fmt.Errorf("cannot append two different types (%s, %s)", src.Kind(), dst.Kind())
return
}
switch dst.Kind() { switch dst.Kind() {
case reflect.Struct: case reflect.Struct:
if hasExportedField(dst) { if hasExportedField(dst) {
dstCp := reflect.New(dst.Type()).Elem()
for i, n := 0, dst.NumField(); i < n; i++ { for i, n := 0, dst.NumField(); i < n; i++ {
dstField := dst.Field(i) if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
structField := dst.Type().Field(i)
// copy un-exported struct fields
if !isExportedComponent(&structField) {
rf := dstCp.Field(i)
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem() //nolint:gosec
dstRF := dst.Field(i)
if !dst.Field(i).CanAddr() {
continue
}
dstRF = reflect.NewAt(dstRF.Type(), unsafe.Pointer(dstRF.UnsafeAddr())).Elem() //nolint:gosec
rf.Set(dstRF)
continue
}
dstField, err = deepMerge(dstField, src.Field(i), visited, depth+1, config)
if err != nil {
return return
} }
dstCp.Field(i).Set(dstField)
} }
if dst.CanSet() {
dst.Set(dstCp)
} else {
dst = dstCp
}
return
} else { } else {
if (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) { if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
dst = src dst.Set(src)
} }
} }
case reflect.Map: case reflect.Map:
if dst.IsNil() && !src.IsNil() { if dst.IsNil() && !src.IsNil() {
if dst.CanSet() { dst.Set(reflect.MakeMap(dst.Type()))
dst.Set(reflect.MakeMap(dst.Type()))
} else {
dst = src
return
}
} }
for _, key := range src.MapKeys() { for _, key := range src.MapKeys() {
srcElement := src.MapIndex(key) srcElement := src.MapIndex(key)
dstElement := dst.MapIndex(key)
if !srcElement.IsValid() { if !srcElement.IsValid() {
continue continue
} }
if dst.MapIndex(key).IsValid() { dstElement := dst.MapIndex(key)
k := dstElement.Interface() switch srcElement.Kind() {
dstElement = reflect.ValueOf(k) case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
} if srcElement.IsNil() {
if isReflectNil(srcElement) { continue
if overwrite || isReflectNil(dstElement) { }
dst.SetMapIndex(key, srcElement) fallthrough
default:
if !srcElement.CanInterface() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fallthrough
case reflect.Map:
srcMapElm := srcElement
dstMapElm := dstElement
if srcMapElm.CanInterface() {
srcMapElm = reflect.ValueOf(srcMapElm.Interface())
if dstMapElm.IsValid() {
dstMapElm = reflect.ValueOf(dstMapElm.Interface())
}
}
if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
return
}
case reflect.Slice:
srcSlice := reflect.ValueOf(srcElement.Interface())
var dstSlice reflect.Value
if !dstElement.IsValid() || dstElement.IsNil() {
dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
} else {
dstSlice = reflect.ValueOf(dstElement.Interface())
}
if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
dstSlice = srcSlice
} else if config.AppendSlice {
if srcSlice.Type() != dstSlice.Type() {
return fmt.Errorf("cannot append two slice with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
}
dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
}
dst.SetMapIndex(key, dstSlice)
} }
continue
} }
if !srcElement.CanInterface() { if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map {
continue continue
} }
if srcElement.CanInterface() { if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) {
srcElement = reflect.ValueOf(srcElement.Interface()) if dst.IsNil() {
if dstElement.IsValid() { dst.Set(reflect.MakeMap(dst.Type()))
dstElement = reflect.ValueOf(dstElement.Interface())
} }
dst.SetMapIndex(key, srcElement)
} }
dstElement, err = deepMerge(dstElement, srcElement, visited, depth+1, config)
if err != nil {
return
}
dst.SetMapIndex(key, dstElement)
} }
case reflect.Slice: case reflect.Slice:
newSlice := dst if !dst.CanSet() {
if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { break
if typeCheck && src.Type() != dst.Type() { }
return dst, fmt.Errorf("cannot override two slices with different type (%s, %s)", src.Type(), dst.Type()) if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
} dst.Set(src)
newSlice = src
} else if config.AppendSlice { } else if config.AppendSlice {
if typeCheck && src.Type() != dst.Type() { if src.Type() != dst.Type() {
err = fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type()) return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
return
} }
newSlice = reflect.AppendSlice(dst, src) dst.Set(reflect.AppendSlice(dst, src))
} }
if dst.CanSet() { case reflect.Ptr:
dst.Set(newSlice) fallthrough
} else { case reflect.Interface:
dst = newSlice if src.IsNil() {
}
case reflect.Ptr, reflect.Interface:
if isReflectNil(src) {
break break
} }
if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) {
if dst.IsNil() || overwrite {
if overwrite || isEmptyValue(dst) {
if dst.CanSet() {
dst.Set(src)
} else {
dst = src
}
}
}
break
}
if src.Kind() != reflect.Interface { if src.Kind() != reflect.Interface {
if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) { if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) { if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src) dst.Set(src)
} }
} else if src.Kind() == reflect.Ptr { } else if src.Kind() == reflect.Ptr {
if dst, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return return
} }
dst = dst.Addr()
} else if dst.Elem().Type() == src.Type() { } else if dst.Elem().Type() == src.Type() {
if dst, err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil { if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
return return
} }
} else { } else {
return dst, ErrDifferentArgumentsTypes return ErrDifferentArgumentsTypes
} }
break break
} }
if dst.IsNil() || overwrite { if dst.IsNil() || overwrite {
if (overwrite || isEmptyValue(dst)) && (overwriteWithEmptySrc || !isEmptyValue(src)) { if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
if dst.CanSet() { dst.Set(src)
dst.Set(src)
} else {
dst = src
}
} }
} else if _, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return return
} }
default: default:
overwriteFull := (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
if overwriteFull { dst.Set(src)
if dst.CanSet() {
dst.Set(src)
} else {
dst = src
}
} }
} }
return return
} }
@ -260,7 +206,7 @@ func Merge(dst, src interface{}, opts ...func(*Config)) error {
return merge(dst, src, opts...) return merge(dst, src, opts...)
} }
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values. // non-empty src attribute values.
// Deprecated: use Merge(…) with WithOverride // Deprecated: use Merge(…) with WithOverride
func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error { func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
@ -279,26 +225,11 @@ func WithOverride(config *Config) {
config.Overwrite = true config.Overwrite = true
} }
// WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values. // WithAppendSlice will make merge append slices instead of overwriting it
func WithOverwriteWithEmptyValue(config *Config) {
config.overwriteWithEmptyValue = true
}
// WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
func WithOverrideEmptySlice(config *Config) {
config.overwriteSliceWithEmptyValue = true
}
// WithAppendSlice will make merge append slices instead of overwriting it.
func WithAppendSlice(config *Config) { func WithAppendSlice(config *Config) {
config.AppendSlice = true config.AppendSlice = true
} }
// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
func WithTypeCheck(config *Config) {
config.TypeCheck = true
}
func merge(dst, src interface{}, opts ...func(*Config)) error { func merge(dst, src interface{}, opts ...func(*Config)) error {
var ( var (
vDst, vSrc reflect.Value vDst, vSrc reflect.Value
@ -314,25 +245,8 @@ func merge(dst, src interface{}, opts ...func(*Config)) error {
if vDst, vSrc, err = resolveValues(dst, src); err != nil { if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err return err
} }
if !vDst.CanSet() {
return fmt.Errorf("cannot set dst, needs reference")
}
if vDst.Type() != vSrc.Type() { if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes return ErrDifferentArgumentsTypes
} }
_, err = deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
return err
}
// IsReflectNil is the reflect value provided nil
func isReflectNil(v reflect.Value) bool {
k := v.Kind()
switch k {
case reflect.Interface, reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr:
// Both interface and slice are nil if first word is 0.
// Both are always bigger than a word; assume flagIndir.
return v.IsNil()
default:
return false
}
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 The Kubernetes Authors. Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Code generated by client-gen. DO NOT EDIT. // +k8s:deepcopy-gen=package
// +groupName=snapshot.storage.k8s.io
// This package has the automatically generated clientset. package v1
package versioned

View File

@ -0,0 +1,58 @@
/*
Copyright 2018 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 v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package.
const GroupName = "snapshot.storage.k8s.io"
var (
// SchemeBuilder is the new scheme builder
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme adds to scheme
AddToScheme = SchemeBuilder.AddToScheme
// SchemeGroupVersion is the group version used to register these objects.
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
)
// Resource takes an unqualified resource and returns a Group-qualified GroupResource.
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
SchemeBuilder.Register(addKnownTypes)
}
// addKnownTypes adds the set of types defined in this package to the supplied scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&VolumeSnapshotClass{},
&VolumeSnapshotClassList{},
&VolumeSnapshot{},
&VolumeSnapshotList{},
&VolumeSnapshotContent{},
&VolumeSnapshotContentList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@ -0,0 +1,440 @@
/*
Copyright 2020 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.
*/
// +kubebuilder:object:generate=true
package v1
import (
core_v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshot is a user's request for either creating a point-in-time
// snapshot of a persistent volume, or binding to a pre-existing snapshot.
// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Namespaced
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="ReadyToUse",type=boolean,JSONPath=`.status.readyToUse`,description="Indicates if the snapshot is ready to be used to restore a volume."
// +kubebuilder:printcolumn:name="SourcePVC",type=string,JSONPath=`.spec.source.persistentVolumeClaimName`,description="If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created."
// +kubebuilder:printcolumn:name="SourceSnapshotContent",type=string,JSONPath=`.spec.source.volumeSnapshotContentName`,description="If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot."
// +kubebuilder:printcolumn:name="RestoreSize",type=string,JSONPath=`.status.restoreSize`,description="Represents the minimum size of volume required to rehydrate from this snapshot."
// +kubebuilder:printcolumn:name="SnapshotClass",type=string,JSONPath=`.spec.volumeSnapshotClassName`,description="The name of the VolumeSnapshotClass requested by the VolumeSnapshot."
// +kubebuilder:printcolumn:name="SnapshotContent",type=string,JSONPath=`.status.boundVolumeSnapshotContentName`,description="Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object."
// +kubebuilder:printcolumn:name="CreationTime",type=date,JSONPath=`.status.creationTime`,description="Timestamp when the point-in-time snapshot was taken by the underlying storage system."
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
type VolumeSnapshot struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// spec defines the desired characteristics of a snapshot requested by a user.
// More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots
// Required.
Spec VolumeSnapshotSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// status represents the current information of a snapshot.
// Consumers must verify binding between VolumeSnapshot and
// VolumeSnapshotContent objects is successful (by validating that both
// VolumeSnapshot and VolumeSnapshotContent point at each other) before
// using this object.
// +optional
Status *VolumeSnapshotStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshotList is a list of VolumeSnapshot objects
type VolumeSnapshotList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// List of VolumeSnapshots
Items []VolumeSnapshot `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// VolumeSnapshotSpec describes the common attributes of a volume snapshot.
type VolumeSnapshotSpec struct {
// source specifies where a snapshot will be created from.
// This field is immutable after creation.
// Required.
Source VolumeSnapshotSource `json:"source" protobuf:"bytes,1,opt,name=source"`
// VolumeSnapshotClassName is the name of the VolumeSnapshotClass
// requested by the VolumeSnapshot.
// VolumeSnapshotClassName may be left nil to indicate that the default
// SnapshotClass should be used.
// A given cluster may have multiple default Volume SnapshotClasses: one
// default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass,
// VolumeSnapshotSource will be checked to figure out what the associated
// CSI Driver is, and the default VolumeSnapshotClass associated with that
// CSI Driver will be used. If more than one VolumeSnapshotClass exist for
// a given CSI Driver and more than one have been marked as default,
// CreateSnapshot will fail and generate an event.
// Empty string is not allowed for this field.
// +optional
VolumeSnapshotClassName *string `json:"volumeSnapshotClassName,omitempty" protobuf:"bytes,2,opt,name=volumeSnapshotClassName"`
}
// VolumeSnapshotSource specifies whether the underlying snapshot should be
// dynamically taken upon creation or if a pre-existing VolumeSnapshotContent
// object should be used.
// Exactly one of its members must be set.
// Members in VolumeSnapshotSource are immutable.
type VolumeSnapshotSource struct {
// persistentVolumeClaimName specifies the name of the PersistentVolumeClaim
// object representing the volume from which a snapshot should be created.
// This PVC is assumed to be in the same namespace as the VolumeSnapshot
// object.
// This field should be set if the snapshot does not exists, and needs to be
// created.
// This field is immutable.
// +optional
PersistentVolumeClaimName *string `json:"persistentVolumeClaimName,omitempty" protobuf:"bytes,1,opt,name=persistentVolumeClaimName"`
// volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent
// object representing an existing volume snapshot.
// This field should be set if the snapshot already exists and only needs a representation in Kubernetes.
// This field is immutable.
// +optional
VolumeSnapshotContentName *string `json:"volumeSnapshotContentName,omitempty" protobuf:"bytes,2,opt,name=volumeSnapshotContentName"`
}
// VolumeSnapshotStatus is the status of the VolumeSnapshot
// Note that CreationTime, RestoreSize, ReadyToUse, and Error are in both
// VolumeSnapshotStatus and VolumeSnapshotContentStatus. Fields in VolumeSnapshotStatus
// are updated based on fields in VolumeSnapshotContentStatus. They are eventual
// consistency. These fields are duplicate in both objects due to the following reasons:
// - Fields in VolumeSnapshotContentStatus can be used for filtering when importing a
// volumesnapshot.
// - VolumsnapshotStatus is used by end users because they cannot see VolumeSnapshotContent.
// - CSI snapshotter sidecar is light weight as it only watches VolumeSnapshotContent
// object, not VolumeSnapshot object.
type VolumeSnapshotStatus struct {
// boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent
// object to which this VolumeSnapshot object intends to bind to.
// If not specified, it indicates that the VolumeSnapshot object has not been
// successfully bound to a VolumeSnapshotContent object yet.
// NOTE: To avoid possible security issues, consumers must verify binding between
// VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that
// both VolumeSnapshot and VolumeSnapshotContent point at each other) before using
// this object.
// +optional
BoundVolumeSnapshotContentName *string `json:"boundVolumeSnapshotContentName,omitempty" protobuf:"bytes,1,opt,name=boundVolumeSnapshotContentName"`
// creationTime is the timestamp when the point-in-time snapshot is taken
// by the underlying storage system.
// In dynamic snapshot creation case, this field will be filled in by the
// snapshot controller with the "creation_time" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "creation_time"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it.
// If not specified, it may indicate that the creation time of the snapshot is unknown.
// +optional
CreationTime *metav1.Time `json:"creationTime,omitempty" protobuf:"bytes,2,opt,name=creationTime"`
// readyToUse indicates if the snapshot is ready to be used to restore a volume.
// In dynamic snapshot creation case, this field will be filled in by the
// snapshot controller with the "ready_to_use" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "ready_to_use"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it,
// otherwise, this field will be set to "True".
// If not specified, it means the readiness of a snapshot is unknown.
// +optional
ReadyToUse *bool `json:"readyToUse,omitempty" protobuf:"varint,3,opt,name=readyToUse"`
// restoreSize represents the minimum size of volume required to create a volume
// from this snapshot.
// In dynamic snapshot creation case, this field will be filled in by the
// snapshot controller with the "size_bytes" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "size_bytes"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it.
// When restoring a volume from this snapshot, the size of the volume MUST NOT
// be smaller than the restoreSize if it is specified, otherwise the restoration will fail.
// If not specified, it indicates that the size is unknown.
// +optional
RestoreSize *resource.Quantity `json:"restoreSize,omitempty" protobuf:"bytes,4,opt,name=restoreSize"`
// error is the last observed error during snapshot creation, if any.
// This field could be helpful to upper level controllers(i.e., application controller)
// to decide whether they should continue on waiting for the snapshot to be created
// based on the type of error reported.
// The snapshot controller will keep retrying when an error occurrs during the
// snapshot creation. Upon success, this error field will be cleared.
// +optional
Error *VolumeSnapshotError `json:"error,omitempty" protobuf:"bytes,5,opt,name=error,casttype=VolumeSnapshotError"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshotClass specifies parameters that a underlying storage system uses when
// creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its
// name in a VolumeSnapshot object.
// VolumeSnapshotClasses are non-namespaced
// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:printcolumn:name="Driver",type=string,JSONPath=`.driver`
// +kubebuilder:printcolumn:name="DeletionPolicy",type=string,JSONPath=`.deletionPolicy`,description="Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted."
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
type VolumeSnapshotClass struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// driver is the name of the storage driver that handles this VolumeSnapshotClass.
// Required.
Driver string `json:"driver" protobuf:"bytes,2,opt,name=driver"`
// parameters is a key-value map with storage driver specific parameters for creating snapshots.
// These values are opaque to Kubernetes.
// +optional
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
// deletionPolicy determines whether a VolumeSnapshotContent created through
// the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted.
// Supported values are "Retain" and "Delete".
// "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept.
// "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted.
// Required.
DeletionPolicy DeletionPolicy `json:"deletionPolicy" protobuf:"bytes,4,opt,name=deletionPolicy"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshotClassList is a collection of VolumeSnapshotClasses.
// +kubebuilder:object:root=true
type VolumeSnapshotClassList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of VolumeSnapshotClasses
Items []VolumeSnapshotClass `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshotContent represents the actual "on-disk" snapshot object in the
// underlying storage system
// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="ReadyToUse",type=boolean,JSONPath=`.status.readyToUse`,description="Indicates if the snapshot is ready to be used to restore a volume."
// +kubebuilder:printcolumn:name="RestoreSize",type=integer,JSONPath=`.status.restoreSize`,description="Represents the complete size of the snapshot in bytes"
// +kubebuilder:printcolumn:name="DeletionPolicy",type=string,JSONPath=`.spec.deletionPolicy`,description="Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted."
// +kubebuilder:printcolumn:name="Driver",type=string,JSONPath=`.spec.driver`,description="Name of the CSI driver used to create the physical snapshot on the underlying storage system."
// +kubebuilder:printcolumn:name="VolumeSnapshotClass",type=string,JSONPath=`.spec.volumeSnapshotClassName`,description="Name of the VolumeSnapshotClass to which this snapshot belongs."
// +kubebuilder:printcolumn:name="VolumeSnapshot",type=string,JSONPath=`.spec.volumeSnapshotRef.name`,description="Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound."
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
type VolumeSnapshotContent struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// spec defines properties of a VolumeSnapshotContent created by the underlying storage system.
// Required.
Spec VolumeSnapshotContentSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// status represents the current information of a snapshot.
// +optional
Status *VolumeSnapshotContentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// VolumeSnapshotContentList is a list of VolumeSnapshotContent objects
// +kubebuilder:object:root=true
type VolumeSnapshotContentList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of VolumeSnapshotContents
Items []VolumeSnapshotContent `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// VolumeSnapshotContentSpec is the specification of a VolumeSnapshotContent
type VolumeSnapshotContentSpec struct {
// volumeSnapshotRef specifies the VolumeSnapshot object to which this
// VolumeSnapshotContent object is bound.
// VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to
// this VolumeSnapshotContent's name for the bidirectional binding to be valid.
// For a pre-existing VolumeSnapshotContent object, name and namespace of the
// VolumeSnapshot object MUST be provided for binding to happen.
// This field is immutable after creation.
// Required.
VolumeSnapshotRef core_v1.ObjectReference `json:"volumeSnapshotRef" protobuf:"bytes,1,opt,name=volumeSnapshotRef"`
// deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on
// the underlying storage system should be deleted when its bound VolumeSnapshot is deleted.
// Supported values are "Retain" and "Delete".
// "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept.
// "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted.
// For dynamically provisioned snapshots, this field will automatically be filled in by the
// CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding
// VolumeSnapshotClass.
// For pre-existing snapshots, users MUST specify this field when creating the
// VolumeSnapshotContent object.
// Required.
DeletionPolicy DeletionPolicy `json:"deletionPolicy" protobuf:"bytes,2,opt,name=deletionPolicy"`
// driver is the name of the CSI driver used to create the physical snapshot on
// the underlying storage system.
// This MUST be the same as the name returned by the CSI GetPluginName() call for
// that driver.
// Required.
Driver string `json:"driver" protobuf:"bytes,3,opt,name=driver"`
// name of the VolumeSnapshotClass from which this snapshot was (or will be)
// created.
// Note that after provisioning, the VolumeSnapshotClass may be deleted or
// recreated with different set of values, and as such, should not be referenced
// post-snapshot creation.
// +optional
VolumeSnapshotClassName *string `json:"volumeSnapshotClassName,omitempty" protobuf:"bytes,4,opt,name=volumeSnapshotClassName"`
// source specifies whether the snapshot is (or should be) dynamically provisioned
// or already exists, and just requires a Kubernetes object representation.
// This field is immutable after creation.
// Required.
Source VolumeSnapshotContentSource `json:"source" protobuf:"bytes,5,opt,name=source"`
}
// VolumeSnapshotContentSource represents the CSI source of a snapshot.
// Exactly one of its members must be set.
// Members in VolumeSnapshotContentSource are immutable.
// TODO(xiangqian): Add a webhook to ensure that VolumeSnapshotContentSource members
// will be immutable once specified.
type VolumeSnapshotContentSource struct {
// volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot
// should be dynamically taken from.
// This field is immutable.
// +optional
VolumeHandle *string `json:"volumeHandle,omitempty" protobuf:"bytes,1,opt,name=volumeHandle"`
// snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on
// the underlying storage system for which a Kubernetes object representation
// was (or should be) created.
// This field is immutable.
// +optional
SnapshotHandle *string `json:"snapshotHandle,omitempty" protobuf:"bytes,2,opt,name=snapshotHandle"`
}
// VolumeSnapshotContentStatus is the status of a VolumeSnapshotContent object
// Note that CreationTime, RestoreSize, ReadyToUse, and Error are in both
// VolumeSnapshotStatus and VolumeSnapshotContentStatus. Fields in VolumeSnapshotStatus
// are updated based on fields in VolumeSnapshotContentStatus. They are eventual
// consistency. These fields are duplicate in both objects due to the following reasons:
// - Fields in VolumeSnapshotContentStatus can be used for filtering when importing a
// volumesnapshot.
// - VolumsnapshotStatus is used by end users because they cannot see VolumeSnapshotContent.
// - CSI snapshotter sidecar is light weight as it only watches VolumeSnapshotContent
// object, not VolumeSnapshot object.
type VolumeSnapshotContentStatus struct {
// snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system.
// If not specified, it indicates that dynamic snapshot creation has either failed
// or it is still in progress.
// +optional
SnapshotHandle *string `json:"snapshotHandle,omitempty" protobuf:"bytes,1,opt,name=snapshotHandle"`
// creationTime is the timestamp when the point-in-time snapshot is taken
// by the underlying storage system.
// In dynamic snapshot creation case, this field will be filled in by the
// CSI snapshotter sidecar with the "creation_time" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "creation_time"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it.
// If not specified, it indicates the creation time is unknown.
// The format of this field is a Unix nanoseconds time encoded as an int64.
// On Unix, the command `date +%s%N` returns the current time in nanoseconds
// since 1970-01-01 00:00:00 UTC.
// +optional
CreationTime *int64 `json:"creationTime,omitempty" protobuf:"varint,2,opt,name=creationTime"`
// restoreSize represents the complete size of the snapshot in bytes.
// In dynamic snapshot creation case, this field will be filled in by the
// CSI snapshotter sidecar with the "size_bytes" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "size_bytes"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it.
// When restoring a volume from this snapshot, the size of the volume MUST NOT
// be smaller than the restoreSize if it is specified, otherwise the restoration will fail.
// If not specified, it indicates that the size is unknown.
// +kubebuilder:validation:Minimum=0
// +optional
RestoreSize *int64 `json:"restoreSize,omitempty" protobuf:"bytes,3,opt,name=restoreSize"`
// readyToUse indicates if a snapshot is ready to be used to restore a volume.
// In dynamic snapshot creation case, this field will be filled in by the
// CSI snapshotter sidecar with the "ready_to_use" value returned from CSI
// "CreateSnapshot" gRPC call.
// For a pre-existing snapshot, this field will be filled with the "ready_to_use"
// value returned from the CSI "ListSnapshots" gRPC call if the driver supports it,
// otherwise, this field will be set to "True".
// If not specified, it means the readiness of a snapshot is unknown.
// +optional.
ReadyToUse *bool `json:"readyToUse,omitempty" protobuf:"varint,4,opt,name=readyToUse"`
// error is the last observed error during snapshot creation, if any.
// Upon success after retry, this error field will be cleared.
// +optional
Error *VolumeSnapshotError `json:"error,omitempty" protobuf:"bytes,5,opt,name=error,casttype=VolumeSnapshotError"`
}
// DeletionPolicy describes a policy for end-of-life maintenance of volume snapshot contents
// +kubebuilder:validation:Enum=Delete;Retain
type DeletionPolicy string
const (
// volumeSnapshotContentDelete means the snapshot will be deleted from the
// underlying storage system on release from its volume snapshot.
VolumeSnapshotContentDelete DeletionPolicy = "Delete"
// volumeSnapshotContentRetain means the snapshot will be left in its current
// state on release from its volume snapshot.
VolumeSnapshotContentRetain DeletionPolicy = "Retain"
)
// VolumeSnapshotError describes an error encountered during snapshot creation.
type VolumeSnapshotError struct {
// time is the timestamp when the error was encountered.
// +optional
Time *metav1.Time `json:"time,omitempty" protobuf:"bytes,1,opt,name=time"`
// message is a string detailing the encountered error during snapshot
// creation if specified.
// NOTE: message may be logged, and it should not contain sensitive
// information.
// +optional
Message *string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`
}

View File

@ -0,0 +1,424 @@
// +build !ignore_autogenerated
/*
Copyright 2020 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.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshot) DeepCopyInto(out *VolumeSnapshot) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
if in.Status != nil {
in, out := &in.Status, &out.Status
*out = new(VolumeSnapshotStatus)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshot.
func (in *VolumeSnapshot) DeepCopy() *VolumeSnapshot {
if in == nil {
return nil
}
out := new(VolumeSnapshot)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshot) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotClass) DeepCopyInto(out *VolumeSnapshotClass) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotClass.
func (in *VolumeSnapshotClass) DeepCopy() *VolumeSnapshotClass {
if in == nil {
return nil
}
out := new(VolumeSnapshotClass)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshotClass) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotClassList) DeepCopyInto(out *VolumeSnapshotClassList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]VolumeSnapshotClass, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotClassList.
func (in *VolumeSnapshotClassList) DeepCopy() *VolumeSnapshotClassList {
if in == nil {
return nil
}
out := new(VolumeSnapshotClassList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshotClassList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotContent) DeepCopyInto(out *VolumeSnapshotContent) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
if in.Status != nil {
in, out := &in.Status, &out.Status
*out = new(VolumeSnapshotContentStatus)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContent.
func (in *VolumeSnapshotContent) DeepCopy() *VolumeSnapshotContent {
if in == nil {
return nil
}
out := new(VolumeSnapshotContent)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshotContent) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotContentList) DeepCopyInto(out *VolumeSnapshotContentList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]VolumeSnapshotContent, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentList.
func (in *VolumeSnapshotContentList) DeepCopy() *VolumeSnapshotContentList {
if in == nil {
return nil
}
out := new(VolumeSnapshotContentList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshotContentList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotContentSource) DeepCopyInto(out *VolumeSnapshotContentSource) {
*out = *in
if in.VolumeHandle != nil {
in, out := &in.VolumeHandle, &out.VolumeHandle
*out = new(string)
**out = **in
}
if in.SnapshotHandle != nil {
in, out := &in.SnapshotHandle, &out.SnapshotHandle
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentSource.
func (in *VolumeSnapshotContentSource) DeepCopy() *VolumeSnapshotContentSource {
if in == nil {
return nil
}
out := new(VolumeSnapshotContentSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotContentSpec) DeepCopyInto(out *VolumeSnapshotContentSpec) {
*out = *in
out.VolumeSnapshotRef = in.VolumeSnapshotRef
if in.VolumeSnapshotClassName != nil {
in, out := &in.VolumeSnapshotClassName, &out.VolumeSnapshotClassName
*out = new(string)
**out = **in
}
in.Source.DeepCopyInto(&out.Source)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentSpec.
func (in *VolumeSnapshotContentSpec) DeepCopy() *VolumeSnapshotContentSpec {
if in == nil {
return nil
}
out := new(VolumeSnapshotContentSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotContentStatus) DeepCopyInto(out *VolumeSnapshotContentStatus) {
*out = *in
if in.SnapshotHandle != nil {
in, out := &in.SnapshotHandle, &out.SnapshotHandle
*out = new(string)
**out = **in
}
if in.CreationTime != nil {
in, out := &in.CreationTime, &out.CreationTime
*out = new(int64)
**out = **in
}
if in.RestoreSize != nil {
in, out := &in.RestoreSize, &out.RestoreSize
*out = new(int64)
**out = **in
}
if in.ReadyToUse != nil {
in, out := &in.ReadyToUse, &out.ReadyToUse
*out = new(bool)
**out = **in
}
if in.Error != nil {
in, out := &in.Error, &out.Error
*out = new(VolumeSnapshotError)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotContentStatus.
func (in *VolumeSnapshotContentStatus) DeepCopy() *VolumeSnapshotContentStatus {
if in == nil {
return nil
}
out := new(VolumeSnapshotContentStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotError) DeepCopyInto(out *VolumeSnapshotError) {
*out = *in
if in.Time != nil {
in, out := &in.Time, &out.Time
*out = (*in).DeepCopy()
}
if in.Message != nil {
in, out := &in.Message, &out.Message
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotError.
func (in *VolumeSnapshotError) DeepCopy() *VolumeSnapshotError {
if in == nil {
return nil
}
out := new(VolumeSnapshotError)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotList) DeepCopyInto(out *VolumeSnapshotList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]VolumeSnapshot, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotList.
func (in *VolumeSnapshotList) DeepCopy() *VolumeSnapshotList {
if in == nil {
return nil
}
out := new(VolumeSnapshotList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *VolumeSnapshotList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotSource) DeepCopyInto(out *VolumeSnapshotSource) {
*out = *in
if in.PersistentVolumeClaimName != nil {
in, out := &in.PersistentVolumeClaimName, &out.PersistentVolumeClaimName
*out = new(string)
**out = **in
}
if in.VolumeSnapshotContentName != nil {
in, out := &in.VolumeSnapshotContentName, &out.VolumeSnapshotContentName
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotSource.
func (in *VolumeSnapshotSource) DeepCopy() *VolumeSnapshotSource {
if in == nil {
return nil
}
out := new(VolumeSnapshotSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotSpec) DeepCopyInto(out *VolumeSnapshotSpec) {
*out = *in
in.Source.DeepCopyInto(&out.Source)
if in.VolumeSnapshotClassName != nil {
in, out := &in.VolumeSnapshotClassName, &out.VolumeSnapshotClassName
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotSpec.
func (in *VolumeSnapshotSpec) DeepCopy() *VolumeSnapshotSpec {
if in == nil {
return nil
}
out := new(VolumeSnapshotSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolumeSnapshotStatus) DeepCopyInto(out *VolumeSnapshotStatus) {
*out = *in
if in.BoundVolumeSnapshotContentName != nil {
in, out := &in.BoundVolumeSnapshotContentName, &out.BoundVolumeSnapshotContentName
*out = new(string)
**out = **in
}
if in.CreationTime != nil {
in, out := &in.CreationTime, &out.CreationTime
*out = (*in).DeepCopy()
}
if in.ReadyToUse != nil {
in, out := &in.ReadyToUse, &out.ReadyToUse
*out = new(bool)
**out = **in
}
if in.RestoreSize != nil {
in, out := &in.RestoreSize, &out.RestoreSize
x := (*in).DeepCopy()
*out = &x
}
if in.Error != nil {
in, out := &in.Error, &out.Error
*out = new(VolumeSnapshotError)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotStatus.
func (in *VolumeSnapshotStatus) DeepCopy() *VolumeSnapshotStatus {
if in == nil {
return nil
}
out := new(VolumeSnapshotStatus)
in.DeepCopyInto(out)
return out
}

View File

@ -19,7 +19,8 @@ limitations under the License.
package scheme package scheme
import ( import (
snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema" schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -32,6 +33,7 @@ var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{ var localSchemeBuilder = runtime.SchemeBuilder{
snapshotv1beta1.AddToScheme, snapshotv1beta1.AddToScheme,
snapshotv1.AddToScheme,
} }
// AddToScheme adds all types of this clientset into the given scheme. This allows composition // AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@ -17,4 +17,4 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients. // This package has the automatically generated typed clients.
package v1beta1 package v1

View File

@ -16,7 +16,7 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
package v1beta1 package v1
type VolumeSnapshotExpansion interface{} type VolumeSnapshotExpansion interface{}

View File

@ -16,15 +16,15 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
package v1beta1 package v1
import ( import (
"context" "context"
"time" "time"
v1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
scheme "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/scheme" scheme "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types" types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch" watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
@ -38,15 +38,15 @@ type VolumeSnapshotsGetter interface {
// VolumeSnapshotInterface has methods to work with VolumeSnapshot resources. // VolumeSnapshotInterface has methods to work with VolumeSnapshot resources.
type VolumeSnapshotInterface interface { type VolumeSnapshotInterface interface {
Create(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.CreateOptions) (*v1beta1.VolumeSnapshot, error) Create(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.CreateOptions) (*v1.VolumeSnapshot, error)
Update(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.UpdateOptions) (*v1beta1.VolumeSnapshot, error) Update(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.UpdateOptions) (*v1.VolumeSnapshot, error)
UpdateStatus(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.UpdateOptions) (*v1beta1.VolumeSnapshot, error) UpdateStatus(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.UpdateOptions) (*v1.VolumeSnapshot, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.VolumeSnapshot, error) Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.VolumeSnapshot, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.VolumeSnapshotList, error) List(ctx context.Context, opts metav1.ListOptions) (*v1.VolumeSnapshotList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshot, err error) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshot, err error)
VolumeSnapshotExpansion VolumeSnapshotExpansion
} }
@ -57,7 +57,7 @@ type volumeSnapshots struct {
} }
// newVolumeSnapshots returns a VolumeSnapshots // newVolumeSnapshots returns a VolumeSnapshots
func newVolumeSnapshots(c *SnapshotV1beta1Client, namespace string) *volumeSnapshots { func newVolumeSnapshots(c *SnapshotV1Client, namespace string) *volumeSnapshots {
return &volumeSnapshots{ return &volumeSnapshots{
client: c.RESTClient(), client: c.RESTClient(),
ns: namespace, ns: namespace,
@ -65,8 +65,8 @@ func newVolumeSnapshots(c *SnapshotV1beta1Client, namespace string) *volumeSnaps
} }
// Get takes name of the volumeSnapshot, and returns the corresponding volumeSnapshot object, and an error if there is any. // Get takes name of the volumeSnapshot, and returns the corresponding volumeSnapshot object, and an error if there is any.
func (c *volumeSnapshots) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.VolumeSnapshot, err error) { func (c *volumeSnapshots) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.VolumeSnapshot, err error) {
result = &v1beta1.VolumeSnapshot{} result = &v1.VolumeSnapshot{}
err = c.client.Get(). err = c.client.Get().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -78,12 +78,12 @@ func (c *volumeSnapshots) Get(ctx context.Context, name string, options v1.GetOp
} }
// List takes label and field selectors, and returns the list of VolumeSnapshots that match those selectors. // List takes label and field selectors, and returns the list of VolumeSnapshots that match those selectors.
func (c *volumeSnapshots) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.VolumeSnapshotList, err error) { func (c *volumeSnapshots) List(ctx context.Context, opts metav1.ListOptions) (result *v1.VolumeSnapshotList, err error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
result = &v1beta1.VolumeSnapshotList{} result = &v1.VolumeSnapshotList{}
err = c.client.Get(). err = c.client.Get().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -95,7 +95,7 @@ func (c *volumeSnapshots) List(ctx context.Context, opts v1.ListOptions) (result
} }
// Watch returns a watch.Interface that watches the requested volumeSnapshots. // Watch returns a watch.Interface that watches the requested volumeSnapshots.
func (c *volumeSnapshots) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { func (c *volumeSnapshots) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
@ -110,8 +110,8 @@ func (c *volumeSnapshots) Watch(ctx context.Context, opts v1.ListOptions) (watch
} }
// Create takes the representation of a volumeSnapshot and creates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any. // Create takes the representation of a volumeSnapshot and creates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any.
func (c *volumeSnapshots) Create(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.CreateOptions) (result *v1beta1.VolumeSnapshot, err error) { func (c *volumeSnapshots) Create(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.CreateOptions) (result *v1.VolumeSnapshot, err error) {
result = &v1beta1.VolumeSnapshot{} result = &v1.VolumeSnapshot{}
err = c.client.Post(). err = c.client.Post().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -123,8 +123,8 @@ func (c *volumeSnapshots) Create(ctx context.Context, volumeSnapshot *v1beta1.Vo
} }
// Update takes the representation of a volumeSnapshot and updates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any. // Update takes the representation of a volumeSnapshot and updates it. Returns the server's representation of the volumeSnapshot, and an error, if there is any.
func (c *volumeSnapshots) Update(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.UpdateOptions) (result *v1beta1.VolumeSnapshot, err error) { func (c *volumeSnapshots) Update(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.UpdateOptions) (result *v1.VolumeSnapshot, err error) {
result = &v1beta1.VolumeSnapshot{} result = &v1.VolumeSnapshot{}
err = c.client.Put(). err = c.client.Put().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -138,8 +138,8 @@ func (c *volumeSnapshots) Update(ctx context.Context, volumeSnapshot *v1beta1.Vo
// UpdateStatus was generated because the type contains a Status member. // UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *volumeSnapshots) UpdateStatus(ctx context.Context, volumeSnapshot *v1beta1.VolumeSnapshot, opts v1.UpdateOptions) (result *v1beta1.VolumeSnapshot, err error) { func (c *volumeSnapshots) UpdateStatus(ctx context.Context, volumeSnapshot *v1.VolumeSnapshot, opts metav1.UpdateOptions) (result *v1.VolumeSnapshot, err error) {
result = &v1beta1.VolumeSnapshot{} result = &v1.VolumeSnapshot{}
err = c.client.Put(). err = c.client.Put().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -153,7 +153,7 @@ func (c *volumeSnapshots) UpdateStatus(ctx context.Context, volumeSnapshot *v1be
} }
// Delete takes name of the volumeSnapshot and deletes it. Returns an error if one occurs. // Delete takes name of the volumeSnapshot and deletes it. Returns an error if one occurs.
func (c *volumeSnapshots) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { func (c *volumeSnapshots) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
return c.client.Delete(). return c.client.Delete().
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").
@ -164,7 +164,7 @@ func (c *volumeSnapshots) Delete(ctx context.Context, name string, opts v1.Delet
} }
// DeleteCollection deletes a collection of objects. // DeleteCollection deletes a collection of objects.
func (c *volumeSnapshots) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { func (c *volumeSnapshots) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
var timeout time.Duration var timeout time.Duration
if listOpts.TimeoutSeconds != nil { if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
@ -180,8 +180,8 @@ func (c *volumeSnapshots) DeleteCollection(ctx context.Context, opts v1.DeleteOp
} }
// Patch applies the patch and returns the patched volumeSnapshot. // Patch applies the patch and returns the patched volumeSnapshot.
func (c *volumeSnapshots) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshot, err error) { func (c *volumeSnapshots) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshot, err error) {
result = &v1beta1.VolumeSnapshot{} result = &v1.VolumeSnapshot{}
err = c.client.Patch(pt). err = c.client.Patch(pt).
Namespace(c.ns). Namespace(c.ns).
Resource("volumesnapshots"). Resource("volumesnapshots").

View File

@ -16,40 +16,40 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
package v1beta1 package v1
import ( import (
v1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/scheme" "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/scheme"
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
) )
type SnapshotV1beta1Interface interface { type SnapshotV1Interface interface {
RESTClient() rest.Interface RESTClient() rest.Interface
VolumeSnapshotsGetter VolumeSnapshotsGetter
VolumeSnapshotClassesGetter VolumeSnapshotClassesGetter
VolumeSnapshotContentsGetter VolumeSnapshotContentsGetter
} }
// SnapshotV1beta1Client is used to interact with features provided by the snapshot.storage.k8s.io group. // SnapshotV1Client is used to interact with features provided by the snapshot.storage.k8s.io group.
type SnapshotV1beta1Client struct { type SnapshotV1Client struct {
restClient rest.Interface restClient rest.Interface
} }
func (c *SnapshotV1beta1Client) VolumeSnapshots(namespace string) VolumeSnapshotInterface { func (c *SnapshotV1Client) VolumeSnapshots(namespace string) VolumeSnapshotInterface {
return newVolumeSnapshots(c, namespace) return newVolumeSnapshots(c, namespace)
} }
func (c *SnapshotV1beta1Client) VolumeSnapshotClasses() VolumeSnapshotClassInterface { func (c *SnapshotV1Client) VolumeSnapshotClasses() VolumeSnapshotClassInterface {
return newVolumeSnapshotClasses(c) return newVolumeSnapshotClasses(c)
} }
func (c *SnapshotV1beta1Client) VolumeSnapshotContents() VolumeSnapshotContentInterface { func (c *SnapshotV1Client) VolumeSnapshotContents() VolumeSnapshotContentInterface {
return newVolumeSnapshotContents(c) return newVolumeSnapshotContents(c)
} }
// NewForConfig creates a new SnapshotV1beta1Client for the given config. // NewForConfig creates a new SnapshotV1Client for the given config.
func NewForConfig(c *rest.Config) (*SnapshotV1beta1Client, error) { func NewForConfig(c *rest.Config) (*SnapshotV1Client, error) {
config := *c config := *c
if err := setConfigDefaults(&config); err != nil { if err := setConfigDefaults(&config); err != nil {
return nil, err return nil, err
@ -58,12 +58,12 @@ func NewForConfig(c *rest.Config) (*SnapshotV1beta1Client, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &SnapshotV1beta1Client{client}, nil return &SnapshotV1Client{client}, nil
} }
// NewForConfigOrDie creates a new SnapshotV1beta1Client for the given config and // NewForConfigOrDie creates a new SnapshotV1Client for the given config and
// panics if there is an error in the config. // panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *SnapshotV1beta1Client { func NewForConfigOrDie(c *rest.Config) *SnapshotV1Client {
client, err := NewForConfig(c) client, err := NewForConfig(c)
if err != nil { if err != nil {
panic(err) panic(err)
@ -71,13 +71,13 @@ func NewForConfigOrDie(c *rest.Config) *SnapshotV1beta1Client {
return client return client
} }
// New creates a new SnapshotV1beta1Client for the given RESTClient. // New creates a new SnapshotV1Client for the given RESTClient.
func New(c rest.Interface) *SnapshotV1beta1Client { func New(c rest.Interface) *SnapshotV1Client {
return &SnapshotV1beta1Client{c} return &SnapshotV1Client{c}
} }
func setConfigDefaults(config *rest.Config) error { func setConfigDefaults(config *rest.Config) error {
gv := v1beta1.SchemeGroupVersion gv := v1.SchemeGroupVersion
config.GroupVersion = &gv config.GroupVersion = &gv
config.APIPath = "/apis" config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
@ -91,7 +91,7 @@ func setConfigDefaults(config *rest.Config) error {
// RESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *SnapshotV1beta1Client) RESTClient() rest.Interface { func (c *SnapshotV1Client) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }

View File

@ -16,15 +16,15 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
package v1beta1 package v1
import ( import (
"context" "context"
"time" "time"
v1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
scheme "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/scheme" scheme "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types" types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch" watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
@ -38,14 +38,14 @@ type VolumeSnapshotClassesGetter interface {
// VolumeSnapshotClassInterface has methods to work with VolumeSnapshotClass resources. // VolumeSnapshotClassInterface has methods to work with VolumeSnapshotClass resources.
type VolumeSnapshotClassInterface interface { type VolumeSnapshotClassInterface interface {
Create(ctx context.Context, volumeSnapshotClass *v1beta1.VolumeSnapshotClass, opts v1.CreateOptions) (*v1beta1.VolumeSnapshotClass, error) Create(ctx context.Context, volumeSnapshotClass *v1.VolumeSnapshotClass, opts metav1.CreateOptions) (*v1.VolumeSnapshotClass, error)
Update(ctx context.Context, volumeSnapshotClass *v1beta1.VolumeSnapshotClass, opts v1.UpdateOptions) (*v1beta1.VolumeSnapshotClass, error) Update(ctx context.Context, volumeSnapshotClass *v1.VolumeSnapshotClass, opts metav1.UpdateOptions) (*v1.VolumeSnapshotClass, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.VolumeSnapshotClass, error) Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.VolumeSnapshotClass, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.VolumeSnapshotClassList, error) List(ctx context.Context, opts metav1.ListOptions) (*v1.VolumeSnapshotClassList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshotClass, err error) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshotClass, err error)
VolumeSnapshotClassExpansion VolumeSnapshotClassExpansion
} }
@ -55,15 +55,15 @@ type volumeSnapshotClasses struct {
} }
// newVolumeSnapshotClasses returns a VolumeSnapshotClasses // newVolumeSnapshotClasses returns a VolumeSnapshotClasses
func newVolumeSnapshotClasses(c *SnapshotV1beta1Client) *volumeSnapshotClasses { func newVolumeSnapshotClasses(c *SnapshotV1Client) *volumeSnapshotClasses {
return &volumeSnapshotClasses{ return &volumeSnapshotClasses{
client: c.RESTClient(), client: c.RESTClient(),
} }
} }
// Get takes name of the volumeSnapshotClass, and returns the corresponding volumeSnapshotClass object, and an error if there is any. // Get takes name of the volumeSnapshotClass, and returns the corresponding volumeSnapshotClass object, and an error if there is any.
func (c *volumeSnapshotClasses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.VolumeSnapshotClass, err error) { func (c *volumeSnapshotClasses) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.VolumeSnapshotClass, err error) {
result = &v1beta1.VolumeSnapshotClass{} result = &v1.VolumeSnapshotClass{}
err = c.client.Get(). err = c.client.Get().
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
Name(name). Name(name).
@ -74,12 +74,12 @@ func (c *volumeSnapshotClasses) Get(ctx context.Context, name string, options v1
} }
// List takes label and field selectors, and returns the list of VolumeSnapshotClasses that match those selectors. // List takes label and field selectors, and returns the list of VolumeSnapshotClasses that match those selectors.
func (c *volumeSnapshotClasses) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.VolumeSnapshotClassList, err error) { func (c *volumeSnapshotClasses) List(ctx context.Context, opts metav1.ListOptions) (result *v1.VolumeSnapshotClassList, err error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
result = &v1beta1.VolumeSnapshotClassList{} result = &v1.VolumeSnapshotClassList{}
err = c.client.Get(). err = c.client.Get().
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
VersionedParams(&opts, scheme.ParameterCodec). VersionedParams(&opts, scheme.ParameterCodec).
@ -90,7 +90,7 @@ func (c *volumeSnapshotClasses) List(ctx context.Context, opts v1.ListOptions) (
} }
// Watch returns a watch.Interface that watches the requested volumeSnapshotClasses. // Watch returns a watch.Interface that watches the requested volumeSnapshotClasses.
func (c *volumeSnapshotClasses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { func (c *volumeSnapshotClasses) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
@ -104,8 +104,8 @@ func (c *volumeSnapshotClasses) Watch(ctx context.Context, opts v1.ListOptions)
} }
// Create takes the representation of a volumeSnapshotClass and creates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any. // Create takes the representation of a volumeSnapshotClass and creates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any.
func (c *volumeSnapshotClasses) Create(ctx context.Context, volumeSnapshotClass *v1beta1.VolumeSnapshotClass, opts v1.CreateOptions) (result *v1beta1.VolumeSnapshotClass, err error) { func (c *volumeSnapshotClasses) Create(ctx context.Context, volumeSnapshotClass *v1.VolumeSnapshotClass, opts metav1.CreateOptions) (result *v1.VolumeSnapshotClass, err error) {
result = &v1beta1.VolumeSnapshotClass{} result = &v1.VolumeSnapshotClass{}
err = c.client.Post(). err = c.client.Post().
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
VersionedParams(&opts, scheme.ParameterCodec). VersionedParams(&opts, scheme.ParameterCodec).
@ -116,8 +116,8 @@ func (c *volumeSnapshotClasses) Create(ctx context.Context, volumeSnapshotClass
} }
// Update takes the representation of a volumeSnapshotClass and updates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any. // Update takes the representation of a volumeSnapshotClass and updates it. Returns the server's representation of the volumeSnapshotClass, and an error, if there is any.
func (c *volumeSnapshotClasses) Update(ctx context.Context, volumeSnapshotClass *v1beta1.VolumeSnapshotClass, opts v1.UpdateOptions) (result *v1beta1.VolumeSnapshotClass, err error) { func (c *volumeSnapshotClasses) Update(ctx context.Context, volumeSnapshotClass *v1.VolumeSnapshotClass, opts metav1.UpdateOptions) (result *v1.VolumeSnapshotClass, err error) {
result = &v1beta1.VolumeSnapshotClass{} result = &v1.VolumeSnapshotClass{}
err = c.client.Put(). err = c.client.Put().
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
Name(volumeSnapshotClass.Name). Name(volumeSnapshotClass.Name).
@ -129,7 +129,7 @@ func (c *volumeSnapshotClasses) Update(ctx context.Context, volumeSnapshotClass
} }
// Delete takes name of the volumeSnapshotClass and deletes it. Returns an error if one occurs. // Delete takes name of the volumeSnapshotClass and deletes it. Returns an error if one occurs.
func (c *volumeSnapshotClasses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { func (c *volumeSnapshotClasses) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
return c.client.Delete(). return c.client.Delete().
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
Name(name). Name(name).
@ -139,7 +139,7 @@ func (c *volumeSnapshotClasses) Delete(ctx context.Context, name string, opts v1
} }
// DeleteCollection deletes a collection of objects. // DeleteCollection deletes a collection of objects.
func (c *volumeSnapshotClasses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { func (c *volumeSnapshotClasses) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
var timeout time.Duration var timeout time.Duration
if listOpts.TimeoutSeconds != nil { if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
@ -154,8 +154,8 @@ func (c *volumeSnapshotClasses) DeleteCollection(ctx context.Context, opts v1.De
} }
// Patch applies the patch and returns the patched volumeSnapshotClass. // Patch applies the patch and returns the patched volumeSnapshotClass.
func (c *volumeSnapshotClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshotClass, err error) { func (c *volumeSnapshotClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshotClass, err error) {
result = &v1beta1.VolumeSnapshotClass{} result = &v1.VolumeSnapshotClass{}
err = c.client.Patch(pt). err = c.client.Patch(pt).
Resource("volumesnapshotclasses"). Resource("volumesnapshotclasses").
Name(name). Name(name).

View File

@ -16,15 +16,15 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT. // Code generated by client-gen. DO NOT EDIT.
package v1beta1 package v1
import ( import (
"context" "context"
"time" "time"
v1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
scheme "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/scheme" scheme "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types" types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch" watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
@ -38,15 +38,15 @@ type VolumeSnapshotContentsGetter interface {
// VolumeSnapshotContentInterface has methods to work with VolumeSnapshotContent resources. // VolumeSnapshotContentInterface has methods to work with VolumeSnapshotContent resources.
type VolumeSnapshotContentInterface interface { type VolumeSnapshotContentInterface interface {
Create(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.CreateOptions) (*v1beta1.VolumeSnapshotContent, error) Create(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.CreateOptions) (*v1.VolumeSnapshotContent, error)
Update(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.UpdateOptions) (*v1beta1.VolumeSnapshotContent, error) Update(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.UpdateOptions) (*v1.VolumeSnapshotContent, error)
UpdateStatus(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.UpdateOptions) (*v1beta1.VolumeSnapshotContent, error) UpdateStatus(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.UpdateOptions) (*v1.VolumeSnapshotContent, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.VolumeSnapshotContent, error) Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.VolumeSnapshotContent, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.VolumeSnapshotContentList, error) List(ctx context.Context, opts metav1.ListOptions) (*v1.VolumeSnapshotContentList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshotContent, err error) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshotContent, err error)
VolumeSnapshotContentExpansion VolumeSnapshotContentExpansion
} }
@ -56,15 +56,15 @@ type volumeSnapshotContents struct {
} }
// newVolumeSnapshotContents returns a VolumeSnapshotContents // newVolumeSnapshotContents returns a VolumeSnapshotContents
func newVolumeSnapshotContents(c *SnapshotV1beta1Client) *volumeSnapshotContents { func newVolumeSnapshotContents(c *SnapshotV1Client) *volumeSnapshotContents {
return &volumeSnapshotContents{ return &volumeSnapshotContents{
client: c.RESTClient(), client: c.RESTClient(),
} }
} }
// Get takes name of the volumeSnapshotContent, and returns the corresponding volumeSnapshotContent object, and an error if there is any. // Get takes name of the volumeSnapshotContent, and returns the corresponding volumeSnapshotContent object, and an error if there is any.
func (c *volumeSnapshotContents) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.VolumeSnapshotContent, err error) { func (c *volumeSnapshotContents) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.VolumeSnapshotContent, err error) {
result = &v1beta1.VolumeSnapshotContent{} result = &v1.VolumeSnapshotContent{}
err = c.client.Get(). err = c.client.Get().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
Name(name). Name(name).
@ -75,12 +75,12 @@ func (c *volumeSnapshotContents) Get(ctx context.Context, name string, options v
} }
// List takes label and field selectors, and returns the list of VolumeSnapshotContents that match those selectors. // List takes label and field selectors, and returns the list of VolumeSnapshotContents that match those selectors.
func (c *volumeSnapshotContents) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.VolumeSnapshotContentList, err error) { func (c *volumeSnapshotContents) List(ctx context.Context, opts metav1.ListOptions) (result *v1.VolumeSnapshotContentList, err error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
result = &v1beta1.VolumeSnapshotContentList{} result = &v1.VolumeSnapshotContentList{}
err = c.client.Get(). err = c.client.Get().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
VersionedParams(&opts, scheme.ParameterCodec). VersionedParams(&opts, scheme.ParameterCodec).
@ -91,7 +91,7 @@ func (c *volumeSnapshotContents) List(ctx context.Context, opts v1.ListOptions)
} }
// Watch returns a watch.Interface that watches the requested volumeSnapshotContents. // Watch returns a watch.Interface that watches the requested volumeSnapshotContents.
func (c *volumeSnapshotContents) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { func (c *volumeSnapshotContents) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration var timeout time.Duration
if opts.TimeoutSeconds != nil { if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
@ -105,8 +105,8 @@ func (c *volumeSnapshotContents) Watch(ctx context.Context, opts v1.ListOptions)
} }
// Create takes the representation of a volumeSnapshotContent and creates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any. // Create takes the representation of a volumeSnapshotContent and creates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any.
func (c *volumeSnapshotContents) Create(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.CreateOptions) (result *v1beta1.VolumeSnapshotContent, err error) { func (c *volumeSnapshotContents) Create(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.CreateOptions) (result *v1.VolumeSnapshotContent, err error) {
result = &v1beta1.VolumeSnapshotContent{} result = &v1.VolumeSnapshotContent{}
err = c.client.Post(). err = c.client.Post().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
VersionedParams(&opts, scheme.ParameterCodec). VersionedParams(&opts, scheme.ParameterCodec).
@ -117,8 +117,8 @@ func (c *volumeSnapshotContents) Create(ctx context.Context, volumeSnapshotConte
} }
// Update takes the representation of a volumeSnapshotContent and updates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any. // Update takes the representation of a volumeSnapshotContent and updates it. Returns the server's representation of the volumeSnapshotContent, and an error, if there is any.
func (c *volumeSnapshotContents) Update(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.UpdateOptions) (result *v1beta1.VolumeSnapshotContent, err error) { func (c *volumeSnapshotContents) Update(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.UpdateOptions) (result *v1.VolumeSnapshotContent, err error) {
result = &v1beta1.VolumeSnapshotContent{} result = &v1.VolumeSnapshotContent{}
err = c.client.Put(). err = c.client.Put().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
Name(volumeSnapshotContent.Name). Name(volumeSnapshotContent.Name).
@ -131,8 +131,8 @@ func (c *volumeSnapshotContents) Update(ctx context.Context, volumeSnapshotConte
// UpdateStatus was generated because the type contains a Status member. // UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *volumeSnapshotContents) UpdateStatus(ctx context.Context, volumeSnapshotContent *v1beta1.VolumeSnapshotContent, opts v1.UpdateOptions) (result *v1beta1.VolumeSnapshotContent, err error) { func (c *volumeSnapshotContents) UpdateStatus(ctx context.Context, volumeSnapshotContent *v1.VolumeSnapshotContent, opts metav1.UpdateOptions) (result *v1.VolumeSnapshotContent, err error) {
result = &v1beta1.VolumeSnapshotContent{} result = &v1.VolumeSnapshotContent{}
err = c.client.Put(). err = c.client.Put().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
Name(volumeSnapshotContent.Name). Name(volumeSnapshotContent.Name).
@ -145,7 +145,7 @@ func (c *volumeSnapshotContents) UpdateStatus(ctx context.Context, volumeSnapsho
} }
// Delete takes name of the volumeSnapshotContent and deletes it. Returns an error if one occurs. // Delete takes name of the volumeSnapshotContent and deletes it. Returns an error if one occurs.
func (c *volumeSnapshotContents) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { func (c *volumeSnapshotContents) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
return c.client.Delete(). return c.client.Delete().
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
Name(name). Name(name).
@ -155,7 +155,7 @@ func (c *volumeSnapshotContents) Delete(ctx context.Context, name string, opts v
} }
// DeleteCollection deletes a collection of objects. // DeleteCollection deletes a collection of objects.
func (c *volumeSnapshotContents) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { func (c *volumeSnapshotContents) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
var timeout time.Duration var timeout time.Duration
if listOpts.TimeoutSeconds != nil { if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
@ -170,8 +170,8 @@ func (c *volumeSnapshotContents) DeleteCollection(ctx context.Context, opts v1.D
} }
// Patch applies the patch and returns the patched volumeSnapshotContent. // Patch applies the patch and returns the patched volumeSnapshotContent.
func (c *volumeSnapshotContents) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VolumeSnapshotContent, err error) { func (c *volumeSnapshotContents) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VolumeSnapshotContent, err error) {
result = &v1beta1.VolumeSnapshotContent{} result = &v1.VolumeSnapshotContent{}
err = c.client.Patch(pt). err = c.client.Patch(pt).
Resource("volumesnapshotcontents"). Resource("volumesnapshotcontents").
Name(name). Name(name).

View File

@ -1,97 +0,0 @@
/*
Copyright 2020 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package versioned
import (
"fmt"
snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/typed/volumesnapshot/v1beta1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
)
type Interface interface {
Discovery() discovery.DiscoveryInterface
SnapshotV1beta1() snapshotv1beta1.SnapshotV1beta1Interface
}
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
snapshotV1beta1 *snapshotv1beta1.SnapshotV1beta1Client
}
// SnapshotV1beta1 retrieves the SnapshotV1beta1Client
func (c *Clientset) SnapshotV1beta1() snapshotv1beta1.SnapshotV1beta1Interface {
return c.snapshotV1beta1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
return nil
}
return c.DiscoveryClient
}
// NewForConfig creates a new Clientset for the given config.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfig will generate a rate-limiter in configShallowCopy.
func NewForConfig(c *rest.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
if configShallowCopy.Burst <= 0 {
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var cs Clientset
var err error
cs.snapshotV1beta1, err = snapshotv1beta1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
return &cs, nil
}
// NewForConfigOrDie creates a new Clientset for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.snapshotV1beta1 = snapshotv1beta1.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
}
// New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.snapshotV1beta1 = snapshotv1beta1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs
}

View File

@ -101,9 +101,6 @@ type SubConn interface {
// a new connection will be created. // a new connection will be created.
// //
// This will trigger a state transition for the SubConn. // This will trigger a state transition for the SubConn.
//
// Deprecated: This method is now part of the ClientConn interface and will
// eventually be removed from here.
UpdateAddresses([]resolver.Address) UpdateAddresses([]resolver.Address)
// Connect starts the connecting for this SubConn. // Connect starts the connecting for this SubConn.
Connect() Connect()
@ -146,13 +143,6 @@ type ClientConn interface {
// RemoveSubConn removes the SubConn from ClientConn. // RemoveSubConn removes the SubConn from ClientConn.
// The SubConn will be shutdown. // The SubConn will be shutdown.
RemoveSubConn(SubConn) RemoveSubConn(SubConn)
// UpdateAddresses updates the addresses used in the passed in SubConn.
// gRPC checks if the currently connected address is still in the new list.
// If so, the connection will be kept. Else, the connection will be
// gracefully closed, and a new connection will be created.
//
// This will trigger a state transition for the SubConn.
UpdateAddresses(SubConn, []resolver.Address)
// UpdateState notifies gRPC that the balancer's internal state has // UpdateState notifies gRPC that the balancer's internal state has
// changed. // changed.

View File

@ -22,7 +22,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
@ -42,7 +41,7 @@ func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions)
cc: cc, cc: cc,
pickerBuilder: bb.pickerBuilder, pickerBuilder: bb.pickerBuilder,
subConns: make(map[resolver.Address]subConnInfo), subConns: make(map[resolver.Address]balancer.SubConn),
scStates: make(map[balancer.SubConn]connectivity.State), scStates: make(map[balancer.SubConn]connectivity.State),
csEvltr: &balancer.ConnectivityStateEvaluator{}, csEvltr: &balancer.ConnectivityStateEvaluator{},
config: bb.config, config: bb.config,
@ -58,11 +57,6 @@ func (bb *baseBuilder) Name() string {
return bb.name return bb.name
} }
type subConnInfo struct {
subConn balancer.SubConn
attrs *attributes.Attributes
}
type baseBalancer struct { type baseBalancer struct {
cc balancer.ClientConn cc balancer.ClientConn
pickerBuilder PickerBuilder pickerBuilder PickerBuilder
@ -70,7 +64,7 @@ type baseBalancer struct {
csEvltr *balancer.ConnectivityStateEvaluator csEvltr *balancer.ConnectivityStateEvaluator
state connectivity.State state connectivity.State
subConns map[resolver.Address]subConnInfo // `attributes` is stripped from the keys of this map (the addresses) subConns map[resolver.Address]balancer.SubConn // `attributes` is stripped from the keys of this map (the addresses)
scStates map[balancer.SubConn]connectivity.State scStates map[balancer.SubConn]connectivity.State
picker balancer.Picker picker balancer.Picker
config Config config Config
@ -120,7 +114,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
aNoAttrs := a aNoAttrs := a
aNoAttrs.Attributes = nil aNoAttrs.Attributes = nil
addrsSet[aNoAttrs] = struct{}{} addrsSet[aNoAttrs] = struct{}{}
if scInfo, ok := b.subConns[aNoAttrs]; !ok { if sc, ok := b.subConns[aNoAttrs]; !ok {
// a is a new address (not existing in b.subConns). // a is a new address (not existing in b.subConns).
// //
// When creating SubConn, the original address with attributes is // When creating SubConn, the original address with attributes is
@ -131,7 +125,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err) logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
continue continue
} }
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes} b.subConns[aNoAttrs] = sc
b.scStates[sc] = connectivity.Idle b.scStates[sc] = connectivity.Idle
sc.Connect() sc.Connect()
} else { } else {
@ -141,15 +135,13 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
// The SubConn does a reflect.DeepEqual of the new and old // The SubConn does a reflect.DeepEqual of the new and old
// addresses. So this is a noop if the current address is the same // addresses. So this is a noop if the current address is the same
// as the old one (including attributes). // as the old one (including attributes).
scInfo.attrs = a.Attributes sc.UpdateAddresses([]resolver.Address{a})
b.subConns[aNoAttrs] = scInfo
b.cc.UpdateAddresses(scInfo.subConn, []resolver.Address{a})
} }
} }
for a, scInfo := range b.subConns { for a, sc := range b.subConns {
// a was removed by resolver. // a was removed by resolver.
if _, ok := addrsSet[a]; !ok { if _, ok := addrsSet[a]; !ok {
b.cc.RemoveSubConn(scInfo.subConn) b.cc.RemoveSubConn(sc)
delete(b.subConns, a) delete(b.subConns, a)
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown. // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
// The entry will be deleted in UpdateSubConnState. // The entry will be deleted in UpdateSubConnState.
@ -192,10 +184,9 @@ func (b *baseBalancer) regeneratePicker() {
readySCs := make(map[balancer.SubConn]SubConnInfo) readySCs := make(map[balancer.SubConn]SubConnInfo)
// Filter out all ready SCs from full subConn map. // Filter out all ready SCs from full subConn map.
for addr, scInfo := range b.subConns { for addr, sc := range b.subConns {
if st, ok := b.scStates[scInfo.subConn]; ok && st == connectivity.Ready { if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
addr.Attributes = scInfo.attrs readySCs[sc] = SubConnInfo{Address: addr}
readySCs[scInfo.subConn] = SubConnInfo{Address: addr}
} }
} }
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs}) b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})

View File

@ -163,14 +163,6 @@ func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain) ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
} }
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
acbw, ok := sc.(*acBalancerWrapper)
if !ok {
return
}
acbw.UpdateAddresses(addrs)
}
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) { func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
ccb.mu.Lock() ccb.mu.Lock()
defer ccb.mu.Unlock() defer ccb.mu.Unlock()
@ -205,7 +197,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
acbw.mu.Lock() acbw.mu.Lock()
defer acbw.mu.Unlock() defer acbw.mu.Unlock()
if len(addrs) <= 0 { if len(addrs) <= 0 {
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain) acbw.ac.tearDown(errConnDrain)
return return
} }
if !acbw.ac.tryUpdateAddrs(addrs) { if !acbw.ac.tryUpdateAddrs(addrs) {
@ -220,7 +212,7 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
acbw.ac.acbw = nil acbw.ac.acbw = nil
acbw.ac.mu.Unlock() acbw.ac.mu.Unlock()
acState := acbw.ac.getState() acState := acbw.ac.getState()
acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain) acbw.ac.tearDown(errConnDrain)
if acState == connectivity.Shutdown { if acState == connectivity.Shutdown {
return return

View File

@ -143,7 +143,6 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
firstResolveEvent: grpcsync.NewEvent(), firstResolveEvent: grpcsync.NewEvent(),
} }
cc.retryThrottler.Store((*retryThrottler)(nil)) cc.retryThrottler.Store((*retryThrottler)(nil))
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil})
cc.ctx, cc.cancel = context.WithCancel(context.Background()) cc.ctx, cc.cancel = context.WithCancel(context.Background())
for _, opt := range opts { for _, opt := range opts {
@ -1198,7 +1197,7 @@ func (ac *addrConn) resetTransport() {
ac.mu.Lock() ac.mu.Lock()
if ac.state == connectivity.Shutdown { if ac.state == connectivity.Shutdown {
ac.mu.Unlock() ac.mu.Unlock()
newTr.Close(fmt.Errorf("reached connectivity state: SHUTDOWN")) newTr.Close()
return return
} }
ac.curAddr = addr ac.curAddr = addr
@ -1330,7 +1329,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
select { select {
case <-time.After(time.Until(connectDeadline)): case <-time.After(time.Until(connectDeadline)):
// We didn't get the preface in time. // We didn't get the preface in time.
newTr.Close(fmt.Errorf("failed to receive server preface within timeout")) newTr.Close()
channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr) channelz.Warningf(logger, ac.channelzID, "grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting...", addr)
return nil, nil, errors.New("timed out waiting for server handshake") return nil, nil, errors.New("timed out waiting for server handshake")
case <-prefaceReceived: case <-prefaceReceived:
@ -1447,9 +1446,10 @@ func (ac *addrConn) getReadyTransport() (transport.ClientTransport, bool) {
} }
// tearDown starts to tear down the addrConn. // tearDown starts to tear down the addrConn.
// // TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
// Note that tearDown doesn't remove ac from ac.cc.conns, so the addrConn struct // some edge cases (e.g., the caller opens and closes many addrConn's in a
// will leak. In most cases, call cc.removeAddrConn() instead. // tight loop.
// tearDown doesn't remove ac from ac.cc.conns.
func (ac *addrConn) tearDown(err error) { func (ac *addrConn) tearDown(err error) {
ac.mu.Lock() ac.mu.Lock()
if ac.state == connectivity.Shutdown { if ac.state == connectivity.Shutdown {

View File

@ -30,7 +30,7 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"google.golang.org/grpc/attributes" "google.golang.org/grpc/attributes"
icredentials "google.golang.org/grpc/internal/credentials" "google.golang.org/grpc/internal"
) )
// PerRPCCredentials defines the common interface for the credentials which need to // PerRPCCredentials defines the common interface for the credentials which need to
@ -188,12 +188,15 @@ type RequestInfo struct {
AuthInfo AuthInfo AuthInfo AuthInfo
} }
// requestInfoKey is a struct to be used as the key when attaching a RequestInfo to a context object.
type requestInfoKey struct{}
// RequestInfoFromContext extracts the RequestInfo from the context if it exists. // RequestInfoFromContext extracts the RequestInfo from the context if it exists.
// //
// This API is experimental. // This API is experimental.
func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) { func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
ri, ok = icredentials.RequestInfoFromContext(ctx).(RequestInfo) ri, ok = ctx.Value(requestInfoKey{}).(RequestInfo)
return ri, ok return
} }
// ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes // ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
@ -208,12 +211,16 @@ type ClientHandshakeInfo struct {
Attributes *attributes.Attributes Attributes *attributes.Attributes
} }
// clientHandshakeInfoKey is a struct used as the key to store
// ClientHandshakeInfo in a context.
type clientHandshakeInfoKey struct{}
// ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored // ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
// in ctx. // in ctx.
// //
// This API is experimental. // This API is experimental.
func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo { func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
chi, _ := icredentials.ClientHandshakeInfoFromContext(ctx).(ClientHandshakeInfo) chi, _ := ctx.Value(clientHandshakeInfoKey{}).(ClientHandshakeInfo)
return chi return chi
} }
@ -242,6 +249,15 @@ func CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {
return nil return nil
} }
func init() {
internal.NewRequestInfoContext = func(ctx context.Context, ri RequestInfo) context.Context {
return context.WithValue(ctx, requestInfoKey{}, ri)
}
internal.NewClientHandshakeInfoContext = func(ctx context.Context, chi ClientHandshakeInfo) context.Context {
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
}
}
// ChannelzSecurityInfo defines the interface that security protocols should implement // ChannelzSecurityInfo defines the interface that security protocols should implement
// in order to provide security info to channelz. // in order to provide security info to channelz.
// //

View File

@ -66,7 +66,11 @@ type dialOptions struct {
minConnectTimeout func() time.Duration minConnectTimeout func() time.Duration
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON. defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
defaultServiceConfigRawJSON *string defaultServiceConfigRawJSON *string
resolvers []resolver.Builder // This is used by ccResolverWrapper to backoff between successive calls to
// resolver.ResolveNow(). The user will have no need to configure this, but
// we need to be able to configure this in tests.
resolveNowBackoff func(int) time.Duration
resolvers []resolver.Builder
} }
// DialOption configures how we set up the connection. // DialOption configures how we set up the connection.
@ -592,6 +596,7 @@ func defaultDialOptions() dialOptions {
ReadBufferSize: defaultReadBufSize, ReadBufferSize: defaultReadBufSize,
UseProxy: true, UseProxy: true,
}, },
resolveNowBackoff: internalbackoff.DefaultExponential.Backoff,
} }
} }
@ -606,6 +611,16 @@ func withMinConnectDeadline(f func() time.Duration) DialOption {
}) })
} }
// withResolveNowBackoff specifies the function that clientconn uses to backoff
// between successive calls to resolver.ResolveNow().
//
// For testing purpose only.
func withResolveNowBackoff(f func(int) time.Duration) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.resolveNowBackoff = f
})
}
// WithResolvers allows a list of resolver implementations to be registered // WithResolvers allows a list of resolver implementations to be registered
// locally with the ClientConn without needing to be globally registered via // locally with the ClientConn without needing to be globally registered via
// resolver.Register. They will be matched against the scheme used for the // resolver.Register. They will be matched against the scheme used for the

View File

@ -21,8 +21,6 @@
package proto package proto
import ( import (
"fmt"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding"
) )
@ -38,19 +36,11 @@ func init() {
type codec struct{} type codec struct{}
func (codec) Marshal(v interface{}) ([]byte, error) { func (codec) Marshal(v interface{}) ([]byte, error) {
vv, ok := v.(proto.Message) return proto.Marshal(v.(proto.Message))
if !ok {
return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v)
}
return proto.Marshal(vv)
} }
func (codec) Unmarshal(data []byte, v interface{}) error { func (codec) Unmarshal(data []byte, v interface{}) error {
vv, ok := v.(proto.Message) return proto.Unmarshal(data, v.(proto.Message))
if !ok {
return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v)
}
return proto.Unmarshal(data, vv)
} }
func (codec) Name() string { func (codec) Name() string {

View File

@ -4,7 +4,7 @@ go 1.11
require ( require (
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/protobuf v1.4.2 github.com/golang/protobuf v1.4.2
github.com/google/go-cmp v0.5.0 github.com/google/go-cmp v0.5.0

View File

@ -1,8 +1,10 @@
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@ -10,8 +12,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
@ -41,6 +43,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=

View File

@ -1,49 +0,0 @@
/*
* Copyright 2021 gRPC 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 credentials
import (
"context"
)
// requestInfoKey is a struct to be used as the key to store RequestInfo in a
// context.
type requestInfoKey struct{}
// NewRequestInfoContext creates a context with ri.
func NewRequestInfoContext(ctx context.Context, ri interface{}) context.Context {
return context.WithValue(ctx, requestInfoKey{}, ri)
}
// RequestInfoFromContext extracts the RequestInfo from ctx.
func RequestInfoFromContext(ctx context.Context) interface{} {
return ctx.Value(requestInfoKey{})
}
// clientHandshakeInfoKey is a struct used as the key to store
// ClientHandshakeInfo in a context.
type clientHandshakeInfoKey struct{}
// ClientHandshakeInfoFromContext extracts the ClientHandshakeInfo from ctx.
func ClientHandshakeInfoFromContext(ctx context.Context) interface{} {
return ctx.Value(clientHandshakeInfoKey{})
}
// NewClientHandshakeInfoContext creates a context with chi.
func NewClientHandshakeInfoContext(ctx context.Context, chi interface{}) context.Context {
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
}

View File

@ -38,6 +38,12 @@ var (
// KeepaliveMinPingTime is the minimum ping interval. This must be 10s by // KeepaliveMinPingTime is the minimum ping interval. This must be 10s by
// default, but tests may wish to set it lower for convenience. // default, but tests may wish to set it lower for convenience.
KeepaliveMinPingTime = 10 * time.Second KeepaliveMinPingTime = 10 * time.Second
// NewRequestInfoContext creates a new context based on the argument context attaching
// the passed in RequestInfo to the new context.
NewRequestInfoContext interface{} // func(context.Context, credentials.RequestInfo) context.Context
// NewClientHandshakeInfoContext returns a copy of the input context with
// the passed in ClientHandshakeInfo struct added to it.
NewClientHandshakeInfoContext interface{} // func(context.Context, credentials.ClientHandshakeInfo) context.Context
// ParseServiceConfigForTesting is for creating a fake // ParseServiceConfigForTesting is for creating a fake
// ClientConn for resolver testing only // ClientConn for resolver testing only
ParseServiceConfigForTesting interface{} // func(string) *serviceconfig.ParseResult ParseServiceConfigForTesting interface{} // func(string) *serviceconfig.ParseResult
@ -59,11 +65,6 @@ var (
// gRPC server. An xDS-enabled server needs to know what type of credentials // gRPC server. An xDS-enabled server needs to know what type of credentials
// is configured on the underlying gRPC server. This is set by server.go. // is configured on the underlying gRPC server. This is set by server.go.
GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials
// DrainServerTransports initiates a graceful close of existing connections
// on a gRPC server accepted on the provided listener address. An
// xDS-enabled server invokes this method on a grpc.Server when a particular
// listener moves to "not-serving" mode.
DrainServerTransports interface{} // func(*grpc.Server, string)
) )
// HealthChecker defines the signature of the client-side LB channel health checking function. // HealthChecker defines the signature of the client-side LB channel health checking function.

View File

@ -24,7 +24,6 @@ import (
"sync" "sync"
"google.golang.org/grpc/internal/serviceconfig" "google.golang.org/grpc/internal/serviceconfig"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
) )
@ -52,74 +51,6 @@ type RPCConfig struct {
Context context.Context Context context.Context
MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC MethodConfig serviceconfig.MethodConfig // configuration to use for this RPC
OnCommitted func() // Called when the RPC has been committed (retries no longer possible) OnCommitted func() // Called when the RPC has been committed (retries no longer possible)
Interceptor ClientInterceptor
}
// ClientStream is the same as grpc.ClientStream, but defined here for circular
// dependency reasons.
type ClientStream interface {
// Header returns the header metadata received from the server if there
// is any. It blocks if the metadata is not ready to read.
Header() (metadata.MD, error)
// Trailer returns the trailer metadata from the server, if there is any.
// It must only be called after stream.CloseAndRecv has returned, or
// stream.Recv has returned a non-nil error (including io.EOF).
Trailer() metadata.MD
// CloseSend closes the send direction of the stream. It closes the stream
// when non-nil error is met. It is also not safe to call CloseSend
// concurrently with SendMsg.
CloseSend() error
// Context returns the context for this stream.
//
// It should not be called until after Header or RecvMsg has returned. Once
// called, subsequent client-side retries are disabled.
Context() context.Context
// SendMsg is generally called by generated code. On error, SendMsg aborts
// the stream. If the error was generated by the client, the status is
// returned directly; otherwise, io.EOF is returned and the status of
// the stream may be discovered using RecvMsg.
//
// SendMsg blocks until:
// - There is sufficient flow control to schedule m with the transport, or
// - The stream is done, or
// - The stream breaks.
//
// SendMsg does not wait until the message is received by the server. An
// untimely stream closure may result in lost messages. To ensure delivery,
// users should ensure the RPC completed successfully using RecvMsg.
//
// It is safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time, but it is not safe
// to call SendMsg on the same stream in different goroutines. It is also
// not safe to call CloseSend concurrently with SendMsg.
SendMsg(m interface{}) error
// RecvMsg blocks until it receives a message into m or the stream is
// done. It returns io.EOF when the stream completes successfully. On
// any other error, the stream is aborted and the error contains the RPC
// status.
//
// It is safe to have a goroutine calling SendMsg and another goroutine
// calling RecvMsg on the same stream at the same time, but it is not
// safe to call RecvMsg on the same stream in different goroutines.
RecvMsg(m interface{}) error
}
// ClientInterceptor is an interceptor for gRPC client streams.
type ClientInterceptor interface {
// NewStream produces a ClientStream for an RPC which may optionally use
// the provided function to produce a stream for delegation. Note:
// RPCInfo.Context should not be used (will be nil).
//
// done is invoked when the RPC is finished using its connection, or could
// not be assigned a connection. RPC operations may still occur on
// ClientStream after done is called, since the interceptor is invoked by
// application-layer operations. done must never be nil when called.
NewStream(ctx context.Context, ri RPCInfo, done func(), newStream func(ctx context.Context, done func()) (ClientStream, error)) (ClientStream, error)
}
// ServerInterceptor is unimplementable; do not use.
type ServerInterceptor interface {
notDefined()
} }
type csKeyType string type csKeyType string

View File

@ -34,7 +34,6 @@ import (
grpclbstate "google.golang.org/grpc/balancer/grpclb/state" grpclbstate "google.golang.org/grpc/balancer/grpclb/state"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal/backoff"
"google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/grpcrand"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
@ -47,13 +46,6 @@ var EnableSRVLookups = false
var logger = grpclog.Component("dns") var logger = grpclog.Component("dns")
// Globals to stub out in tests. TODO: Perhaps these two can be combined into a
// single variable for testing the resolver?
var (
newTimer = time.NewTimer
newTimerDNSResRate = time.NewTimer
)
func init() { func init() {
resolver.Register(NewBuilder()) resolver.Register(NewBuilder())
} }
@ -151,6 +143,7 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
d.wg.Add(1) d.wg.Add(1)
go d.watcher() go d.watcher()
d.ResolveNow(resolver.ResolveNowOptions{})
return d, nil return d, nil
} }
@ -208,38 +201,28 @@ func (d *dnsResolver) Close() {
func (d *dnsResolver) watcher() { func (d *dnsResolver) watcher() {
defer d.wg.Done() defer d.wg.Done()
backoffIndex := 1
for { for {
state, err := d.lookup()
if err != nil {
// Report error to the underlying grpc.ClientConn.
d.cc.ReportError(err)
} else {
err = d.cc.UpdateState(*state)
}
var timer *time.Timer
if err == nil {
// Success resolving, wait for the next ResolveNow. However, also wait 30 seconds at the very least
// to prevent constantly re-resolving.
backoffIndex = 1
timer = newTimerDNSResRate(minDNSResRate)
select {
case <-d.ctx.Done():
timer.Stop()
return
case <-d.rn:
}
} else {
// Poll on an error found in DNS Resolver or an error received from ClientConn.
timer = newTimer(backoff.DefaultExponential.Backoff(backoffIndex))
backoffIndex++
}
select { select {
case <-d.ctx.Done(): case <-d.ctx.Done():
timer.Stop()
return return
case <-timer.C: case <-d.rn:
}
state, err := d.lookup()
if err != nil {
d.cc.ReportError(err)
} else {
d.cc.UpdateState(*state)
}
// Sleep to prevent excessive re-resolutions. Incoming resolution requests
// will be queued in d.rn.
t := time.NewTimer(minDNSResRate)
select {
case <-t.C:
case <-d.ctx.Done():
t.Stop()
return
} }
} }
} }

View File

@ -46,22 +46,6 @@ type BalancerConfig struct {
type intermediateBalancerConfig []map[string]json.RawMessage type intermediateBalancerConfig []map[string]json.RawMessage
// MarshalJSON implements the json.Marshaler interface.
//
// It marshals the balancer and config into a length-1 slice
// ([]map[string]config).
func (bc *BalancerConfig) MarshalJSON() ([]byte, error) {
if bc.Config == nil {
// If config is nil, return empty config `{}`.
return []byte(fmt.Sprintf(`[{%q: %v}]`, bc.Name, "{}")), nil
}
c, err := json.Marshal(bc.Config)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf(`[{%q: %s}]`, bc.Name, c)), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface. // UnmarshalJSON implements the json.Unmarshaler interface.
// //
// ServiceConfig contains a list of loadBalancingConfigs, each with a name and // ServiceConfig contains a list of loadBalancingConfigs, each with a name and

View File

@ -20,17 +20,13 @@ package transport
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"runtime" "runtime"
"strconv"
"sync" "sync"
"sync/atomic" "sync/atomic"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"google.golang.org/grpc/internal/grpcutil"
"google.golang.org/grpc/status"
) )
var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) { var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
@ -132,14 +128,6 @@ type cleanupStream struct {
func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM
type earlyAbortStream struct {
streamID uint32
contentSubtype string
status *status.Status
}
func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
type dataFrame struct { type dataFrame struct {
streamID uint32 streamID uint32
endStream bool endStream bool
@ -761,24 +749,6 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
return nil return nil
} }
func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error {
if l.side == clientSide {
return errors.New("earlyAbortStream not handled on client")
}
headerFields := []hpack.HeaderField{
{Name: ":status", Value: "200"},
{Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)},
{Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))},
{Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())},
}
if err := l.writeHeader(eas.streamID, true, headerFields, nil); err != nil {
return err
}
return nil
}
func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error { func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
if l.side == clientSide { if l.side == clientSide {
l.draining = true l.draining = true
@ -817,8 +787,6 @@ func (l *loopyWriter) handle(i interface{}) error {
return l.registerStreamHandler(i) return l.registerStreamHandler(i)
case *cleanupStream: case *cleanupStream:
return l.cleanupStreamHandler(i) return l.cleanupStreamHandler(i)
case *earlyAbortStream:
return l.earlyAbortStreamHandler(i)
case *incomingGoAway: case *incomingGoAway:
return l.incomingGoAwayHandler(i) return l.incomingGoAwayHandler(i)
case *dataFrame: case *dataFrame:

View File

@ -32,14 +32,15 @@ import (
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/channelz"
icredentials "google.golang.org/grpc/internal/credentials"
"google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/grpcutil"
imetadata "google.golang.org/grpc/internal/metadata" imetadata "google.golang.org/grpc/internal/metadata"
"google.golang.org/grpc/internal/syscall"
"google.golang.org/grpc/internal/transport/networktype" "google.golang.org/grpc/internal/transport/networktype"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/syscall"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer" "google.golang.org/grpc/peer"
@ -115,9 +116,6 @@ type http2Client struct {
// goAwayReason records the http2.ErrCode and debug data received with the // goAwayReason records the http2.ErrCode and debug data received with the
// GoAway frame. // GoAway frame.
goAwayReason GoAwayReason goAwayReason GoAwayReason
// goAwayDebugMessage contains a detailed human readable string about a
// GoAway frame, useful for error messages.
goAwayDebugMessage string
// A condition variable used to signal when the keepalive goroutine should // A condition variable used to signal when the keepalive goroutine should
// go dormant. The condition for dormancy is based on the number of active // go dormant. The condition for dormancy is based on the number of active
// streams and the `PermitWithoutStream` keepalive client parameter. And // streams and the `PermitWithoutStream` keepalive client parameter. And
@ -240,7 +238,8 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
// Attributes field of resolver.Address, which is shoved into connectCtx // Attributes field of resolver.Address, which is shoved into connectCtx
// and passed to the credential handshaker. This makes it possible for // and passed to the credential handshaker. This makes it possible for
// address specific arbitrary data to reach the credential handshaker. // address specific arbitrary data to reach the credential handshaker.
connectCtx = icredentials.NewClientHandshakeInfoContext(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes}) contextWithHandshakeInfo := internal.NewClientHandshakeInfoContext.(func(context.Context, credentials.ClientHandshakeInfo) context.Context)
connectCtx = contextWithHandshakeInfo(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes})
conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, conn) conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.ServerName, conn)
if err != nil { if err != nil {
return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err) return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err)
@ -348,14 +347,12 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
// Send connection preface to server. // Send connection preface to server.
n, err := t.conn.Write(clientPreface) n, err := t.conn.Write(clientPreface)
if err != nil { if err != nil {
err = connectionErrorf(true, err, "transport: failed to write client preface: %v", err) t.Close()
t.Close(err) return nil, connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
return nil, err
} }
if n != len(clientPreface) { if n != len(clientPreface) {
err = connectionErrorf(true, nil, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) t.Close()
t.Close(err) return nil, connectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
return nil, err
} }
var ss []http2.Setting var ss []http2.Setting
@ -373,16 +370,14 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
} }
err = t.framer.fr.WriteSettings(ss...) err = t.framer.fr.WriteSettings(ss...)
if err != nil { if err != nil {
err = connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err) t.Close()
t.Close(err) return nil, connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
return nil, err
} }
// Adjust the connection flow control window if needed. // Adjust the connection flow control window if needed.
if delta := uint32(icwz - defaultWindowSize); delta > 0 { if delta := uint32(icwz - defaultWindowSize); delta > 0 {
if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil { if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil {
err = connectionErrorf(true, err, "transport: failed to write window update: %v", err) t.Close()
t.Close(err) return nil, connectionErrorf(true, err, "transport: failed to write window update: %v", err)
return nil, err
} }
} }
@ -419,7 +414,6 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
buf: newRecvBuffer(), buf: newRecvBuffer(),
headerChan: make(chan struct{}), headerChan: make(chan struct{}),
contentSubtype: callHdr.ContentSubtype, contentSubtype: callHdr.ContentSubtype,
doneFunc: callHdr.DoneFunc,
} }
s.wq = newWriteQuota(defaultWriteQuota, s.done) s.wq = newWriteQuota(defaultWriteQuota, s.done)
s.requestRead = func(n int) { s.requestRead = func(n int) {
@ -459,7 +453,7 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
Method: callHdr.Method, Method: callHdr.Method,
AuthInfo: t.authInfo, AuthInfo: t.authInfo,
} }
ctxWithRequestInfo := icredentials.NewRequestInfoContext(ctx, ri) ctxWithRequestInfo := internal.NewRequestInfoContext.(func(context.Context, credentials.RequestInfo) context.Context)(ctx, ri)
authData, err := t.getTrAuthData(ctxWithRequestInfo, aud) authData, err := t.getTrAuthData(ctxWithRequestInfo, aud)
if err != nil { if err != nil {
return nil, err return nil, err
@ -838,9 +832,6 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.
t.controlBuf.executeAndPut(addBackStreamQuota, cleanup) t.controlBuf.executeAndPut(addBackStreamQuota, cleanup)
// This will unblock write. // This will unblock write.
close(s.done) close(s.done)
if s.doneFunc != nil {
s.doneFunc()
}
} }
// Close kicks off the shutdown process of the transport. This should be called // Close kicks off the shutdown process of the transport. This should be called
@ -850,12 +841,12 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.
// This method blocks until the addrConn that initiated this transport is // This method blocks until the addrConn that initiated this transport is
// re-connected. This happens because t.onClose() begins reconnect logic at the // re-connected. This happens because t.onClose() begins reconnect logic at the
// addrConn level and blocks until the addrConn is successfully connected. // addrConn level and blocks until the addrConn is successfully connected.
func (t *http2Client) Close(err error) { func (t *http2Client) Close() error {
t.mu.Lock() t.mu.Lock()
// Make sure we only Close once. // Make sure we only Close once.
if t.state == closing { if t.state == closing {
t.mu.Unlock() t.mu.Unlock()
return return nil
} }
// Call t.onClose before setting the state to closing to prevent the client // Call t.onClose before setting the state to closing to prevent the client
// from attempting to create new streams ASAP. // from attempting to create new streams ASAP.
@ -871,19 +862,13 @@ func (t *http2Client) Close(err error) {
t.mu.Unlock() t.mu.Unlock()
t.controlBuf.finish() t.controlBuf.finish()
t.cancel() t.cancel()
t.conn.Close() err := t.conn.Close()
if channelz.IsOn() { if channelz.IsOn() {
channelz.RemoveEntry(t.channelzID) channelz.RemoveEntry(t.channelzID)
} }
// Append info about previous goaways if there were any, since this may be important
// for understanding the root cause for this connection to be closed.
_, goAwayDebugMessage := t.GetGoAwayReason()
if len(goAwayDebugMessage) > 0 {
err = fmt.Errorf("closing transport due to: %v, received prior goaway: %v", err, goAwayDebugMessage)
}
// Notify all active streams. // Notify all active streams.
for _, s := range streams { for _, s := range streams {
t.closeStream(s, err, false, http2.ErrCodeNo, status.New(codes.Unavailable, err.Error()), nil, false) t.closeStream(s, ErrConnClosing, false, http2.ErrCodeNo, status.New(codes.Unavailable, ErrConnClosing.Desc), nil, false)
} }
if t.statsHandler != nil { if t.statsHandler != nil {
connEnd := &stats.ConnEnd{ connEnd := &stats.ConnEnd{
@ -891,6 +876,7 @@ func (t *http2Client) Close(err error) {
} }
t.statsHandler.HandleConn(t.ctx, connEnd) t.statsHandler.HandleConn(t.ctx, connEnd)
} }
return err
} }
// GracefulClose sets the state to draining, which prevents new streams from // GracefulClose sets the state to draining, which prevents new streams from
@ -909,7 +895,7 @@ func (t *http2Client) GracefulClose() {
active := len(t.activeStreams) active := len(t.activeStreams)
t.mu.Unlock() t.mu.Unlock()
if active == 0 { if active == 0 {
t.Close(ErrConnClosing) t.Close()
return return
} }
t.controlBuf.put(&incomingGoAway{}) t.controlBuf.put(&incomingGoAway{})
@ -1155,9 +1141,9 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
} }
} }
id := f.LastStreamID id := f.LastStreamID
if id > 0 && id%2 == 0 { if id > 0 && id%2 != 1 {
t.mu.Unlock() t.mu.Unlock()
t.Close(connectionErrorf(true, nil, "received goaway with non-zero even-numbered numbered stream id: %v", id)) t.Close()
return return
} }
// A client can receive multiple GoAways from the server (see // A client can receive multiple GoAways from the server (see
@ -1175,7 +1161,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
// If there are multiple GoAways the first one should always have an ID greater than the following ones. // If there are multiple GoAways the first one should always have an ID greater than the following ones.
if id > t.prevGoAwayID { if id > t.prevGoAwayID {
t.mu.Unlock() t.mu.Unlock()
t.Close(connectionErrorf(true, nil, "received goaway with stream id: %v, which exceeds stream id of previous goaway: %v", id, t.prevGoAwayID)) t.Close()
return return
} }
default: default:
@ -1205,7 +1191,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
active := len(t.activeStreams) active := len(t.activeStreams)
t.mu.Unlock() t.mu.Unlock()
if active == 0 { if active == 0 {
t.Close(connectionErrorf(true, nil, "received goaway and there are no active streams")) t.Close()
} }
} }
@ -1221,13 +1207,12 @@ func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
t.goAwayReason = GoAwayTooManyPings t.goAwayReason = GoAwayTooManyPings
} }
} }
t.goAwayDebugMessage = fmt.Sprintf("code: %s, debug data: %v", f.ErrCode, string(f.DebugData()))
} }
func (t *http2Client) GetGoAwayReason() (GoAwayReason, string) { func (t *http2Client) GetGoAwayReason() GoAwayReason {
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
return t.goAwayReason, t.goAwayDebugMessage return t.goAwayReason
} }
func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) { func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
@ -1324,8 +1309,7 @@ func (t *http2Client) reader() {
// Check the validity of server preface. // Check the validity of server preface.
frame, err := t.framer.fr.ReadFrame() frame, err := t.framer.fr.ReadFrame()
if err != nil { if err != nil {
err = connectionErrorf(true, err, "error reading server preface: %v", err) t.Close() // this kicks off resetTransport, so must be last before return
t.Close(err) // this kicks off resetTransport, so must be last before return
return return
} }
t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!) t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!)
@ -1334,8 +1318,7 @@ func (t *http2Client) reader() {
} }
sf, ok := frame.(*http2.SettingsFrame) sf, ok := frame.(*http2.SettingsFrame)
if !ok { if !ok {
// this kicks off resetTransport, so must be last before return t.Close() // this kicks off resetTransport, so must be last before return
t.Close(connectionErrorf(true, nil, "initial http2 frame from server is not a settings frame: %T", frame))
return return
} }
t.onPrefaceReceipt() t.onPrefaceReceipt()
@ -1371,7 +1354,7 @@ func (t *http2Client) reader() {
continue continue
} else { } else {
// Transport error. // Transport error.
t.Close(connectionErrorf(true, err, "error reading from server: %v", err)) t.Close()
return return
} }
} }
@ -1430,7 +1413,7 @@ func (t *http2Client) keepalive() {
continue continue
} }
if outstandingPing && timeoutLeft <= 0 { if outstandingPing && timeoutLeft <= 0 {
t.Close(connectionErrorf(true, nil, "keepalive ping failed to receive ACK within timeout")) t.Close()
return return
} }
t.mu.Lock() t.mu.Lock()

View File

@ -26,7 +26,6 @@ import (
"io" "io"
"math" "math"
"net" "net"
"net/http"
"strconv" "strconv"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -356,6 +355,26 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
if state.data.statsTrace != nil { if state.data.statsTrace != nil {
s.ctx = stats.SetIncomingTrace(s.ctx, state.data.statsTrace) s.ctx = stats.SetIncomingTrace(s.ctx, state.data.statsTrace)
} }
if t.inTapHandle != nil {
var err error
info := &tap.Info{
FullMethodName: state.data.method,
}
s.ctx, err = t.inTapHandle(s.ctx, info)
if err != nil {
if logger.V(logLevel) {
logger.Warningf("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
}
t.controlBuf.put(&cleanupStream{
streamID: s.id,
rst: true,
rstCode: http2.ErrCodeRefusedStream,
onWrite: func() {},
})
s.cancel()
return false
}
}
t.mu.Lock() t.mu.Lock()
if t.state != reachable { if t.state != reachable {
t.mu.Unlock() t.mu.Unlock()
@ -383,39 +402,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
return true return true
} }
t.maxStreamID = streamID t.maxStreamID = streamID
if state.data.httpMethod != http.MethodPost {
t.mu.Unlock()
if logger.V(logLevel) {
logger.Warningf("transport: http2Server.operateHeaders parsed a :method field: %v which should be POST", state.data.httpMethod)
}
t.controlBuf.put(&cleanupStream{
streamID: streamID,
rst: true,
rstCode: http2.ErrCodeProtocol,
onWrite: func() {},
})
s.cancel()
return false
}
if t.inTapHandle != nil {
var err error
if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: state.data.method}); err != nil {
t.mu.Unlock()
if logger.V(logLevel) {
logger.Infof("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
}
stat, ok := status.FromError(err)
if !ok {
stat = status.New(codes.PermissionDenied, err.Error())
}
t.controlBuf.put(&earlyAbortStream{
streamID: s.id,
contentSubtype: s.contentSubtype,
status: stat,
})
return false
}
}
t.activeStreams[streamID] = s t.activeStreams[streamID] = s
if len(t.activeStreams) == 1 { if len(t.activeStreams) == 1 {
t.idle = time.Time{} t.idle = time.Time{}

View File

@ -111,7 +111,6 @@ type parsedHeaderData struct {
timeoutSet bool timeoutSet bool
timeout time.Duration timeout time.Duration
method string method string
httpMethod string
// key-value metadata map from the peer. // key-value metadata map from the peer.
mdata map[string][]string mdata map[string][]string
statsTags []byte statsTags []byte
@ -364,8 +363,6 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) {
} }
d.data.statsTrace = v d.data.statsTrace = v
d.addMetadata(f.Name, string(v)) d.addMetadata(f.Name, string(v))
case ":method":
d.data.httpMethod = f.Value
default: default:
if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) { if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
break break

View File

@ -241,7 +241,6 @@ type Stream struct {
ctx context.Context // the associated context of the stream ctx context.Context // the associated context of the stream
cancel context.CancelFunc // always nil for client side Stream cancel context.CancelFunc // always nil for client side Stream
done chan struct{} // closed at the end of stream to unblock writers. On the client side. done chan struct{} // closed at the end of stream to unblock writers. On the client side.
doneFunc func() // invoked at the end of stream on client side.
ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance) ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
method string // the associated RPC method of the stream method string // the associated RPC method of the stream
recvCompress string recvCompress string
@ -612,8 +611,6 @@ type CallHdr struct {
ContentSubtype string ContentSubtype string
PreviousAttempts int // value of grpc-previous-rpc-attempts header to set PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
DoneFunc func() // called when the stream is finished
} }
// ClientTransport is the common interface for all gRPC client-side transport // ClientTransport is the common interface for all gRPC client-side transport
@ -622,7 +619,7 @@ type ClientTransport interface {
// Close tears down this transport. Once it returns, the transport // Close tears down this transport. Once it returns, the transport
// should not be accessed any more. The caller must make sure this // should not be accessed any more. The caller must make sure this
// is called only once. // is called only once.
Close(err error) Close() error
// GracefulClose starts to tear down the transport: the transport will stop // GracefulClose starts to tear down the transport: the transport will stop
// accepting new RPCs and NewStream will return error. Once all streams are // accepting new RPCs and NewStream will return error. Once all streams are
@ -656,9 +653,8 @@ type ClientTransport interface {
// HTTP/2). // HTTP/2).
GoAway() <-chan struct{} GoAway() <-chan struct{}
// GetGoAwayReason returns the reason why GoAway frame was received, along // GetGoAwayReason returns the reason why GoAway frame was received.
// with a human readable string with debug info. GetGoAwayReason() GoAwayReason
GetGoAwayReason() (GoAwayReason, string)
// RemoteAddr returns the remote network address. // RemoteAddr returns the remote network address.
RemoteAddr() net.Addr RemoteAddr() net.Addr

View File

@ -1,40 +0,0 @@
/*
* Copyright 2021 gRPC 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 internal
import (
"google.golang.org/grpc/attributes"
"google.golang.org/grpc/resolver"
)
// handshakeClusterNameKey is the type used as the key to store cluster name in
// the Attributes field of resolver.Address.
type handshakeClusterNameKey struct{}
// SetXDSHandshakeClusterName returns a copy of addr in which the Attributes field
// is updated with the cluster name.
func SetXDSHandshakeClusterName(addr resolver.Address, clusterName string) resolver.Address {
addr.Attributes = addr.Attributes.WithValues(handshakeClusterNameKey{}, clusterName)
return addr
}
// GetXDSHandshakeClusterName returns cluster name stored in attr.
func GetXDSHandshakeClusterName(attr *attributes.Attributes) (string, bool) {
v := attr.Value(handshakeClusterNameKey{})
name, ok := v.(string)
return name, ok
}

View File

@ -75,9 +75,13 @@ func Pairs(kv ...string) MD {
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv))) panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
} }
md := MD{} md := MD{}
for i := 0; i < len(kv); i += 2 { var key string
key := strings.ToLower(kv[i]) for i, s := range kv {
md[key] = append(md[key], kv[i+1]) if i%2 == 0 {
key = strings.ToLower(s)
continue
}
md[key] = append(md[key], s)
} }
return md return md
} }
@ -191,18 +195,12 @@ func FromOutgoingContext(ctx context.Context) (MD, bool) {
return nil, false return nil, false
} }
out := raw.md.Copy() mds := make([]MD, 0, len(raw.added)+1)
for _, added := range raw.added { mds = append(mds, raw.md)
if len(added)%2 == 1 { for _, vv := range raw.added {
panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added))) mds = append(mds, Pairs(vv...))
}
for i := 0; i < len(added); i += 2 {
key := strings.ToLower(added[i])
out[key] = append(out[key], added[i+1])
}
} }
return out, ok return Join(mds...), ok
} }
type rawMD struct { type rawMD struct {

View File

@ -84,7 +84,7 @@ func (b *pickfirstBalancer) UpdateClientConnState(cs balancer.ClientConnState) e
b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &picker{result: balancer.PickResult{SubConn: b.sc}}}) b.cc.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &picker{result: balancer.PickResult{SubConn: b.sc}}})
b.sc.Connect() b.sc.Connect()
} else { } else {
b.cc.UpdateAddresses(b.sc, cs.ResolverState.Addresses) b.sc.UpdateAddresses(cs.ResolverState.Addresses)
b.sc.Connect() b.sc.Connect()
} }
return nil return nil

View File

@ -40,14 +40,16 @@ echo "go install cmd/protoc-gen-go-grpc"
echo "git clone https://github.com/grpc/grpc-proto" echo "git clone https://github.com/grpc/grpc-proto"
git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto
echo "git clone https://github.com/protocolbuffers/protobuf"
git clone --quiet https://github.com/protocolbuffers/protobuf ${WORKDIR}/protobuf
# Pull in code.proto as a proto dependency # Pull in code.proto as a proto dependency
mkdir -p ${WORKDIR}/googleapis/google/rpc mkdir -p ${WORKDIR}/googleapis/google/rpc
echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto" echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto"
curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto
# Pull in the MeshCA service proto.
mkdir -p ${WORKDIR}/istio/istio/google/security/meshca/v1
echo "curl https://raw.githubusercontent.com/istio/istio/master/security/proto/providers/google/meshca.proto"
curl --silent https://raw.githubusercontent.com/istio/istio/master/security/proto/providers/google/meshca.proto > ${WORKDIR}/istio/istio/google/security/meshca/v1/meshca.proto
mkdir -p ${WORKDIR}/out mkdir -p ${WORKDIR}/out
# Generates sources without the embed requirement # Generates sources without the embed requirement
@ -71,6 +73,7 @@ SOURCES=(
${WORKDIR}/grpc-proto/grpc/service_config/service_config.proto ${WORKDIR}/grpc-proto/grpc/service_config/service_config.proto
${WORKDIR}/grpc-proto/grpc/testing/*.proto ${WORKDIR}/grpc-proto/grpc/testing/*.proto
${WORKDIR}/grpc-proto/grpc/core/*.proto ${WORKDIR}/grpc-proto/grpc/core/*.proto
${WORKDIR}/istio/istio/google/security/meshca/v1/meshca.proto
) )
# These options of the form 'Mfoo.proto=bar' instruct the codegen to use an # These options of the form 'Mfoo.proto=bar' instruct the codegen to use an
@ -84,7 +87,6 @@ for src in ${SOURCES[@]}; do
-I"." \ -I"." \
-I${WORKDIR}/grpc-proto \ -I${WORKDIR}/grpc-proto \
-I${WORKDIR}/googleapis \ -I${WORKDIR}/googleapis \
-I${WORKDIR}/protobuf/src \
-I${WORKDIR}/istio \ -I${WORKDIR}/istio \
${src} ${src}
done done
@ -95,7 +97,6 @@ for src in ${LEGACY_SOURCES[@]}; do
-I"." \ -I"." \
-I${WORKDIR}/grpc-proto \ -I${WORKDIR}/grpc-proto \
-I${WORKDIR}/googleapis \ -I${WORKDIR}/googleapis \
-I${WORKDIR}/protobuf/src \
-I${WORKDIR}/istio \ -I${WORKDIR}/istio \
${src} ${src}
done done
@ -116,4 +117,8 @@ mv ${WORKDIR}/out/grpc/service_config/service_config.pb.go internal/proto/grpc_s
mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/ mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/
mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/ mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/
# istio/google/security/meshca/v1/meshca.proto does not have a go_package option.
mkdir -p ${WORKDIR}/out/google.golang.org/grpc/credentials/tls/certprovider/meshca/internal/v1/
mv ${WORKDIR}/out/istio/google/security/meshca/v1/* ${WORKDIR}/out/google.golang.org/grpc/credentials/tls/certprovider/meshca/internal/v1/
cp -R ${WORKDIR}/out/google.golang.org/grpc/* . cp -R ${WORKDIR}/out/google.golang.org/grpc/* .

View File

@ -181,7 +181,7 @@ type State struct {
// gRPC to add new methods to this interface. // gRPC to add new methods to this interface.
type ClientConn interface { type ClientConn interface {
// UpdateState updates the state of the ClientConn appropriately. // UpdateState updates the state of the ClientConn appropriately.
UpdateState(State) error UpdateState(State)
// ReportError notifies the ClientConn that the Resolver encountered an // ReportError notifies the ClientConn that the Resolver encountered an
// error. The ClientConn will notify the load balancer and begin calling // error. The ClientConn will notify the load balancer and begin calling
// ResolveNow on the Resolver with exponential backoff. // ResolveNow on the Resolver with exponential backoff.

View File

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"sync" "sync"
"time"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
@ -39,6 +40,9 @@ type ccResolverWrapper struct {
resolver resolver.Resolver resolver resolver.Resolver
done *grpcsync.Event done *grpcsync.Event
curState resolver.State curState resolver.State
pollingMu sync.Mutex
polling chan struct{}
} }
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and // newCCResolverWrapper uses the resolver.Builder to build a Resolver and
@ -89,19 +93,59 @@ func (ccr *ccResolverWrapper) close() {
ccr.resolverMu.Unlock() ccr.resolverMu.Unlock()
} }
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error { // poll begins or ends asynchronous polling of the resolver based on whether
// err is ErrBadResolverState.
func (ccr *ccResolverWrapper) poll(err error) {
ccr.pollingMu.Lock()
defer ccr.pollingMu.Unlock()
if err != balancer.ErrBadResolverState {
// stop polling
if ccr.polling != nil {
close(ccr.polling)
ccr.polling = nil
}
return
}
if ccr.polling != nil {
// already polling
return
}
p := make(chan struct{})
ccr.polling = p
go func() {
for i := 0; ; i++ {
ccr.resolveNow(resolver.ResolveNowOptions{})
t := time.NewTimer(ccr.cc.dopts.resolveNowBackoff(i))
select {
case <-p:
t.Stop()
return
case <-ccr.done.Done():
// Resolver has been closed.
t.Stop()
return
case <-t.C:
select {
case <-p:
return
default:
}
// Timer expired; re-resolve.
}
}
}()
}
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) {
if ccr.done.HasFired() { if ccr.done.HasFired() {
return nil return
} }
channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending update to cc: %v", s) channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: sending update to cc: %v", s)
if channelz.IsOn() { if channelz.IsOn() {
ccr.addChannelzTraceEvent(s) ccr.addChannelzTraceEvent(s)
} }
ccr.curState = s ccr.curState = s
if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState { ccr.poll(ccr.cc.updateResolverState(ccr.curState, nil))
return balancer.ErrBadResolverState
}
return nil
} }
func (ccr *ccResolverWrapper) ReportError(err error) { func (ccr *ccResolverWrapper) ReportError(err error) {
@ -109,7 +153,7 @@ func (ccr *ccResolverWrapper) ReportError(err error) {
return return
} }
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err) channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
ccr.cc.updateResolverState(resolver.State{}, err) ccr.poll(ccr.cc.updateResolverState(resolver.State{}, err))
} }
// NewAddress is called by the resolver implementation to send addresses to gRPC. // NewAddress is called by the resolver implementation to send addresses to gRPC.
@ -122,7 +166,7 @@ func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig}) ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
} }
ccr.curState.Addresses = addrs ccr.curState.Addresses = addrs
ccr.cc.updateResolverState(ccr.curState, nil) ccr.poll(ccr.cc.updateResolverState(ccr.curState, nil))
} }
// NewServiceConfig is called by the resolver implementation to send service // NewServiceConfig is called by the resolver implementation to send service
@ -139,13 +183,14 @@ func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
scpr := parseServiceConfig(sc) scpr := parseServiceConfig(sc)
if scpr.Err != nil { if scpr.Err != nil {
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err) channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
ccr.poll(balancer.ErrBadResolverState)
return return
} }
if channelz.IsOn() { if channelz.IsOn() {
ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr}) ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
} }
ccr.curState.ServiceConfig = scpr ccr.curState.ServiceConfig = scpr
ccr.cc.updateResolverState(ccr.curState, nil) ccr.poll(ccr.cc.updateResolverState(ccr.curState, nil))
} }
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult { func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {

View File

@ -429,10 +429,9 @@ func (o ContentSubtypeCallOption) before(c *callInfo) error {
} }
func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {} func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {}
// ForceCodec returns a CallOption that will set codec to be used for all // ForceCodec returns a CallOption that will set the given Codec to be
// request and response messages for a call. The result of calling Name() will // used for all request and response messages for a call. The result of calling
// be used as the content-subtype after converting to lowercase, unless // String() will be used as the content-subtype in a case-insensitive manner.
// CallContentSubtype is also used.
// //
// See Content-Type on // See Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
@ -854,17 +853,7 @@ func toRPCErr(err error) error {
// setCallInfoCodec should only be called after CallOptions have been applied. // setCallInfoCodec should only be called after CallOptions have been applied.
func setCallInfoCodec(c *callInfo) error { func setCallInfoCodec(c *callInfo) error {
if c.codec != nil { if c.codec != nil {
// codec was already set by a CallOption; use it, but set the content // codec was already set by a CallOption; use it.
// subtype if it is not set.
if c.contentSubtype == "" {
// c.codec is a baseCodec to hide the difference between grpc.Codec and
// encoding.Codec (Name vs. String method name). We only support
// setting content subtype from encoding.Codec to avoid a behavior
// change with the deprecated version.
if ec, ok := c.codec.(encoding.Codec); ok {
c.contentSubtype = strings.ToLower(ec.Name())
}
}
return nil return nil
} }
@ -899,7 +888,8 @@ type channelzData struct {
// buffer files to ensure compatibility with the gRPC version used. The latest // buffer files to ensure compatibility with the gRPC version used. The latest
// support package version is 7. // support package version is 7.
// //
// Older versions are kept for compatibility. // Older versions are kept for compatibility. They may be removed if
// compatibility cannot be maintained.
// //
// These constants should not be referenced from any other code. // These constants should not be referenced from any other code.
const ( const (

View File

@ -57,22 +57,12 @@ import (
const ( const (
defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4 defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4
defaultServerMaxSendMessageSize = math.MaxInt32 defaultServerMaxSendMessageSize = math.MaxInt32
// Server transports are tracked in a map which is keyed on listener
// address. For regular gRPC traffic, connections are accepted in Serve()
// through a call to Accept(), and we use the actual listener address as key
// when we add it to the map. But for connections received through
// ServeHTTP(), we do not have a listener and hence use this dummy value.
listenerAddressForServeHTTP = "listenerAddressForServeHTTP"
) )
func init() { func init() {
internal.GetServerCredentials = func(srv *Server) credentials.TransportCredentials { internal.GetServerCredentials = func(srv *Server) credentials.TransportCredentials {
return srv.opts.creds return srv.opts.creds
} }
internal.DrainServerTransports = func(srv *Server, addr string) {
srv.drainServerTransports(addr)
}
} }
var statusOK = status.New(codes.OK, "") var statusOK = status.New(codes.OK, "")
@ -117,12 +107,9 @@ type serverWorkerData struct {
type Server struct { type Server struct {
opts serverOptions opts serverOptions
mu sync.Mutex // guards following mu sync.Mutex // guards following
lis map[net.Listener]bool lis map[net.Listener]bool
// conns contains all active server transports. It is a map keyed on a conns map[transport.ServerTransport]bool
// listener address with the value being the set of active transports
// belonging to that listener.
conns map[string]map[transport.ServerTransport]bool
serve bool serve bool
drain bool drain bool
cv *sync.Cond // signaled when connections close for GracefulStop cv *sync.Cond // signaled when connections close for GracefulStop
@ -279,35 +266,6 @@ func CustomCodec(codec Codec) ServerOption {
}) })
} }
// ForceServerCodec returns a ServerOption that sets a codec for message
// marshaling and unmarshaling.
//
// This will override any lookups by content-subtype for Codecs registered
// with RegisterCodec.
//
// See Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details. Also see the documentation on RegisterCodec and
// CallContentSubtype for more details on the interaction between encoding.Codec
// and content-subtype.
//
// This function is provided for advanced users; prefer to register codecs
// using encoding.RegisterCodec.
// The server will automatically use registered codecs based on the incoming
// requests' headers. See also
// https://github.com/grpc/grpc-go/blob/master/Documentation/encoding.md#using-a-codec.
// Will be supported throughout 1.x.
//
// Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func ForceServerCodec(codec encoding.Codec) ServerOption {
return newFuncServerOption(func(o *serverOptions) {
o.codec = codec
})
}
// RPCCompressor returns a ServerOption that sets a compressor for outbound // RPCCompressor returns a ServerOption that sets a compressor for outbound
// messages. For backward compatibility, all outbound messages will be sent // messages. For backward compatibility, all outbound messages will be sent
// using this compressor, regardless of incoming message compression. By // using this compressor, regardless of incoming message compression. By
@ -418,11 +376,6 @@ func ChainStreamInterceptor(interceptors ...StreamServerInterceptor) ServerOptio
// InTapHandle returns a ServerOption that sets the tap handle for all the server // InTapHandle returns a ServerOption that sets the tap handle for all the server
// transport to be created. Only one can be installed. // transport to be created. Only one can be installed.
//
// Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func InTapHandle(h tap.ServerInHandle) ServerOption { func InTapHandle(h tap.ServerInHandle) ServerOption {
return newFuncServerOption(func(o *serverOptions) { return newFuncServerOption(func(o *serverOptions) {
if o.inTapHandle != nil { if o.inTapHandle != nil {
@ -566,7 +519,7 @@ func NewServer(opt ...ServerOption) *Server {
s := &Server{ s := &Server{
lis: make(map[net.Listener]bool), lis: make(map[net.Listener]bool),
opts: opts, opts: opts,
conns: make(map[string]map[transport.ServerTransport]bool), conns: make(map[transport.ServerTransport]bool),
services: make(map[string]*serviceInfo), services: make(map[string]*serviceInfo),
quit: grpcsync.NewEvent(), quit: grpcsync.NewEvent(),
done: grpcsync.NewEvent(), done: grpcsync.NewEvent(),
@ -825,7 +778,7 @@ func (s *Server) Serve(lis net.Listener) error {
// s.conns before this conn can be added. // s.conns before this conn can be added.
s.serveWG.Add(1) s.serveWG.Add(1)
go func() { go func() {
s.handleRawConn(lis.Addr().String(), rawConn) s.handleRawConn(rawConn)
s.serveWG.Done() s.serveWG.Done()
}() }()
} }
@ -833,7 +786,7 @@ func (s *Server) Serve(lis net.Listener) error {
// handleRawConn forks a goroutine to handle a just-accepted connection that // handleRawConn forks a goroutine to handle a just-accepted connection that
// has not had any I/O performed on it yet. // has not had any I/O performed on it yet.
func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) { func (s *Server) handleRawConn(rawConn net.Conn) {
if s.quit.HasFired() { if s.quit.HasFired() {
rawConn.Close() rawConn.Close()
return return
@ -861,24 +814,15 @@ func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
} }
rawConn.SetDeadline(time.Time{}) rawConn.SetDeadline(time.Time{})
if !s.addConn(lisAddr, st) { if !s.addConn(st) {
return return
} }
go func() { go func() {
s.serveStreams(st) s.serveStreams(st)
s.removeConn(lisAddr, st) s.removeConn(st)
}() }()
} }
func (s *Server) drainServerTransports(addr string) {
s.mu.Lock()
conns := s.conns[addr]
for st := range conns {
st.Drain()
}
s.mu.Unlock()
}
// newHTTP2Transport sets up a http/2 transport (using the // newHTTP2Transport sets up a http/2 transport (using the
// gRPC http2 server transport in transport/http2_server.go). // gRPC http2 server transport in transport/http2_server.go).
func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport { func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport {
@ -980,10 +924,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
if !s.addConn(listenerAddressForServeHTTP, st) { if !s.addConn(st) {
return return
} }
defer s.removeConn(listenerAddressForServeHTTP, st) defer s.removeConn(st)
s.serveStreams(st) s.serveStreams(st)
} }
@ -1011,7 +955,7 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea
return trInfo return trInfo
} }
func (s *Server) addConn(addr string, st transport.ServerTransport) bool { func (s *Server) addConn(st transport.ServerTransport) bool {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
if s.conns == nil { if s.conns == nil {
@ -1023,28 +967,15 @@ func (s *Server) addConn(addr string, st transport.ServerTransport) bool {
// immediately. // immediately.
st.Drain() st.Drain()
} }
s.conns[st] = true
if s.conns[addr] == nil {
// Create a map entry if this is the first connection on this listener.
s.conns[addr] = make(map[transport.ServerTransport]bool)
}
s.conns[addr][st] = true
return true return true
} }
func (s *Server) removeConn(addr string, st transport.ServerTransport) { func (s *Server) removeConn(st transport.ServerTransport) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
if s.conns != nil {
conns := s.conns[addr] delete(s.conns, st)
if conns != nil {
delete(conns, st)
if len(conns) == 0 {
// If the last connection for this address is being removed, also
// remove the map entry corresponding to the address. This is used
// in GracefulStop() when waiting for all connections to be closed.
delete(s.conns, addr)
}
s.cv.Broadcast() s.cv.Broadcast()
} }
} }
@ -1708,7 +1639,7 @@ func (s *Server) Stop() {
s.mu.Lock() s.mu.Lock()
listeners := s.lis listeners := s.lis
s.lis = nil s.lis = nil
conns := s.conns st := s.conns
s.conns = nil s.conns = nil
// interrupt GracefulStop if Stop and GracefulStop are called concurrently. // interrupt GracefulStop if Stop and GracefulStop are called concurrently.
s.cv.Broadcast() s.cv.Broadcast()
@ -1717,10 +1648,8 @@ func (s *Server) Stop() {
for lis := range listeners { for lis := range listeners {
lis.Close() lis.Close()
} }
for _, cs := range conns { for c := range st {
for st := range cs { c.Close()
st.Close()
}
} }
if s.opts.numServerWorkers > 0 { if s.opts.numServerWorkers > 0 {
s.stopServerWorkers() s.stopServerWorkers()
@ -1757,10 +1686,8 @@ func (s *Server) GracefulStop() {
} }
s.lis = nil s.lis = nil
if !s.drain { if !s.drain {
for _, conns := range s.conns { for st := range s.conns {
for st := range conns { st.Drain()
st.Drain()
}
} }
s.drain = true s.drain = true
} }

View File

@ -73,11 +73,9 @@ func FromProto(s *spb.Status) *Status {
return status.FromProto(s) return status.FromProto(s)
} }
// FromError returns a Status representing err if it was produced by this // FromError returns a Status representing err if it was produced from this
// package or has a method `GRPCStatus() *Status`. // package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
// If err is nil, a Status is returned with codes.OK and no message. // Status is returned with codes.Unknown and the original error message.
// Otherwise, ok is false and a Status is returned with codes.Unknown and
// the original error message.
func FromError(err error) (s *Status, ok bool) { func FromError(err error) (s *Status, ok bool) {
if err == nil { if err == nil {
return nil, true return nil, true

View File

@ -52,20 +52,14 @@ import (
// of the RPC. // of the RPC.
type StreamHandler func(srv interface{}, stream ServerStream) error type StreamHandler func(srv interface{}, stream ServerStream) error
// StreamDesc represents a streaming RPC service's method specification. Used // StreamDesc represents a streaming RPC service's method specification.
// on the server when registering services and on the client when initiating
// new streams.
type StreamDesc struct { type StreamDesc struct {
// StreamName and Handler are only used when registering handlers on a StreamName string
// server. Handler StreamHandler
StreamName string // the name of the method excluding the service
Handler StreamHandler // the handler called for the method
// ServerStreams and ClientStreams are used for registering handlers on a // At least one of these is true.
// server as well as defining RPC behavior when passed to NewClientStream ServerStreams bool
// and ClientConn.NewStream. At least one must be true. ClientStreams bool
ServerStreams bool // indicates the server can perform streaming sends
ClientStreams bool // indicates the client can perform streaming sends
} }
// Stream defines the common interface a client or server stream has to satisfy. // Stream defines the common interface a client or server stream has to satisfy.
@ -172,6 +166,7 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
} }
}() }()
} }
c := defaultCallInfo()
// Provide an opportunity for the first RPC to see the first service config // Provide an opportunity for the first RPC to see the first service config
// provided by the resolver. // provided by the resolver.
if err := cc.waitForResolvedAddrs(ctx); err != nil { if err := cc.waitForResolvedAddrs(ctx); err != nil {
@ -180,40 +175,18 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
var mc serviceconfig.MethodConfig var mc serviceconfig.MethodConfig
var onCommit func() var onCommit func()
var newStream = func(ctx context.Context, done func()) (iresolver.ClientStream, error) { rpcConfig, err := cc.safeConfigSelector.SelectConfig(iresolver.RPCInfo{Context: ctx, Method: method})
return newClientStreamWithParams(ctx, desc, cc, method, mc, onCommit, done, opts...)
}
rpcInfo := iresolver.RPCInfo{Context: ctx, Method: method}
rpcConfig, err := cc.safeConfigSelector.SelectConfig(rpcInfo)
if err != nil { if err != nil {
return nil, toRPCErr(err) return nil, status.Convert(err).Err()
} }
if rpcConfig != nil { if rpcConfig != nil {
if rpcConfig.Context != nil { if rpcConfig.Context != nil {
ctx = rpcConfig.Context ctx = rpcConfig.Context
} }
mc = rpcConfig.MethodConfig mc = rpcConfig.MethodConfig
onCommit = rpcConfig.OnCommitted onCommit = rpcConfig.OnCommitted
if rpcConfig.Interceptor != nil {
rpcInfo.Context = nil
ns := newStream
newStream = func(ctx context.Context, done func()) (iresolver.ClientStream, error) {
cs, err := rpcConfig.Interceptor.NewStream(ctx, rpcInfo, done, ns)
if err != nil {
return nil, toRPCErr(err)
}
return cs, nil
}
}
} }
return newStream(ctx, func() {})
}
func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc serviceconfig.MethodConfig, onCommit, doneFunc func(), opts ...CallOption) (_ iresolver.ClientStream, err error) {
c := defaultCallInfo()
if mc.WaitForReady != nil { if mc.WaitForReady != nil {
c.failFast = !*mc.WaitForReady c.failFast = !*mc.WaitForReady
} }
@ -250,7 +223,6 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client
Host: cc.authority, Host: cc.authority,
Method: method, Method: method,
ContentSubtype: c.contentSubtype, ContentSubtype: c.contentSubtype,
DoneFunc: doneFunc,
} }
// Set our outgoing compression according to the UseCompressor CallOption, if // Set our outgoing compression according to the UseCompressor CallOption, if

View File

@ -37,16 +37,16 @@ type Info struct {
// TODO: More to be added. // TODO: More to be added.
} }
// ServerInHandle defines the function which runs before a new stream is // ServerInHandle defines the function which runs before a new stream is created
// created on the server side. If it returns a non-nil error, the stream will // on the server side. If it returns a non-nil error, the stream will not be
// not be created and an error will be returned to the client. If the error // created and a RST_STREAM will be sent back to the client with REFUSED_STREAM.
// returned is a status error, that status code and message will be used, // The client will receive an RPC error "code = Unavailable, desc = stream
// otherwise PermissionDenied will be the code and err.Error() will be the // terminated by RST_STREAM with error code: REFUSED_STREAM".
// message.
// //
// It's intended to be used in situations where you don't want to waste the // It's intended to be used in situations where you don't want to waste the
// resources to accept the new stream (e.g. rate-limiting). For other general // resources to accept the new stream (e.g. rate-limiting). And the content of
// usages, please use interceptors. // the error will be ignored and won't be sent back to the client. For other
// general usages, please use interceptors.
// //
// Note that it is executed in the per-connection I/O goroutine(s) instead of // Note that it is executed in the per-connection I/O goroutine(s) instead of
// per-RPC goroutine. Therefore, users should NOT have any // per-RPC goroutine. Therefore, users should NOT have any

View File

@ -19,4 +19,4 @@
package grpc package grpc
// Version is the current grpc version. // Version is the current grpc version.
const Version = "1.38.0" const Version = "1.35.0"

43
vendor/google.golang.org/grpc/vet.sh generated vendored
View File

@ -28,8 +28,7 @@ cleanup() {
} }
trap cleanup EXIT trap cleanup EXIT
PATH="${HOME}/go/bin:${GOROOT}/bin:${PATH}" PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"
go version
if [[ "$1" = "-install" ]]; then if [[ "$1" = "-install" ]]; then
# Check for module support # Check for module support
@ -105,6 +104,12 @@ git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.
# TODO: Remove when we drop Go 1.10 support # TODO: Remove when we drop Go 1.10 support
go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
# - gofmt, goimports, golint (with exceptions for generated code), go vet.
gofmt -s -d -l . 2>&1 | fail_on_output
goimports -l . 2>&1 | not grep -vE "\.pb\.go"
golint ./... 2>&1 | not grep -vE "\.pb\.go:"
go vet -all ./...
misspell -error . misspell -error .
# - Check that generated proto files are up to date. # - Check that generated proto files are up to date.
@ -114,22 +119,12 @@ if [[ -z "${VET_SKIP_PROTO}" ]]; then
(git status; git --no-pager diff; exit 1) (git status; git --no-pager diff; exit 1)
fi fi
# - gofmt, goimports, golint (with exceptions for generated code), go vet, # - Check that our modules are tidy.
# go mod tidy. if go help mod >& /dev/null; then
# Perform these checks on each module inside gRPC. find . -name 'go.mod' | xargs -IXXX bash -c 'cd $(dirname XXX); go mod tidy'
for MOD_FILE in $(find . -name 'go.mod'); do
MOD_DIR=$(dirname ${MOD_FILE})
pushd ${MOD_DIR}
go vet -all ./... | fail_on_output
gofmt -s -d -l . 2>&1 | fail_on_output
goimports -l . 2>&1 | not grep -vE "\.pb\.go"
golint ./... 2>&1 | not grep -vE "/testv3\.pb\.go:"
go mod tidy
git status --porcelain 2>&1 | fail_on_output || \ git status --porcelain 2>&1 | fail_on_output || \
(git status; git --no-pager diff; exit 1) (git status; git --no-pager diff; exit 1)
popd fi
done
# - Collection of static analysis checks # - Collection of static analysis checks
# #
@ -146,11 +141,8 @@ not grep -Fv '.CredsBundle
.NewAddress .NewAddress
.NewServiceConfig .NewServiceConfig
.Type is deprecated: use Attributes .Type is deprecated: use Attributes
BuildVersion is deprecated
balancer.ErrTransientFailure balancer.ErrTransientFailure
balancer.Picker balancer.Picker
extDesc.Filename is deprecated
github.com/golang/protobuf/jsonpb is deprecated
grpc.CallCustomCodec grpc.CallCustomCodec
grpc.Code grpc.Code
grpc.Compressor grpc.Compressor
@ -172,7 +164,13 @@ grpc.WithServiceConfig
grpc.WithTimeout grpc.WithTimeout
http.CloseNotifier http.CloseNotifier
info.SecurityVersion info.SecurityVersion
resolver.Backend
resolver.GRPCLB
extDesc.Filename is deprecated
BuildVersion is deprecated
github.com/golang/protobuf/jsonpb is deprecated
proto is deprecated proto is deprecated
xxx_messageInfo_
proto.InternalMessageInfo is deprecated proto.InternalMessageInfo is deprecated
proto.EnumName is deprecated proto.EnumName is deprecated
proto.ErrInternalBadWireType is deprecated proto.ErrInternalBadWireType is deprecated
@ -186,12 +184,7 @@ proto.RegisterExtension is deprecated
proto.RegisteredExtension is deprecated proto.RegisteredExtension is deprecated
proto.RegisteredExtensions is deprecated proto.RegisteredExtensions is deprecated
proto.RegisterMapType is deprecated proto.RegisterMapType is deprecated
proto.Unmarshaler is deprecated proto.Unmarshaler is deprecated' "${SC_OUT}"
resolver.Backend
resolver.GRPCLB
Target is deprecated: Use the Target field in the BuildOptions instead.
xxx_messageInfo_
' "${SC_OUT}"
# - special golint on package comments. # - special golint on package comments.
lint_package_comment_per_package() { lint_package_comment_per_package() {

16
vendor/modules.txt vendored
View File

@ -164,7 +164,7 @@ github.com/hashicorp/vault/sdk/helper/hclutil
github.com/hashicorp/vault/sdk/helper/jsonutil github.com/hashicorp/vault/sdk/helper/jsonutil
github.com/hashicorp/vault/sdk/helper/parseutil github.com/hashicorp/vault/sdk/helper/parseutil
github.com/hashicorp/vault/sdk/helper/strutil github.com/hashicorp/vault/sdk/helper/strutil
# github.com/imdario/mergo v0.3.9 # github.com/imdario/mergo v0.3.6
github.com/imdario/mergo github.com/imdario/mergo
# github.com/jmespath/go-jmespath v0.4.0 # github.com/jmespath/go-jmespath v0.4.0
github.com/jmespath/go-jmespath github.com/jmespath/go-jmespath
@ -176,12 +176,12 @@ github.com/kubernetes-csi/csi-lib-utils/connection
github.com/kubernetes-csi/csi-lib-utils/metrics github.com/kubernetes-csi/csi-lib-utils/metrics
github.com/kubernetes-csi/csi-lib-utils/protosanitizer github.com/kubernetes-csi/csi-lib-utils/protosanitizer
github.com/kubernetes-csi/csi-lib-utils/rpc github.com/kubernetes-csi/csi-lib-utils/rpc
# github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1 => github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1-0.20200504125226-859696c419ff # github.com/kubernetes-csi/external-snapshotter/client/v4 v4.1.0
## explicit ## explicit
github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1 github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1
github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1beta1
github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/scheme github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/scheme
github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/typed/volumesnapshot/v1beta1 github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/typed/volumesnapshot/v1
# github.com/libopenstorage/secrets v0.0.0-20201006135900-af310b01fe47 # github.com/libopenstorage/secrets v0.0.0-20201006135900-af310b01fe47
## explicit ## explicit
github.com/libopenstorage/secrets github.com/libopenstorage/secrets
@ -354,7 +354,7 @@ google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a # google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a
google.golang.org/genproto/googleapis/rpc/status google.golang.org/genproto/googleapis/rpc/status
# google.golang.org/grpc v1.38.0 # google.golang.org/grpc v1.38.0 => google.golang.org/grpc v1.35.0
## explicit ## explicit
google.golang.org/grpc google.golang.org/grpc
google.golang.org/grpc/attributes google.golang.org/grpc/attributes
@ -920,7 +920,7 @@ sigs.k8s.io/yaml
# github.com/golang/protobuf => github.com/golang/protobuf v1.4.3 # github.com/golang/protobuf => github.com/golang/protobuf v1.4.3
# github.com/hashicorp/vault/api => github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a # github.com/hashicorp/vault/api => github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a
# github.com/hashicorp/vault/sdk => github.com/hashicorp/vault/sdk v0.1.14-0.20201116234512-b4d4137dfe8b # github.com/hashicorp/vault/sdk => github.com/hashicorp/vault/sdk v0.1.14-0.20201116234512-b4d4137dfe8b
# github.com/kubernetes-csi/external-snapshotter/v2 => github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1-0.20200504125226-859696c419ff # google.golang.org/grpc => google.golang.org/grpc v1.35.0
# k8s.io/api => k8s.io/api v0.20.6 # k8s.io/api => k8s.io/api v0.20.6
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.6 # k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.6
# k8s.io/apimachinery => k8s.io/apimachinery v0.20.6 # k8s.io/apimachinery => k8s.io/apimachinery v0.20.6