Merge pull request #273 from red-hat-storage/sync_us--devel

Syncing latest changes from upstream devel for ceph-csi
This commit is contained in:
openshift-merge-bot[bot] 2024-03-18 13:48:07 +00:00 committed by GitHub
commit de17a0de72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
340 changed files with 38772 additions and 1186 deletions

View File

@ -4,4 +4,6 @@
## Features ## Features
- kms: added Azure Key Vault as a supported KMS in [PR](https://github.com/ceph/ceph-csi/pull/4455)
## NOTE ## NOTE

View File

@ -12,5 +12,5 @@ require (
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/net v0.22.0 // indirect golang.org/x/net v0.22.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.33.0 // indirect
) )

View File

@ -24,5 +24,5 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=

View File

@ -21,7 +21,7 @@ import (
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
// Unmarshal reads the given []byte into the given proto.Message. // Unmarshal reads the given []byte into the given [proto.Message].
// The provided message must be mutable (e.g., a non-nil pointer to a message). // The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error { func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m) return UnmarshalOptions{}.Unmarshal(b, m)
@ -51,7 +51,7 @@ type UnmarshalOptions struct {
} }
} }
// Unmarshal reads the given []byte and populates the given proto.Message // Unmarshal reads the given []byte and populates the given [proto.Message]
// using options in the UnmarshalOptions object. // using options in the UnmarshalOptions object.
// The provided message must be mutable (e.g., a non-nil pointer to a message). // The provided message must be mutable (e.g., a non-nil pointer to a message).
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
@ -739,7 +739,9 @@ func (d decoder) skipValue() error {
case text.ListClose: case text.ListClose:
return nil return nil
case text.MessageOpen: case text.MessageOpen:
return d.skipMessageValue() if err := d.skipMessageValue(); err != nil {
return err
}
default: default:
// Skip items. This will not validate whether skipped values are // Skip items. This will not validate whether skipped values are
// of the same type or not, same behavior as C++ // of the same type or not, same behavior as C++

View File

@ -33,7 +33,7 @@ func Format(m proto.Message) string {
return MarshalOptions{Multiline: true}.Format(m) return MarshalOptions{Multiline: true}.Format(m)
} }
// Marshal writes the given proto.Message in textproto format using default // Marshal writes the given [proto.Message] in textproto format using default
// options. Do not depend on the output being stable. It may change over time // options. Do not depend on the output being stable. It may change over time
// across different versions of the program. // across different versions of the program.
func Marshal(m proto.Message) ([]byte, error) { func Marshal(m proto.Message) ([]byte, error) {
@ -97,7 +97,7 @@ func (o MarshalOptions) Format(m proto.Message) string {
return string(b) return string(b)
} }
// Marshal writes the given proto.Message in textproto format using options in // Marshal writes the given [proto.Message] in textproto format using options in
// MarshalOptions object. Do not depend on the output being stable. It may // MarshalOptions object. Do not depend on the output being stable. It may
// change over time across different versions of the program. // change over time across different versions of the program.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {

View File

@ -6,7 +6,7 @@
// See https://protobuf.dev/programming-guides/encoding. // See https://protobuf.dev/programming-guides/encoding.
// //
// For marshaling and unmarshaling entire protobuf messages, // For marshaling and unmarshaling entire protobuf messages,
// use the "google.golang.org/protobuf/proto" package instead. // use the [google.golang.org/protobuf/proto] package instead.
package protowire package protowire
import ( import (
@ -87,7 +87,7 @@ func ParseError(n int) error {
// ConsumeField parses an entire field record (both tag and value) and returns // ConsumeField parses an entire field record (both tag and value) and returns
// the field number, the wire type, and the total length. // the field number, the wire type, and the total length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
// //
// The total length includes the tag header and the end group marker (if the // The total length includes the tag header and the end group marker (if the
// field is a group). // field is a group).
@ -104,8 +104,8 @@ func ConsumeField(b []byte) (Number, Type, int) {
} }
// ConsumeFieldValue parses a field value and returns its length. // ConsumeFieldValue parses a field value and returns its length.
// This assumes that the field Number and wire Type have already been parsed. // This assumes that the field [Number] and wire [Type] have already been parsed.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
// //
// When parsing a group, the length includes the end group marker and // When parsing a group, the length includes the end group marker and
// the end group is verified to match the starting field number. // the end group is verified to match the starting field number.
@ -164,7 +164,7 @@ func AppendTag(b []byte, num Number, typ Type) []byte {
} }
// ConsumeTag parses b as a varint-encoded tag, reporting its length. // ConsumeTag parses b as a varint-encoded tag, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeTag(b []byte) (Number, Type, int) { func ConsumeTag(b []byte) (Number, Type, int) {
v, n := ConsumeVarint(b) v, n := ConsumeVarint(b)
if n < 0 { if n < 0 {
@ -263,7 +263,7 @@ func AppendVarint(b []byte, v uint64) []byte {
} }
// ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeVarint(b []byte) (v uint64, n int) { func ConsumeVarint(b []byte) (v uint64, n int) {
var y uint64 var y uint64
if len(b) <= 0 { if len(b) <= 0 {
@ -384,7 +384,7 @@ func AppendFixed32(b []byte, v uint32) []byte {
} }
// ConsumeFixed32 parses b as a little-endian uint32, reporting its length. // ConsumeFixed32 parses b as a little-endian uint32, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed32(b []byte) (v uint32, n int) { func ConsumeFixed32(b []byte) (v uint32, n int) {
if len(b) < 4 { if len(b) < 4 {
return 0, errCodeTruncated return 0, errCodeTruncated
@ -412,7 +412,7 @@ func AppendFixed64(b []byte, v uint64) []byte {
} }
// ConsumeFixed64 parses b as a little-endian uint64, reporting its length. // ConsumeFixed64 parses b as a little-endian uint64, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed64(b []byte) (v uint64, n int) { func ConsumeFixed64(b []byte) (v uint64, n int) {
if len(b) < 8 { if len(b) < 8 {
return 0, errCodeTruncated return 0, errCodeTruncated
@ -432,7 +432,7 @@ func AppendBytes(b []byte, v []byte) []byte {
} }
// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeBytes(b []byte) (v []byte, n int) { func ConsumeBytes(b []byte) (v []byte, n int) {
m, n := ConsumeVarint(b) m, n := ConsumeVarint(b)
if n < 0 { if n < 0 {
@ -456,7 +456,7 @@ func AppendString(b []byte, v string) []byte {
} }
// ConsumeString parses b as a length-prefixed bytes value, reporting its length. // ConsumeString parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeString(b []byte) (v string, n int) { func ConsumeString(b []byte) (v string, n int) {
bb, n := ConsumeBytes(b) bb, n := ConsumeBytes(b)
return string(bb), n return string(bb), n
@ -471,7 +471,7 @@ func AppendGroup(b []byte, num Number, v []byte) []byte {
// ConsumeGroup parses b as a group value until the trailing end group marker, // ConsumeGroup parses b as a group value until the trailing end group marker,
// and verifies that the end marker matches the provided num. The value v // and verifies that the end marker matches the provided num. The value v
// does not contain the end marker, while the length does contain the end marker. // does not contain the end marker, while the length does contain the end marker.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeGroup(num Number, b []byte) (v []byte, n int) { func ConsumeGroup(num Number, b []byte) (v []byte, n int) {
n = ConsumeFieldValue(num, StartGroupType, b) n = ConsumeFieldValue(num, StartGroupType, b)
if n < 0 { if n < 0 {
@ -495,8 +495,8 @@ func SizeGroup(num Number, n int) int {
return n + SizeTag(num) return n + SizeTag(num)
} }
// DecodeTag decodes the field Number and wire Type from its unified form. // DecodeTag decodes the field [Number] and wire [Type] from its unified form.
// The Number is -1 if the decoded field number overflows int32. // The [Number] is -1 if the decoded field number overflows int32.
// Other than overflow, this does not check for field number validity. // Other than overflow, this does not check for field number validity.
func DecodeTag(x uint64) (Number, Type) { func DecodeTag(x uint64) (Number, Type) {
// NOTE: MessageSet allows for larger field numbers than normal. // NOTE: MessageSet allows for larger field numbers than normal.
@ -506,7 +506,7 @@ func DecodeTag(x uint64) (Number, Type) {
return Number(x >> 3), Type(x & 7) return Number(x >> 3), Type(x & 7)
} }
// EncodeTag encodes the field Number and wire Type into its unified form. // EncodeTag encodes the field [Number] and wire [Type] into its unified form.
func EncodeTag(num Number, typ Type) uint64 { func EncodeTag(num Number, typ Type) uint64 {
return uint64(num)<<3 | uint64(typ&7) return uint64(num)<<3 | uint64(typ&7)
} }

View File

@ -83,7 +83,13 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
case protoreflect.FileImports: case protoreflect.FileImports:
for i := 0; i < vs.Len(); i++ { for i := 0; i < vs.Len(); i++ {
var rs records var rs records
rs.Append(reflect.ValueOf(vs.Get(i)), "Path", "Package", "IsPublic", "IsWeak") rv := reflect.ValueOf(vs.Get(i))
rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("IsPublic"), "IsPublic"},
{rv.MethodByName("IsWeak"), "IsWeak"},
}...)
ss = append(ss, "{"+rs.Join()+"}") ss = append(ss, "{"+rs.Join()+"}")
} }
return start + joinStrings(ss, allowMulti) + end return start + joinStrings(ss, allowMulti) + end
@ -92,34 +98,26 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
for i := 0; i < vs.Len(); i++ { for i := 0; i < vs.Len(); i++ {
m := reflect.ValueOf(vs).MethodByName("Get") m := reflect.ValueOf(vs).MethodByName("Get")
v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface() v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface()
ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue)) ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue, nil))
} }
return start + joinStrings(ss, allowMulti && isEnumValue) + end return start + joinStrings(ss, allowMulti && isEnumValue) + end
} }
} }
// descriptorAccessors is a list of accessors to print for each descriptor. type methodAndName struct {
// method reflect.Value
// Do not print all accessors since some contain redundant information, name string
// while others are pointers that we do not want to follow since the descriptor
// is actually a cyclic graph.
//
// Using a list allows us to print the accessors in a sensible order.
var descriptorAccessors = map[reflect.Type][]string{
reflect.TypeOf((*protoreflect.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
reflect.TypeOf((*protoreflect.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
reflect.TypeOf((*protoreflect.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
reflect.TypeOf((*protoreflect.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt
reflect.TypeOf((*protoreflect.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"},
reflect.TypeOf((*protoreflect.EnumValueDescriptor)(nil)).Elem(): {"Number"},
reflect.TypeOf((*protoreflect.ServiceDescriptor)(nil)).Elem(): {"Methods"},
reflect.TypeOf((*protoreflect.MethodDescriptor)(nil)).Elem(): {"Input", "Output", "IsStreamingClient", "IsStreamingServer"},
} }
func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) { func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) {
io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')), nil))
} }
func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
func InternalFormatDescOptForTesting(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
return formatDescOpt(t, isRoot, allowMulti, record)
}
func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
rv := reflect.ValueOf(t) rv := reflect.ValueOf(t)
rt := rv.MethodByName("ProtoType").Type().In(0) rt := rv.MethodByName("ProtoType").Type().In(0)
@ -129,26 +127,60 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
} }
_, isFile := t.(protoreflect.FileDescriptor) _, isFile := t.(protoreflect.FileDescriptor)
rs := records{allowMulti: allowMulti} rs := records{
allowMulti: allowMulti,
record: record,
}
if t.IsPlaceholder() { if t.IsPlaceholder() {
if isFile { if isFile {
rs.Append(rv, "Path", "Package", "IsPlaceholder") rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
}...)
} else { } else {
rs.Append(rv, "FullName", "IsPlaceholder") rs.Append(rv, []methodAndName{
{rv.MethodByName("FullName"), "FullName"},
{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
}...)
} }
} else { } else {
switch { switch {
case isFile: case isFile:
rs.Append(rv, "Syntax") rs.Append(rv, methodAndName{rv.MethodByName("Syntax"), "Syntax"})
case isRoot: case isRoot:
rs.Append(rv, "Syntax", "FullName") rs.Append(rv, []methodAndName{
{rv.MethodByName("Syntax"), "Syntax"},
{rv.MethodByName("FullName"), "FullName"},
}...)
default: default:
rs.Append(rv, "Name") rs.Append(rv, methodAndName{rv.MethodByName("Name"), "Name"})
} }
switch t := t.(type) { switch t := t.(type) {
case protoreflect.FieldDescriptor: case protoreflect.FieldDescriptor:
for _, s := range descriptorAccessors[rt] { accessors := []methodAndName{
switch s { {rv.MethodByName("Number"), "Number"},
{rv.MethodByName("Cardinality"), "Cardinality"},
{rv.MethodByName("Kind"), "Kind"},
{rv.MethodByName("HasJSONName"), "HasJSONName"},
{rv.MethodByName("JSONName"), "JSONName"},
{rv.MethodByName("HasPresence"), "HasPresence"},
{rv.MethodByName("IsExtension"), "IsExtension"},
{rv.MethodByName("IsPacked"), "IsPacked"},
{rv.MethodByName("IsWeak"), "IsWeak"},
{rv.MethodByName("IsList"), "IsList"},
{rv.MethodByName("IsMap"), "IsMap"},
{rv.MethodByName("MapKey"), "MapKey"},
{rv.MethodByName("MapValue"), "MapValue"},
{rv.MethodByName("HasDefault"), "HasDefault"},
{rv.MethodByName("Default"), "Default"},
{rv.MethodByName("ContainingOneof"), "ContainingOneof"},
{rv.MethodByName("ContainingMessage"), "ContainingMessage"},
{rv.MethodByName("Message"), "Message"},
{rv.MethodByName("Enum"), "Enum"},
}
for _, s := range accessors {
switch s.name {
case "MapKey": case "MapKey":
if k := t.MapKey(); k != nil { if k := t.MapKey(); k != nil {
rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()}) rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()})
@ -157,20 +189,20 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
if v := t.MapValue(); v != nil { if v := t.MapValue(); v != nil {
switch v.Kind() { switch v.Kind() {
case protoreflect.EnumKind: case protoreflect.EnumKind:
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())}) rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Enum().FullName())})
case protoreflect.MessageKind, protoreflect.GroupKind: case protoreflect.MessageKind, protoreflect.GroupKind:
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())}) rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Message().FullName())})
default: default:
rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()}) rs.AppendRecs("MapValue", [2]string{"MapValue", v.Kind().String()})
} }
} }
case "ContainingOneof": case "ContainingOneof":
if od := t.ContainingOneof(); od != nil { if od := t.ContainingOneof(); od != nil {
rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())}) rs.AppendRecs("ContainingOneof", [2]string{"Oneof", string(od.Name())})
} }
case "ContainingMessage": case "ContainingMessage":
if t.IsExtension() { if t.IsExtension() {
rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())}) rs.AppendRecs("ContainingMessage", [2]string{"Extendee", string(t.ContainingMessage().FullName())})
} }
case "Message": case "Message":
if !t.IsMap() { if !t.IsMap() {
@ -187,13 +219,61 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
ss = append(ss, string(fs.Get(i).Name())) ss = append(ss, string(fs.Get(i).Name()))
} }
if len(ss) > 0 { if len(ss) > 0 {
rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"}) rs.AppendRecs("Fields", [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
} }
default:
rs.Append(rv, descriptorAccessors[rt]...) case protoreflect.FileDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("Imports"), "Imports"},
{rv.MethodByName("Messages"), "Messages"},
{rv.MethodByName("Enums"), "Enums"},
{rv.MethodByName("Extensions"), "Extensions"},
{rv.MethodByName("Services"), "Services"},
}...)
case protoreflect.MessageDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("IsMapEntry"), "IsMapEntry"},
{rv.MethodByName("Fields"), "Fields"},
{rv.MethodByName("Oneofs"), "Oneofs"},
{rv.MethodByName("ReservedNames"), "ReservedNames"},
{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
{rv.MethodByName("RequiredNumbers"), "RequiredNumbers"},
{rv.MethodByName("ExtensionRanges"), "ExtensionRanges"},
{rv.MethodByName("Messages"), "Messages"},
{rv.MethodByName("Enums"), "Enums"},
{rv.MethodByName("Extensions"), "Extensions"},
}...)
case protoreflect.EnumDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Values"), "Values"},
{rv.MethodByName("ReservedNames"), "ReservedNames"},
{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
}...)
case protoreflect.EnumValueDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Number"), "Number"},
}...)
case protoreflect.ServiceDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Methods"), "Methods"},
}...)
case protoreflect.MethodDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Input"), "Input"},
{rv.MethodByName("Output"), "Output"},
{rv.MethodByName("IsStreamingClient"), "IsStreamingClient"},
{rv.MethodByName("IsStreamingServer"), "IsStreamingServer"},
}...)
} }
if rv.MethodByName("GoType").IsValid() { if m := rv.MethodByName("GoType"); m.IsValid() {
rs.Append(rv, "GoType") rs.Append(rv, methodAndName{m, "GoType"})
} }
} }
return start + rs.Join() + end return start + rs.Join() + end
@ -202,19 +282,34 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
type records struct { type records struct {
recs [][2]string recs [][2]string
allowMulti bool allowMulti bool
// record is a function that will be called for every Append() or
// AppendRecs() call, to be used for testing with the
// InternalFormatDescOptForTesting function.
record func(string)
} }
func (rs *records) Append(v reflect.Value, accessors ...string) { func (rs *records) AppendRecs(fieldName string, newRecs [2]string) {
if rs.record != nil {
rs.record(fieldName)
}
rs.recs = append(rs.recs, newRecs)
}
func (rs *records) Append(v reflect.Value, accessors ...methodAndName) {
for _, a := range accessors { for _, a := range accessors {
if rs.record != nil {
rs.record(a.name)
}
var rv reflect.Value var rv reflect.Value
if m := v.MethodByName(a); m.IsValid() { if a.method.IsValid() {
rv = m.Call(nil)[0] rv = a.method.Call(nil)[0]
} }
if v.Kind() == reflect.Struct && !rv.IsValid() { if v.Kind() == reflect.Struct && !rv.IsValid() {
rv = v.FieldByName(a) rv = v.FieldByName(a.name)
} }
if !rv.IsValid() { if !rv.IsValid() {
panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a)) panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a.name))
} }
if _, ok := rv.Interface().(protoreflect.Value); ok { if _, ok := rv.Interface().(protoreflect.Value); ok {
rv = rv.MethodByName("Interface").Call(nil)[0] rv = rv.MethodByName("Interface").Call(nil)[0]
@ -261,7 +356,7 @@ func (rs *records) Append(v reflect.Value, accessors ...string) {
default: default:
s = fmt.Sprint(v) s = fmt.Sprint(v)
} }
rs.recs = append(rs.recs, [2]string{a, s}) rs.recs = append(rs.recs, [2]string{a.name, s})
} }
} }

View File

@ -0,0 +1,12 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package editiondefaults contains the binary representation of the editions
// defaults.
package editiondefaults
import _ "embed"
//go:embed editions_defaults.binpb
var Defaults []byte

View File

@ -0,0 +1,4 @@
  (0ж
  (0з
  (0и ж

View File

@ -21,11 +21,26 @@ import (
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
// Edition is an Enum for proto2.Edition
type Edition int32
// These values align with the value of Enum in descriptor.proto which allows
// direct conversion between the proto enum and this enum.
const (
EditionUnknown Edition = 0
EditionProto2 Edition = 998
EditionProto3 Edition = 999
Edition2023 Edition = 1000
EditionUnsupported Edition = 100000
)
// The types in this file may have a suffix: // The types in this file may have a suffix:
// • L0: Contains fields common to all descriptors (except File) and // • L0: Contains fields common to all descriptors (except File) and
// must be initialized up front. // must be initialized up front.
// • L1: Contains fields specific to a descriptor and // • L1: Contains fields specific to a descriptor and
// must be initialized up front. // must be initialized up front. If the associated proto uses Editions, the
// Editions features must always be resolved. If not explicitly set, the
// appropriate default must be resolved and set.
// • L2: Contains fields that are lazily initialized when constructing // • L2: Contains fields that are lazily initialized when constructing
// from the raw file descriptor. When constructing as a literal, the L2 // from the raw file descriptor. When constructing as a literal, the L2
// fields must be initialized up front. // fields must be initialized up front.
@ -44,6 +59,7 @@ type (
} }
FileL1 struct { FileL1 struct {
Syntax protoreflect.Syntax Syntax protoreflect.Syntax
Edition Edition // Only used if Syntax == Editions
Path string Path string
Package protoreflect.FullName Package protoreflect.FullName
@ -51,12 +67,41 @@ type (
Messages Messages Messages Messages
Extensions Extensions Extensions Extensions
Services Services Services Services
EditionFeatures EditionFeatures
} }
FileL2 struct { FileL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
Imports FileImports Imports FileImports
Locations SourceLocations Locations SourceLocations
} }
EditionFeatures struct {
// IsFieldPresence is true if field_presence is EXPLICIT
// https://protobuf.dev/editions/features/#field_presence
IsFieldPresence bool
// IsFieldPresence is true if field_presence is LEGACY_REQUIRED
// https://protobuf.dev/editions/features/#field_presence
IsLegacyRequired bool
// IsOpenEnum is true if enum_type is OPEN
// https://protobuf.dev/editions/features/#enum_type
IsOpenEnum bool
// IsPacked is true if repeated_field_encoding is PACKED
// https://protobuf.dev/editions/features/#repeated_field_encoding
IsPacked bool
// IsUTF8Validated is true if utf_validation is VERIFY
// https://protobuf.dev/editions/features/#utf8_validation
IsUTF8Validated bool
// IsDelimitedEncoded is true if message_encoding is DELIMITED
// https://protobuf.dev/editions/features/#message_encoding
IsDelimitedEncoded bool
// IsJSONCompliant is true if json_format is ALLOW
// https://protobuf.dev/editions/features/#json_format
IsJSONCompliant bool
// GenerateLegacyUnmarshalJSON determines if the plugin generates the
// UnmarshalJSON([]byte) error method for enums.
GenerateLegacyUnmarshalJSON bool
}
) )
func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd } func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
@ -117,6 +162,8 @@ type (
} }
EnumL1 struct { EnumL1 struct {
eagerValues bool // controls whether EnumL2.Values is already populated eagerValues bool // controls whether EnumL2.Values is already populated
EditionFeatures EditionFeatures
} }
EnumL2 struct { EnumL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
@ -178,6 +225,8 @@ type (
Extensions Extensions Extensions Extensions
IsMapEntry bool // promoted from google.protobuf.MessageOptions IsMapEntry bool // promoted from google.protobuf.MessageOptions
IsMessageSet bool // promoted from google.protobuf.MessageOptions IsMessageSet bool // promoted from google.protobuf.MessageOptions
EditionFeatures EditionFeatures
} }
MessageL2 struct { MessageL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
@ -210,6 +259,8 @@ type (
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
Enum protoreflect.EnumDescriptor Enum protoreflect.EnumDescriptor
Message protoreflect.MessageDescriptor Message protoreflect.MessageDescriptor
EditionFeatures EditionFeatures
} }
Oneof struct { Oneof struct {
@ -219,6 +270,8 @@ type (
OneofL1 struct { OneofL1 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
Fields OneofFields // must be consistent with Message.Fields.ContainingOneof Fields OneofFields // must be consistent with Message.Fields.ContainingOneof
EditionFeatures EditionFeatures
} }
) )
@ -268,23 +321,36 @@ func (fd *Field) Options() protoreflect.ProtoMessage {
} }
func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number } func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number }
func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality } func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
func (fd *Field) Kind() protoreflect.Kind { return fd.L1.Kind } func (fd *Field) Kind() protoreflect.Kind {
return fd.L1.Kind
}
func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON } func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) } func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) }
func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) } func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) }
func (fd *Field) HasPresence() bool { func (fd *Field) HasPresence() bool {
return fd.L1.Cardinality != protoreflect.Repeated && (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil) if fd.L1.Cardinality == protoreflect.Repeated {
return false
}
explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence
return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
} }
func (fd *Field) HasOptionalKeyword() bool { func (fd *Field) HasOptionalKeyword() bool {
return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
} }
func (fd *Field) IsPacked() bool { func (fd *Field) IsPacked() bool {
if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Repeated { if fd.L1.Cardinality != protoreflect.Repeated {
return false
}
switch fd.L1.Kind { switch fd.L1.Kind {
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
default: return false
return true
} }
if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
return fd.L1.EditionFeatures.IsPacked
}
if fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3 {
// proto3 repeated fields are packed by default.
return !fd.L1.HasPacked || fd.L1.IsPacked
} }
return fd.L1.IsPacked return fd.L1.IsPacked
} }
@ -333,6 +399,9 @@ func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
// WARNING: This method is exempt from the compatibility promise and may be // WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning. // removed in the future without warning.
func (fd *Field) EnforceUTF8() bool { func (fd *Field) EnforceUTF8() bool {
if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
return fd.L1.EditionFeatures.IsUTF8Validated
}
if fd.L1.HasEnforceUTF8 { if fd.L1.HasEnforceUTF8 {
return fd.L1.EnforceUTF8 return fd.L1.EnforceUTF8
} }
@ -363,6 +432,7 @@ type (
Extendee protoreflect.MessageDescriptor Extendee protoreflect.MessageDescriptor
Cardinality protoreflect.Cardinality Cardinality protoreflect.Cardinality
Kind protoreflect.Kind Kind protoreflect.Kind
EditionFeatures EditionFeatures
} }
ExtensionL2 struct { ExtensionL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage

View File

@ -5,6 +5,7 @@
package filedesc package filedesc
import ( import (
"fmt"
"sync" "sync"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
@ -98,6 +99,7 @@ func (fd *File) unmarshalSeed(b []byte) {
var prevField protoreflect.FieldNumber var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions, numServices int var numEnums, numMessages, numExtensions, numServices int
var posEnums, posMessages, posExtensions, posServices int var posEnums, posMessages, posExtensions, posServices int
var options []byte
b0 := b b0 := b
for len(b) > 0 { for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b) num, typ, n := protowire.ConsumeTag(b)
@ -113,6 +115,8 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Syntax = protoreflect.Proto2 fd.L1.Syntax = protoreflect.Proto2
case "proto3": case "proto3":
fd.L1.Syntax = protoreflect.Proto3 fd.L1.Syntax = protoreflect.Proto3
case "editions":
fd.L1.Syntax = protoreflect.Editions
default: default:
panic("invalid syntax") panic("invalid syntax")
} }
@ -120,6 +124,8 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Path = sb.MakeString(v) fd.L1.Path = sb.MakeString(v)
case genid.FileDescriptorProto_Package_field_number: case genid.FileDescriptorProto_Package_field_number:
fd.L1.Package = protoreflect.FullName(sb.MakeString(v)) fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
case genid.FileDescriptorProto_Options_field_number:
options = v
case genid.FileDescriptorProto_EnumType_field_number: case genid.FileDescriptorProto_EnumType_field_number:
if prevField != genid.FileDescriptorProto_EnumType_field_number { if prevField != genid.FileDescriptorProto_EnumType_field_number {
if numEnums > 0 { if numEnums > 0 {
@ -154,6 +160,13 @@ func (fd *File) unmarshalSeed(b []byte) {
numServices++ numServices++
} }
prevField = num prevField = num
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FileDescriptorProto_Edition_field_number:
fd.L1.Edition = Edition(v)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]
@ -166,6 +179,15 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Syntax = protoreflect.Proto2 fd.L1.Syntax = protoreflect.Proto2
} }
if fd.L1.Syntax == protoreflect.Editions {
fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition)
}
// Parse editions features from options if any
if options != nil {
fd.unmarshalSeedOptions(options)
}
// Must allocate all declarations before parsing each descriptor type // Must allocate all declarations before parsing each descriptor type
// to ensure we handled all descriptors in "flattened ordering". // to ensure we handled all descriptors in "flattened ordering".
if numEnums > 0 { if numEnums > 0 {
@ -219,6 +241,28 @@ func (fd *File) unmarshalSeed(b []byte) {
} }
} }
func (fd *File) unmarshalSeedOptions(b []byte) {
for b := b; len(b) > 0; {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FileOptions_Features_field_number:
if fd.Syntax() != protoreflect.Editions {
panic(fmt.Sprintf("invalid descriptor: using edition features in a proto with syntax %s", fd.Syntax()))
}
fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
}
default:
m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:]
}
}
}
func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) { func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
ed.L0.ParentFile = pf ed.L0.ParentFile = pf
ed.L0.Parent = pd ed.L0.Parent = pd
@ -275,6 +319,7 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
md.L0.ParentFile = pf md.L0.ParentFile = pf
md.L0.Parent = pd md.L0.Parent = pd
md.L0.Index = i md.L0.Index = i
md.L1.EditionFeatures = featuresFromParentDesc(md.Parent())
var prevField protoreflect.FieldNumber var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions int var numEnums, numMessages, numExtensions int
@ -380,6 +425,13 @@ func (md *Message) unmarshalSeedOptions(b []byte) {
case genid.MessageOptions_MessageSetWireFormat_field_number: case genid.MessageOptions_MessageSetWireFormat_field_number:
md.L1.IsMessageSet = protowire.DecodeBool(v) md.L1.IsMessageSet = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.MessageOptions_Features_field_number:
md.L1.EditionFeatures = unmarshalFeatureSet(v, md.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]

View File

@ -414,6 +414,7 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
fd.L0.ParentFile = pf fd.L0.ParentFile = pf
fd.L0.Parent = pd fd.L0.Parent = pd
fd.L0.Index = i fd.L0.Index = i
fd.L1.EditionFeatures = featuresFromParentDesc(fd.Parent())
var rawTypeName []byte var rawTypeName []byte
var rawOptions []byte var rawOptions []byte
@ -465,6 +466,12 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
b = b[m:] b = b[m:]
} }
} }
if fd.Syntax() == protoreflect.Editions && fd.L1.Kind == protoreflect.MessageKind && fd.L1.EditionFeatures.IsDelimitedEncoded {
fd.L1.Kind = protoreflect.GroupKind
}
if fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsLegacyRequired {
fd.L1.Cardinality = protoreflect.Required
}
if rawTypeName != nil { if rawTypeName != nil {
name := makeFullName(sb, rawTypeName) name := makeFullName(sb, rawTypeName)
switch fd.L1.Kind { switch fd.L1.Kind {
@ -497,6 +504,13 @@ func (fd *Field) unmarshalOptions(b []byte) {
fd.L1.HasEnforceUTF8 = true fd.L1.HasEnforceUTF8 = true
fd.L1.EnforceUTF8 = protowire.DecodeBool(v) fd.L1.EnforceUTF8 = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FieldOptions_Features_field_number:
fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]
@ -534,6 +548,7 @@ func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
var rawTypeName []byte var rawTypeName []byte
var rawOptions []byte var rawOptions []byte
xd.L1.EditionFeatures = featuresFromParentDesc(xd.L1.Extendee)
xd.L2 = new(ExtensionL2) xd.L2 = new(ExtensionL2)
for len(b) > 0 { for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b) num, typ, n := protowire.ConsumeTag(b)
@ -565,6 +580,12 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
b = b[m:] b = b[m:]
} }
} }
if xd.Syntax() == protoreflect.Editions && xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded {
xd.L1.Kind = protoreflect.GroupKind
}
if xd.Syntax() == protoreflect.Editions && xd.L1.EditionFeatures.IsLegacyRequired {
xd.L1.Cardinality = protoreflect.Required
}
if rawTypeName != nil { if rawTypeName != nil {
name := makeFullName(sb, rawTypeName) name := makeFullName(sb, rawTypeName)
switch xd.L1.Kind { switch xd.L1.Kind {
@ -589,6 +610,13 @@ func (xd *Extension) unmarshalOptions(b []byte) {
case genid.FieldOptions_Packed_field_number: case genid.FieldOptions_Packed_field_number:
xd.L2.IsPacked = protowire.DecodeBool(v) xd.L2.IsPacked = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FieldOptions_Features_field_number:
xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]

View File

@ -0,0 +1,142 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package filedesc
import (
"fmt"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/editiondefaults"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect"
)
var defaultsCache = make(map[Edition]EditionFeatures)
func init() {
unmarshalEditionDefaults(editiondefaults.Defaults)
}
func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
for len(b) > 0 {
num, _, n := protowire.ConsumeTag(b)
b = b[n:]
switch num {
case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
}
}
return parent
}
func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FeatureSet_FieldPresence_field_number:
parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
case genid.FeatureSet_EnumType_field_number:
parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
case genid.FeatureSet_RepeatedFieldEncoding_field_number:
parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
case genid.FeatureSet_Utf8Validation_field_number:
parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
case genid.FeatureSet_MessageEncoding_field_number:
parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
case genid.FeatureSet_JsonFormat_field_number:
parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
parent = unmarshalGoFeature(v, parent)
}
}
}
return parent
}
func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
var parentFS EditionFeatures
switch p := parentDesc.(type) {
case *File:
parentFS = p.L1.EditionFeatures
case *Message:
parentFS = p.L1.EditionFeatures
default:
panic(fmt.Sprintf("unknown parent type %T", parentDesc))
}
return parentFS
}
func unmarshalEditionDefault(b []byte) {
var ed Edition
var fs EditionFeatures
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
ed = Edition(v)
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number:
fs = unmarshalFeatureSet(v, fs)
}
}
}
defaultsCache[ed] = fs
}
func unmarshalEditionDefaults(b []byte) {
for len(b) > 0 {
num, _, n := protowire.ConsumeTag(b)
b = b[n:]
switch num {
case genid.FeatureSetDefaults_Defaults_field_number:
def, m := protowire.ConsumeBytes(b)
b = b[m:]
unmarshalEditionDefault(def)
case genid.FeatureSetDefaults_MinimumEdition_field_number,
genid.FeatureSetDefaults_MaximumEdition_field_number:
// We don't care about the minimum and maximum editions. If the
// edition we are looking for later on is not in the cache we know
// it is outside of the range between minimum and maximum edition.
_, m := protowire.ConsumeVarint(b)
b = b[m:]
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
}
}
}
func getFeaturesFor(ed Edition) EditionFeatures {
if def, ok := defaultsCache[ed]; ok {
return def
}
panic(fmt.Sprintf("unsupported edition: %v", ed))
}

View File

@ -12,6 +12,27 @@ import (
const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto" const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto"
// Full and short names for google.protobuf.Edition.
const (
Edition_enum_fullname = "google.protobuf.Edition"
Edition_enum_name = "Edition"
)
// Enum values for google.protobuf.Edition.
const (
Edition_EDITION_UNKNOWN_enum_value = 0
Edition_EDITION_PROTO2_enum_value = 998
Edition_EDITION_PROTO3_enum_value = 999
Edition_EDITION_2023_enum_value = 1000
Edition_EDITION_2024_enum_value = 1001
Edition_EDITION_1_TEST_ONLY_enum_value = 1
Edition_EDITION_2_TEST_ONLY_enum_value = 2
Edition_EDITION_99997_TEST_ONLY_enum_value = 99997
Edition_EDITION_99998_TEST_ONLY_enum_value = 99998
Edition_EDITION_99999_TEST_ONLY_enum_value = 99999
Edition_EDITION_MAX_enum_value = 2147483647
)
// Names for google.protobuf.FileDescriptorSet. // Names for google.protobuf.FileDescriptorSet.
const ( const (
FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet" FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet"
@ -81,7 +102,7 @@ const (
FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8
FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9 FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9
FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12 FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12
FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 13 FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 14
) )
// Names for google.protobuf.DescriptorProto. // Names for google.protobuf.DescriptorProto.
@ -184,10 +205,12 @@ const (
const ( const (
ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ExtensionRangeOptions_Declaration_field_name protoreflect.Name = "declaration" ExtensionRangeOptions_Declaration_field_name protoreflect.Name = "declaration"
ExtensionRangeOptions_Features_field_name protoreflect.Name = "features"
ExtensionRangeOptions_Verification_field_name protoreflect.Name = "verification" ExtensionRangeOptions_Verification_field_name protoreflect.Name = "verification"
ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option"
ExtensionRangeOptions_Declaration_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.declaration" ExtensionRangeOptions_Declaration_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.declaration"
ExtensionRangeOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.features"
ExtensionRangeOptions_Verification_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.verification" ExtensionRangeOptions_Verification_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.verification"
) )
@ -195,6 +218,7 @@ const (
const ( const (
ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
ExtensionRangeOptions_Declaration_field_number protoreflect.FieldNumber = 2 ExtensionRangeOptions_Declaration_field_number protoreflect.FieldNumber = 2
ExtensionRangeOptions_Features_field_number protoreflect.FieldNumber = 50
ExtensionRangeOptions_Verification_field_number protoreflect.FieldNumber = 3 ExtensionRangeOptions_Verification_field_number protoreflect.FieldNumber = 3
) )
@ -204,6 +228,12 @@ const (
ExtensionRangeOptions_VerificationState_enum_name = "VerificationState" ExtensionRangeOptions_VerificationState_enum_name = "VerificationState"
) )
// Enum values for google.protobuf.ExtensionRangeOptions.VerificationState.
const (
ExtensionRangeOptions_DECLARATION_enum_value = 0
ExtensionRangeOptions_UNVERIFIED_enum_value = 1
)
// Names for google.protobuf.ExtensionRangeOptions.Declaration. // Names for google.protobuf.ExtensionRangeOptions.Declaration.
const ( const (
ExtensionRangeOptions_Declaration_message_name protoreflect.Name = "Declaration" ExtensionRangeOptions_Declaration_message_name protoreflect.Name = "Declaration"
@ -215,14 +245,12 @@ const (
ExtensionRangeOptions_Declaration_Number_field_name protoreflect.Name = "number" ExtensionRangeOptions_Declaration_Number_field_name protoreflect.Name = "number"
ExtensionRangeOptions_Declaration_FullName_field_name protoreflect.Name = "full_name" ExtensionRangeOptions_Declaration_FullName_field_name protoreflect.Name = "full_name"
ExtensionRangeOptions_Declaration_Type_field_name protoreflect.Name = "type" ExtensionRangeOptions_Declaration_Type_field_name protoreflect.Name = "type"
ExtensionRangeOptions_Declaration_IsRepeated_field_name protoreflect.Name = "is_repeated"
ExtensionRangeOptions_Declaration_Reserved_field_name protoreflect.Name = "reserved" ExtensionRangeOptions_Declaration_Reserved_field_name protoreflect.Name = "reserved"
ExtensionRangeOptions_Declaration_Repeated_field_name protoreflect.Name = "repeated" ExtensionRangeOptions_Declaration_Repeated_field_name protoreflect.Name = "repeated"
ExtensionRangeOptions_Declaration_Number_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.number" ExtensionRangeOptions_Declaration_Number_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.number"
ExtensionRangeOptions_Declaration_FullName_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.full_name" ExtensionRangeOptions_Declaration_FullName_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.full_name"
ExtensionRangeOptions_Declaration_Type_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.type" ExtensionRangeOptions_Declaration_Type_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.type"
ExtensionRangeOptions_Declaration_IsRepeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.is_repeated"
ExtensionRangeOptions_Declaration_Reserved_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.reserved" ExtensionRangeOptions_Declaration_Reserved_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.reserved"
ExtensionRangeOptions_Declaration_Repeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.repeated" ExtensionRangeOptions_Declaration_Repeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.repeated"
) )
@ -232,7 +260,6 @@ const (
ExtensionRangeOptions_Declaration_Number_field_number protoreflect.FieldNumber = 1 ExtensionRangeOptions_Declaration_Number_field_number protoreflect.FieldNumber = 1
ExtensionRangeOptions_Declaration_FullName_field_number protoreflect.FieldNumber = 2 ExtensionRangeOptions_Declaration_FullName_field_number protoreflect.FieldNumber = 2
ExtensionRangeOptions_Declaration_Type_field_number protoreflect.FieldNumber = 3 ExtensionRangeOptions_Declaration_Type_field_number protoreflect.FieldNumber = 3
ExtensionRangeOptions_Declaration_IsRepeated_field_number protoreflect.FieldNumber = 4
ExtensionRangeOptions_Declaration_Reserved_field_number protoreflect.FieldNumber = 5 ExtensionRangeOptions_Declaration_Reserved_field_number protoreflect.FieldNumber = 5
ExtensionRangeOptions_Declaration_Repeated_field_number protoreflect.FieldNumber = 6 ExtensionRangeOptions_Declaration_Repeated_field_number protoreflect.FieldNumber = 6
) )
@ -291,12 +318,41 @@ const (
FieldDescriptorProto_Type_enum_name = "Type" FieldDescriptorProto_Type_enum_name = "Type"
) )
// Enum values for google.protobuf.FieldDescriptorProto.Type.
const (
FieldDescriptorProto_TYPE_DOUBLE_enum_value = 1
FieldDescriptorProto_TYPE_FLOAT_enum_value = 2
FieldDescriptorProto_TYPE_INT64_enum_value = 3
FieldDescriptorProto_TYPE_UINT64_enum_value = 4
FieldDescriptorProto_TYPE_INT32_enum_value = 5
FieldDescriptorProto_TYPE_FIXED64_enum_value = 6
FieldDescriptorProto_TYPE_FIXED32_enum_value = 7
FieldDescriptorProto_TYPE_BOOL_enum_value = 8
FieldDescriptorProto_TYPE_STRING_enum_value = 9
FieldDescriptorProto_TYPE_GROUP_enum_value = 10
FieldDescriptorProto_TYPE_MESSAGE_enum_value = 11
FieldDescriptorProto_TYPE_BYTES_enum_value = 12
FieldDescriptorProto_TYPE_UINT32_enum_value = 13
FieldDescriptorProto_TYPE_ENUM_enum_value = 14
FieldDescriptorProto_TYPE_SFIXED32_enum_value = 15
FieldDescriptorProto_TYPE_SFIXED64_enum_value = 16
FieldDescriptorProto_TYPE_SINT32_enum_value = 17
FieldDescriptorProto_TYPE_SINT64_enum_value = 18
)
// Full and short names for google.protobuf.FieldDescriptorProto.Label. // Full and short names for google.protobuf.FieldDescriptorProto.Label.
const ( const (
FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label" FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label"
FieldDescriptorProto_Label_enum_name = "Label" FieldDescriptorProto_Label_enum_name = "Label"
) )
// Enum values for google.protobuf.FieldDescriptorProto.Label.
const (
FieldDescriptorProto_LABEL_OPTIONAL_enum_value = 1
FieldDescriptorProto_LABEL_REPEATED_enum_value = 3
FieldDescriptorProto_LABEL_REQUIRED_enum_value = 2
)
// Names for google.protobuf.OneofDescriptorProto. // Names for google.protobuf.OneofDescriptorProto.
const ( const (
OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto" OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto"
@ -468,7 +524,6 @@ const (
FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services" FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services"
FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services" FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services"
FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services" FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services"
FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services"
FileOptions_Deprecated_field_name protoreflect.Name = "deprecated" FileOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas" FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix" FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix"
@ -478,6 +533,7 @@ const (
FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace" FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace"
FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace" FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace"
FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package" FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package"
FileOptions_Features_field_name protoreflect.Name = "features"
FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package" FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package"
@ -490,7 +546,6 @@ const (
FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services" FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services"
FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services" FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services"
FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services" FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services"
FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services"
FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated" FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated"
FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas" FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix" FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix"
@ -500,6 +555,7 @@ const (
FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace" FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace"
FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace" FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace"
FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package" FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package"
FileOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.features"
FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option" FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option"
) )
@ -515,7 +571,6 @@ const (
FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16 FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16
FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17 FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17
FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18 FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18
FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42
FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23 FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23
FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31 FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31
FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36 FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36
@ -525,6 +580,7 @@ const (
FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41 FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41
FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44 FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44
FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45 FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45
FileOptions_Features_field_number protoreflect.FieldNumber = 50
FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -534,6 +590,13 @@ const (
FileOptions_OptimizeMode_enum_name = "OptimizeMode" FileOptions_OptimizeMode_enum_name = "OptimizeMode"
) )
// Enum values for google.protobuf.FileOptions.OptimizeMode.
const (
FileOptions_SPEED_enum_value = 1
FileOptions_CODE_SIZE_enum_value = 2
FileOptions_LITE_RUNTIME_enum_value = 3
)
// Names for google.protobuf.MessageOptions. // Names for google.protobuf.MessageOptions.
const ( const (
MessageOptions_message_name protoreflect.Name = "MessageOptions" MessageOptions_message_name protoreflect.Name = "MessageOptions"
@ -547,6 +610,7 @@ const (
MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry"
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts" MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
MessageOptions_Features_field_name protoreflect.Name = "features"
MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format"
@ -554,6 +618,7 @@ const (
MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated"
MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry"
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated_legacy_json_field_conflicts" MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated_legacy_json_field_conflicts"
MessageOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.features"
MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option"
) )
@ -564,6 +629,7 @@ const (
MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3
MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 11 MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 11
MessageOptions_Features_field_number protoreflect.FieldNumber = 12
MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -584,8 +650,9 @@ const (
FieldOptions_Weak_field_name protoreflect.Name = "weak" FieldOptions_Weak_field_name protoreflect.Name = "weak"
FieldOptions_DebugRedact_field_name protoreflect.Name = "debug_redact" FieldOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
FieldOptions_Retention_field_name protoreflect.Name = "retention" FieldOptions_Retention_field_name protoreflect.Name = "retention"
FieldOptions_Target_field_name protoreflect.Name = "target"
FieldOptions_Targets_field_name protoreflect.Name = "targets" FieldOptions_Targets_field_name protoreflect.Name = "targets"
FieldOptions_EditionDefaults_field_name protoreflect.Name = "edition_defaults"
FieldOptions_Features_field_name protoreflect.Name = "features"
FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype"
@ -597,8 +664,9 @@ const (
FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak" FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak"
FieldOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.debug_redact" FieldOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.debug_redact"
FieldOptions_Retention_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.retention" FieldOptions_Retention_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.retention"
FieldOptions_Target_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.target"
FieldOptions_Targets_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.targets" FieldOptions_Targets_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.targets"
FieldOptions_EditionDefaults_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.edition_defaults"
FieldOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.features"
FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option"
) )
@ -613,8 +681,9 @@ const (
FieldOptions_Weak_field_number protoreflect.FieldNumber = 10 FieldOptions_Weak_field_number protoreflect.FieldNumber = 10
FieldOptions_DebugRedact_field_number protoreflect.FieldNumber = 16 FieldOptions_DebugRedact_field_number protoreflect.FieldNumber = 16
FieldOptions_Retention_field_number protoreflect.FieldNumber = 17 FieldOptions_Retention_field_number protoreflect.FieldNumber = 17
FieldOptions_Target_field_number protoreflect.FieldNumber = 18
FieldOptions_Targets_field_number protoreflect.FieldNumber = 19 FieldOptions_Targets_field_number protoreflect.FieldNumber = 19
FieldOptions_EditionDefaults_field_number protoreflect.FieldNumber = 20
FieldOptions_Features_field_number protoreflect.FieldNumber = 21
FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -624,24 +693,80 @@ const (
FieldOptions_CType_enum_name = "CType" FieldOptions_CType_enum_name = "CType"
) )
// Enum values for google.protobuf.FieldOptions.CType.
const (
FieldOptions_STRING_enum_value = 0
FieldOptions_CORD_enum_value = 1
FieldOptions_STRING_PIECE_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.JSType. // Full and short names for google.protobuf.FieldOptions.JSType.
const ( const (
FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType" FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType"
FieldOptions_JSType_enum_name = "JSType" FieldOptions_JSType_enum_name = "JSType"
) )
// Enum values for google.protobuf.FieldOptions.JSType.
const (
FieldOptions_JS_NORMAL_enum_value = 0
FieldOptions_JS_STRING_enum_value = 1
FieldOptions_JS_NUMBER_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.OptionRetention. // Full and short names for google.protobuf.FieldOptions.OptionRetention.
const ( const (
FieldOptions_OptionRetention_enum_fullname = "google.protobuf.FieldOptions.OptionRetention" FieldOptions_OptionRetention_enum_fullname = "google.protobuf.FieldOptions.OptionRetention"
FieldOptions_OptionRetention_enum_name = "OptionRetention" FieldOptions_OptionRetention_enum_name = "OptionRetention"
) )
// Enum values for google.protobuf.FieldOptions.OptionRetention.
const (
FieldOptions_RETENTION_UNKNOWN_enum_value = 0
FieldOptions_RETENTION_RUNTIME_enum_value = 1
FieldOptions_RETENTION_SOURCE_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.OptionTargetType. // Full and short names for google.protobuf.FieldOptions.OptionTargetType.
const ( const (
FieldOptions_OptionTargetType_enum_fullname = "google.protobuf.FieldOptions.OptionTargetType" FieldOptions_OptionTargetType_enum_fullname = "google.protobuf.FieldOptions.OptionTargetType"
FieldOptions_OptionTargetType_enum_name = "OptionTargetType" FieldOptions_OptionTargetType_enum_name = "OptionTargetType"
) )
// Enum values for google.protobuf.FieldOptions.OptionTargetType.
const (
FieldOptions_TARGET_TYPE_UNKNOWN_enum_value = 0
FieldOptions_TARGET_TYPE_FILE_enum_value = 1
FieldOptions_TARGET_TYPE_EXTENSION_RANGE_enum_value = 2
FieldOptions_TARGET_TYPE_MESSAGE_enum_value = 3
FieldOptions_TARGET_TYPE_FIELD_enum_value = 4
FieldOptions_TARGET_TYPE_ONEOF_enum_value = 5
FieldOptions_TARGET_TYPE_ENUM_enum_value = 6
FieldOptions_TARGET_TYPE_ENUM_ENTRY_enum_value = 7
FieldOptions_TARGET_TYPE_SERVICE_enum_value = 8
FieldOptions_TARGET_TYPE_METHOD_enum_value = 9
)
// Names for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_message_name protoreflect.Name = "EditionDefault"
FieldOptions_EditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault"
)
// Field names for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_Edition_field_name protoreflect.Name = "edition"
FieldOptions_EditionDefault_Value_field_name protoreflect.Name = "value"
FieldOptions_EditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.edition"
FieldOptions_EditionDefault_Value_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.value"
)
// Field numbers for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_Edition_field_number protoreflect.FieldNumber = 3
FieldOptions_EditionDefault_Value_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.OneofOptions. // Names for google.protobuf.OneofOptions.
const ( const (
OneofOptions_message_name protoreflect.Name = "OneofOptions" OneofOptions_message_name protoreflect.Name = "OneofOptions"
@ -650,13 +775,16 @@ const (
// Field names for google.protobuf.OneofOptions. // Field names for google.protobuf.OneofOptions.
const ( const (
OneofOptions_Features_field_name protoreflect.Name = "features"
OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
OneofOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.features"
OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option" OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.OneofOptions. // Field numbers for google.protobuf.OneofOptions.
const ( const (
OneofOptions_Features_field_number protoreflect.FieldNumber = 1
OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -671,11 +799,13 @@ const (
EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias"
EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts" EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
EnumOptions_Features_field_name protoreflect.Name = "features"
EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias"
EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated"
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated_legacy_json_field_conflicts" EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated_legacy_json_field_conflicts"
EnumOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.features"
EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option"
) )
@ -684,6 +814,7 @@ const (
EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2
EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 6 EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 6
EnumOptions_Features_field_number protoreflect.FieldNumber = 7
EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -696,15 +827,21 @@ const (
// Field names for google.protobuf.EnumValueOptions. // Field names for google.protobuf.EnumValueOptions.
const ( const (
EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumValueOptions_Features_field_name protoreflect.Name = "features"
EnumValueOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated" EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated"
EnumValueOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.features"
EnumValueOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.debug_redact"
EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option" EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.EnumValueOptions. // Field numbers for google.protobuf.EnumValueOptions.
const ( const (
EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1 EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1
EnumValueOptions_Features_field_number protoreflect.FieldNumber = 2
EnumValueOptions_DebugRedact_field_number protoreflect.FieldNumber = 3
EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -716,15 +853,18 @@ const (
// Field names for google.protobuf.ServiceOptions. // Field names for google.protobuf.ServiceOptions.
const ( const (
ServiceOptions_Features_field_name protoreflect.Name = "features"
ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated" ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated"
ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ServiceOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.features"
ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated" ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated"
ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option" ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.ServiceOptions. // Field numbers for google.protobuf.ServiceOptions.
const ( const (
ServiceOptions_Features_field_number protoreflect.FieldNumber = 34
ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33 ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33
ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -739,10 +879,12 @@ const (
const ( const (
MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated" MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level" MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level"
MethodOptions_Features_field_name protoreflect.Name = "features"
MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated" MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated"
MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level" MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level"
MethodOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.features"
MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option" MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option"
) )
@ -750,6 +892,7 @@ const (
const ( const (
MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33 MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33
MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34 MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34
MethodOptions_Features_field_number protoreflect.FieldNumber = 35
MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -759,6 +902,13 @@ const (
MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel" MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel"
) )
// Enum values for google.protobuf.MethodOptions.IdempotencyLevel.
const (
MethodOptions_IDEMPOTENCY_UNKNOWN_enum_value = 0
MethodOptions_NO_SIDE_EFFECTS_enum_value = 1
MethodOptions_IDEMPOTENT_enum_value = 2
)
// Names for google.protobuf.UninterpretedOption. // Names for google.protobuf.UninterpretedOption.
const ( const (
UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption" UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption"
@ -816,6 +966,163 @@ const (
UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2 UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2
) )
// Names for google.protobuf.FeatureSet.
const (
FeatureSet_message_name protoreflect.Name = "FeatureSet"
FeatureSet_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet"
)
// Field names for google.protobuf.FeatureSet.
const (
FeatureSet_FieldPresence_field_name protoreflect.Name = "field_presence"
FeatureSet_EnumType_field_name protoreflect.Name = "enum_type"
FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
FeatureSet_Utf8Validation_field_name protoreflect.Name = "utf8_validation"
FeatureSet_MessageEncoding_field_name protoreflect.Name = "message_encoding"
FeatureSet_JsonFormat_field_name protoreflect.Name = "json_format"
FeatureSet_FieldPresence_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
FeatureSet_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
FeatureSet_Utf8Validation_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
FeatureSet_MessageEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
FeatureSet_JsonFormat_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
)
// Field numbers for google.protobuf.FeatureSet.
const (
FeatureSet_FieldPresence_field_number protoreflect.FieldNumber = 1
FeatureSet_EnumType_field_number protoreflect.FieldNumber = 2
FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
FeatureSet_Utf8Validation_field_number protoreflect.FieldNumber = 4
FeatureSet_MessageEncoding_field_number protoreflect.FieldNumber = 5
FeatureSet_JsonFormat_field_number protoreflect.FieldNumber = 6
)
// Full and short names for google.protobuf.FeatureSet.FieldPresence.
const (
FeatureSet_FieldPresence_enum_fullname = "google.protobuf.FeatureSet.FieldPresence"
FeatureSet_FieldPresence_enum_name = "FieldPresence"
)
// Enum values for google.protobuf.FeatureSet.FieldPresence.
const (
FeatureSet_FIELD_PRESENCE_UNKNOWN_enum_value = 0
FeatureSet_EXPLICIT_enum_value = 1
FeatureSet_IMPLICIT_enum_value = 2
FeatureSet_LEGACY_REQUIRED_enum_value = 3
)
// Full and short names for google.protobuf.FeatureSet.EnumType.
const (
FeatureSet_EnumType_enum_fullname = "google.protobuf.FeatureSet.EnumType"
FeatureSet_EnumType_enum_name = "EnumType"
)
// Enum values for google.protobuf.FeatureSet.EnumType.
const (
FeatureSet_ENUM_TYPE_UNKNOWN_enum_value = 0
FeatureSet_OPEN_enum_value = 1
FeatureSet_CLOSED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.RepeatedFieldEncoding.
const (
FeatureSet_RepeatedFieldEncoding_enum_fullname = "google.protobuf.FeatureSet.RepeatedFieldEncoding"
FeatureSet_RepeatedFieldEncoding_enum_name = "RepeatedFieldEncoding"
)
// Enum values for google.protobuf.FeatureSet.RepeatedFieldEncoding.
const (
FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN_enum_value = 0
FeatureSet_PACKED_enum_value = 1
FeatureSet_EXPANDED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.Utf8Validation.
const (
FeatureSet_Utf8Validation_enum_fullname = "google.protobuf.FeatureSet.Utf8Validation"
FeatureSet_Utf8Validation_enum_name = "Utf8Validation"
)
// Enum values for google.protobuf.FeatureSet.Utf8Validation.
const (
FeatureSet_UTF8_VALIDATION_UNKNOWN_enum_value = 0
FeatureSet_VERIFY_enum_value = 2
FeatureSet_NONE_enum_value = 3
)
// Full and short names for google.protobuf.FeatureSet.MessageEncoding.
const (
FeatureSet_MessageEncoding_enum_fullname = "google.protobuf.FeatureSet.MessageEncoding"
FeatureSet_MessageEncoding_enum_name = "MessageEncoding"
)
// Enum values for google.protobuf.FeatureSet.MessageEncoding.
const (
FeatureSet_MESSAGE_ENCODING_UNKNOWN_enum_value = 0
FeatureSet_LENGTH_PREFIXED_enum_value = 1
FeatureSet_DELIMITED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.JsonFormat.
const (
FeatureSet_JsonFormat_enum_fullname = "google.protobuf.FeatureSet.JsonFormat"
FeatureSet_JsonFormat_enum_name = "JsonFormat"
)
// Enum values for google.protobuf.FeatureSet.JsonFormat.
const (
FeatureSet_JSON_FORMAT_UNKNOWN_enum_value = 0
FeatureSet_ALLOW_enum_value = 1
FeatureSet_LEGACY_BEST_EFFORT_enum_value = 2
)
// Names for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_message_name protoreflect.Name = "FeatureSetDefaults"
FeatureSetDefaults_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults"
)
// Field names for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_Defaults_field_name protoreflect.Name = "defaults"
FeatureSetDefaults_MinimumEdition_field_name protoreflect.Name = "minimum_edition"
FeatureSetDefaults_MaximumEdition_field_name protoreflect.Name = "maximum_edition"
FeatureSetDefaults_Defaults_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.defaults"
FeatureSetDefaults_MinimumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.minimum_edition"
FeatureSetDefaults_MaximumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.maximum_edition"
)
// Field numbers for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_Defaults_field_number protoreflect.FieldNumber = 1
FeatureSetDefaults_MinimumEdition_field_number protoreflect.FieldNumber = 4
FeatureSetDefaults_MaximumEdition_field_number protoreflect.FieldNumber = 5
)
// Names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_message_name protoreflect.Name = "FeatureSetEditionDefault"
FeatureSetDefaults_FeatureSetEditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"
)
// Field names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_name protoreflect.Name = "edition"
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_name protoreflect.Name = "features"
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition"
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.features"
)
// Field numbers for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number protoreflect.FieldNumber = 3
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.SourceCodeInfo. // Names for google.protobuf.SourceCodeInfo.
const ( const (
SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo" SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo"
@ -917,3 +1224,10 @@ const (
GeneratedCodeInfo_Annotation_Semantic_enum_fullname = "google.protobuf.GeneratedCodeInfo.Annotation.Semantic" GeneratedCodeInfo_Annotation_Semantic_enum_fullname = "google.protobuf.GeneratedCodeInfo.Annotation.Semantic"
GeneratedCodeInfo_Annotation_Semantic_enum_name = "Semantic" GeneratedCodeInfo_Annotation_Semantic_enum_name = "Semantic"
) )
// Enum values for google.protobuf.GeneratedCodeInfo.Annotation.Semantic.
const (
GeneratedCodeInfo_Annotation_NONE_enum_value = 0
GeneratedCodeInfo_Annotation_SET_enum_value = 1
GeneratedCodeInfo_Annotation_ALIAS_enum_value = 2
)

View File

@ -0,0 +1,31 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_reflect_protodesc_proto_go_features_proto = "reflect/protodesc/proto/go_features.proto"
// Names for google.protobuf.GoFeatures.
const (
GoFeatures_message_name protoreflect.Name = "GoFeatures"
GoFeatures_message_fullname protoreflect.FullName = "google.protobuf.GoFeatures"
)
// Field names for google.protobuf.GoFeatures.
const (
GoFeatures_LegacyUnmarshalJsonEnum_field_name protoreflect.Name = "legacy_unmarshal_json_enum"
GoFeatures_LegacyUnmarshalJsonEnum_field_fullname protoreflect.FullName = "google.protobuf.GoFeatures.legacy_unmarshal_json_enum"
)
// Field numbers for google.protobuf.GoFeatures.
const (
GoFeatures_LegacyUnmarshalJsonEnum_field_number protoreflect.FieldNumber = 1
)

View File

@ -18,6 +18,11 @@ const (
NullValue_enum_name = "NullValue" NullValue_enum_name = "NullValue"
) )
// Enum values for google.protobuf.NullValue.
const (
NullValue_NULL_VALUE_enum_value = 0
)
// Names for google.protobuf.Struct. // Names for google.protobuf.Struct.
const ( const (
Struct_message_name protoreflect.Name = "Struct" Struct_message_name protoreflect.Name = "Struct"

View File

@ -18,6 +18,13 @@ const (
Syntax_enum_name = "Syntax" Syntax_enum_name = "Syntax"
) )
// Enum values for google.protobuf.Syntax.
const (
Syntax_SYNTAX_PROTO2_enum_value = 0
Syntax_SYNTAX_PROTO3_enum_value = 1
Syntax_SYNTAX_EDITIONS_enum_value = 2
)
// Names for google.protobuf.Type. // Names for google.protobuf.Type.
const ( const (
Type_message_name protoreflect.Name = "Type" Type_message_name protoreflect.Name = "Type"
@ -105,12 +112,43 @@ const (
Field_Kind_enum_name = "Kind" Field_Kind_enum_name = "Kind"
) )
// Enum values for google.protobuf.Field.Kind.
const (
Field_TYPE_UNKNOWN_enum_value = 0
Field_TYPE_DOUBLE_enum_value = 1
Field_TYPE_FLOAT_enum_value = 2
Field_TYPE_INT64_enum_value = 3
Field_TYPE_UINT64_enum_value = 4
Field_TYPE_INT32_enum_value = 5
Field_TYPE_FIXED64_enum_value = 6
Field_TYPE_FIXED32_enum_value = 7
Field_TYPE_BOOL_enum_value = 8
Field_TYPE_STRING_enum_value = 9
Field_TYPE_GROUP_enum_value = 10
Field_TYPE_MESSAGE_enum_value = 11
Field_TYPE_BYTES_enum_value = 12
Field_TYPE_UINT32_enum_value = 13
Field_TYPE_ENUM_enum_value = 14
Field_TYPE_SFIXED32_enum_value = 15
Field_TYPE_SFIXED64_enum_value = 16
Field_TYPE_SINT32_enum_value = 17
Field_TYPE_SINT64_enum_value = 18
)
// Full and short names for google.protobuf.Field.Cardinality. // Full and short names for google.protobuf.Field.Cardinality.
const ( const (
Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality" Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality"
Field_Cardinality_enum_name = "Cardinality" Field_Cardinality_enum_name = "Cardinality"
) )
// Enum values for google.protobuf.Field.Cardinality.
const (
Field_CARDINALITY_UNKNOWN_enum_value = 0
Field_CARDINALITY_OPTIONAL_enum_value = 1
Field_CARDINALITY_REQUIRED_enum_value = 2
Field_CARDINALITY_REPEATED_enum_value = 3
)
// Names for google.protobuf.Enum. // Names for google.protobuf.Enum.
const ( const (
Enum_message_name protoreflect.Name = "Enum" Enum_message_name protoreflect.Name = "Enum"

View File

@ -21,26 +21,18 @@ type extensionFieldInfo struct {
validation validationInfo validation validationInfo
} }
var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo
func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
if xi, ok := xt.(*ExtensionInfo); ok { if xi, ok := xt.(*ExtensionInfo); ok {
xi.lazyInit() xi.lazyInit()
return xi.info return xi.info
} }
return legacyLoadExtensionFieldInfo(xt) // Ideally we'd cache the resulting *extensionFieldInfo so we don't have to
} // recompute this metadata repeatedly. But without support for something like
// weak references, such a cache would pin temporary values (like dynamic
// legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. // extension types, constructed for the duration of a user request) to the
func legacyLoadExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { // heap forever, causing memory usage of the cache to grow unbounded.
if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { // See discussion in https://github.com/golang/protobuf/issues/1521.
return xi.(*extensionFieldInfo) return makeExtensionFieldInfo(xt.TypeDescriptor())
}
e := makeExtensionFieldInfo(xt.TypeDescriptor())
if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok {
return e.(*extensionFieldInfo)
}
return e
} }
func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo { func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo {

View File

@ -162,11 +162,20 @@ func appendBoolSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions
func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.BoolSlice() sp := p.BoolSlice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growBoolSlice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -732,11 +741,20 @@ func appendInt32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1138,11 +1156,20 @@ func appendSint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1544,11 +1571,20 @@ func appendUint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice() sp := p.Uint32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growUint32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1950,11 +1986,20 @@ func appendInt64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -2356,11 +2401,20 @@ func appendSint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -2762,11 +2816,20 @@ func appendUint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice() sp := p.Uint64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growUint64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -3145,11 +3208,15 @@ func appendSfixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -3461,11 +3528,15 @@ func appendFixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice() sp := p.Uint32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growUint32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -3777,11 +3848,15 @@ func appendFloatSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float32Slice() sp := p.Float32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growFloat32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -4093,11 +4168,15 @@ func appendSfixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
@ -4409,11 +4488,15 @@ func appendFixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice() sp := p.Uint64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growUint64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
@ -4725,11 +4808,15 @@ func appendDoubleSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float64Slice() sp := p.Float64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growFloat64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {

View File

@ -197,7 +197,7 @@ func fieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) (*MessageInfo,
return getMessageInfo(ft), makeMessageFieldCoder(fd, ft) return getMessageInfo(ft), makeMessageFieldCoder(fd, ft)
case fd.Kind() == protoreflect.GroupKind: case fd.Kind() == protoreflect.GroupKind:
return getMessageInfo(ft), makeGroupFieldCoder(fd, ft) return getMessageInfo(ft), makeGroupFieldCoder(fd, ft)
case fd.Syntax() == protoreflect.Proto3 && fd.ContainingOneof() == nil: case !fd.HasPresence() && fd.ContainingOneof() == nil:
// Populated oneof fields always encode even if set to the zero value, // Populated oneof fields always encode even if set to the zero value,
// which normally are not encoded in proto3. // which normally are not encoded in proto3.
switch fd.Kind() { switch fd.Kind() {

View File

@ -206,8 +206,14 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
// Obtain a list of oneof wrapper types. // Obtain a list of oneof wrapper types.
var oneofWrappers []reflect.Type var oneofWrappers []reflect.Type
for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { methods := make([]reflect.Method, 0, 2)
if fn, ok := t.MethodByName(method); ok { if m, ok := t.MethodByName("XXX_OneofFuncs"); ok {
methods = append(methods, m)
}
if m, ok := t.MethodByName("XXX_OneofWrappers"); ok {
methods = append(methods, m)
}
for _, fn := range methods {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
if vs, ok := v.Interface().([]interface{}); ok { if vs, ok := v.Interface().([]interface{}); ok {
for _, v := range vs { for _, v := range vs {
@ -216,7 +222,6 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
} }
} }
} }
}
// Obtain a list of the extension ranges. // Obtain a list of the extension ranges.
if fn, ok := t.MethodByName("ExtensionRangeArray"); ok { if fn, ok := t.MethodByName("ExtensionRangeArray"); ok {

View File

@ -192,15 +192,20 @@ fieldLoop:
// Derive a mapping of oneof wrappers to fields. // Derive a mapping of oneof wrappers to fields.
oneofWrappers := mi.OneofWrappers oneofWrappers := mi.OneofWrappers
for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { methods := make([]reflect.Method, 0, 2)
if fn, ok := reflect.PtrTo(t).MethodByName(method); ok { if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
methods = append(methods, m)
}
if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
methods = append(methods, m)
}
for _, fn := range methods {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
if vs, ok := v.Interface().([]interface{}); ok { if vs, ok := v.Interface().([]interface{}); ok {
oneofWrappers = vs oneofWrappers = vs
} }
} }
} }
}
for _, v := range oneofWrappers { for _, v := range oneofWrappers {
tf := reflect.TypeOf(v).Elem() tf := reflect.TypeOf(v).Elem()
f := tf.Field(0) f := tf.Field(0)

View File

@ -538,6 +538,6 @@ func isZero(v reflect.Value) bool {
} }
return true return true
default: default:
panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()}) panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()})
} }
} }

View File

@ -159,6 +159,42 @@ func (p pointer) SetPointer(v pointer) {
p.v.Elem().Set(v.v) p.v.Elem().Set(v.v)
} }
func growSlice(p pointer, addCap int) {
// TODO: Once we only support Go 1.20 and newer, use reflect.Grow.
in := p.v.Elem()
out := reflect.MakeSlice(in.Type(), in.Len(), in.Len()+addCap)
reflect.Copy(out, in)
p.v.Elem().Set(out)
}
func (p pointer) growBoolSlice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growInt32Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growUint32Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growInt64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growUint64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growFloat64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growFloat32Slice(addCap int) {
growSlice(p, addCap)
}
func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") }
func (ms *messageState) pointer() pointer { panic("not supported") } func (ms *messageState) pointer() pointer { panic("not supported") }
func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") }

View File

@ -138,6 +138,46 @@ func (p pointer) SetPointer(v pointer) {
*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p) *(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
} }
func (p pointer) growBoolSlice(addCap int) {
sp := p.BoolSlice()
s := make([]bool, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growInt32Slice(addCap int) {
sp := p.Int32Slice()
s := make([]int32, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growUint32Slice(addCap int) {
p.growInt32Slice(addCap)
}
func (p pointer) growFloat32Slice(addCap int) {
p.growInt32Slice(addCap)
}
func (p pointer) growInt64Slice(addCap int) {
sp := p.Int64Slice()
s := make([]int64, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growUint64Slice(addCap int) {
p.growInt64Slice(addCap)
}
func (p pointer) growFloat64Slice(addCap int) {
p.growInt64Slice(addCap)
}
// Static check that MessageState does not exceed the size of a pointer. // Static check that MessageState does not exceed the size of a pointer.
const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{})) const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))

View File

@ -17,7 +17,7 @@ import (
// EnforceUTF8 reports whether to enforce strict UTF-8 validation. // EnforceUTF8 reports whether to enforce strict UTF-8 validation.
func EnforceUTF8(fd protoreflect.FieldDescriptor) bool { func EnforceUTF8(fd protoreflect.FieldDescriptor) bool {
if flags.ProtoLegacy { if flags.ProtoLegacy || fd.Syntax() == protoreflect.Editions {
if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok { if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok {
return fd.EnforceUTF8() return fd.EnforceUTF8()
} }

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !purego && !appengine //go:build !purego && !appengine && !go1.21
// +build !purego,!appengine // +build !purego,!appengine,!go1.21
package strs package strs

View File

@ -0,0 +1,74 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !purego && !appengine && go1.21
// +build !purego,!appengine,go1.21
package strs
import (
"unsafe"
"google.golang.org/protobuf/reflect/protoreflect"
)
// UnsafeString returns an unsafe string reference of b.
// The caller must treat the input slice as immutable.
//
// WARNING: Use carefully. The returned result must not leak to the end user
// unless the input slice is provably immutable.
func UnsafeString(b []byte) string {
return unsafe.String(unsafe.SliceData(b), len(b))
}
// UnsafeBytes returns an unsafe bytes slice reference of s.
// The caller must treat returned slice as immutable.
//
// WARNING: Use carefully. The returned result must not leak to the end user.
func UnsafeBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
// Builder builds a set of strings with shared lifetime.
// This differs from strings.Builder, which is for building a single string.
type Builder struct {
buf []byte
}
// AppendFullName is equivalent to protoreflect.FullName.Append,
// but optimized for large batches where each name has a shared lifetime.
func (sb *Builder) AppendFullName(prefix protoreflect.FullName, name protoreflect.Name) protoreflect.FullName {
n := len(prefix) + len(".") + len(name)
if len(prefix) == 0 {
n -= len(".")
}
sb.grow(n)
sb.buf = append(sb.buf, prefix...)
sb.buf = append(sb.buf, '.')
sb.buf = append(sb.buf, name...)
return protoreflect.FullName(sb.last(n))
}
// MakeString is equivalent to string(b), but optimized for large batches
// with a shared lifetime.
func (sb *Builder) MakeString(b []byte) string {
sb.grow(len(b))
sb.buf = append(sb.buf, b...)
return sb.last(len(b))
}
func (sb *Builder) grow(n int) {
if cap(sb.buf)-len(sb.buf) >= n {
return
}
// Unlike strings.Builder, we do not need to copy over the contents
// of the old buffer since our builder provides no API for
// retrieving previously created strings.
sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n))
}
func (sb *Builder) last(n int) string {
return UnsafeString(sb.buf[len(sb.buf)-n:])
}

View File

@ -51,7 +51,7 @@ import (
// 10. Send out the CL for review and submit it. // 10. Send out the CL for review and submit it.
const ( const (
Major = 1 Major = 1
Minor = 31 Minor = 33
Patch = 0 Patch = 0
PreRelease = "" PreRelease = ""
) )

View File

@ -69,7 +69,7 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
// UnmarshalState parses a wire-format message and places the result in m. // UnmarshalState parses a wire-format message and places the result in m.
// //
// This method permits fine-grained control over the unmarshaler. // This method permits fine-grained control over the unmarshaler.
// Most users should use Unmarshal instead. // Most users should use [Unmarshal] instead.
func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
if o.RecursionLimit == 0 { if o.RecursionLimit == 0 {
o.RecursionLimit = protowire.DefaultRecursionLimit o.RecursionLimit = protowire.DefaultRecursionLimit

View File

@ -18,27 +18,27 @@
// This package contains functions to convert to and from the wire format, // This package contains functions to convert to and from the wire format,
// an efficient binary serialization of protocol buffers. // an efficient binary serialization of protocol buffers.
// //
// • Size reports the size of a message in the wire format. // - [Size] reports the size of a message in the wire format.
// //
// • Marshal converts a message to the wire format. // - [Marshal] converts a message to the wire format.
// The MarshalOptions type provides more control over wire marshaling. // The [MarshalOptions] type provides more control over wire marshaling.
// //
// • Unmarshal converts a message from the wire format. // - [Unmarshal] converts a message from the wire format.
// The UnmarshalOptions type provides more control over wire unmarshaling. // The [UnmarshalOptions] type provides more control over wire unmarshaling.
// //
// # Basic message operations // # Basic message operations
// //
// • Clone makes a deep copy of a message. // - [Clone] makes a deep copy of a message.
// //
// • Merge merges the content of a message into another. // - [Merge] merges the content of a message into another.
// //
// • Equal compares two messages. For more control over comparisons // - [Equal] compares two messages. For more control over comparisons
// and detailed reporting of differences, see package // and detailed reporting of differences, see package
// "google.golang.org/protobuf/testing/protocmp". // [google.golang.org/protobuf/testing/protocmp].
// //
// • Reset clears the content of a message. // - [Reset] clears the content of a message.
// //
// • CheckInitialized reports whether all required fields in a message are set. // - [CheckInitialized] reports whether all required fields in a message are set.
// //
// # Optional scalar constructors // # Optional scalar constructors
// //
@ -46,7 +46,7 @@
// as pointers to a value. For example, an optional string field has the // as pointers to a value. For example, an optional string field has the
// Go type *string. // Go type *string.
// //
// • Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, and String // - [Bool], [Int32], [Int64], [Uint32], [Uint64], [Float32], [Float64], and [String]
// take a value and return a pointer to a new instance of it, // take a value and return a pointer to a new instance of it,
// to simplify construction of optional field values. // to simplify construction of optional field values.
// //
@ -57,27 +57,27 @@
// //
// # Extension accessors // # Extension accessors
// //
// • HasExtension, GetExtension, SetExtension, and ClearExtension // - [HasExtension], [GetExtension], [SetExtension], and [ClearExtension]
// access extension field values in a protocol buffer message. // access extension field values in a protocol buffer message.
// //
// Extension fields are only supported in proto2. // Extension fields are only supported in proto2.
// //
// # Related packages // # Related packages
// //
// • Package "google.golang.org/protobuf/encoding/protojson" converts messages to // - Package [google.golang.org/protobuf/encoding/protojson] converts messages to
// and from JSON. // and from JSON.
// //
// • Package "google.golang.org/protobuf/encoding/prototext" converts messages to // - Package [google.golang.org/protobuf/encoding/prototext] converts messages to
// and from the text format. // and from the text format.
// //
// • Package "google.golang.org/protobuf/reflect/protoreflect" provides a // - Package [google.golang.org/protobuf/reflect/protoreflect] provides a
// reflection interface for protocol buffer data types. // reflection interface for protocol buffer data types.
// //
// • Package "google.golang.org/protobuf/testing/protocmp" provides features // - Package [google.golang.org/protobuf/testing/protocmp] provides features
// to compare protocol buffer messages with the "github.com/google/go-cmp/cmp" // to compare protocol buffer messages with the [github.com/google/go-cmp/cmp]
// package. // package.
// //
// • Package "google.golang.org/protobuf/types/dynamicpb" provides a dynamic // - Package [google.golang.org/protobuf/types/dynamicpb] provides a dynamic
// message type, suitable for working with messages where the protocol buffer // message type, suitable for working with messages where the protocol buffer
// type is only known at runtime. // type is only known at runtime.
// //

View File

@ -129,7 +129,7 @@ func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
// MarshalState returns the wire-format encoding of a message. // MarshalState returns the wire-format encoding of a message.
// //
// This method permits fine-grained control over the marshaler. // This method permits fine-grained control over the marshaler.
// Most users should use Marshal instead. // Most users should use [Marshal] instead.
func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) { func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
return o.marshal(in.Buf, in.Message) return o.marshal(in.Buf, in.Message)
} }

View File

@ -26,7 +26,7 @@ func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
} }
// ClearExtension clears an extension field such that subsequent // ClearExtension clears an extension field such that subsequent
// HasExtension calls return false. // [HasExtension] calls return false.
// It panics if m is invalid or if xt does not extend m. // It panics if m is invalid or if xt does not extend m.
func ClearExtension(m Message, xt protoreflect.ExtensionType) { func ClearExtension(m Message, xt protoreflect.ExtensionType) {
m.ProtoReflect().Clear(xt.TypeDescriptor()) m.ProtoReflect().Clear(xt.TypeDescriptor())

View File

@ -21,7 +21,7 @@ import (
// The unknown fields of src are appended to the unknown fields of dst. // The unknown fields of src are appended to the unknown fields of dst.
// //
// It is semantically equivalent to unmarshaling the encoded form of src // It is semantically equivalent to unmarshaling the encoded form of src
// into dst with the UnmarshalOptions.Merge option specified. // into dst with the [UnmarshalOptions.Merge] option specified.
func Merge(dst, src Message) { func Merge(dst, src Message) {
// TODO: Should nil src be treated as semantically equivalent to a // TODO: Should nil src be treated as semantically equivalent to a
// untyped, read-only, empty message? What about a nil dst? // untyped, read-only, empty message? What about a nil dst?

View File

@ -15,18 +15,20 @@ import (
// protobuf module that accept a Message, except where otherwise specified. // protobuf module that accept a Message, except where otherwise specified.
// //
// This is the v2 interface definition for protobuf messages. // This is the v2 interface definition for protobuf messages.
// The v1 interface definition is "github.com/golang/protobuf/proto".Message. // The v1 interface definition is [github.com/golang/protobuf/proto.Message].
// //
// To convert a v1 message to a v2 message, // - To convert a v1 message to a v2 message,
// use "github.com/golang/protobuf/proto".MessageV2. // use [google.golang.org/protobuf/protoadapt.MessageV2Of].
// To convert a v2 message to a v1 message, // - To convert a v2 message to a v1 message,
// use "github.com/golang/protobuf/proto".MessageV1. // use [google.golang.org/protobuf/protoadapt.MessageV1Of].
type Message = protoreflect.ProtoMessage type Message = protoreflect.ProtoMessage
// Error matches all errors produced by packages in the protobuf module. // Error matches all errors produced by packages in the protobuf module
// according to [errors.Is].
// //
// That is, errors.Is(err, Error) reports whether an error is produced // Example usage:
// by this module. //
// if errors.Is(err, proto.Error) { ... }
var Error error var Error error
func init() { func init() {

View File

@ -3,11 +3,11 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package protodesc provides functionality for converting // Package protodesc provides functionality for converting
// FileDescriptorProto messages to/from protoreflect.FileDescriptor values. // FileDescriptorProto messages to/from [protoreflect.FileDescriptor] values.
// //
// The google.protobuf.FileDescriptorProto is a protobuf message that describes // The google.protobuf.FileDescriptorProto is a protobuf message that describes
// the type information for a .proto file in a form that is easily serializable. // the type information for a .proto file in a form that is easily serializable.
// The protoreflect.FileDescriptor is a more structured representation of // The [protoreflect.FileDescriptor] is a more structured representation of
// the FileDescriptorProto message where references and remote dependencies // the FileDescriptorProto message where references and remote dependencies
// can be directly followed. // can be directly followed.
package protodesc package protodesc
@ -24,11 +24,11 @@ import (
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
) )
// Resolver is the resolver used by NewFile to resolve dependencies. // Resolver is the resolver used by [NewFile] to resolve dependencies.
// The enums and messages provided must belong to some parent file, // The enums and messages provided must belong to some parent file,
// which is also registered. // which is also registered.
// //
// It is implemented by protoregistry.Files. // It is implemented by [protoregistry.Files].
type Resolver interface { type Resolver interface {
FindFileByPath(string) (protoreflect.FileDescriptor, error) FindFileByPath(string) (protoreflect.FileDescriptor, error)
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
@ -61,19 +61,19 @@ type FileOptions struct {
AllowUnresolvable bool AllowUnresolvable bool
} }
// NewFile creates a new protoreflect.FileDescriptor from the provided // NewFile creates a new [protoreflect.FileDescriptor] from the provided
// file descriptor message. See FileOptions.New for more information. // file descriptor message. See [FileOptions.New] for more information.
func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
return FileOptions{}.New(fd, r) return FileOptions{}.New(fd, r)
} }
// NewFiles creates a new protoregistry.Files from the provided // NewFiles creates a new [protoregistry.Files] from the provided
// FileDescriptorSet message. See FileOptions.NewFiles for more information. // FileDescriptorSet message. See [FileOptions.NewFiles] for more information.
func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
return FileOptions{}.NewFiles(fd) return FileOptions{}.NewFiles(fd)
} }
// New creates a new protoreflect.FileDescriptor from the provided // New creates a new [protoreflect.FileDescriptor] from the provided
// file descriptor message. The file must represent a valid proto file according // file descriptor message. The file must represent a valid proto file according
// to protobuf semantics. The returned descriptor is a deep copy of the input. // to protobuf semantics. The returned descriptor is a deep copy of the input.
// //
@ -93,9 +93,15 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
f.L1.Syntax = protoreflect.Proto2 f.L1.Syntax = protoreflect.Proto2
case "proto3": case "proto3":
f.L1.Syntax = protoreflect.Proto3 f.L1.Syntax = protoreflect.Proto3
case "editions":
f.L1.Syntax = protoreflect.Editions
f.L1.Edition = fromEditionProto(fd.GetEdition())
default: default:
return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
} }
if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < SupportedEditionsMinimum || fd.GetEdition() > SupportedEditionsMaximum) {
return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition())
}
f.L1.Path = fd.GetName() f.L1.Path = fd.GetName()
if f.L1.Path == "" { if f.L1.Path == "" {
return nil, errors.New("file path must be populated") return nil, errors.New("file path must be populated")
@ -108,6 +114,9 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
opts = proto.Clone(opts).(*descriptorpb.FileOptions) opts = proto.Clone(opts).(*descriptorpb.FileOptions)
f.L2.Options = func() protoreflect.ProtoMessage { return opts } f.L2.Options = func() protoreflect.ProtoMessage { return opts }
} }
if f.L1.Syntax == protoreflect.Editions {
initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures())
}
f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency())) f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency()))
for _, i := range fd.GetPublicDependency() { for _, i := range fd.GetPublicDependency() {
@ -231,7 +240,7 @@ func (is importSet) importPublic(imps protoreflect.FileImports) {
} }
} }
// NewFiles creates a new protoregistry.Files from the provided // NewFiles creates a new [protoregistry.Files] from the provided
// FileDescriptorSet message. The descriptor set must include only // FileDescriptorSet message. The descriptor set must include only
// valid files according to protobuf semantics. The returned descriptors // valid files according to protobuf semantics. The returned descriptors
// are a deep copy of the input. // are a deep copy of the input.

View File

@ -28,6 +28,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
opts = proto.Clone(opts).(*descriptorpb.EnumOptions) opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
e.L2.Options = func() protoreflect.ProtoMessage { return opts } e.L2.Options = func() protoreflect.ProtoMessage { return opts }
} }
e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
for _, s := range ed.GetReservedName() { for _, s := range ed.GetReservedName() {
e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s)) e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
} }
@ -68,6 +69,9 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
return nil, err return nil, err
} }
if m.Base.L0.ParentFile.Syntax() == protoreflect.Editions {
m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
}
if opts := md.GetOptions(); opts != nil { if opts := md.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.MessageOptions) opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
m.L2.Options = func() protoreflect.ProtoMessage { return opts } m.L2.Options = func() protoreflect.ProtoMessage { return opts }
@ -114,6 +118,27 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
return ms, nil return ms, nil
} }
// canBePacked returns whether the field can use packed encoding:
// https://protobuf.dev/programming-guides/encoding/#packed
func canBePacked(fd *descriptorpb.FieldDescriptorProto) bool {
if fd.GetLabel() != descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
return false // not a repeated field
}
switch protoreflect.Kind(fd.GetType()) {
case protoreflect.MessageKind, protoreflect.GroupKind:
return false // not a scalar type field
case protoreflect.StringKind, protoreflect.BytesKind:
// string and bytes can explicitly not be declared as packed,
// see https://protobuf.dev/programming-guides/encoding/#packed
return false
default:
return true
}
}
func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) { func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
for i, fd := range fds { for i, fd := range fds {
@ -137,6 +162,34 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
if fd.JsonName != nil { if fd.JsonName != nil {
f.L1.StringName.InitJSON(fd.GetJsonName()) f.L1.StringName.InitJSON(fd.GetJsonName())
} }
if f.Base.L0.ParentFile.Syntax() == protoreflect.Editions {
f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures())
if f.L1.EditionFeatures.IsLegacyRequired {
f.L1.Cardinality = protoreflect.Required
}
// We reuse the existing field because the old option `[packed =
// true]` is mutually exclusive with the editions feature.
if canBePacked(fd) {
f.L1.HasPacked = true
f.L1.IsPacked = f.L1.EditionFeatures.IsPacked
}
// We pretend this option is always explicitly set because the only
// use of HasEnforceUTF8 is to determine whether to use EnforceUTF8
// or to return the appropriate default.
// When using editions we either parse the option or resolve the
// appropriate default here (instead of later when this option is
// requested from the descriptor).
// In proto2/proto3 syntax HasEnforceUTF8 might be false.
f.L1.HasEnforceUTF8 = true
f.L1.EnforceUTF8 = f.L1.EditionFeatures.IsUTF8Validated
if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded {
f.L1.Kind = protoreflect.GroupKind
}
}
} }
return fs, nil return fs, nil
} }
@ -151,6 +204,9 @@ func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDesc
if opts := od.GetOptions(); opts != nil { if opts := od.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.OneofOptions) opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
o.L1.Options = func() protoreflect.ProtoMessage { return opts } o.L1.Options = func() protoreflect.ProtoMessage { return opts }
if parent.Syntax() == protoreflect.Editions {
o.L1.EditionFeatures = mergeEditionFeatures(parent, opts.GetFeatures())
}
} }
} }
return os, nil return os, nil

View File

@ -276,8 +276,8 @@ func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvab
} else if err != nil { } else if err != nil {
return v, ev, err return v, ev, err
} }
if fd.Syntax() == protoreflect.Proto3 { if !fd.HasPresence() {
return v, ev, errors.New("cannot be specified under proto3 semantics") return v, ev, errors.New("cannot be specified with implicit field presence")
} }
if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated { if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
return v, ev, errors.New("cannot be specified on composite types") return v, ev, errors.New("cannot be specified on composite types")

View File

@ -107,7 +107,7 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
if isMessageSet && !flags.ProtoLegacy { if isMessageSet && !flags.ProtoLegacy {
return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName()) return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName())
} }
if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { if isMessageSet && (m.Syntax() == protoreflect.Proto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
return errors.New("message %q is an invalid proto1 MessageSet", m.FullName()) return errors.New("message %q is an invalid proto1 MessageSet", m.FullName())
} }
if m.Syntax() == protoreflect.Proto3 { if m.Syntax() == protoreflect.Proto3 {
@ -314,8 +314,8 @@ func checkValidGroup(fd protoreflect.FieldDescriptor) error {
switch { switch {
case fd.Kind() != protoreflect.GroupKind: case fd.Kind() != protoreflect.GroupKind:
return nil return nil
case fd.Syntax() != protoreflect.Proto2: case fd.Syntax() == protoreflect.Proto3:
return errors.New("invalid under proto2 semantics") return errors.New("invalid under proto3 semantics")
case md == nil || md.IsPlaceholder(): case md == nil || md.IsPlaceholder():
return errors.New("message must be resolvable") return errors.New("message must be resolvable")
case fd.FullName().Parent() != md.FullName().Parent(): case fd.FullName().Parent() != md.FullName().Parent():

View File

@ -0,0 +1,148 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package protodesc
import (
"fmt"
"os"
"sync"
"google.golang.org/protobuf/internal/editiondefaults"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
gofeaturespb "google.golang.org/protobuf/types/gofeaturespb"
)
const (
SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2
SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
)
var defaults = &descriptorpb.FeatureSetDefaults{}
var defaultsCacheMu sync.Mutex
var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)
func init() {
err := proto.Unmarshal(editiondefaults.Defaults, defaults)
if err != nil {
fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err)
os.Exit(1)
}
}
func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition {
return filedesc.Edition(epb)
}
func toEditionProto(ed filedesc.Edition) descriptorpb.Edition {
switch ed {
case filedesc.EditionUnknown:
return descriptorpb.Edition_EDITION_UNKNOWN
case filedesc.EditionProto2:
return descriptorpb.Edition_EDITION_PROTO2
case filedesc.EditionProto3:
return descriptorpb.Edition_EDITION_PROTO3
case filedesc.Edition2023:
return descriptorpb.Edition_EDITION_2023
default:
panic(fmt.Sprintf("unknown value for edition: %v", ed))
}
}
func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet {
defaultsCacheMu.Lock()
defer defaultsCacheMu.Unlock()
if def, ok := defaultsCache[ed]; ok {
return def
}
edpb := toEditionProto(ed)
if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
// This should never happen protodesc.(FileOptions).New would fail when
// initializing the file descriptor.
// This most likely means the embedded defaults were not updated.
fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb)
os.Exit(1)
}
fs := defaults.GetDefaults()[0].GetFeatures()
// Using a linear search for now.
// Editions are guaranteed to be sorted and thus we could use a binary search.
// Given that there are only a handful of editions (with one more per year)
// there is not much reason to use a binary search.
for _, def := range defaults.GetDefaults() {
if def.GetEdition() <= edpb {
fs = def.GetFeatures()
} else {
break
}
}
defaultsCache[ed] = fs
return fs
}
// mergeEditionFeatures merges the parent and child feature sets. This function
// should be used when initializing Go descriptors from descriptor protos which
// is why the parent is a filedesc.EditionsFeatures (Go representation) while
// the child is a descriptorproto.FeatureSet (protoc representation).
// Any feature set by the child overwrites what is set by the parent.
func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorpb.FeatureSet) filedesc.EditionFeatures {
var parentFS filedesc.EditionFeatures
switch p := parentDesc.(type) {
case *filedesc.File:
parentFS = p.L1.EditionFeatures
case *filedesc.Message:
parentFS = p.L1.EditionFeatures
default:
panic(fmt.Sprintf("unknown parent type %T", parentDesc))
}
if child == nil {
return parentFS
}
if fp := child.FieldPresence; fp != nil {
parentFS.IsFieldPresence = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
*fp == descriptorpb.FeatureSet_EXPLICIT
parentFS.IsLegacyRequired = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED
}
if et := child.EnumType; et != nil {
parentFS.IsOpenEnum = *et == descriptorpb.FeatureSet_OPEN
}
if rfe := child.RepeatedFieldEncoding; rfe != nil {
parentFS.IsPacked = *rfe == descriptorpb.FeatureSet_PACKED
}
if utf8val := child.Utf8Validation; utf8val != nil {
parentFS.IsUTF8Validated = *utf8val == descriptorpb.FeatureSet_VERIFY
}
if me := child.MessageEncoding; me != nil {
parentFS.IsDelimitedEncoded = *me == descriptorpb.FeatureSet_DELIMITED
}
if jf := child.JsonFormat; jf != nil {
parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW
}
if goFeatures, ok := proto.GetExtension(child, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures); ok && goFeatures != nil {
if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil {
parentFS.GenerateLegacyUnmarshalJSON = *luje
}
}
return parentFS
}
// initFileDescFromFeatureSet initializes editions related fields in fd based
// on fs. If fs is nil it is assumed to be an empty featureset and all fields
// will be initialized with the appropriate default. fd.L1.Edition must be set
// before calling this function.
func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) {
dfs := getFeatureSetFor(fd.L1.Edition)
// initialize the featureset with the defaults
fd.L1.EditionFeatures = mergeEditionFeatures(fd, dfs)
// overwrite any options explicitly specified
fd.L1.EditionFeatures = mergeEditionFeatures(fd, fs)
}

View File

@ -16,7 +16,7 @@ import (
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
) )
// ToFileDescriptorProto copies a protoreflect.FileDescriptor into a // ToFileDescriptorProto copies a [protoreflect.FileDescriptor] into a
// google.protobuf.FileDescriptorProto message. // google.protobuf.FileDescriptorProto message.
func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto { func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto {
p := &descriptorpb.FileDescriptorProto{ p := &descriptorpb.FileDescriptorProto{
@ -70,13 +70,13 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
for i, exts := 0, file.Extensions(); i < exts.Len(); i++ { for i, exts := 0, file.Extensions(); i < exts.Len(); i++ {
p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i)))
} }
if syntax := file.Syntax(); syntax != protoreflect.Proto2 { if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
p.Syntax = proto.String(file.Syntax().String()) p.Syntax = proto.String(file.Syntax().String())
} }
return p return p
} }
// ToDescriptorProto copies a protoreflect.MessageDescriptor into a // ToDescriptorProto copies a [protoreflect.MessageDescriptor] into a
// google.protobuf.DescriptorProto message. // google.protobuf.DescriptorProto message.
func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto { func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto {
p := &descriptorpb.DescriptorProto{ p := &descriptorpb.DescriptorProto{
@ -119,7 +119,7 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
return p return p
} }
// ToFieldDescriptorProto copies a protoreflect.FieldDescriptor into a // ToFieldDescriptorProto copies a [protoreflect.FieldDescriptor] into a
// google.protobuf.FieldDescriptorProto message. // google.protobuf.FieldDescriptorProto message.
func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto { func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto {
p := &descriptorpb.FieldDescriptorProto{ p := &descriptorpb.FieldDescriptorProto{
@ -168,7 +168,7 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi
return p return p
} }
// ToOneofDescriptorProto copies a protoreflect.OneofDescriptor into a // ToOneofDescriptorProto copies a [protoreflect.OneofDescriptor] into a
// google.protobuf.OneofDescriptorProto message. // google.protobuf.OneofDescriptorProto message.
func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto { func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto {
return &descriptorpb.OneofDescriptorProto{ return &descriptorpb.OneofDescriptorProto{
@ -177,7 +177,7 @@ func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.On
} }
} }
// ToEnumDescriptorProto copies a protoreflect.EnumDescriptor into a // ToEnumDescriptorProto copies a [protoreflect.EnumDescriptor] into a
// google.protobuf.EnumDescriptorProto message. // google.protobuf.EnumDescriptorProto message.
func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto { func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto {
p := &descriptorpb.EnumDescriptorProto{ p := &descriptorpb.EnumDescriptorProto{
@ -200,7 +200,7 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
return p return p
} }
// ToEnumValueDescriptorProto copies a protoreflect.EnumValueDescriptor into a // ToEnumValueDescriptorProto copies a [protoreflect.EnumValueDescriptor] into a
// google.protobuf.EnumValueDescriptorProto message. // google.protobuf.EnumValueDescriptorProto message.
func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto { func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto {
return &descriptorpb.EnumValueDescriptorProto{ return &descriptorpb.EnumValueDescriptorProto{
@ -210,7 +210,7 @@ func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descrip
} }
} }
// ToServiceDescriptorProto copies a protoreflect.ServiceDescriptor into a // ToServiceDescriptorProto copies a [protoreflect.ServiceDescriptor] into a
// google.protobuf.ServiceDescriptorProto message. // google.protobuf.ServiceDescriptorProto message.
func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto { func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto {
p := &descriptorpb.ServiceDescriptorProto{ p := &descriptorpb.ServiceDescriptorProto{
@ -223,7 +223,7 @@ func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descripto
return p return p
} }
// ToMethodDescriptorProto copies a protoreflect.MethodDescriptor into a // ToMethodDescriptorProto copies a [protoreflect.MethodDescriptor] into a
// google.protobuf.MethodDescriptorProto message. // google.protobuf.MethodDescriptorProto message.
func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto { func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto {
p := &descriptorpb.MethodDescriptorProto{ p := &descriptorpb.MethodDescriptorProto{

View File

@ -10,46 +10,46 @@
// //
// # Protocol Buffer Descriptors // # Protocol Buffer Descriptors
// //
// Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor) // Protobuf descriptors (e.g., [EnumDescriptor] or [MessageDescriptor])
// are immutable objects that represent protobuf type information. // are immutable objects that represent protobuf type information.
// They are wrappers around the messages declared in descriptor.proto. // They are wrappers around the messages declared in descriptor.proto.
// Protobuf descriptors alone lack any information regarding Go types. // Protobuf descriptors alone lack any information regarding Go types.
// //
// Enums and messages generated by this module implement Enum and ProtoMessage, // Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Descriptor and ProtoReflect.Descriptor accessors respectively // where the Descriptor and ProtoReflect.Descriptor accessors respectively
// return the protobuf descriptor for the values. // return the protobuf descriptor for the values.
// //
// The protobuf descriptor interfaces are not meant to be implemented by // The protobuf descriptor interfaces are not meant to be implemented by
// user code since they might need to be extended in the future to support // user code since they might need to be extended in the future to support
// additions to the protobuf language. // additions to the protobuf language.
// The "google.golang.org/protobuf/reflect/protodesc" package converts between // The [google.golang.org/protobuf/reflect/protodesc] package converts between
// google.protobuf.DescriptorProto messages and protobuf descriptors. // google.protobuf.DescriptorProto messages and protobuf descriptors.
// //
// # Go Type Descriptors // # Go Type Descriptors
// //
// A type descriptor (e.g., EnumType or MessageType) is a constructor for // A type descriptor (e.g., [EnumType] or [MessageType]) is a constructor for
// a concrete Go type that represents the associated protobuf descriptor. // a concrete Go type that represents the associated protobuf descriptor.
// There is commonly a one-to-one relationship between protobuf descriptors and // There is commonly a one-to-one relationship between protobuf descriptors and
// Go type descriptors, but it can potentially be a one-to-many relationship. // Go type descriptors, but it can potentially be a one-to-many relationship.
// //
// Enums and messages generated by this module implement Enum and ProtoMessage, // Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Type and ProtoReflect.Type accessors respectively // where the Type and ProtoReflect.Type accessors respectively
// return the protobuf descriptor for the values. // return the protobuf descriptor for the values.
// //
// The "google.golang.org/protobuf/types/dynamicpb" package can be used to // The [google.golang.org/protobuf/types/dynamicpb] package can be used to
// create Go type descriptors from protobuf descriptors. // create Go type descriptors from protobuf descriptors.
// //
// # Value Interfaces // # Value Interfaces
// //
// The Enum and Message interfaces provide a reflective view over an // The [Enum] and [Message] interfaces provide a reflective view over an
// enum or message instance. For enums, it provides the ability to retrieve // enum or message instance. For enums, it provides the ability to retrieve
// the enum value number for any concrete enum type. For messages, it provides // the enum value number for any concrete enum type. For messages, it provides
// the ability to access or manipulate fields of the message. // the ability to access or manipulate fields of the message.
// //
// To convert a proto.Message to a protoreflect.Message, use the // To convert a [google.golang.org/protobuf/proto.Message] to a [protoreflect.Message], use the
// former's ProtoReflect method. Since the ProtoReflect method is new to the // former's ProtoReflect method. Since the ProtoReflect method is new to the
// v2 message interface, it may not be present on older message implementations. // v2 message interface, it may not be present on older message implementations.
// The "github.com/golang/protobuf/proto".MessageReflect function can be used // The [github.com/golang/protobuf/proto.MessageReflect] function can be used
// to obtain a reflective view on older messages. // to obtain a reflective view on older messages.
// //
// # Relationships // # Relationships
@ -71,12 +71,12 @@
// │ │ // │ │
// └────────────────── Type() ───────┘ // └────────────────── Type() ───────┘
// //
// • An EnumType describes a concrete Go enum type. // • An [EnumType] describes a concrete Go enum type.
// It has an EnumDescriptor and can construct an Enum instance. // It has an EnumDescriptor and can construct an Enum instance.
// //
// • An EnumDescriptor describes an abstract protobuf enum type. // • An [EnumDescriptor] describes an abstract protobuf enum type.
// //
// • An Enum is a concrete enum instance. Generated enums implement Enum. // • An [Enum] is a concrete enum instance. Generated enums implement Enum.
// //
// ┌──────────────── New() ─────────────────┐ // ┌──────────────── New() ─────────────────┐
// │ │ // │ │
@ -90,24 +90,26 @@
// │ │ // │ │
// └─────────────────── Type() ─────────┘ // └─────────────────── Type() ─────────┘
// //
// • A MessageType describes a concrete Go message type. // • A [MessageType] describes a concrete Go message type.
// It has a MessageDescriptor and can construct a Message instance. // It has a [MessageDescriptor] and can construct a [Message] instance.
// Just as how Go's reflect.Type is a reflective description of a Go type, // Just as how Go's [reflect.Type] is a reflective description of a Go type,
// a MessageType is a reflective description of a Go type for a protobuf message. // a [MessageType] is a reflective description of a Go type for a protobuf message.
// //
// • A MessageDescriptor describes an abstract protobuf message type. // • A [MessageDescriptor] describes an abstract protobuf message type.
// It has no understanding of Go types. In order to construct a MessageType // It has no understanding of Go types. In order to construct a [MessageType]
// from just a MessageDescriptor, you can consider looking up the message type // from just a [MessageDescriptor], you can consider looking up the message type
// in the global registry using protoregistry.GlobalTypes.FindMessageByName // in the global registry using the FindMessageByName method on
// or constructing a dynamic MessageType using dynamicpb.NewMessageType. // [google.golang.org/protobuf/reflect/protoregistry.GlobalTypes]
// or constructing a dynamic [MessageType] using
// [google.golang.org/protobuf/types/dynamicpb.NewMessageType].
// //
// • A Message is a reflective view over a concrete message instance. // • A [Message] is a reflective view over a concrete message instance.
// Generated messages implement ProtoMessage, which can convert to a Message. // Generated messages implement [ProtoMessage], which can convert to a [Message].
// Just as how Go's reflect.Value is a reflective view over a Go value, // Just as how Go's [reflect.Value] is a reflective view over a Go value,
// a Message is a reflective view over a concrete protobuf message instance. // a [Message] is a reflective view over a concrete protobuf message instance.
// Using Go reflection as an analogy, the ProtoReflect method is similar to // Using Go reflection as an analogy, the [ProtoMessage.ProtoReflect] method is similar to
// calling reflect.ValueOf, and the Message.Interface method is similar to // calling [reflect.ValueOf], and the [Message.Interface] method is similar to
// calling reflect.Value.Interface. // calling [reflect.Value.Interface].
// //
// ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ // ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐
// │ V │ V // │ V │ V
@ -119,15 +121,15 @@
// │ │ // │ │
// └────── implements ────────┘ // └────── implements ────────┘
// //
// • An ExtensionType describes a concrete Go implementation of an extension. // • An [ExtensionType] describes a concrete Go implementation of an extension.
// It has an ExtensionTypeDescriptor and can convert to/from // It has an [ExtensionTypeDescriptor] and can convert to/from
// abstract Values and Go values. // an abstract [Value] and a Go value.
// //
// • An ExtensionTypeDescriptor is an ExtensionDescriptor // • An [ExtensionTypeDescriptor] is an [ExtensionDescriptor]
// which also has an ExtensionType. // which also has an [ExtensionType].
// //
// • An ExtensionDescriptor describes an abstract protobuf extension field and // • An [ExtensionDescriptor] describes an abstract protobuf extension field and
// may not always be an ExtensionTypeDescriptor. // may not always be an [ExtensionTypeDescriptor].
package protoreflect package protoreflect
import ( import (
@ -142,7 +144,7 @@ type doNotImplement pragma.DoNotImplement
// ProtoMessage is the top-level interface that all proto messages implement. // ProtoMessage is the top-level interface that all proto messages implement.
// This is declared in the protoreflect package to avoid a cyclic dependency; // This is declared in the protoreflect package to avoid a cyclic dependency;
// use the proto.Message type instead, which aliases this type. // use the [google.golang.org/protobuf/proto.Message] type instead, which aliases this type.
type ProtoMessage interface{ ProtoReflect() Message } type ProtoMessage interface{ ProtoReflect() Message }
// Syntax is the language version of the proto file. // Syntax is the language version of the proto file.
@ -153,6 +155,7 @@ type syntax int8 // keep exact type opaque as the int type may change
const ( const (
Proto2 Syntax = 2 Proto2 Syntax = 2
Proto3 Syntax = 3 Proto3 Syntax = 3
Editions Syntax = 4
) )
// IsValid reports whether the syntax is valid. // IsValid reports whether the syntax is valid.
@ -172,6 +175,8 @@ func (s Syntax) String() string {
return "proto2" return "proto2"
case Proto3: case Proto3:
return "proto3" return "proto3"
case Editions:
return "editions"
default: default:
return fmt.Sprintf("<unknown:%d>", s) return fmt.Sprintf("<unknown:%d>", s)
} }
@ -436,7 +441,7 @@ type Names interface {
// FullName is a qualified name that uniquely identifies a proto declaration. // FullName is a qualified name that uniquely identifies a proto declaration.
// A qualified name is the concatenation of the proto package along with the // A qualified name is the concatenation of the proto package along with the
// fully-declared name (i.e., name of parent preceding the name of the child), // fully-declared name (i.e., name of parent preceding the name of the child),
// with a '.' delimiter placed between each Name. // with a '.' delimiter placed between each [Name].
// //
// This should not have any leading or trailing dots. // This should not have any leading or trailing dots.
type FullName string // e.g., "google.protobuf.Field.Kind" type FullName string // e.g., "google.protobuf.Field.Kind"
@ -480,7 +485,7 @@ func isLetterDigit(c byte) bool {
} }
// Name returns the short name, which is the last identifier segment. // Name returns the short name, which is the last identifier segment.
// A single segment FullName is the Name itself. // A single segment FullName is the [Name] itself.
func (n FullName) Name() Name { func (n FullName) Name() Name {
if i := strings.LastIndexByte(string(n), '.'); i >= 0 { if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
return Name(n[i+1:]) return Name(n[i+1:])

View File

@ -35,7 +35,7 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo) b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo)
case 12: case 12:
b = p.appendSingularField(b, "syntax", nil) b = p.appendSingularField(b, "syntax", nil)
case 13: case 14:
b = p.appendSingularField(b, "edition", nil) b = p.appendSingularField(b, "edition", nil)
} }
return b return b
@ -160,8 +160,6 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "java_generic_services", nil) b = p.appendSingularField(b, "java_generic_services", nil)
case 18: case 18:
b = p.appendSingularField(b, "py_generic_services", nil) b = p.appendSingularField(b, "py_generic_services", nil)
case 42:
b = p.appendSingularField(b, "php_generic_services", nil)
case 23: case 23:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 31: case 31:
@ -180,6 +178,8 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "php_metadata_namespace", nil) b = p.appendSingularField(b, "php_metadata_namespace", nil)
case 45: case 45:
b = p.appendSingularField(b, "ruby_package", nil) b = p.appendSingularField(b, "ruby_package", nil)
case 50:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -240,6 +240,8 @@ func (p *SourcePath) appendMessageOptions(b []byte) []byte {
b = p.appendSingularField(b, "map_entry", nil) b = p.appendSingularField(b, "map_entry", nil)
case 11: case 11:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil) b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
case 12:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -285,6 +287,8 @@ func (p *SourcePath) appendEnumOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 6: case 6:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil) b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
case 7:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -330,6 +334,8 @@ func (p *SourcePath) appendServiceOptions(b []byte) []byte {
return b return b
} }
switch (*p)[0] { switch (*p)[0] {
case 34:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 33: case 33:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 999: case 999:
@ -361,16 +367,39 @@ func (p *SourcePath) appendFieldOptions(b []byte) []byte {
b = p.appendSingularField(b, "debug_redact", nil) b = p.appendSingularField(b, "debug_redact", nil)
case 17: case 17:
b = p.appendSingularField(b, "retention", nil) b = p.appendSingularField(b, "retention", nil)
case 18:
b = p.appendSingularField(b, "target", nil)
case 19: case 19:
b = p.appendRepeatedField(b, "targets", nil) b = p.appendRepeatedField(b, "targets", nil)
case 20:
b = p.appendRepeatedField(b, "edition_defaults", (*SourcePath).appendFieldOptions_EditionDefault)
case 21:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
return b return b
} }
func (p *SourcePath) appendFeatureSet(b []byte) []byte {
if len(*p) == 0 {
return b
}
switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "field_presence", nil)
case 2:
b = p.appendSingularField(b, "enum_type", nil)
case 3:
b = p.appendSingularField(b, "repeated_field_encoding", nil)
case 4:
b = p.appendSingularField(b, "utf8_validation", nil)
case 5:
b = p.appendSingularField(b, "message_encoding", nil)
case 6:
b = p.appendSingularField(b, "json_format", nil)
}
return b
}
func (p *SourcePath) appendUninterpretedOption(b []byte) []byte { func (p *SourcePath) appendUninterpretedOption(b []byte) []byte {
if len(*p) == 0 { if len(*p) == 0 {
return b return b
@ -422,6 +451,8 @@ func (p *SourcePath) appendExtensionRangeOptions(b []byte) []byte {
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
case 2: case 2:
b = p.appendRepeatedField(b, "declaration", (*SourcePath).appendExtensionRangeOptions_Declaration) b = p.appendRepeatedField(b, "declaration", (*SourcePath).appendExtensionRangeOptions_Declaration)
case 50:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 3: case 3:
b = p.appendSingularField(b, "verification", nil) b = p.appendSingularField(b, "verification", nil)
} }
@ -433,6 +464,8 @@ func (p *SourcePath) appendOneofOptions(b []byte) []byte {
return b return b
} }
switch (*p)[0] { switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -446,6 +479,10 @@ func (p *SourcePath) appendEnumValueOptions(b []byte) []byte {
switch (*p)[0] { switch (*p)[0] {
case 1: case 1:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 2:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 3:
b = p.appendSingularField(b, "debug_redact", nil)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -461,12 +498,27 @@ func (p *SourcePath) appendMethodOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 34: case 34:
b = p.appendSingularField(b, "idempotency_level", nil) b = p.appendSingularField(b, "idempotency_level", nil)
case 35:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
return b return b
} }
func (p *SourcePath) appendFieldOptions_EditionDefault(b []byte) []byte {
if len(*p) == 0 {
return b
}
switch (*p)[0] {
case 3:
b = p.appendSingularField(b, "edition", nil)
case 2:
b = p.appendSingularField(b, "value", nil)
}
return b
}
func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte { func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte {
if len(*p) == 0 { if len(*p) == 0 {
return b return b
@ -491,8 +543,6 @@ func (p *SourcePath) appendExtensionRangeOptions_Declaration(b []byte) []byte {
b = p.appendSingularField(b, "full_name", nil) b = p.appendSingularField(b, "full_name", nil)
case 3: case 3:
b = p.appendSingularField(b, "type", nil) b = p.appendSingularField(b, "type", nil)
case 4:
b = p.appendSingularField(b, "is_repeated", nil)
case 5: case 5:
b = p.appendSingularField(b, "reserved", nil) b = p.appendSingularField(b, "reserved", nil)
case 6: case 6:

View File

@ -12,7 +12,7 @@ package protoreflect
// exactly identical. However, it is possible for the same semantically // exactly identical. However, it is possible for the same semantically
// identical proto type to be represented by multiple type descriptors. // identical proto type to be represented by multiple type descriptors.
// //
// For example, suppose we have t1 and t2 which are both MessageDescriptors. // For example, suppose we have t1 and t2 which are both an [MessageDescriptor].
// If t1 == t2, then the types are definitely equal and all accessors return // If t1 == t2, then the types are definitely equal and all accessors return
// the same information. However, if t1 != t2, then it is still possible that // the same information. However, if t1 != t2, then it is still possible that
// they still represent the same proto type (e.g., t1.FullName == t2.FullName). // they still represent the same proto type (e.g., t1.FullName == t2.FullName).
@ -115,7 +115,7 @@ type Descriptor interface {
// corresponds with the google.protobuf.FileDescriptorProto message. // corresponds with the google.protobuf.FileDescriptorProto message.
// //
// Top-level declarations: // Top-level declarations:
// EnumDescriptor, MessageDescriptor, FieldDescriptor, and/or ServiceDescriptor. // [EnumDescriptor], [MessageDescriptor], [FieldDescriptor], and/or [ServiceDescriptor].
type FileDescriptor interface { type FileDescriptor interface {
Descriptor // Descriptor.FullName is identical to Package Descriptor // Descriptor.FullName is identical to Package
@ -180,8 +180,8 @@ type FileImport struct {
// corresponds with the google.protobuf.DescriptorProto message. // corresponds with the google.protobuf.DescriptorProto message.
// //
// Nested declarations: // Nested declarations:
// FieldDescriptor, OneofDescriptor, FieldDescriptor, EnumDescriptor, // [FieldDescriptor], [OneofDescriptor], [FieldDescriptor], [EnumDescriptor],
// and/or MessageDescriptor. // and/or [MessageDescriptor].
type MessageDescriptor interface { type MessageDescriptor interface {
Descriptor Descriptor
@ -214,7 +214,7 @@ type MessageDescriptor interface {
ExtensionRanges() FieldRanges ExtensionRanges() FieldRanges
// ExtensionRangeOptions returns the ith extension range options. // ExtensionRangeOptions returns the ith extension range options.
// //
// To avoid a dependency cycle, this method returns a proto.Message value, // To avoid a dependency cycle, this method returns a proto.Message] value,
// which always contains a google.protobuf.ExtensionRangeOptions message. // which always contains a google.protobuf.ExtensionRangeOptions message.
// This method returns a typed nil-pointer if no options are present. // This method returns a typed nil-pointer if no options are present.
// The caller must import the descriptorpb package to use this. // The caller must import the descriptorpb package to use this.
@ -231,9 +231,9 @@ type MessageDescriptor interface {
} }
type isMessageDescriptor interface{ ProtoType(MessageDescriptor) } type isMessageDescriptor interface{ ProtoType(MessageDescriptor) }
// MessageType encapsulates a MessageDescriptor with a concrete Go implementation. // MessageType encapsulates a [MessageDescriptor] with a concrete Go implementation.
// It is recommended that implementations of this interface also implement the // It is recommended that implementations of this interface also implement the
// MessageFieldTypes interface. // [MessageFieldTypes] interface.
type MessageType interface { type MessageType interface {
// New returns a newly allocated empty message. // New returns a newly allocated empty message.
// It may return nil for synthetic messages representing a map entry. // It may return nil for synthetic messages representing a map entry.
@ -249,19 +249,19 @@ type MessageType interface {
Descriptor() MessageDescriptor Descriptor() MessageDescriptor
} }
// MessageFieldTypes extends a MessageType by providing type information // MessageFieldTypes extends a [MessageType] by providing type information
// regarding enums and messages referenced by the message fields. // regarding enums and messages referenced by the message fields.
type MessageFieldTypes interface { type MessageFieldTypes interface {
MessageType MessageType
// Enum returns the EnumType for the ith field in Descriptor.Fields. // Enum returns the EnumType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not an enum kind. // It returns nil if the ith field is not an enum kind.
// It panics if out of bounds. // It panics if out of bounds.
// //
// Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum() // Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum()
Enum(i int) EnumType Enum(i int) EnumType
// Message returns the MessageType for the ith field in Descriptor.Fields. // Message returns the MessageType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not a message or group kind. // It returns nil if the ith field is not a message or group kind.
// It panics if out of bounds. // It panics if out of bounds.
// //
@ -286,8 +286,8 @@ type MessageDescriptors interface {
// corresponds with the google.protobuf.FieldDescriptorProto message. // corresponds with the google.protobuf.FieldDescriptorProto message.
// //
// It is used for both normal fields defined within the parent message // It is used for both normal fields defined within the parent message
// (e.g., MessageDescriptor.Fields) and fields that extend some remote message // (e.g., [MessageDescriptor.Fields]) and fields that extend some remote message
// (e.g., FileDescriptor.Extensions or MessageDescriptor.Extensions). // (e.g., [FileDescriptor.Extensions] or [MessageDescriptor.Extensions]).
type FieldDescriptor interface { type FieldDescriptor interface {
Descriptor Descriptor
@ -344,7 +344,7 @@ type FieldDescriptor interface {
// IsMap reports whether this field represents a map, // IsMap reports whether this field represents a map,
// where the value type for the associated field is a Map. // where the value type for the associated field is a Map.
// It is equivalent to checking whether Cardinality is Repeated, // It is equivalent to checking whether Cardinality is Repeated,
// that the Kind is MessageKind, and that Message.IsMapEntry reports true. // that the Kind is MessageKind, and that MessageDescriptor.IsMapEntry reports true.
IsMap() bool IsMap() bool
// MapKey returns the field descriptor for the key in the map entry. // MapKey returns the field descriptor for the key in the map entry.
@ -419,7 +419,7 @@ type OneofDescriptor interface {
// IsSynthetic reports whether this is a synthetic oneof created to support // IsSynthetic reports whether this is a synthetic oneof created to support
// proto3 optional semantics. If true, Fields contains exactly one field // proto3 optional semantics. If true, Fields contains exactly one field
// with HasOptionalKeyword specified. // with FieldDescriptor.HasOptionalKeyword specified.
IsSynthetic() bool IsSynthetic() bool
// Fields is a list of fields belonging to this oneof. // Fields is a list of fields belonging to this oneof.
@ -442,10 +442,10 @@ type OneofDescriptors interface {
doNotImplement doNotImplement
} }
// ExtensionDescriptor is an alias of FieldDescriptor for documentation. // ExtensionDescriptor is an alias of [FieldDescriptor] for documentation.
type ExtensionDescriptor = FieldDescriptor type ExtensionDescriptor = FieldDescriptor
// ExtensionTypeDescriptor is an ExtensionDescriptor with an associated ExtensionType. // ExtensionTypeDescriptor is an [ExtensionDescriptor] with an associated [ExtensionType].
type ExtensionTypeDescriptor interface { type ExtensionTypeDescriptor interface {
ExtensionDescriptor ExtensionDescriptor
@ -470,12 +470,12 @@ type ExtensionDescriptors interface {
doNotImplement doNotImplement
} }
// ExtensionType encapsulates an ExtensionDescriptor with a concrete // ExtensionType encapsulates an [ExtensionDescriptor] with a concrete
// Go implementation. The nested field descriptor must be for a extension field. // Go implementation. The nested field descriptor must be for a extension field.
// //
// While a normal field is a member of the parent message that it is declared // While a normal field is a member of the parent message that it is declared
// within (see Descriptor.Parent), an extension field is a member of some other // within (see [Descriptor.Parent]), an extension field is a member of some other
// target message (see ExtensionDescriptor.Extendee) and may have no // target message (see [FieldDescriptor.ContainingMessage]) and may have no
// relationship with the parent. However, the full name of an extension field is // relationship with the parent. However, the full name of an extension field is
// relative to the parent that it is declared within. // relative to the parent that it is declared within.
// //
@ -532,7 +532,7 @@ type ExtensionType interface {
// corresponds with the google.protobuf.EnumDescriptorProto message. // corresponds with the google.protobuf.EnumDescriptorProto message.
// //
// Nested declarations: // Nested declarations:
// EnumValueDescriptor. // [EnumValueDescriptor].
type EnumDescriptor interface { type EnumDescriptor interface {
Descriptor Descriptor
@ -548,7 +548,7 @@ type EnumDescriptor interface {
} }
type isEnumDescriptor interface{ ProtoType(EnumDescriptor) } type isEnumDescriptor interface{ ProtoType(EnumDescriptor) }
// EnumType encapsulates an EnumDescriptor with a concrete Go implementation. // EnumType encapsulates an [EnumDescriptor] with a concrete Go implementation.
type EnumType interface { type EnumType interface {
// New returns an instance of this enum type with its value set to n. // New returns an instance of this enum type with its value set to n.
New(n EnumNumber) Enum New(n EnumNumber) Enum
@ -610,7 +610,7 @@ type EnumValueDescriptors interface {
// ServiceDescriptor describes a service and // ServiceDescriptor describes a service and
// corresponds with the google.protobuf.ServiceDescriptorProto message. // corresponds with the google.protobuf.ServiceDescriptorProto message.
// //
// Nested declarations: MethodDescriptor. // Nested declarations: [MethodDescriptor].
type ServiceDescriptor interface { type ServiceDescriptor interface {
Descriptor Descriptor

View File

@ -27,16 +27,16 @@ type Enum interface {
// Message is a reflective interface for a concrete message value, // Message is a reflective interface for a concrete message value,
// encapsulating both type and value information for the message. // encapsulating both type and value information for the message.
// //
// Accessor/mutators for individual fields are keyed by FieldDescriptor. // Accessor/mutators for individual fields are keyed by [FieldDescriptor].
// For non-extension fields, the descriptor must exactly match the // For non-extension fields, the descriptor must exactly match the
// field known by the parent message. // field known by the parent message.
// For extension fields, the descriptor must implement ExtensionTypeDescriptor, // For extension fields, the descriptor must implement [ExtensionTypeDescriptor],
// extend the parent message (i.e., have the same message FullName), and // extend the parent message (i.e., have the same message [FullName]), and
// be within the parent's extension range. // be within the parent's extension range.
// //
// Each field Value can be a scalar or a composite type (Message, List, or Map). // Each field [Value] can be a scalar or a composite type ([Message], [List], or [Map]).
// See Value for the Go types associated with a FieldDescriptor. // See [Value] for the Go types associated with a [FieldDescriptor].
// Providing a Value that is invalid or of an incorrect type panics. // Providing a [Value] that is invalid or of an incorrect type panics.
type Message interface { type Message interface {
// Descriptor returns message descriptor, which contains only the protobuf // Descriptor returns message descriptor, which contains only the protobuf
// type information for the message. // type information for the message.
@ -152,7 +152,7 @@ type Message interface {
// This method may return nil. // This method may return nil.
// //
// The returned methods type is identical to // The returned methods type is identical to
// "google.golang.org/protobuf/runtime/protoiface".Methods. // google.golang.org/protobuf/runtime/protoiface.Methods.
// Consult the protoiface package documentation for details. // Consult the protoiface package documentation for details.
ProtoMethods() *methods ProtoMethods() *methods
} }
@ -175,8 +175,8 @@ func (b RawFields) IsValid() bool {
} }
// List is a zero-indexed, ordered list. // List is a zero-indexed, ordered list.
// The element Value type is determined by FieldDescriptor.Kind. // The element [Value] type is determined by [FieldDescriptor.Kind].
// Providing a Value that is invalid or of an incorrect type panics. // Providing a [Value] that is invalid or of an incorrect type panics.
type List interface { type List interface {
// Len reports the number of entries in the List. // Len reports the number of entries in the List.
// Get, Set, and Truncate panic with out of bound indexes. // Get, Set, and Truncate panic with out of bound indexes.
@ -226,9 +226,9 @@ type List interface {
} }
// Map is an unordered, associative map. // Map is an unordered, associative map.
// The entry MapKey type is determined by FieldDescriptor.MapKey.Kind. // The entry [MapKey] type is determined by [FieldDescriptor.MapKey].Kind.
// The entry Value type is determined by FieldDescriptor.MapValue.Kind. // The entry [Value] type is determined by [FieldDescriptor.MapValue].Kind.
// Providing a MapKey or Value that is invalid or of an incorrect type panics. // Providing a [MapKey] or [Value] that is invalid or of an incorrect type panics.
type Map interface { type Map interface {
// Len reports the number of elements in the map. // Len reports the number of elements in the map.
Len() int Len() int

View File

@ -24,19 +24,19 @@ import (
// Unlike the == operator, a NaN is equal to another NaN. // Unlike the == operator, a NaN is equal to another NaN.
// //
// - Enums are equal if they contain the same number. // - Enums are equal if they contain the same number.
// Since Value does not contain an enum descriptor, // Since [Value] does not contain an enum descriptor,
// enum values do not consider the type of the enum. // enum values do not consider the type of the enum.
// //
// - Other scalar values are equal if they contain the same value. // - Other scalar values are equal if they contain the same value.
// //
// - Message values are equal if they belong to the same message descriptor, // - [Message] values are equal if they belong to the same message descriptor,
// have the same set of populated known and extension field values, // have the same set of populated known and extension field values,
// and the same set of unknown fields values. // and the same set of unknown fields values.
// //
// - Lists are equal if they are the same length and // - [List] values are equal if they are the same length and
// each corresponding element is equal. // each corresponding element is equal.
// //
// - Maps are equal if they have the same set of keys and // - [Map] values are equal if they have the same set of keys and
// the corresponding value for each key is equal. // the corresponding value for each key is equal.
func (v1 Value) Equal(v2 Value) bool { func (v1 Value) Equal(v2 Value) bool {
return equalValue(v1, v2) return equalValue(v1, v2)

View File

@ -11,7 +11,7 @@ import (
// Value is a union where only one Go type may be set at a time. // Value is a union where only one Go type may be set at a time.
// The Value is used to represent all possible values a field may take. // The Value is used to represent all possible values a field may take.
// The following shows which Go type is used to represent each proto Kind: // The following shows which Go type is used to represent each proto [Kind]:
// //
// ╔════════════╤═════════════════════════════════════╗ // ╔════════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║ // ║ Go type │ Protobuf kind ║
@ -31,22 +31,22 @@ import (
// //
// Multiple protobuf Kinds may be represented by a single Go type if the type // Multiple protobuf Kinds may be represented by a single Go type if the type
// can losslessly represent the information for the proto kind. For example, // can losslessly represent the information for the proto kind. For example,
// Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64, // [Int64Kind], [Sint64Kind], and [Sfixed64Kind] are all represented by int64,
// but use different integer encoding methods. // but use different integer encoding methods.
// //
// The List or Map types are used if the field cardinality is repeated. // The [List] or [Map] types are used if the field cardinality is repeated.
// A field is a List if FieldDescriptor.IsList reports true. // A field is a [List] if [FieldDescriptor.IsList] reports true.
// A field is a Map if FieldDescriptor.IsMap reports true. // A field is a [Map] if [FieldDescriptor.IsMap] reports true.
// //
// Converting to/from a Value and a concrete Go value panics on type mismatch. // Converting to/from a Value and a concrete Go value panics on type mismatch.
// For example, ValueOf("hello").Int() panics because this attempts to // For example, [ValueOf]("hello").Int() panics because this attempts to
// retrieve an int64 from a string. // retrieve an int64 from a string.
// //
// List, Map, and Message Values are called "composite" values. // [List], [Map], and [Message] Values are called "composite" values.
// //
// A composite Value may alias (reference) memory at some location, // A composite Value may alias (reference) memory at some location,
// such that changes to the Value updates the that location. // such that changes to the Value updates the that location.
// A composite value acquired with a Mutable method, such as Message.Mutable, // A composite value acquired with a Mutable method, such as [Message.Mutable],
// always references the source object. // always references the source object.
// //
// For example: // For example:
@ -65,7 +65,7 @@ import (
// // appending to the List here may or may not modify the message. // // appending to the List here may or may not modify the message.
// list.Append(protoreflect.ValueOfInt32(0)) // list.Append(protoreflect.ValueOfInt32(0))
// //
// Some operations, such as Message.Get, may return an "empty, read-only" // Some operations, such as [Message.Get], may return an "empty, read-only"
// composite Value. Modifying an empty, read-only value panics. // composite Value. Modifying an empty, read-only value panics.
type Value value type Value value
@ -306,7 +306,7 @@ func (v Value) Float() float64 {
} }
} }
// String returns v as a string. Since this method implements fmt.Stringer, // String returns v as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type. // this returns the formatted string value for any non-string type.
func (v Value) String() string { func (v Value) String() string {
switch v.typ { switch v.typ {
@ -327,7 +327,7 @@ func (v Value) Bytes() []byte {
} }
} }
// Enum returns v as a EnumNumber and panics if the type is not a EnumNumber. // Enum returns v as a [EnumNumber] and panics if the type is not a [EnumNumber].
func (v Value) Enum() EnumNumber { func (v Value) Enum() EnumNumber {
switch v.typ { switch v.typ {
case enumType: case enumType:
@ -337,7 +337,7 @@ func (v Value) Enum() EnumNumber {
} }
} }
// Message returns v as a Message and panics if the type is not a Message. // Message returns v as a [Message] and panics if the type is not a [Message].
func (v Value) Message() Message { func (v Value) Message() Message {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case Message: case Message:
@ -347,7 +347,7 @@ func (v Value) Message() Message {
} }
} }
// List returns v as a List and panics if the type is not a List. // List returns v as a [List] and panics if the type is not a [List].
func (v Value) List() List { func (v Value) List() List {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case List: case List:
@ -357,7 +357,7 @@ func (v Value) List() List {
} }
} }
// Map returns v as a Map and panics if the type is not a Map. // Map returns v as a [Map] and panics if the type is not a [Map].
func (v Value) Map() Map { func (v Value) Map() Map {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case Map: case Map:
@ -367,7 +367,7 @@ func (v Value) Map() Map {
} }
} }
// MapKey returns v as a MapKey and panics for invalid MapKey types. // MapKey returns v as a [MapKey] and panics for invalid [MapKey] types.
func (v Value) MapKey() MapKey { func (v Value) MapKey() MapKey {
switch v.typ { switch v.typ {
case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType: case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType:
@ -378,8 +378,8 @@ func (v Value) MapKey() MapKey {
} }
// MapKey is used to index maps, where the Go type of the MapKey must match // MapKey is used to index maps, where the Go type of the MapKey must match
// the specified key Kind (see MessageDescriptor.IsMapEntry). // the specified key [Kind] (see [MessageDescriptor.IsMapEntry]).
// The following shows what Go type is used to represent each proto Kind: // The following shows what Go type is used to represent each proto [Kind]:
// //
// ╔═════════╤═════════════════════════════════════╗ // ╔═════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║ // ║ Go type │ Protobuf kind ║
@ -392,13 +392,13 @@ func (v Value) MapKey() MapKey {
// ║ string │ StringKind ║ // ║ string │ StringKind ║
// ╚═════════╧═════════════════════════════════════╝ // ╚═════════╧═════════════════════════════════════╝
// //
// A MapKey is constructed and accessed through a Value: // A MapKey is constructed and accessed through a [Value]:
// //
// k := ValueOf("hash").MapKey() // convert string to MapKey // k := ValueOf("hash").MapKey() // convert string to MapKey
// s := k.String() // convert MapKey to string // s := k.String() // convert MapKey to string
// //
// The MapKey is a strict subset of valid types used in Value; // The MapKey is a strict subset of valid types used in [Value];
// converting a Value to a MapKey with an invalid type panics. // converting a [Value] to a MapKey with an invalid type panics.
type MapKey value type MapKey value
// IsValid reports whether k is populated with a value. // IsValid reports whether k is populated with a value.
@ -426,13 +426,13 @@ func (k MapKey) Uint() uint64 {
return Value(k).Uint() return Value(k).Uint()
} }
// String returns k as a string. Since this method implements fmt.Stringer, // String returns k as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type. // this returns the formatted string value for any non-string type.
func (k MapKey) String() string { func (k MapKey) String() string {
return Value(k).String() return Value(k).String()
} }
// Value returns k as a Value. // Value returns k as a [Value].
func (k MapKey) Value() Value { func (k MapKey) Value() Value {
return Value(k) return Value(k)
} }

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !purego && !appengine //go:build !purego && !appengine && !go1.21
// +build !purego,!appengine // +build !purego,!appengine,!go1.21
package protoreflect package protoreflect

View File

@ -0,0 +1,87 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !purego && !appengine && go1.21
// +build !purego,!appengine,go1.21
package protoreflect
import (
"unsafe"
"google.golang.org/protobuf/internal/pragma"
)
type (
ifaceHeader struct {
_ [0]interface{} // if interfaces have greater alignment than unsafe.Pointer, this will enforce it.
Type unsafe.Pointer
Data unsafe.Pointer
}
)
var (
nilType = typeOf(nil)
boolType = typeOf(*new(bool))
int32Type = typeOf(*new(int32))
int64Type = typeOf(*new(int64))
uint32Type = typeOf(*new(uint32))
uint64Type = typeOf(*new(uint64))
float32Type = typeOf(*new(float32))
float64Type = typeOf(*new(float64))
stringType = typeOf(*new(string))
bytesType = typeOf(*new([]byte))
enumType = typeOf(*new(EnumNumber))
)
// typeOf returns a pointer to the Go type information.
// The pointer is comparable and equal if and only if the types are identical.
func typeOf(t interface{}) unsafe.Pointer {
return (*ifaceHeader)(unsafe.Pointer(&t)).Type
}
// value is a union where only one type can be represented at a time.
// The struct is 24B large on 64-bit systems and requires the minimum storage
// necessary to represent each possible type.
//
// The Go GC needs to be able to scan variables containing pointers.
// As such, pointers and non-pointers cannot be intermixed.
type value struct {
pragma.DoNotCompare // 0B
// typ stores the type of the value as a pointer to the Go type.
typ unsafe.Pointer // 8B
// ptr stores the data pointer for a String, Bytes, or interface value.
ptr unsafe.Pointer // 8B
// num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or
// Enum value as a raw uint64.
//
// It is also used to store the length of a String or Bytes value;
// the capacity is ignored.
num uint64 // 8B
}
func valueOfString(v string) Value {
return Value{typ: stringType, ptr: unsafe.Pointer(unsafe.StringData(v)), num: uint64(len(v))}
}
func valueOfBytes(v []byte) Value {
return Value{typ: bytesType, ptr: unsafe.Pointer(unsafe.SliceData(v)), num: uint64(len(v))}
}
func valueOfIface(v interface{}) Value {
p := (*ifaceHeader)(unsafe.Pointer(&v))
return Value{typ: p.Type, ptr: p.Data}
}
func (v Value) getString() string {
return unsafe.String((*byte)(v.ptr), v.num)
}
func (v Value) getBytes() []byte {
return unsafe.Slice((*byte)(v.ptr), v.num)
}
func (v Value) getIface() (x interface{}) {
*(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr}
return x
}

View File

@ -5,12 +5,12 @@
// Package protoregistry provides data structures to register and lookup // Package protoregistry provides data structures to register and lookup
// protobuf descriptor types. // protobuf descriptor types.
// //
// The Files registry contains file descriptors and provides the ability // The [Files] registry contains file descriptors and provides the ability
// to iterate over the files or lookup a specific descriptor within the files. // to iterate over the files or lookup a specific descriptor within the files.
// Files only contains protobuf descriptors and has no understanding of Go // [Files] only contains protobuf descriptors and has no understanding of Go
// type information that may be associated with each descriptor. // type information that may be associated with each descriptor.
// //
// The Types registry contains descriptor types for which there is a known // The [Types] registry contains descriptor types for which there is a known
// Go type associated with that descriptor. It provides the ability to iterate // Go type associated with that descriptor. It provides the ability to iterate
// over the registered types or lookup a type by name. // over the registered types or lookup a type by name.
package protoregistry package protoregistry
@ -218,7 +218,7 @@ func (r *Files) checkGenProtoConflict(path string) {
// FindDescriptorByName looks up a descriptor by the full name. // FindDescriptorByName looks up a descriptor by the full name.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -310,7 +310,7 @@ func (s *nameSuffix) Pop() (name protoreflect.Name) {
// FindFileByPath looks up a file by the path. // FindFileByPath looks up a file by the path.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
// This returns an error if multiple files have the same path. // This returns an error if multiple files have the same path.
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
if r == nil { if r == nil {
@ -431,7 +431,7 @@ func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflec
// A compliant implementation must deterministically return the same type // A compliant implementation must deterministically return the same type
// if no error is encountered. // if no error is encountered.
// //
// The Types type implements this interface. // The [Types] type implements this interface.
type MessageTypeResolver interface { type MessageTypeResolver interface {
// FindMessageByName looks up a message by its full name. // FindMessageByName looks up a message by its full name.
// E.g., "google.protobuf.Any" // E.g., "google.protobuf.Any"
@ -451,7 +451,7 @@ type MessageTypeResolver interface {
// A compliant implementation must deterministically return the same type // A compliant implementation must deterministically return the same type
// if no error is encountered. // if no error is encountered.
// //
// The Types type implements this interface. // The [Types] type implements this interface.
type ExtensionTypeResolver interface { type ExtensionTypeResolver interface {
// FindExtensionByName looks up a extension field by the field's full name. // FindExtensionByName looks up a extension field by the field's full name.
// Note that this is the full name of the field as determined by // Note that this is the full name of the field as determined by
@ -590,7 +590,7 @@ func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interfac
// FindEnumByName looks up an enum by its full name. // FindEnumByName looks up an enum by its full name.
// E.g., "google.protobuf.Field.Kind". // E.g., "google.protobuf.Field.Kind".
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) { func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -611,7 +611,7 @@ func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumTyp
// FindMessageByName looks up a message by its full name, // FindMessageByName looks up a message by its full name,
// e.g. "google.protobuf.Any". // e.g. "google.protobuf.Any".
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -632,7 +632,7 @@ func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.M
// FindMessageByURL looks up a message by a URL identifier. // FindMessageByURL looks up a message by a URL identifier.
// See documentation on google.protobuf.Any.type_url for the URL format. // See documentation on google.protobuf.Any.type_url for the URL format.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) { func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// This function is similar to FindMessageByName but // This function is similar to FindMessageByName but
// truncates anything before and including '/' in the URL. // truncates anything before and including '/' in the URL.
@ -662,7 +662,7 @@ func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// where the extension is declared and is unrelated to the full name of the // where the extension is declared and is unrelated to the full name of the
// message being extended. // message being extended.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -703,7 +703,7 @@ func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.E
// FindExtensionByNumber looks up a extension field by the field number // FindExtensionByNumber looks up a extension field by the field number
// within some parent message, identified by full name. // within some parent message, identified by full name.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: reflect/protodesc/proto/go_features.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
type GoFeatures struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Whether or not to generate the deprecated UnmarshalJSON method for enums.
LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"`
}
func (x *GoFeatures) Reset() {
*x = GoFeatures{}
if protoimpl.UnsafeEnabled {
mi := &file_reflect_protodesc_proto_go_features_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GoFeatures) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GoFeatures) ProtoMessage() {}
func (x *GoFeatures) ProtoReflect() protoreflect.Message {
mi := &file_reflect_protodesc_proto_go_features_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GoFeatures.ProtoReflect.Descriptor instead.
func (*GoFeatures) Descriptor() ([]byte, []int) {
return file_reflect_protodesc_proto_go_features_proto_rawDescGZIP(), []int{0}
}
func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool {
if x != nil && x.LegacyUnmarshalJsonEnum != nil {
return *x.LegacyUnmarshalJsonEnum
}
return false
}
var file_reflect_protodesc_proto_go_features_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.FeatureSet)(nil),
ExtensionType: (*GoFeatures)(nil),
Field: 1002,
Name: "google.protobuf.go",
Tag: "bytes,1002,opt,name=go",
Filename: "reflect/protodesc/proto/go_features.proto",
},
}
// Extension fields to descriptorpb.FeatureSet.
var (
// optional google.protobuf.GoFeatures go = 1002;
E_Go = &file_reflect_protodesc_proto_go_features_proto_extTypes[0]
)
var File_reflect_protodesc_proto_go_features_proto protoreflect.FileDescriptor
var file_reflect_protodesc_proto_go_features_proto_rawDesc = []byte{
0x0a, 0x29, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x64,
0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61,
0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x1a, 0x20, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a,
0x0a, 0x0a, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x1a,
0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x42, 0x1f, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, 0x75,
0x65, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, 0xe7,
0x07, 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68,
0x61, 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x49, 0x0a, 0x02, 0x67, 0x6f,
0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x64, 0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
file_reflect_protodesc_proto_go_features_proto_rawDescOnce sync.Once
file_reflect_protodesc_proto_go_features_proto_rawDescData = file_reflect_protodesc_proto_go_features_proto_rawDesc
)
func file_reflect_protodesc_proto_go_features_proto_rawDescGZIP() []byte {
file_reflect_protodesc_proto_go_features_proto_rawDescOnce.Do(func() {
file_reflect_protodesc_proto_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflect_protodesc_proto_go_features_proto_rawDescData)
})
return file_reflect_protodesc_proto_go_features_proto_rawDescData
}
var file_reflect_protodesc_proto_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_reflect_protodesc_proto_go_features_proto_goTypes = []interface{}{
(*GoFeatures)(nil), // 0: google.protobuf.GoFeatures
(*descriptorpb.FeatureSet)(nil), // 1: google.protobuf.FeatureSet
}
var file_reflect_protodesc_proto_go_features_proto_depIdxs = []int32{
1, // 0: google.protobuf.go:extendee -> google.protobuf.FeatureSet
0, // 1: google.protobuf.go:type_name -> google.protobuf.GoFeatures
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
1, // [1:2] is the sub-list for extension type_name
0, // [0:1] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_reflect_protodesc_proto_go_features_proto_init() }
func file_reflect_protodesc_proto_go_features_proto_init() {
if File_reflect_protodesc_proto_go_features_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_reflect_protodesc_proto_go_features_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GoFeatures); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_reflect_protodesc_proto_go_features_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 1,
NumServices: 0,
},
GoTypes: file_reflect_protodesc_proto_go_features_proto_goTypes,
DependencyIndexes: file_reflect_protodesc_proto_go_features_proto_depIdxs,
MessageInfos: file_reflect_protodesc_proto_go_features_proto_msgTypes,
ExtensionInfos: file_reflect_protodesc_proto_go_features_proto_extTypes,
}.Build()
File_reflect_protodesc_proto_go_features_proto = out.File
file_reflect_protodesc_proto_go_features_proto_rawDesc = nil
file_reflect_protodesc_proto_go_features_proto_goTypes = nil
file_reflect_protodesc_proto_go_features_proto_depIdxs = nil
}

View File

@ -0,0 +1,28 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
syntax = "proto2";
package google.protobuf;
import "google/protobuf/descriptor.proto";
option go_package = "google.golang.org/protobuf/types/gofeaturespb";
extend google.protobuf.FeatureSet {
optional GoFeatures go = 1002;
}
message GoFeatures {
// Whether or not to generate the deprecated UnmarshalJSON method for enums.
optional bool legacy_unmarshal_json_enum = 1 [
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_ENUM,
edition_defaults = { edition: EDITION_PROTO2, value: "true" },
edition_defaults = { edition: EDITION_PROTO3, value: "false" }
];
}

View File

@ -23,13 +23,14 @@ google.golang.org/appengine/internal/log
google.golang.org/appengine/internal/remote_api google.golang.org/appengine/internal/remote_api
google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch google.golang.org/appengine/urlfetch
# google.golang.org/protobuf v1.31.0 # google.golang.org/protobuf v1.33.0
## explicit; go 1.11 ## explicit; go 1.17
google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descfmt
google.golang.org/protobuf/internal/descopts google.golang.org/protobuf/internal/descopts
google.golang.org/protobuf/internal/detrand google.golang.org/protobuf/internal/detrand
google.golang.org/protobuf/internal/editiondefaults
google.golang.org/protobuf/internal/encoding/defval google.golang.org/protobuf/internal/encoding/defval
google.golang.org/protobuf/internal/encoding/messageset google.golang.org/protobuf/internal/encoding/messageset
google.golang.org/protobuf/internal/encoding/tag google.golang.org/protobuf/internal/encoding/tag
@ -52,3 +53,4 @@ google.golang.org/protobuf/reflect/protoregistry
google.golang.org/protobuf/runtime/protoiface google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/descriptorpb google.golang.org/protobuf/types/descriptorpb
google.golang.org/protobuf/types/gofeaturespb

View File

@ -0,0 +1,48 @@
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-external-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "update", "delete", "patch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments/status"]
verbs: ["patch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims/status"]
verbs: ["update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]

View File

@ -0,0 +1,13 @@
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: "{{ .ServiceAccount }}-role"
subjects:
- kind: ServiceAccount
name: "{{ .ServiceAccount }}"
namespace: "{{ .Namespace }}"
roleRef:
kind: ClusterRole
name: nfs-external-provisioner-runner
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,14 @@
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: "{{ .Namespace }}"
name: nfs-external-provisioner-cfg
rules:
# remove this once we stop supporting v1.0.0
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "create", "delete"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "watch", "list", "delete", "update", "create"]

View File

@ -0,0 +1,14 @@
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: "{{ .ServiceAccount }}-role-cfg"
namespace: "{{ .Namespace }}"
subjects:
- kind: ServiceAccount
name: "{{ .ServiceAccount }}"
namespace: "{{ .Namespace }}"
roleRef:
kind: Role
name: nfs-external-provisioner-cfg
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,6 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: "{{ .ServiceAccount }}"
namespace: "{{ .Namespace }}"

View File

@ -0,0 +1,244 @@
/*
Copyright 2024 The Ceph-CSI 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 nfs
import (
"bytes"
_ "embed"
"fmt"
"text/template"
"strings"
"github.com/ghodss/yaml"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"github.com/ceph/ceph-csi/api/deploy/kubernetes"
)
//go:embed csi-provisioner-rbac-sa.yaml
var csiProvisionerServiceAccount string
//go:embed csi-provisioner-rbac-cr.yaml
var csiProvisionerClusterRole string
//go:embed csi-provisioner-rbac-crb.yaml
var csiProvisionerClusterRoleBinding string
//go:embed csi-provisioner-rbac-r.yaml
var csiProvisionerRole string
//go:embed csi-provisioner-rbac-rb.yaml
var csiProvisionerRoleBinding string
var CSIProvisionerRBACDefaults = kubernetes.CSIProvisionerRBACValues{
Namespace: "default",
ServiceAccount: "nfs-csi-provisioner",
}
// NewCSIProvisionerRBAC takes a driver name from the CSIProvisionerRBACValues
// struct and replaces the value in the template. A CSIProvisionerRBAC object
// is returned which can be used to create permissions for the provisioner in
// the Kubernetes cluster.
func NewCSIProvisionerRBAC(values kubernetes.CSIProvisionerRBACValues) (kubernetes.CSIProvisionerRBAC, error) {
sa := &corev1.ServiceAccount{}
sa.Namespace = values.Namespace
sa.Name = values.ServiceAccount
cr, err := newClusterRole(values)
if err != nil {
return nil, err
}
crb, err := newClusterRoleBinding(values)
if err != nil {
return nil, err
}
r, err := newRole(values)
if err != nil {
return nil, err
}
rb, err := newRoleBinding(values)
if err != nil {
return nil, err
}
return &csiProvisionerRBAC{
serviceAccount: sa,
clusterRole: cr,
clusterRoleBinding: crb,
role: r,
roleBinding: rb,
}, nil
}
func NewCSIProvisionerRBACYAML(values kubernetes.CSIProvisionerRBACValues) (string, error) {
docs := []string{}
data, err := newYAML("csiProvisionerServiceAccount", csiProvisionerServiceAccount, values)
if err != nil {
return "", err
}
docs = append(docs, data)
data, err = newYAML("csiProvisionerClusterRole", csiProvisionerClusterRole, values)
if err != nil {
return "", err
}
docs = append(docs, data)
data, err = newYAML("csiProvisionerClusterRoleBinding", csiProvisionerClusterRoleBinding, values)
if err != nil {
return "", err
}
docs = append(docs, data)
data, err = newYAML("csiProvisionerRole", csiProvisionerRole, values)
if err != nil {
return "", err
}
docs = append(docs, data)
data, err = newYAML("csiProvisionerRoleBinding", csiProvisionerRoleBinding, values)
if err != nil {
return "", err
}
docs = append(docs, data)
return strings.Join(docs, "\n"), nil
}
func newYAML(name, data string, values kubernetes.CSIProvisionerRBACValues) (string, error) {
var buf bytes.Buffer
tmpl, err := template.New(name).Parse(data)
if err != nil {
return "", fmt.Errorf("failed to parse template: %w", err)
}
err = tmpl.Execute(&buf, values)
if err != nil {
return "", fmt.Errorf("failed to replace values in template: %w", err)
}
return buf.String(), nil
}
func newServiceAccount(values kubernetes.CSIProvisionerRBACValues) (*corev1.ServiceAccount, error) {
data, err := newYAML("csiProvisionerServiceAccount", csiProvisionerServiceAccount, values)
if err != nil {
return nil, err
}
sa := &corev1.ServiceAccount{}
err = yaml.Unmarshal([]byte(data), sa)
if err != nil {
return nil, fmt.Errorf("failed convert YAML to %T: %w", sa, err)
}
return sa, nil
}
func newClusterRole(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.ClusterRole, error) {
data, err := newYAML("csiProvisionerClusterRole", csiProvisionerClusterRole, values)
if err != nil {
return nil, err
}
cr := &rbacv1.ClusterRole{}
err = yaml.Unmarshal([]byte(data), cr)
if err != nil {
return nil, fmt.Errorf("failed convert YAML to %T: %w", cr, err)
}
return cr, nil
}
func newClusterRoleBinding(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.ClusterRoleBinding, error) {
data, err := newYAML("csiProvisionerClusterRoleBinding", csiProvisionerClusterRoleBinding, values)
if err != nil {
return nil, err
}
crb := &rbacv1.ClusterRoleBinding{}
err = yaml.Unmarshal([]byte(data), crb)
if err != nil {
return nil, fmt.Errorf("failed convert YAML to %T: %w", crb, err)
}
return crb, nil
}
func newRole(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.Role, error) {
data, err := newYAML("csiProvisionerRole", csiProvisionerRole, values)
if err != nil {
return nil, err
}
r := &rbacv1.Role{}
err = yaml.Unmarshal([]byte(data), r)
if err != nil {
return nil, fmt.Errorf("failed convert YAML to %T: %w", r, err)
}
return r, nil
}
func newRoleBinding(values kubernetes.CSIProvisionerRBACValues) (*rbacv1.RoleBinding, error) {
data, err := newYAML("csiProvisionerRoleBinding", csiProvisionerRoleBinding, values)
if err != nil {
return nil, err
}
rb := &rbacv1.RoleBinding{}
err = yaml.Unmarshal([]byte(data), rb)
if err != nil {
return nil, fmt.Errorf("failed convert YAML to %T: %w", rb, err)
}
return rb, nil
}
type csiProvisionerRBAC struct {
serviceAccount *corev1.ServiceAccount
clusterRole *rbacv1.ClusterRole
clusterRoleBinding *rbacv1.ClusterRoleBinding
role *rbacv1.Role
roleBinding *rbacv1.RoleBinding
}
func (rbac *csiProvisionerRBAC) GetServiceAccount() *corev1.ServiceAccount {
return rbac.serviceAccount
}
func (rbac *csiProvisionerRBAC) GetClusterRole() *rbacv1.ClusterRole {
return rbac.clusterRole
}
func (rbac *csiProvisionerRBAC) GetClusterRoleBinding() *rbacv1.ClusterRoleBinding {
return rbac.clusterRoleBinding
}
func (rbac *csiProvisionerRBAC) GetRole() *rbacv1.Role {
return rbac.role
}
func (rbac *csiProvisionerRBAC) GetRoleBinding() *rbacv1.RoleBinding {
return rbac.roleBinding
}

View File

@ -0,0 +1,67 @@
/*
Copyright 2024 The Ceph-CSI 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 nfs
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestNewCSIProvisionerRBAC(t *testing.T) {
rbac, err := NewCSIProvisionerRBAC(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotNil(t, rbac)
require.Equal(t, rbac.GetServiceAccount().Namespace, CSIProvisionerRBACDefaults.Namespace)
require.Equal(t, rbac.GetServiceAccount().Name, CSIProvisionerRBACDefaults.ServiceAccount)
}
func TestNewCSIProvisionerRBACYAML(t *testing.T) {
yaml, err := NewCSIProvisionerRBACYAML(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotEqual(t, "", yaml)
}
func TestNewClusterRole(t *testing.T) {
cr, err := newClusterRole(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotNil(t, cr)
}
func TestNewClusterRoleBinding(t *testing.T) {
crb, err := newClusterRoleBinding(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotNil(t, crb)
}
func TestNewRole(t *testing.T) {
r, err := newRole(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotNil(t, r)
}
func TestNewRoleBinding(t *testing.T) {
rb, err := newRoleBinding(CSIProvisionerRBACDefaults)
require.NoError(t, err)
require.NotNil(t, rb)
}

View File

@ -0,0 +1,39 @@
/*
Copyright 2024 The Ceph-CSI 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 kubernetes
import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
)
// CSIProvisionerRBAC describes the interface that is provided by different
// provisioner backends to get details about the required RBAC.
type CSIProvisionerRBAC interface {
GetServiceAccount() *corev1.ServiceAccount
GetClusterRole() *rbacv1.ClusterRole
GetClusterRoleBinding() *rbacv1.ClusterRoleBinding
GetRole() *rbacv1.Role
GetRoleBinding() *rbacv1.RoleBinding
}
// CSIProvisionerRBACValues contains values that can be passed to
// NewCSIProvisionerRBAC() functions for different provisioner backends.
type CSIProvisionerRBACValues struct {
Namespace string
ServiceAccount string
}

23
api/vendor/k8s.io/api/rbac/v1/doc.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
/*
Copyright 2017 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.
*/
// +k8s:deepcopy-gen=package
// +k8s:protobuf-gen=package
// +k8s:openapi-gen=true
// +groupName=rbac.authorization.k8s.io
package v1 // import "k8s.io/api/rbac/v1"

3230
api/vendor/k8s.io/api/rbac/v1/generated.pb.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

203
api/vendor/k8s.io/api/rbac/v1/generated.proto generated vendored Normal file
View File

@ -0,0 +1,203 @@
/*
Copyright 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.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = "proto2";
package k8s.io.api.rbac.v1;
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "k8s.io/api/rbac/v1";
// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole
message AggregationRule {
// ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules.
// If any of the selectors match, then the ClusterRole's permissions will be added
// +optional
repeated k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector clusterRoleSelectors = 1;
}
// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding.
message ClusterRole {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Rules holds all the PolicyRules for this ClusterRole
// +optional
repeated PolicyRule rules = 2;
// AggregationRule is an optional field that describes how to build the Rules for this ClusterRole.
// If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be
// stomped by the controller.
// +optional
optional AggregationRule aggregationRule = 3;
}
// ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace,
// and adds who information via Subject.
message ClusterRoleBinding {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Subjects holds references to the objects the role applies to.
// +optional
repeated Subject subjects = 2;
// RoleRef can only reference a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
// This field is immutable.
optional RoleRef roleRef = 3;
}
// ClusterRoleBindingList is a collection of ClusterRoleBindings
message ClusterRoleBindingList {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// Items is a list of ClusterRoleBindings
repeated ClusterRoleBinding items = 2;
}
// ClusterRoleList is a collection of ClusterRoles
message ClusterRoleList {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// Items is a list of ClusterRoles
repeated ClusterRole items = 2;
}
// PolicyRule holds information that describes a policy rule, but does not contain information
// about who the rule applies to or which namespace the rule applies to.
message PolicyRule {
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
repeated string verbs = 1;
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
// the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
// +optional
repeated string apiGroups = 2;
// Resources is a list of resources this rule applies to. '*' represents all resources.
// +optional
repeated string resources = 3;
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
// +optional
repeated string resourceNames = 4;
// NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
// Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
// Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
// +optional
repeated string nonResourceURLs = 5;
}
// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding.
message Role {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Rules holds all the PolicyRules for this Role
// +optional
repeated PolicyRule rules = 2;
}
// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace.
// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given
// namespace only have effect in that namespace.
message RoleBinding {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Subjects holds references to the objects the role applies to.
// +optional
repeated Subject subjects = 2;
// RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
// This field is immutable.
optional RoleRef roleRef = 3;
}
// RoleBindingList is a collection of RoleBindings
message RoleBindingList {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// Items is a list of RoleBindings
repeated RoleBinding items = 2;
}
// RoleList is a collection of Roles
message RoleList {
// Standard object's metadata.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// Items is a list of Roles
repeated Role items = 2;
}
// RoleRef contains information that points to the role being used
// +structType=atomic
message RoleRef {
// APIGroup is the group for the resource being referenced
optional string apiGroup = 1;
// Kind is the type of resource being referenced
optional string kind = 2;
// Name is the name of resource being referenced
optional string name = 3;
}
// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference,
// or a value for non-objects such as user and group names.
// +structType=atomic
message Subject {
// Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount".
// If the Authorizer does not recognized the kind value, the Authorizer should report an error.
optional string kind = 1;
// APIGroup holds the API group of the referenced subject.
// Defaults to "" for ServiceAccount subjects.
// Defaults to "rbac.authorization.k8s.io" for User and Group subjects.
// +optional
optional string apiGroup = 2;
// Name of the object being referenced.
optional string name = 3;
// Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty
// the Authorizer should report an error.
// +optional
optional string namespace = 4;
}

58
api/vendor/k8s.io/api/rbac/v1/register.go generated vendored Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright 2017 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"
)
const GroupName = "rbac.authorization.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var 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()
}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Role{},
&RoleBinding{},
&RoleBindingList{},
&RoleList{},
&ClusterRole{},
&ClusterRoleBinding{},
&ClusterRoleBindingList{},
&ClusterRoleList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

241
api/vendor/k8s.io/api/rbac/v1/types.go generated vendored Normal file
View File

@ -0,0 +1,241 @@
/*
Copyright 2017 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"
)
// Authorization is calculated against
// 1. evaluation of ClusterRoleBindings - short circuit on match
// 2. evaluation of RoleBindings in the namespace requested - short circuit on match
// 3. deny by default
const (
APIGroupAll = "*"
ResourceAll = "*"
VerbAll = "*"
NonResourceAll = "*"
GroupKind = "Group"
ServiceAccountKind = "ServiceAccount"
UserKind = "User"
// AutoUpdateAnnotationKey is the name of an annotation which prevents reconciliation if set to "false"
AutoUpdateAnnotationKey = "rbac.authorization.kubernetes.io/autoupdate"
)
// Authorization is calculated against
// 1. evaluation of ClusterRoleBindings - short circuit on match
// 2. evaluation of RoleBindings in the namespace requested - short circuit on match
// 3. deny by default
// PolicyRule holds information that describes a policy rule, but does not contain information
// about who the rule applies to or which namespace the rule applies to.
type PolicyRule struct {
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
// the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
// +optional
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
// Resources is a list of resources this rule applies to. '*' represents all resources.
// +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
// +optional
ResourceNames []string `json:"resourceNames,omitempty" protobuf:"bytes,4,rep,name=resourceNames"`
// NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
// Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
// Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
// +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,5,rep,name=nonResourceURLs"`
}
// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference,
// or a value for non-objects such as user and group names.
// +structType=atomic
type Subject struct {
// Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount".
// If the Authorizer does not recognized the kind value, the Authorizer should report an error.
Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
// APIGroup holds the API group of the referenced subject.
// Defaults to "" for ServiceAccount subjects.
// Defaults to "rbac.authorization.k8s.io" for User and Group subjects.
// +optional
APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,2,opt.name=apiGroup"`
// Name of the object being referenced.
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
// Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty
// the Authorizer should report an error.
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"`
}
// RoleRef contains information that points to the role being used
// +structType=atomic
type RoleRef struct {
// APIGroup is the group for the resource being referenced
APIGroup string `json:"apiGroup" protobuf:"bytes,1,opt,name=apiGroup"`
// Kind is the type of resource being referenced
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
// Name is the name of resource being referenced
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding.
type Role struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Rules holds all the PolicyRules for this Role
// +optional
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace.
// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given
// namespace only have effect in that namespace.
type RoleBinding struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Subjects holds references to the objects the role applies to.
// +optional
Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"`
// RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
// This field is immutable.
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RoleBindingList is a collection of RoleBindings
type RoleBindingList struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items is a list of RoleBindings
Items []RoleBinding `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RoleList is a collection of Roles
type RoleList struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items is a list of Roles
Items []Role `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding.
type ClusterRole struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Rules holds all the PolicyRules for this ClusterRole
// +optional
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
// AggregationRule is an optional field that describes how to build the Rules for this ClusterRole.
// If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be
// stomped by the controller.
// +optional
AggregationRule *AggregationRule `json:"aggregationRule,omitempty" protobuf:"bytes,3,opt,name=aggregationRule"`
}
// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole
type AggregationRule struct {
// ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules.
// If any of the selectors match, then the ClusterRole's permissions will be added
// +optional
ClusterRoleSelectors []metav1.LabelSelector `json:"clusterRoleSelectors,omitempty" protobuf:"bytes,1,rep,name=clusterRoleSelectors"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace,
// and adds who information via Subject.
type ClusterRoleBinding struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Subjects holds references to the objects the role applies to.
// +optional
Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"`
// RoleRef can only reference a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
// This field is immutable.
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterRoleBindingList is a collection of ClusterRoleBindings
type ClusterRoleBindingList struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items is a list of ClusterRoleBindings
Items []ClusterRoleBinding `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterRoleList is a collection of ClusterRoles
type ClusterRoleList struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items is a list of ClusterRoles
Items []ClusterRole `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View File

@ -0,0 +1,158 @@
/*
Copyright 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
// This file contains a collection of methods that can be used from go-restful to
// generate Swagger API documentation for its models. Please read this PR for more
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
//
// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
// they are on one line! For multiple line or blocks that you want to ignore use ---.
// Any context after a --- is ignored.
//
// Those methods can be generated by using hack/update-codegen.sh
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
var map_AggregationRule = map[string]string{
"": "AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole",
"clusterRoleSelectors": "ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. If any of the selectors match, then the ClusterRole's permissions will be added",
}
func (AggregationRule) SwaggerDoc() map[string]string {
return map_AggregationRule
}
var map_ClusterRole = map[string]string{
"": "ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding.",
"metadata": "Standard object's metadata.",
"rules": "Rules holds all the PolicyRules for this ClusterRole",
"aggregationRule": "AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be stomped by the controller.",
}
func (ClusterRole) SwaggerDoc() map[string]string {
return map_ClusterRole
}
var map_ClusterRoleBinding = map[string]string{
"": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, and adds who information via Subject.",
"metadata": "Standard object's metadata.",
"subjects": "Subjects holds references to the objects the role applies to.",
"roleRef": "RoleRef can only reference a ClusterRole in the global namespace. If the RoleRef cannot be resolved, the Authorizer must return an error. This field is immutable.",
}
func (ClusterRoleBinding) SwaggerDoc() map[string]string {
return map_ClusterRoleBinding
}
var map_ClusterRoleBindingList = map[string]string{
"": "ClusterRoleBindingList is a collection of ClusterRoleBindings",
"metadata": "Standard object's metadata.",
"items": "Items is a list of ClusterRoleBindings",
}
func (ClusterRoleBindingList) SwaggerDoc() map[string]string {
return map_ClusterRoleBindingList
}
var map_ClusterRoleList = map[string]string{
"": "ClusterRoleList is a collection of ClusterRoles",
"metadata": "Standard object's metadata.",
"items": "Items is a list of ClusterRoles",
}
func (ClusterRoleList) SwaggerDoc() map[string]string {
return map_ClusterRoleList
}
var map_PolicyRule = map[string]string{
"": "PolicyRule holds information that describes a policy rule, but does not contain information about who the rule applies to or which namespace the rule applies to.",
"verbs": "Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.",
"apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. \"\" represents the core API group and \"*\" represents all API groups.",
"resources": "Resources is a list of resources this rule applies to. '*' represents all resources.",
"resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.",
"nonResourceURLs": "NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to API resources (such as \"pods\" or \"secrets\") or non-resource URL paths (such as \"/api\"), but not both.",
}
func (PolicyRule) SwaggerDoc() map[string]string {
return map_PolicyRule
}
var map_Role = map[string]string{
"": "Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding.",
"metadata": "Standard object's metadata.",
"rules": "Rules holds all the PolicyRules for this Role",
}
func (Role) SwaggerDoc() map[string]string {
return map_Role
}
var map_RoleBinding = map[string]string{
"": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.",
"metadata": "Standard object's metadata.",
"subjects": "Subjects holds references to the objects the role applies to.",
"roleRef": "RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. If the RoleRef cannot be resolved, the Authorizer must return an error. This field is immutable.",
}
func (RoleBinding) SwaggerDoc() map[string]string {
return map_RoleBinding
}
var map_RoleBindingList = map[string]string{
"": "RoleBindingList is a collection of RoleBindings",
"metadata": "Standard object's metadata.",
"items": "Items is a list of RoleBindings",
}
func (RoleBindingList) SwaggerDoc() map[string]string {
return map_RoleBindingList
}
var map_RoleList = map[string]string{
"": "RoleList is a collection of Roles",
"metadata": "Standard object's metadata.",
"items": "Items is a list of Roles",
}
func (RoleList) SwaggerDoc() map[string]string {
return map_RoleList
}
var map_RoleRef = map[string]string{
"": "RoleRef contains information that points to the role being used",
"apiGroup": "APIGroup is the group for the resource being referenced",
"kind": "Kind is the type of resource being referenced",
"name": "Name is the name of resource being referenced",
}
func (RoleRef) SwaggerDoc() map[string]string {
return map_RoleRef
}
var map_Subject = map[string]string{
"": "Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, or a value for non-objects such as user and group names.",
"kind": "Kind of object being referenced. Values defined by this API group are \"User\", \"Group\", and \"ServiceAccount\". If the Authorizer does not recognized the kind value, the Authorizer should report an error.",
"apiGroup": "APIGroup holds the API group of the referenced subject. Defaults to \"\" for ServiceAccount subjects. Defaults to \"rbac.authorization.k8s.io\" for User and Group subjects.",
"name": "Name of the object being referenced.",
"namespace": "Namespace of the referenced object. If the object kind is non-namespace, such as \"User\" or \"Group\", and this value is not empty the Authorizer should report an error.",
}
func (Subject) SwaggerDoc() map[string]string {
return map_Subject
}
// AUTO-GENERATED FUNCTIONS END HERE

390
api/vendor/k8s.io/api/rbac/v1/zz_generated.deepcopy.go generated vendored Normal file
View File

@ -0,0 +1,390 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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 *AggregationRule) DeepCopyInto(out *AggregationRule) {
*out = *in
if in.ClusterRoleSelectors != nil {
in, out := &in.ClusterRoleSelectors, &out.ClusterRoleSelectors
*out = make([]metav1.LabelSelector, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AggregationRule.
func (in *AggregationRule) DeepCopy() *AggregationRule {
if in == nil {
return nil
}
out := new(AggregationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterRole) DeepCopyInto(out *ClusterRole) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]PolicyRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.AggregationRule != nil {
in, out := &in.AggregationRule, &out.AggregationRule
*out = new(AggregationRule)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRole.
func (in *ClusterRole) DeepCopy() *ClusterRole {
if in == nil {
return nil
}
out := new(ClusterRole)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterRole) 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 *ClusterRoleBinding) DeepCopyInto(out *ClusterRoleBinding) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Subjects != nil {
in, out := &in.Subjects, &out.Subjects
*out = make([]Subject, len(*in))
copy(*out, *in)
}
out.RoleRef = in.RoleRef
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRoleBinding.
func (in *ClusterRoleBinding) DeepCopy() *ClusterRoleBinding {
if in == nil {
return nil
}
out := new(ClusterRoleBinding)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterRoleBinding) 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 *ClusterRoleBindingList) DeepCopyInto(out *ClusterRoleBindingList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ClusterRoleBinding, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRoleBindingList.
func (in *ClusterRoleBindingList) DeepCopy() *ClusterRoleBindingList {
if in == nil {
return nil
}
out := new(ClusterRoleBindingList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterRoleBindingList) 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 *ClusterRoleList) DeepCopyInto(out *ClusterRoleList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ClusterRole, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRoleList.
func (in *ClusterRoleList) DeepCopy() *ClusterRoleList {
if in == nil {
return nil
}
out := new(ClusterRoleList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterRoleList) 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 *PolicyRule) DeepCopyInto(out *PolicyRule) {
*out = *in
if in.Verbs != nil {
in, out := &in.Verbs, &out.Verbs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.APIGroups != nil {
in, out := &in.APIGroups, &out.APIGroups
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ResourceNames != nil {
in, out := &in.ResourceNames, &out.ResourceNames
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NonResourceURLs != nil {
in, out := &in.NonResourceURLs, &out.NonResourceURLs
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyRule.
func (in *PolicyRule) DeepCopy() *PolicyRule {
if in == nil {
return nil
}
out := new(PolicyRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Role) DeepCopyInto(out *Role) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]PolicyRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Role.
func (in *Role) DeepCopy() *Role {
if in == nil {
return nil
}
out := new(Role)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Role) 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 *RoleBinding) DeepCopyInto(out *RoleBinding) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Subjects != nil {
in, out := &in.Subjects, &out.Subjects
*out = make([]Subject, len(*in))
copy(*out, *in)
}
out.RoleRef = in.RoleRef
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleBinding.
func (in *RoleBinding) DeepCopy() *RoleBinding {
if in == nil {
return nil
}
out := new(RoleBinding)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RoleBinding) 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 *RoleBindingList) DeepCopyInto(out *RoleBindingList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]RoleBinding, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleBindingList.
func (in *RoleBindingList) DeepCopy() *RoleBindingList {
if in == nil {
return nil
}
out := new(RoleBindingList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RoleBindingList) 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 *RoleList) DeepCopyInto(out *RoleList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Role, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleList.
func (in *RoleList) DeepCopy() *RoleList {
if in == nil {
return nil
}
out := new(RoleList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RoleList) 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 *RoleRef) DeepCopyInto(out *RoleRef) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleRef.
func (in *RoleRef) DeepCopy() *RoleRef {
if in == nil {
return nil
}
out := new(RoleRef)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Subject) DeepCopyInto(out *Subject) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subject.
func (in *Subject) DeepCopy() *Subject {
if in == nil {
return nil
}
out := new(Subject)
in.DeepCopyInto(out)
return out
}

View File

@ -59,6 +59,7 @@ gopkg.in/yaml.v3
# k8s.io/api v0.29.2 # k8s.io/api v0.29.2
## explicit; go 1.21 ## explicit; go 1.21
k8s.io/api/core/v1 k8s.io/api/core/v1
k8s.io/api/rbac/v1
k8s.io/api/storage/v1 k8s.io/api/storage/v1
# k8s.io/apimachinery v0.29.2 # k8s.io/apimachinery v0.29.2
## explicit; go 1.21 ## explicit; go 1.21

View File

@ -19,6 +19,7 @@ all: \
cephfs/kubernetes/csi-config-map.yaml \ cephfs/kubernetes/csi-config-map.yaml \
nfs/kubernetes/csidriver.yaml \ nfs/kubernetes/csidriver.yaml \
nfs/kubernetes/csi-config-map.yaml \ nfs/kubernetes/csi-config-map.yaml \
nfs/kubernetes/csi-provisioner-rbac.yaml \
rbd/kubernetes/csidriver.yaml \ rbd/kubernetes/csidriver.yaml \
rbd/kubernetes/csi-config-map.yaml rbd/kubernetes/csi-config-map.yaml
@ -37,6 +38,9 @@ nfs/kubernetes/csidriver.yaml: ../api/deploy/kubernetes/nfs/csidriver.yaml ../ap
nfs/kubernetes/csi-config-map.yaml: ../api/deploy/kubernetes/nfs/csi-config-map.* nfs/kubernetes/csi-config-map.yaml: ../api/deploy/kubernetes/nfs/csi-config-map.*
$(MAKE) -C ../tools generate-deploy $(MAKE) -C ../tools generate-deploy
nfs/kubernetes/csi-provisioner-rbac.yaml: ../api/deploy/kubernetes/nfs/csi-provisioner-rbac*
$(MAKE) -C ../tools generate-deploy
rbd/kubernetes/csidriver.yaml: ../api/deploy/kubernetes/rbd/csidriver.yaml ../api/deploy/kubernetes/rbd/csidriver.go rbd/kubernetes/csidriver.yaml: ../api/deploy/kubernetes/rbd/csidriver.yaml ../api/deploy/kubernetes/rbd/csidriver.go
$(MAKE) -C ../tools generate-deploy $(MAKE) -C ../tools generate-deploy

View File

@ -1,8 +1,17 @@
#
# /!\ DO NOT MODIFY THIS FILE
#
# This file has been automatically generated by Ceph-CSI yamlgen.
# The source for the contents can be found in the api/deploy directory, make
# your modifications there.
#
--- ---
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
name: nfs-csi-provisioner name: "nfs-csi-provisioner"
namespace: "default"
--- ---
kind: ClusterRole kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
@ -51,25 +60,26 @@ rules:
- apiGroups: ["snapshot.storage.k8s.io"] - apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"] resources: ["volumesnapshots"]
verbs: ["get", "list"] verbs: ["get", "list"]
--- ---
kind: ClusterRoleBinding kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
metadata: metadata:
name: nfs-csi-provisioner-role name: "nfs-csi-provisioner-role"
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: nfs-csi-provisioner name: "nfs-csi-provisioner"
namespace: default namespace: "default"
roleRef: roleRef:
kind: ClusterRole kind: ClusterRole
name: nfs-external-provisioner-runner name: nfs-external-provisioner-runner
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
--- ---
kind: Role kind: Role
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
metadata: metadata:
# replace with non-default namespace name namespace: "default"
namespace: default
name: nfs-external-provisioner-cfg name: nfs-external-provisioner-cfg
rules: rules:
# remove this once we stop supporting v1.0.0 # remove this once we stop supporting v1.0.0
@ -79,18 +89,17 @@ rules:
- apiGroups: ["coordination.k8s.io"] - apiGroups: ["coordination.k8s.io"]
resources: ["leases"] resources: ["leases"]
verbs: ["get", "watch", "list", "delete", "update", "create"] verbs: ["get", "watch", "list", "delete", "update", "create"]
--- ---
kind: RoleBinding kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
metadata: metadata:
name: nfs-csi-provisioner-role-cfg name: "nfs-csi-provisioner-role-cfg"
# replace with non-default namespace name namespace: "default"
namespace: default
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: nfs-csi-provisioner name: "nfs-csi-provisioner"
# replace with non-default namespace name namespace: "default"
namespace: default
roleRef: roleRef:
kind: Role kind: Role
name: nfs-external-provisioner-cfg name: nfs-external-provisioner-cfg

View File

@ -12,43 +12,25 @@ Hence, those capabilities are documented below.
## RBD ## RBD
We have provisioner, controller expand and node stage secrets in storageclass. We have provisioner, controller expand and node stage secrets in storageclass.
For the provisioner and controller expand stage secrets in storageclass, the For RBD the user needs to have the below Ceph capabilities:
user needs to have the below Ceph capabilities.
``` ```
"mon", "profile rbd", mgr "profile rbd pool=csi"
"mgr", "allow rw", osd "profile rbd pool=csi"
"osd", "profile rbd" mon "profile rbd"
```
And for the node stage secret in storageclass, the user needs to have the
below mentioned ceph capabilities.
```
"mon", "profile rbd",
"osd", "profile rbd",
"mgr", "allow rw"
``` ```
## CephFS ## CephFS
Similarly in CephFS, for the provisioner and controller expand stage secret in Similarly in CephFS, we have provisioner, controller expand and node stage
storageclass, the user needs to have the below mentioned ceph capabilities. secrets in storageclass, the user needs to have the below mentioned ceph
capabilities:
``` ```
"mon", "allow r", mgr "allow rw"
"mgr", "allow rw", osd "allow rw tag cephfs metadata=cephfs, allow rw tag cephfs data=cephfs"
"osd", "allow rw tag cephfs metadata=*" mds "allow r fsname=cephfs path=/volumes, allow rws fsname=cephfs path=/volumes/csi"
``` mon "allow r fsname=cephfs"
And for node stage secret in storageclass, the user needs to have
the below mentioned ceph capabilities.
```
"mon", "allow r",
"mgr", "allow rw",
"osd", "allow rw tag cephfs *=*",
"mds", "allow rw"
``` ```
To get more insights on capabilities of CephFS you can refer To get more insights on capabilities of CephFS you can refer
@ -56,8 +38,8 @@ To get more insights on capabilities of CephFS you can refer
## Command to a create user with required capabilities ## Command to a create user with required capabilities
`kubernetes` in the below commands represents an user which is subjected `USER`, `POOL` and `FS_NAME` with `SUB_VOL` variables below is subject to
to change as per your requirement. change, please adjust them to your needs.
### create user for RBD ### create user for RBD
@ -65,25 +47,23 @@ The command for provisioner and node stage secret for rbd will be same as
they have similar capability requirements. they have similar capability requirements.
```bash ```bash
ceph auth get-or-create client.kubernetes \ USER=csi-rbd
mon 'profile rbd' \ POOL=csi
osd 'profile rbd' \ ceph auth get-or-create client.$USER \
mgr 'allow rw' mgr "profile rbd pool=$POOL" \
osd "profile rbd pool=$POOL"
mon "profile rbd"
``` ```
### create user for CephFS ### create user for CephFS
```bash ```bash
ceph auth get-or-create client.kubernetes \ USER=csi-cephfs
mon 'allow r' \ FS_NAME=cephfs
osd 'allow rw tag cephfs metadata=*' \ SUB_VOL=csi
mgr 'allow rw' ceph auth get-or-create client.$USER \
``` mgr "allow rw" \
osd "allow rw tag cephfs metadata=$FS_NAME, allow rw tag cephfs data=$FS_NAME" \
```bash mds "allow r fsname=$FS_NAME path=/volumes, allow rws fsname=$FS_NAME path=/volumes/$SUB_VOL" \
ceph auth get-or-create client.kubernetes \ mon "allow r fsname=$FS_NAME"
mon 'allow r' \
osd 'allow rw tag cephfs *=*' \
mgr 'allow rw' \
mds 'allow rw'
``` ```

View File

@ -448,6 +448,33 @@ the AWS KMS is expected to contain:
This Secret is expected to be created by the tenant/user in each namespace where This Secret is expected to be created by the tenant/user in each namespace where
Ceph-CSI is used to create encrypted rbd volumes. Ceph-CSI is used to create encrypted rbd volumes.
#### Configuring Azure key vault
Ceph-CSI can be configured to use
[Azure key vault](https://azure.microsoft.com/en-in/products/key-vault),
for encrypting RBD volumes.
There are a few settings that need to be included in the [KMS configuration
file](../examples/kms/vault/kms-config.yaml):
1. `KMS_PROVIDER`: should be set to `azure-kv`.
1. `AZURE_CERT_SECRET_NAME`: name of the Kubernetes Secret (in the Namespace where
Ceph-CSI is deployed) which contains the credentials for communicating with
Azure. This defaults to `ceph-csi-azure-credentials`.
1. `AZURE_VAULT_URL`: URL to access the Azure Key Vault service.
1. `AZURE_CLIENT_ID`: Client ID of the Azure application object (service principal)
created in Azure Active Directory that serves as the username.
1. `AZURE_TENANT_ID`: Tenant ID of the service principal.
The [Secret with credentials](../examples/kms/vault/azure-credentials.yaml) for
the Azure KMS is expected to contain:
1. `CLIENT_CERT`: The client certificate used for authentication
with Azure Key Vault.
This Secret is expected to be created by the user in the namespace where Ceph-CSI
is deployed.
#### Configuring KMIP KMS #### Configuring KMIP KMS
The Key Management Interoperability Protocol (KMIP) is an extensible The Key Management Interoperability Protocol (KMIP) is an extensible

View File

@ -0,0 +1,58 @@
# Encrypted volumes with Azure Key Vault
Azure Key Vault is a cloud service for securely storing and accessing secrets.
A secret is anything that you want to tightly control access to, such as API
keys, passwords, certificates, or cryptographic keys.
## Connection to Azure Key Vault
Below values are used to establish the connection to the Key Vault
service from the CSI driver and to make use of the secrets
`GetSecret`/`SetSecret`/`DeleteSecret` operations:
```text
* AZURE_VAULT_URL
The URL used to access the Azure Key Vault service.
* AZURE_CLIENT_ID
The Client ID of the Azure application object (also known as the service principal).
This ID serves as the username.
* AZURE_TENANT_ID
The Tenant ID associated with the service principal.
* CLIENT_CERT
The client certificate (which includes the private key and is not password protected)
used for authentication with Azure Key Vault.
```
### Values provided in the connection secret
Considering `AZURE_CLIENT_CERTIFICATE` is sensitive information,
it will be provided as a Kubernetes secret to the Ceph-CSI driver. The Ceph-CSI
KMS plugin interface for the Azure key vault will read the secret name from the
kms configMap and fetch the certificate.
### Values provided in the config map
`AZURE_VAULT_URL`, `AZURE_CLIENT_ID`, `AZURE_TENANT_ID` are part of the
KMS ConfigMap.
### Storage class values or configuration
The Storage class has to be enabled for encryption and `encryptionKMSID` has
to be provided which is the matching value in the kms config map.
## Volume Encrypt or Decrypt Operation
Ceph-CSI generate's unique passphrase for each volume to be used to
encrypt/decrypt. The passphrase is securely store in Azure key vault
using the `SetSecret` operation. At time of decrypt the passphrase is
retrieved from the key vault using the `GetSecret`operation.
## Volume Delete Operation
When the corresponding volume is deleted, the stored secret in the Azure Key
Vault will be deleted.
> Note: Ceph-CSI solely deletes the secret without permanent removal (purging).

View File

@ -94,5 +94,9 @@ func replaceNamespaceInTemplate(filePath string) (string, error) {
return "", err return "", err
} }
return strings.ReplaceAll(string(read), "namespace: default", fmt.Sprintf("namespace: %s", cephCSINamespace)), nil // template can contain "default" as namespace, with or without ".
templ := strings.ReplaceAll(string(read), "namespace: default", fmt.Sprintf("namespace: %s", cephCSINamespace))
templ = strings.ReplaceAll(templ, "namespace: \"default\"", fmt.Sprintf("namespace: %s", cephCSINamespace))
return templ, nil
} }

View File

@ -0,0 +1,10 @@
---
# This is an example Kubernetes secret that can be created in the Kubernetes
# namespace where Ceph-CSI is deployed. The contents of this secret will be
# used to connect to the Azure Key Vault.
apiVersion: v1
kind: Secret
metadata:
name: ceph-csi-azure-credentials
data:
CLIENT_CERT: ""

View File

@ -83,5 +83,13 @@ data:
"READ_TIMEOUT": 10, "READ_TIMEOUT": 10,
"WRITE_TIMEOUT": 10 "WRITE_TIMEOUT": 10
} }
azure-test: |-
{
"KMS_PROVIDER": "azure-kv",
"AZURE_CERT_SECRET_NAME": "ceph-csi-azure-credentials",
"AZURE_VAULT_URL": "https://vault-name.vault.azure.net/",
"AZURE_CLIENT_ID": "__CLIENT_ID__",
"AZURE_TENANT_ID": "__TENANT_ID__"
}
metadata: metadata:
name: csi-kms-connection-details name: csi-kms-connection-details

View File

@ -108,6 +108,13 @@ data:
"TLS_SERVER_NAME": "kmip.ciphertrustmanager.local", "TLS_SERVER_NAME": "kmip.ciphertrustmanager.local",
"READ_TIMEOUT": 10, "READ_TIMEOUT": 10,
"WRITE_TIMEOUT": 10 "WRITE_TIMEOUT": 10
},
"azure-test": {
"KMS_PROVIDER": "azure-kv",
"AZURE_CERT_SECRET_NAME": "ceph-csi-azure-credentials",
"AZURE_VAULT_URL": "https://vault-name.vault.azure.net/",
"AZURE_CLIENT_ID": "__CLIENT_ID__",
"AZURE_TENANT_ID": "__TENANT_ID__"
} }
} }
metadata: metadata:

14
go.mod
View File

@ -30,7 +30,7 @@ require (
golang.org/x/crypto v0.21.0 golang.org/x/crypto v0.21.0
golang.org/x/net v0.22.0 golang.org/x/net v0.22.0
golang.org/x/sys v0.18.0 golang.org/x/sys v0.18.0
google.golang.org/grpc v1.62.0 google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
// //
// when updating k8s.io/kubernetes, make sure to update the replace section too // when updating k8s.io/kubernetes, make sure to update the replace section too
@ -48,6 +48,15 @@ require (
) )
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0
)
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/ansel1/merry v1.6.2 // indirect github.com/ansel1/merry v1.6.2 // indirect
github.com/ansel1/merry/v2 v2.0.1 // indirect github.com/ansel1/merry/v2 v2.0.1 // indirect
@ -83,6 +92,7 @@ require (
github.com/go-openapi/swag v0.22.3 // indirect github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/cel-go v0.17.7 // indirect github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gnostic-models v0.6.8 // indirect
@ -108,6 +118,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-isatty v0.0.17 // indirect
@ -124,6 +135,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/selinux v1.11.0 // indirect github.com/opencontainers/selinux v1.11.0 // indirect
github.com/openshift/api v0.0.0-20240115183315-0793e918179d // indirect github.com/openshift/api v0.0.0-20240115183315-0793e918179d // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect

24
go.sum
View File

@ -759,6 +759,16 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
github.com/Azure/azure-sdk-for-go v62.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v62.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0 h1:h4Zxgmi9oyZL2l8jeg1iRTqPloHktywWcu0nlJmo1tA=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0/go.mod h1:LgLGXawqSreJz135Elog0ywTJDsm0Hz2k+N+6ZK35u8=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
@ -771,6 +781,8 @@ github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcP
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -916,6 +928,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@ -1051,6 +1065,8 @@ github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
@ -1323,6 +1339,8 @@ github.com/kubernetes-csi/csi-lib-utils v0.17.0/go.mod h1:2Ba5/aQgUjbpqyC2uCcFwM
github.com/kubernetes-csi/external-snapshotter/client/v4 v4.0.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= github.com/kubernetes-csi/external-snapshotter/client/v4 v4.0.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys=
github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 h1:j3YK74myEQRxR/srciTpOrm221SAvz6J5OVWbyfeXFo= github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 h1:j3YK74myEQRxR/srciTpOrm221SAvz6J5OVWbyfeXFo=
github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0/go.mod h1:FlyYFe32mPxKEPaRXKNxfX576d1AoCzstYDoOOnyMA4= github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0/go.mod h1:FlyYFe32mPxKEPaRXKNxfX576d1AoCzstYDoOOnyMA4=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/libopenstorage/autopilot-api v0.6.1-0.20210128210103-5fbb67948648/go.mod h1:6JLrPbR3ZJQFbUY/+QJMl/aF00YdIrLf8/GWAplgvJs= github.com/libopenstorage/autopilot-api v0.6.1-0.20210128210103-5fbb67948648/go.mod h1:6JLrPbR3ZJQFbUY/+QJMl/aF00YdIrLf8/GWAplgvJs=
github.com/libopenstorage/openstorage v8.0.0+incompatible/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= github.com/libopenstorage/openstorage v8.0.0+incompatible/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc=
github.com/libopenstorage/operator v0.0.0-20200725001727-48d03e197117/go.mod h1:Qh+VXOB6hj60VmlgsmY+R1w+dFuHK246UueM4SAqZG0= github.com/libopenstorage/operator v0.0.0-20200725001727-48d03e197117/go.mod h1:Qh+VXOB6hj60VmlgsmY+R1w+dFuHK246UueM4SAqZG0=
@ -1468,6 +1486,8 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -2502,8 +2522,8 @@ google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpX
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View File

@ -192,7 +192,7 @@ func CheckVolExists(ctx context.Context,
// found a volume already available, process and return it! // found a volume already available, process and return it!
vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion) "", volOptions.ClusterID, imageUUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -299,7 +299,7 @@ func ReserveVol(ctx context.Context, volOptions *VolumeOptions, secret map[strin
volOptions.VolID = vid.FsSubvolName volOptions.VolID = vid.FsSubvolName
// generate the volume ID to return to the CO system // generate the volume ID to return to the CO system
vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.VolumeID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion) "", volOptions.ClusterID, imageUUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -345,7 +345,7 @@ func ReserveSnap(
// generate the snapshot ID to return to the CO system // generate the snapshot ID to return to the CO system
vid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, vid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, imageUUID, fsutil.VolIDVersion) "", volOptions.ClusterID, imageUUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -453,7 +453,7 @@ func CheckSnapExists(
// found a snapshot already available, process and return it! // found a snapshot already available, process and return it!
sid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID, sid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
"", volOptions.ClusterID, snapUUID, fsutil.VolIDVersion) "", volOptions.ClusterID, snapUUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -20,9 +20,6 @@ package util
type VolumeID string type VolumeID string
const ( const (
// VolIDVersion is the version number of volume ID encoding scheme.
VolIDVersion uint16 = 1
// RadosNamespace to store CSI specific objects and keys. // RadosNamespace to store CSI specific objects and keys.
RadosNamespace = "csi" RadosNamespace = "csi"
) )

View File

@ -36,7 +36,7 @@ type VolumeGroupJournal interface {
Connect( Connect(
monitors, monitors,
namespace string, namespace string,
cr *util.Credentials) (*volumeGroupJournalConfig, error) cr *util.Credentials) error
// Destroy frees any resources and invalidates the journal connection. // Destroy frees any resources and invalidates the journal connection.
Destroy() Destroy()
// SetNamespace sets the namespace for the journal. // SetNamespace sets the namespace for the journal.
@ -84,8 +84,8 @@ type volumeGroupJournalConfig struct {
*Connection *Connection
} }
// NewCSIVolumeroupJournal returns an instance of VolumeGroupJournal for groups. // NewCSIVolumeGroupJournal returns an instance of VolumeGroupJournal for groups.
func NewCSIVolumeroupJournal(suffix string) VolumeGroupJournal { func NewCSIVolumeGroupJournal(suffix string) VolumeGroupJournal {
return &volumeGroupJournalConfig{ return &volumeGroupJournalConfig{
Config: &Config{ Config: &Config{
csiDirectory: "csi.groups." + suffix, csiDirectory: "csi.groups." + suffix,
@ -105,7 +105,7 @@ func (sgj *volumeGroupJournalConfig) SetNamespace(ns string) {
// NewCSIVolumeGroupJournalWithNamespace returns an instance of VolumeGroupJournal for // NewCSIVolumeGroupJournalWithNamespace returns an instance of VolumeGroupJournal for
// volume groups using a predetermined namespace value. // volume groups using a predetermined namespace value.
func NewCSIVolumeGroupJournalWithNamespace(suffix, ns string) VolumeGroupJournal { func NewCSIVolumeGroupJournalWithNamespace(suffix, ns string) VolumeGroupJournal {
j := NewCSIVolumeroupJournal(suffix) j := NewCSIVolumeGroupJournal(suffix)
j.SetNamespace(ns) j.SetNamespace(ns)
return j return j
@ -115,14 +115,14 @@ func (sgj *volumeGroupJournalConfig) Connect(
monitors, monitors,
namespace string, namespace string,
cr *util.Credentials, cr *util.Credentials,
) (*volumeGroupJournalConfig, error) { ) error {
conn, err := sgj.Config.Connect(monitors, namespace, cr) conn, err := sgj.Config.Connect(monitors, namespace, cr)
if err != nil { if err != nil {
return nil, err return err
} }
sgj.Connection = conn sgj.Connection = conn
return sgj, nil return nil
} }
func (sgj *volumeGroupJournalConfig) Destroy() { func (sgj *volumeGroupJournalConfig) Destroy() {

219
internal/kms/azure_vault.go Normal file
View File

@ -0,0 +1,219 @@
/*
Copyright 2024 The Ceph-CSI 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 kms
import (
"context"
"encoding/base64"
"errors"
"fmt"
"github.com/ceph/ceph-csi/internal/util/k8s"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
kmsTypeAzure = "azure-kv"
// azureDefaultSecretsName is the default name of the Kubernetes secret
// that contains the credentials to access the Azure key vault. The name
// the secret can be configured by setting the `AZURE_CERT_SECRET_NAME` option.
//
// #nosec:G101, value not credentials, just references token.
azureDefaultSecretsName = "ceph-csi-azure-credentials"
// azureSecretNameKey contains the name of the Kubernetes secret that has
// the credentials to access the Azure key vault.
//
// #nosec:G101, no hardcoded secret, this is a configuration key.
azureSecretNameKey = "AZURE_CERT_SECRET_NAME"
azureVaultURL = "AZURE_VAULT_URL"
azureClientID = "AZURE_CLIENT_ID"
azureTenantID = "AZURE_TENANT_ID"
// The following options are part of the Kubernetes secrets.
//
// #nosec:G101, no hardcoded secrets, only configuration keys.
azureClientCertificate = "CLIENT_CERT"
)
var _ = RegisterProvider(Provider{
UniqueID: kmsTypeAzure,
Initializer: initAzureKeyVaultKMS,
})
type azureKMS struct {
// basic
namespace string
secretName string
integratedDEK
// standard
vaultURL string
clientID string
tenantID string
clientCertificate string
}
func initAzureKeyVaultKMS(args ProviderInitArgs) (EncryptionKMS, error) {
kms := &azureKMS{
namespace: args.Namespace,
}
// required options for further configuration (getting secrets)
err := setConfigString(&kms.secretName, args.Config, azureSecretNameKey)
if errors.Is(err, errConfigOptionInvalid) {
return nil, err
} else if errors.Is(err, errConfigOptionMissing) {
kms.secretName = azureDefaultSecretsName
}
err = setConfigString(&kms.vaultURL, args.Config, azureVaultURL)
if err != nil {
return nil, err
}
err = setConfigString(&kms.clientID, args.Config, azureClientID)
if err != nil {
return nil, err
}
err = setConfigString(&kms.tenantID, args.Config, azureTenantID)
if err != nil {
return nil, err
}
// read the kubernetes secret with credentials
secrets, err := kms.getSecrets()
if err != nil {
return nil, fmt.Errorf("failed to get secrets for %T, %w", kms, err)
}
var encodedClientCertificate string
err = setConfigString(&encodedClientCertificate, secrets, azureClientCertificate)
if err != nil {
return nil, err
}
clientCertificate, err := base64.StdEncoding.DecodeString(encodedClientCertificate)
if err != nil {
return nil, fmt.Errorf("failed to decode client certificate: %w", err)
}
kms.clientCertificate = string(clientCertificate)
return kms, nil
}
func (kms *azureKMS) Destroy() {
// Nothing to do.
}
func (kms *azureKMS) getService() (*azsecrets.Client, error) {
certs, key, err := azidentity.ParseCertificates([]byte(kms.clientCertificate), []byte{})
if err != nil {
return nil, fmt.Errorf("failed to parse Azure client certificate: %w", err)
}
creds, err := azidentity.NewClientCertificateCredential(kms.tenantID, kms.clientID, certs, key, nil)
if err != nil {
return nil, fmt.Errorf("failed to create Azure credentials: %w", err)
}
azClient, err := azsecrets.NewClient(kms.vaultURL, creds, nil)
if err != nil {
return nil, fmt.Errorf("failed to create Azure client: %w", err)
}
return azClient, nil
}
func (kms *azureKMS) getSecrets() (map[string]interface{}, error) {
c, err := k8s.NewK8sClient()
if err != nil {
return nil, fmt.Errorf("failed to connect to kubernetes to "+
"get secret %s/%s: %w", kms.namespace, kms.secretName, err)
}
secret, err := c.CoreV1().Secrets(kms.namespace).Get(context.TODO(),
kms.secretName, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to get secret %s/%s: %w", kms.namespace, kms.secretName, err)
}
config := make(map[string]interface{})
for k, v := range secret.Data {
switch k {
case azureClientCertificate:
config[k] = string(v)
default:
return nil, fmt.Errorf("unsupported option for KMS provider %q: %s", kmsTypeAzure, k)
}
}
return config, nil
}
// FetchDEK returns passphrase from Azure key vault.
func (kms *azureKMS) FetchDEK(ctx context.Context, key string) (string, error) {
svc, err := kms.getService()
if err != nil {
return "", fmt.Errorf("failed to get KMS service: %w", err)
}
getSecretResponse, err := svc.GetSecret(ctx, key, "", nil)
if err != nil {
return "", fmt.Errorf("failed to get secret: %w", err)
}
return *getSecretResponse.Value, nil
}
// StoreDEK saves new passphrase to Azure key vault.
func (kms *azureKMS) StoreDEK(ctx context.Context, key, value string) error {
svc, err := kms.getService()
if err != nil {
return fmt.Errorf("failed to get KMS service: %w", err)
}
setSecretParams := azsecrets.SetSecretParameters{
Value: &value,
}
_, err = svc.SetSecret(ctx, key, setSecretParams, nil)
if err != nil {
return fmt.Errorf("failed to set seceret %w", err)
}
return nil
}
// RemoveDEK deletes passphrase from Azure key vault.
func (kms *azureKMS) RemoveDEK(ctx context.Context, key string) error {
svc, err := kms.getService()
if err != nil {
return fmt.Errorf("failed to get KMS service: %w", err)
}
_, err = svc.DeleteSecret(ctx, key, nil)
if err != nil {
return fmt.Errorf("failed to delete seceret %w", err)
}
return nil
}

View File

@ -0,0 +1,29 @@
/*
Copyright 2024 The Ceph-CSI 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 kms
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAzureKMSRegistered(t *testing.T) {
t.Parallel()
_, ok := kmsManager.providers[kmsTypeAzure]
assert.True(t, ok)
}

View File

@ -22,11 +22,6 @@ import (
"github.com/ceph/ceph-csi/internal/journal" "github.com/ceph/ceph-csi/internal/journal"
) )
const (
// volIDVersion is the version number of volume ID encoding scheme.
volIDVersion uint16 = 1
)
var ( var (
// CSIInstanceID is the instance ID that is unique to an instance of CSI, used when sharing // CSIInstanceID is the instance ID that is unique to an instance of CSI, used when sharing
// ceph clusters across CSI instances, to differentiate omap names per CSI instance. // ceph clusters across CSI instances, to differentiate omap names per CSI instance.

View File

@ -143,11 +143,23 @@ type detachRBDImageArgs struct {
// getDeviceList queries rbd about mapped devices and returns a list of deviceInfo // getDeviceList queries rbd about mapped devices and returns a list of deviceInfo
// It will selectively list devices mapped using krbd or nbd as specified by accessType. // It will selectively list devices mapped using krbd or nbd as specified by accessType.
func getDeviceList(ctx context.Context, accessType string) ([]deviceInfo, error) { func getDeviceList(ctx context.Context, accessType string) ([]deviceInfo, error) {
var (
stdout string
err error
)
if accessType == accessTypeKRbd {
// rbd device list --format json --device-type [krbd|nbd] // rbd device list --format json --device-type [krbd|nbd]
stdout, _, err := util.ExecCommand(ctx, rbd, "device", "list", "--format="+"json", "--device-type", accessType) stdout, _, err = util.ExecCommand(ctx, rbd, "device", "list", "--format=json", "--device-type", accessType)
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting device list from rbd for devices of type (%s): %w", accessType, err) return nil, fmt.Errorf("error getting device list from rbd for devices of type (%s): %w", accessType, err)
} }
} else {
stdout, _, err = util.ExecCommand(ctx, "rbd-nbd", "list-mapped", "--format=json")
if err != nil {
return nil, fmt.Errorf("error getting device list from rbd-nbd for devices of type (%s): %w", accessType, err)
}
}
var devices []*rbdDeviceInfo var devices []*rbdDeviceInfo
err = json.Unmarshal([]byte(stdout), &devices) err = json.Unmarshal([]byte(stdout), &devices)
@ -352,29 +364,27 @@ func attachRBDImage(ctx context.Context, volOptions *rbdVolume, device string, c
} }
func appendNbdDeviceTypeAndOptions(cmdArgs []string, userOptions, cookie string) []string { func appendNbdDeviceTypeAndOptions(cmdArgs []string, userOptions, cookie string) []string {
cmdArgs = append(cmdArgs, "--device-type", accessTypeNbd)
isUnmap := CheckSliceContains(cmdArgs, "unmap") isUnmap := CheckSliceContains(cmdArgs, "unmap")
if !isUnmap { if !isUnmap {
if !strings.Contains(userOptions, useNbdNetlink) { if !strings.Contains(userOptions, useNbdNetlink) {
cmdArgs = append(cmdArgs, "--options", useNbdNetlink) cmdArgs = append(cmdArgs, "--"+useNbdNetlink)
} }
if !strings.Contains(userOptions, setNbdReattach) { if !strings.Contains(userOptions, setNbdReattach) {
cmdArgs = append(cmdArgs, "--options", fmt.Sprintf("%s=%d", setNbdReattach, defaultNbdReAttachTimeout)) cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%d", setNbdReattach, defaultNbdReAttachTimeout))
} }
if !strings.Contains(userOptions, setNbdIOTimeout) { if !strings.Contains(userOptions, setNbdIOTimeout) {
cmdArgs = append(cmdArgs, "--options", fmt.Sprintf("%s=%d", setNbdIOTimeout, defaultNbdIOTimeout)) cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%d", setNbdIOTimeout, defaultNbdIOTimeout))
} }
if hasNBDCookieSupport { if hasNBDCookieSupport {
cmdArgs = append(cmdArgs, "--options", fmt.Sprintf("cookie=%s", cookie)) cmdArgs = append(cmdArgs, fmt.Sprintf("--cookie=%s", cookie))
} }
} }
if userOptions != "" { if userOptions != "" {
// userOptions is appended after, possibly overriding the above // userOptions is appended after, possibly overriding the above
// default options. // default options.
cmdArgs = append(cmdArgs, "--options", userOptions) cmdArgs = append(cmdArgs, "--"+userOptions)
} }
return cmdArgs return cmdArgs
@ -436,13 +446,13 @@ func createPath(ctx context.Context, volOpt *rbdVolume, device string, cr *util.
if volOpt.Mounter == rbdTonbd && hasNBD { if volOpt.Mounter == rbdTonbd && hasNBD {
isNbd = true isNbd = true
} }
cli := rbd
if isNbd { if isNbd {
cli = rbdNbdMounter
mapArgs = append(mapArgs, "--log-file", mapArgs = append(mapArgs, "--log-file",
getCephClientLogFileName(volOpt.VolID, volOpt.LogDir, "rbd-nbd")) getCephClientLogFileName(volOpt.VolID, volOpt.LogDir, "rbd-nbd"))
} }
cli := rbd
if device != "" { if device != "" {
// TODO: use rbd cli for attach/detach in the future // TODO: use rbd cli for attach/detach in the future
cli = rbdNbdMounter cli = rbdNbdMounter
@ -576,7 +586,13 @@ func detachRBDImageOrDeviceSpec(
unmapArgs = appendKRbdDeviceTypeAndOptions(unmapArgs, dArgs.unmapOptions) unmapArgs = appendKRbdDeviceTypeAndOptions(unmapArgs, dArgs.unmapOptions)
} }
_, stderr, err := util.ExecCommand(ctx, rbd, unmapArgs...) var err error
var stderr string
if dArgs.isNbd {
_, stderr, err = util.ExecCommand(ctx, rbdTonbd, unmapArgs...)
} else {
_, stderr, err = util.ExecCommand(ctx, rbd, unmapArgs...)
}
if err != nil { if err != nil {
// Messages for krbd and nbd differ, hence checking either of them for missing mapping // Messages for krbd and nbd differ, hence checking either of them for missing mapping
// This is not applicable when a device path is passed in // This is not applicable when a device path is passed in

View File

@ -192,7 +192,7 @@ func checkSnapCloneExists(
rbdSnap.VolSize = vol.VolSize rbdSnap.VolSize = vol.VolSize
// found a snapshot already available, process and return its information // found a snapshot already available, process and return its information
rbdSnap.VolID, err = util.GenerateVolID(ctx, rbdSnap.Monitors, cr, snapData.ImagePoolID, rbdSnap.Pool, rbdSnap.VolID, err = util.GenerateVolID(ctx, rbdSnap.Monitors, cr, snapData.ImagePoolID, rbdSnap.Pool,
rbdSnap.ClusterID, snapUUID, volIDVersion) rbdSnap.ClusterID, snapUUID)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -328,7 +328,7 @@ func (rv *rbdVolume) Exists(ctx context.Context, parentVol *rbdVolume) (bool, er
// found a volume already available, process and return it! // found a volume already available, process and return it!
rv.VolID, err = util.GenerateVolID(ctx, rv.Monitors, rv.conn.Creds, imageData.ImagePoolID, rv.Pool, rv.VolID, err = util.GenerateVolID(ctx, rv.Monitors, rv.conn.Creds, imageData.ImagePoolID, rv.Pool,
rv.ClusterID, rv.ReservedID, volIDVersion) rv.ClusterID, rv.ReservedID)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -405,7 +405,7 @@ func reserveSnap(ctx context.Context, rbdSnap *rbdSnapshot, rbdVol *rbdVolume, c
} }
rbdSnap.VolID, err = util.GenerateVolID(ctx, rbdSnap.Monitors, cr, imagePoolID, rbdSnap.Pool, rbdSnap.VolID, err = util.GenerateVolID(ctx, rbdSnap.Monitors, cr, imagePoolID, rbdSnap.Pool,
rbdSnap.ClusterID, rbdSnap.ReservedID, volIDVersion) rbdSnap.ClusterID, rbdSnap.ReservedID)
if err != nil { if err != nil {
return err return err
} }
@ -482,7 +482,7 @@ func reserveVol(ctx context.Context, rbdVol *rbdVolume, rbdSnap *rbdSnapshot, cr
} }
rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool, rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool,
rbdVol.ClusterID, rbdVol.ReservedID, volIDVersion) rbdVol.ClusterID, rbdVol.ReservedID)
if err != nil { if err != nil {
return err return err
} }
@ -640,7 +640,7 @@ func RegenerateJournal(
} }
// As the omap already exists for this image ID return nil. // As the omap already exists for this image ID return nil.
rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool, rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool,
rbdVol.ClusterID, rbdVol.ReservedID, volIDVersion) rbdVol.ClusterID, rbdVol.ReservedID)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -665,7 +665,7 @@ func RegenerateJournal(
} }
}() }()
rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool, rbdVol.VolID, err = util.GenerateVolID(ctx, rbdVol.Monitors, cr, imagePoolID, rbdVol.Pool,
rbdVol.ClusterID, rbdVol.ReservedID, volIDVersion) rbdVol.ClusterID, rbdVol.ReservedID)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -286,7 +286,6 @@ func GenerateVolID(
cr *Credentials, cr *Credentials,
locationID int64, locationID int64,
pool, clusterID, objUUID string, pool, clusterID, objUUID string,
volIDVersion uint16,
) (string, error) { ) (string, error) {
var err error var err error
@ -300,7 +299,6 @@ func GenerateVolID(
// generate the volume ID to return to the CO system // generate the volume ID to return to the CO system
vi := CSIIdentifier{ vi := CSIIdentifier{
LocationID: locationID, LocationID: locationID,
EncodingVersion: volIDVersion,
ClusterID: clusterID, ClusterID: clusterID,
ObjectUUID: objUUID, ObjectUUID: objUUID,
} }

View File

@ -23,6 +23,11 @@ import (
"strings" "strings"
) )
const (
// defaultEncodingVersion is only one version for the encoding at the moment.
defaultEncodingVersion = uint16(1)
)
/* /*
CSIIdentifier contains the elements that form a CSI ID to be returned by the CSI plugin, and CSIIdentifier contains the elements that form a CSI ID to be returned by the CSI plugin, and
contains enough information to decompose and extract required cluster and pool information to locate contains enough information to decompose and extract required cluster and pool information to locate
@ -34,7 +39,7 @@ DecomposeCSIID is the inverse of the same function.
The CSIIdentifier structure carries the following fields, The CSIIdentifier structure carries the following fields,
- LocationID: 64 bit integer identifier determining the location of the volume on the Ceph cluster. - LocationID: 64 bit integer identifier determining the location of the volume on the Ceph cluster.
It is the ID of the poolname or fsname, for RBD or CephFS backed volumes respectively. It is the ID of the poolname or fsname, for RBD or CephFS backed volumes respectively.
- EncodingVersion: Carries the version number of the encoding scheme used to encode the CSI ID, - encodingVersion: Carries the version number of the encoding scheme used to encode the CSI ID,
and is preserved for any future proofing w.r.t changes in the encoding scheme, and to retain and is preserved for any future proofing w.r.t changes in the encoding scheme, and to retain
ability to parse backward compatible encodings. ability to parse backward compatible encodings.
- ClusterID: Is a unique ID per cluster that the CSI instance is serving and is restricted to - ClusterID: Is a unique ID per cluster that the CSI instance is serving and is restricted to
@ -44,7 +49,7 @@ The CSIIdentifier structure carries the following fields,
*/ */
type CSIIdentifier struct { type CSIIdentifier struct {
LocationID int64 LocationID int64
EncodingVersion uint16 encodingVersion uint16
ClusterID string ClusterID string
ObjectUUID string ObjectUUID string
} }
@ -82,7 +87,13 @@ func (ci CSIIdentifier) ComposeCSIID() (string, error) {
return "", errors.New("CSI ID invalid object uuid") return "", errors.New("CSI ID invalid object uuid")
} }
binary.BigEndian.PutUint16(buf16, ci.EncodingVersion) // set the encoding version, as it is not set by default anywhere else
encodingVersion := ci.encodingVersion
if encodingVersion == 0 {
encodingVersion = defaultEncodingVersion
}
binary.BigEndian.PutUint16(buf16, encodingVersion)
versionEncodedHex := hex.EncodeToString(buf16) versionEncodedHex := hex.EncodeToString(buf16)
binary.BigEndian.PutUint16(buf16, uint16(len(ci.ClusterID))) binary.BigEndian.PutUint16(buf16, uint16(len(ci.ClusterID)))
@ -112,7 +123,7 @@ func (ci *CSIIdentifier) DecomposeCSIID(composedCSIID string) error {
if err != nil { if err != nil {
return err return err
} }
ci.EncodingVersion = binary.BigEndian.Uint16(buf16) ci.encodingVersion = binary.BigEndian.Uint16(buf16)
// 4 for version encoding and 1 for '-' separator // 4 for version encoding and 1 for '-' separator
bytesToProcess -= 5 bytesToProcess -= 5

View File

@ -34,7 +34,7 @@ var testData = []testTuple{
{ {
vID: CSIIdentifier{ vID: CSIIdentifier{
LocationID: 0xffff, LocationID: 0xffff,
EncodingVersion: 0xffff, encodingVersion: 0xffff,
ClusterID: "01616094-9d93-4178-bf45-c7eac19e8b15", ClusterID: "01616094-9d93-4178-bf45-c7eac19e8b15",
ObjectUUID: "00000000-1111-2222-bbbb-cacacacacaca", ObjectUUID: "00000000-1111-2222-bbbb-cacacacacaca",
}, },

View File

@ -69,6 +69,11 @@ var yamlArtifacts = []deploymentArtifact{
reflect.ValueOf(nfs.NewCSIConfigMapYAML), reflect.ValueOf(nfs.NewCSIConfigMapYAML),
reflect.ValueOf(nfs.CSIConfigMapDefaults), reflect.ValueOf(nfs.CSIConfigMapDefaults),
}, },
{
"../deploy/nfs/kubernetes/csi-provisioner-rbac.yaml",
reflect.ValueOf(nfs.NewCSIProvisionerRBACYAML),
reflect.ValueOf(nfs.CSIProvisionerRBACDefaults),
},
{ {
"../deploy/rbd/kubernetes/csidriver.yaml", "../deploy/rbd/kubernetes/csidriver.yaml",
reflect.ValueOf(rbd.NewCSIDriverYAML), reflect.ValueOf(rbd.NewCSIDriverYAML),

View File

@ -0,0 +1,735 @@
# Release History
## 1.9.1 (2023-12-11)
### Bugs Fixed
* The `retry-after-ms` and `x-ms-retry-after-ms` headers weren't being checked during retries.
### Other Changes
* Update dependencies.
## 1.9.0 (2023-11-06)
### Breaking Changes
> These changes affect only code written against previous beta versions of `v1.7.0` and `v1.8.0`
* The function `NewTokenCredential` has been removed from the `fake` package. Use a literal `&fake.TokenCredential{}` instead.
* The field `TracingNamespace` in `runtime.PipelineOptions` has been replaced by `TracingOptions`.
### Bugs Fixed
* Fixed an issue that could cause some allowed HTTP header values to not show up in logs.
* Include error text instead of error type in traces when the transport returns an error.
* Fixed an issue that could cause an HTTP/2 request to hang when the TCP connection becomes unresponsive.
* Block key and SAS authentication for non TLS protected endpoints.
* Passing a `nil` credential value will no longer cause a panic. Instead, the authentication is skipped.
* Calling `Error` on a zero-value `azcore.ResponseError` will no longer panic.
* Fixed an issue in `fake.PagerResponder[T]` that would cause a trailing error to be omitted when iterating over pages.
* Context values created by `azcore` will no longer flow across disjoint HTTP requests.
### Other Changes
* Skip generating trace info for no-op tracers.
* The `clientName` paramater in client constructors has been renamed to `moduleName`.
## 1.9.0-beta.1 (2023-10-05)
### Other Changes
* The beta features for tracing and fakes have been reinstated.
## 1.8.0 (2023-10-05)
### Features Added
* This includes the following features from `v1.8.0-beta.N` releases.
* Claims and CAE for authentication.
* New `messaging` package.
* Various helpers in the `runtime` package.
* Deprecation of `runtime.With*` funcs and their replacements in the `policy` package.
* Added types `KeyCredential` and `SASCredential` to the `azcore` package.
* Includes their respective constructor functions.
* Added types `KeyCredentialPolicy` and `SASCredentialPolicy` to the `azcore/runtime` package.
* Includes their respective constructor functions and options types.
### Breaking Changes
> These changes affect only code written against beta versions of `v1.8.0`
* The beta features for tracing and fakes have been omitted for this release.
### Bugs Fixed
* Fixed an issue that could cause some ARM RPs to not be automatically registered.
* Block bearer token authentication for non TLS protected endpoints.
### Other Changes
* Updated dependencies.
## 1.8.0-beta.3 (2023-09-07)
### Features Added
* Added function `FetcherForNextLink` and `FetcherForNextLinkOptions` to the `runtime` package to centralize creation of `Pager[T].Fetcher` from a next link URL.
### Bugs Fixed
* Suppress creating spans for nested SDK API calls. The HTTP span will be a child of the outer API span.
### Other Changes
* The following functions in the `runtime` package are now exposed from the `policy` package, and the `runtime` versions have been deprecated.
* `WithCaptureResponse`
* `WithHTTPHeader`
* `WithRetryOptions`
## 1.7.2 (2023-09-06)
### Bugs Fixed
* Fix default HTTP transport to work in WASM modules.
## 1.8.0-beta.2 (2023-08-14)
### Features Added
* Added function `SanitizePagerPollerPath` to the `server` package to centralize sanitization and formalize the contract.
* Added `TokenRequestOptions.EnableCAE` to indicate whether to request a CAE token.
### Breaking Changes
> This change affects only code written against beta version `v1.8.0-beta.1`.
* `messaging.CloudEvent` deserializes JSON objects as `[]byte`, instead of `json.RawMessage`. See the documentation for CloudEvent.Data for more information.
> This change affects only code written against beta versions `v1.7.0-beta.2` and `v1.8.0-beta.1`.
* Removed parameter from method `Span.End()` and its type `tracing.SpanEndOptions`. This API GA'ed in `v1.2.0` so we cannot change it.
### Bugs Fixed
* Propagate any query parameters when constructing a fake poller and/or injecting next links.
## 1.7.1 (2023-08-14)
## Bugs Fixed
* Enable TLS renegotiation in the default transport policy.
## 1.8.0-beta.1 (2023-07-12)
### Features Added
- `messaging/CloudEvent` allows you to serialize/deserialize CloudEvents, as described in the CloudEvents 1.0 specification: [link](https://github.com/cloudevents/spec)
### Other Changes
* The beta features for CAE, tracing, and fakes have been reinstated.
## 1.7.0 (2023-07-12)
### Features Added
* Added method `WithClientName()` to type `azcore.Client` to support shallow cloning of a client with a new name used for tracing.
### Breaking Changes
> These changes affect only code written against beta versions v1.7.0-beta.1 or v1.7.0-beta.2
* The beta features for CAE, tracing, and fakes have been omitted for this release.
## 1.7.0-beta.2 (2023-06-06)
### Breaking Changes
> These changes affect only code written against beta version v1.7.0-beta.1
* Method `SpanFromContext()` on type `tracing.Tracer` had the `bool` return value removed.
* This includes the field `SpanFromContext` in supporting type `tracing.TracerOptions`.
* Method `AddError()` has been removed from type `tracing.Span`.
* Method `Span.End()` now requires an argument of type `*tracing.SpanEndOptions`.
## 1.6.1 (2023-06-06)
### Bugs Fixed
* Fixed an issue in `azcore.NewClient()` and `arm.NewClient()` that could cause an incorrect module name to be used in telemetry.
### Other Changes
* This version contains all bug fixes from `v1.7.0-beta.1`
## 1.7.0-beta.1 (2023-05-24)
### Features Added
* Restored CAE support for ARM clients.
* Added supporting features to enable distributed tracing.
* Added func `runtime.StartSpan()` for use by SDKs to start spans.
* Added method `WithContext()` to `runtime.Request` to support shallow cloning with a new context.
* Added field `TracingNamespace` to `runtime.PipelineOptions`.
* Added field `Tracer` to `runtime.NewPollerOptions` and `runtime.NewPollerFromResumeTokenOptions` types.
* Added field `SpanFromContext` to `tracing.TracerOptions`.
* Added methods `Enabled()`, `SetAttributes()`, and `SpanFromContext()` to `tracing.Tracer`.
* Added supporting pipeline policies to include HTTP spans when creating clients.
* Added package `fake` to support generated fakes packages in SDKs.
* The package contains public surface area exposed by fake servers and supporting APIs intended only for use by the fake server implementations.
* Added an internal fake poller implementation.
### Bugs Fixed
* Retry policy always clones the underlying `*http.Request` before invoking the next policy.
* Added some non-standard error codes to the list of error codes for unregistered resource providers.
## 1.6.0 (2023-05-04)
### Features Added
* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable.
* Added `TenantID` field to `policy.TokenRequestOptions`.
## 1.5.0 (2023-04-06)
### Features Added
* Added `ShouldRetry` to `policy.RetryOptions` for finer-grained control over when to retry.
### Breaking Changes
> These changes affect only code written against a beta version such as v1.5.0-beta.1
> These features will return in v1.6.0-beta.1.
* Removed `TokenRequestOptions.Claims` and `.TenantID`
* Removed ARM client support for CAE and cross-tenant auth.
### Bugs Fixed
* Added non-conformant LRO terminal states `Cancelled` and `Completed`.
### Other Changes
* Updated to latest `internal` module.
## 1.5.0-beta.1 (2023-03-02)
### Features Added
* This release includes the features added in v1.4.0-beta.1
## 1.4.0 (2023-03-02)
> This release doesn't include features added in v1.4.0-beta.1. They will return in v1.5.0-beta.1.
### Features Added
* Add `Clone()` method for `arm/policy.ClientOptions`.
### Bugs Fixed
* ARM's RP registration policy will no longer swallow unrecognized errors.
* Fixed an issue in `runtime.NewPollerFromResumeToken()` when resuming a `Poller` with a custom `PollingHandler`.
* Fixed wrong policy copy in `arm/runtime.NewPipeline()`.
## 1.4.0-beta.1 (2023-02-02)
### Features Added
* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable.
* Added `Claims` and `TenantID` fields to `policy.TokenRequestOptions`.
* ARM bearer token policy handles CAE challenges.
## 1.3.1 (2023-02-02)
### Other Changes
* Update dependencies to latest versions.
## 1.3.0 (2023-01-06)
### Features Added
* Added `BearerTokenOptions.AuthorizationHandler` to enable extending `runtime.BearerTokenPolicy`
with custom authorization logic
* Added `Client` types and matching constructors to the `azcore` and `arm` packages. These represent a basic client for HTTP and ARM respectively.
### Other Changes
* Updated `internal` module to latest version.
* `policy/Request.SetBody()` allows replacing a request's body with an empty one
## 1.2.0 (2022-11-04)
### Features Added
* Added `ClientOptions.APIVersion` field, which overrides the default version a client
requests of the service, if the client supports this (all ARM clients do).
* Added package `tracing` that contains the building blocks for distributed tracing.
* Added field `TracingProvider` to type `policy.ClientOptions` that will be used to set the per-client tracing implementation.
### Bugs Fixed
* Fixed an issue in `runtime.SetMultipartFormData` to properly handle slices of `io.ReadSeekCloser`.
* Fixed the MaxRetryDelay default to be 60s.
* Failure to poll the state of an LRO will now return an `*azcore.ResponseError` for poller types that require this behavior.
* Fixed a bug in `runtime.NewPipeline` that would cause pipeline-specified allowed headers and query parameters to be lost.
### Other Changes
* Retain contents of read-only fields when sending requests.
## 1.1.4 (2022-10-06)
### Bugs Fixed
* Don't retry a request if the `Retry-After` delay is greater than the configured `RetryOptions.MaxRetryDelay`.
* `runtime.JoinPaths`: do not unconditionally add a forward slash before the query string
### Other Changes
* Removed logging URL from retry policy as it's redundant.
* Retry policy logs when it exits due to a non-retriable status code.
## 1.1.3 (2022-09-01)
### Bugs Fixed
* Adjusted the initial retry delay to 800ms per the Azure SDK guidelines.
## 1.1.2 (2022-08-09)
### Other Changes
* Fixed various doc bugs.
## 1.1.1 (2022-06-30)
### Bugs Fixed
* Avoid polling when a RELO LRO synchronously terminates.
## 1.1.0 (2022-06-03)
### Other Changes
* The one-second floor for `Frequency` when calling `PollUntilDone()` has been removed when running tests.
## 1.0.0 (2022-05-12)
### Features Added
* Added interface `runtime.PollingHandler` to support custom poller implementations.
* Added field `PollingHandler` of this type to `runtime.NewPollerOptions[T]` and `runtime.NewPollerFromResumeTokenOptions[T]`.
### Breaking Changes
* Renamed `cloud.Configuration.LoginEndpoint` to `.ActiveDirectoryAuthorityHost`
* Renamed `cloud.AzurePublicCloud` to `cloud.AzurePublic`
* Removed `AuxiliaryTenants` field from `arm/ClientOptions` and `arm/policy/BearerTokenOptions`
* Removed `TokenRequestOptions.TenantID`
* `Poller[T].PollUntilDone()` now takes an `options *PollUntilDoneOptions` param instead of `freq time.Duration`
* Removed `arm/runtime.Poller[T]`, `arm/runtime.NewPoller[T]()` and `arm/runtime.NewPollerFromResumeToken[T]()`
* Removed `arm/runtime.FinalStateVia` and related `const` values
* Renamed `runtime.PageProcessor` to `runtime.PagingHandler`
* The `arm/runtime.ProviderRepsonse` and `arm/runtime.Provider` types are no longer exported.
* Renamed `NewRequestIdPolicy()` to `NewRequestIDPolicy()`
* `TokenCredential.GetToken` now returns `AccessToken` by value.
### Bugs Fixed
* When per-try timeouts are enabled, only cancel the context after the body has been read and closed.
* The `Operation-Location` poller now properly handles `final-state-via` values.
* Improvements in `runtime.Poller[T]`
* `Poll()` shouldn't cache errors, allowing for additional retries when in a non-terminal state.
* `Result()` will cache the terminal result or error but not transient errors, allowing for additional retries.
### Other Changes
* Updated to latest `internal` module and absorbed breaking changes.
* Use `temporal.Resource` and deleted copy.
* The internal poller implementation has been refactored.
* The implementation in `internal/pollers/poller.go` has been merged into `runtime/poller.go` with some slight modification.
* The internal poller types had their methods updated to conform to the `runtime.PollingHandler` interface.
* The creation of resume tokens has been refactored so that implementers of `runtime.PollingHandler` don't need to know about it.
* `NewPipeline()` places policies from `ClientOptions` after policies from `PipelineOptions`
* Default User-Agent headers no longer include `azcore` version information
## 0.23.1 (2022-04-14)
### Bugs Fixed
* Include XML header when marshalling XML content.
* Handle XML namespaces when searching for error code.
* Handle `odata.error` when searching for error code.
## 0.23.0 (2022-04-04)
### Features Added
* Added `runtime.Pager[T any]` and `runtime.Poller[T any]` supporting types for central, generic, implementations.
* Added `cloud` package with a new API for cloud configuration
* Added `FinalStateVia` field to `runtime.NewPollerOptions[T any]` type.
### Breaking Changes
* Removed the `Poller` type-alias to the internal poller implementation.
* Added `Ptr[T any]` and `SliceOfPtrs[T any]` in the `to` package and removed all non-generic implementations.
* `NullValue` and `IsNullValue` now take a generic type parameter instead of an interface func parameter.
* Replaced `arm.Endpoint` with `cloud` API
* Removed the `endpoint` parameter from `NewRPRegistrationPolicy()`
* `arm/runtime.NewPipeline()` and `.NewRPRegistrationPolicy()` now return an `error`
* Refactored `NewPoller` and `NewPollerFromResumeToken` funcs in `arm/runtime` and `runtime` packages.
* Removed the `pollerID` parameter as it's no longer required.
* Created optional parameter structs and moved optional parameters into them.
* Changed `FinalStateVia` field to a `const` type.
### Other Changes
* Converted expiring resource and dependent types to use generics.
## 0.22.0 (2022-03-03)
### Features Added
* Added header `WWW-Authenticate` to the default allow-list of headers for logging.
* Added a pipeline policy that enables the retrieval of HTTP responses from API calls.
* Added `runtime.WithCaptureResponse` to enable the policy at the API level (off by default).
### Breaking Changes
* Moved `WithHTTPHeader` and `WithRetryOptions` from the `policy` package to the `runtime` package.
## 0.21.1 (2022-02-04)
### Bugs Fixed
* Restore response body after reading in `Poller.FinalResponse()`. (#16911)
* Fixed bug in `NullValue` that could lead to incorrect comparisons for empty maps/slices (#16969)
### Other Changes
* `BearerTokenPolicy` is more resilient to transient authentication failures. (#16789)
## 0.21.0 (2022-01-11)
### Features Added
* Added `AllowedHeaders` and `AllowedQueryParams` to `policy.LogOptions` to control which headers and query parameters are written to the logger.
* Added `azcore.ResponseError` type which is returned from APIs when a non-success HTTP status code is received.
### Breaking Changes
* Moved `[]policy.Policy` parameters of `arm/runtime.NewPipeline` and `runtime.NewPipeline` into a new struct, `runtime.PipelineOptions`
* Renamed `arm/ClientOptions.Host` to `.Endpoint`
* Moved `Request.SkipBodyDownload` method to function `runtime.SkipBodyDownload`
* Removed `azcore.HTTPResponse` interface type
* `arm.NewPoller()` and `runtime.NewPoller()` no longer require an `eu` parameter
* `runtime.NewResponseError()` no longer requires an `error` parameter
## 0.20.0 (2021-10-22)
### Breaking Changes
* Removed `arm.Connection`
* Removed `azcore.Credential` and `.NewAnonymousCredential()`
* `NewRPRegistrationPolicy` now requires an `azcore.TokenCredential`
* `runtime.NewPipeline` has a new signature that simplifies implementing custom authentication
* `arm/runtime.RegistrationOptions` embeds `policy.ClientOptions`
* Contents in the `log` package have been slightly renamed.
* Removed `AuthenticationOptions` in favor of `policy.BearerTokenOptions`
* Changed parameters for `NewBearerTokenPolicy()`
* Moved policy config options out of `arm/runtime` and into `arm/policy`
### Features Added
* Updating Documentation
* Added string typdef `arm.Endpoint` to provide a hint toward expected ARM client endpoints
* `azcore.ClientOptions` contains common pipeline configuration settings
* Added support for multi-tenant authorization in `arm/runtime`
* Require one second minimum when calling `PollUntilDone()`
### Bug Fixes
* Fixed a potential panic when creating the default Transporter.
* Close LRO initial response body when creating a poller.
* Fixed a panic when recursively cloning structs that contain time.Time.
## 0.19.0 (2021-08-25)
### Breaking Changes
* Split content out of `azcore` into various packages. The intent is to separate content based on its usage (common, uncommon, SDK authors).
* `azcore` has all core functionality.
* `log` contains facilities for configuring in-box logging.
* `policy` is used for configuring pipeline options and creating custom pipeline policies.
* `runtime` contains various helpers used by SDK authors and generated content.
* `streaming` has helpers for streaming IO operations.
* `NewTelemetryPolicy()` now requires module and version parameters and the `Value` option has been removed.
* As a result, the `Request.Telemetry()` method has been removed.
* The telemetry policy now includes the SDK prefix `azsdk-go-` so callers no longer need to provide it.
* The `*http.Request` in `runtime.Request` is no longer anonymously embedded. Use the `Raw()` method to access it.
* The `UserAgent` and `Version` constants have been made internal, `Module` and `Version` respectively.
### Bug Fixes
* Fixed an issue in the retry policy where the request body could be overwritten after a rewind.
### Other Changes
* Moved modules `armcore` and `to` content into `arm` and `to` packages respectively.
* The `Pipeline()` method on `armcore.Connection` has been replaced by `NewPipeline()` in `arm.Connection`. It takes module and version parameters used by the telemetry policy.
* Poller logic has been consolidated across ARM and core implementations.
* This required some changes to the internal interfaces for core pollers.
* The core poller types have been improved, including more logging and test coverage.
## 0.18.1 (2021-08-20)
### Features Added
* Adds an `ETag` type for comparing etags and handling etags on requests
* Simplifies the `requestBodyProgess` and `responseBodyProgress` into a single `progress` object
### Bugs Fixed
* `JoinPaths` will preserve query parameters encoded in the `root` url.
### Other Changes
* Bumps dependency on `internal` module to the latest version (v0.7.0)
## 0.18.0 (2021-07-29)
### Features Added
* Replaces methods from Logger type with two package methods for interacting with the logging functionality.
* `azcore.SetClassifications` replaces `azcore.Logger().SetClassifications`
* `azcore.SetListener` replaces `azcore.Logger().SetListener`
### Breaking Changes
* Removes `Logger` type from `azcore`
## 0.17.0 (2021-07-27)
### Features Added
* Adding TenantID to TokenRequestOptions (https://github.com/Azure/azure-sdk-for-go/pull/14879)
* Adding AuxiliaryTenants to AuthenticationOptions (https://github.com/Azure/azure-sdk-for-go/pull/15123)
### Breaking Changes
* Rename `AnonymousCredential` to `NewAnonymousCredential` (https://github.com/Azure/azure-sdk-for-go/pull/15104)
* rename `AuthenticationPolicyOptions` to `AuthenticationOptions` (https://github.com/Azure/azure-sdk-for-go/pull/15103)
* Make Header constants private (https://github.com/Azure/azure-sdk-for-go/pull/15038)
## 0.16.2 (2021-05-26)
### Features Added
* Improved support for byte arrays [#14715](https://github.com/Azure/azure-sdk-for-go/pull/14715)
## 0.16.1 (2021-05-19)
### Features Added
* Add license.txt to azcore module [#14682](https://github.com/Azure/azure-sdk-for-go/pull/14682)
## 0.16.0 (2021-05-07)
### Features Added
* Remove extra `*` in UnmarshalAsByteArray() [#14642](https://github.com/Azure/azure-sdk-for-go/pull/14642)
## 0.15.1 (2021-05-06)
### Features Added
* Cache the original request body on Request [#14634](https://github.com/Azure/azure-sdk-for-go/pull/14634)
## 0.15.0 (2021-05-05)
### Features Added
* Add support for null map and slice
* Export `Response.Payload` method
### Breaking Changes
* remove `Response.UnmarshalError` as it's no longer required
## 0.14.5 (2021-04-23)
### Features Added
* Add `UnmarshalError()` on `azcore.Response`
## 0.14.4 (2021-04-22)
### Features Added
* Support for basic LRO polling
* Added type `LROPoller` and supporting types for basic polling on long running operations.
* rename poller param and added doc comment
### Bugs Fixed
* Fixed content type detection bug in logging.
## 0.14.3 (2021-03-29)
### Features Added
* Add support for multi-part form data
* Added method `WriteMultipartFormData()` to Request.
## 0.14.2 (2021-03-17)
### Features Added
* Add support for encoding JSON null values
* Adds `NullValue()` and `IsNullValue()` functions for setting and detecting sentinel values used for encoding a JSON null.
* Documentation fixes
### Bugs Fixed
* Fixed improper error wrapping
## 0.14.1 (2021-02-08)
### Features Added
* Add `Pager` and `Poller` interfaces to azcore
## 0.14.0 (2021-01-12)
### Features Added
* Accept zero-value options for default values
* Specify zero-value options structs to accept default values.
* Remove `DefaultXxxOptions()` methods.
* Do not silently change TryTimeout on negative values
* make per-try timeout opt-in
## 0.13.4 (2020-11-20)
### Features Added
* Include telemetry string in User Agent
## 0.13.3 (2020-11-20)
### Features Added
* Updating response body handling on `azcore.Response`
## 0.13.2 (2020-11-13)
### Features Added
* Remove implementation of stateless policies as first-class functions.
## 0.13.1 (2020-11-05)
### Features Added
* Add `Telemetry()` method to `azcore.Request()`
## 0.13.0 (2020-10-14)
### Features Added
* Rename `log` to `logger` to avoid name collision with the log package.
* Documentation improvements
* Simplified `DefaultHTTPClientTransport()` implementation
## 0.12.1 (2020-10-13)
### Features Added
* Update `internal` module dependence to `v0.5.0`
## 0.12.0 (2020-10-08)
### Features Added
* Removed storage specific content
* Removed internal content to prevent API clutter
* Refactored various policy options to conform with our options pattern
## 0.11.0 (2020-09-22)
### Features Added
* Removed `LogError` and `LogSlowResponse`.
* Renamed `options` in `RequestLogOptions`.
* Updated `NewRequestLogPolicy()` to follow standard pattern for options.
* Refactored `requestLogPolicy.Do()` per above changes.
* Cleaned up/added logging in retry policy.
* Export `NewResponseError()`
* Fix `RequestLogOptions` comment
## 0.10.1 (2020-09-17)
### Features Added
* Add default console logger
* Default console logger writes to stderr. To enable it, set env var `AZURE_SDK_GO_LOGGING` to the value 'all'.
* Added `Logger.Writef()` to reduce the need for `ShouldLog()` checks.
* Add `LogLongRunningOperation`
## 0.10.0 (2020-09-10)
### Features Added
* The `request` and `transport` interfaces have been refactored to align with the patterns in the standard library.
* `NewRequest()` now uses `http.NewRequestWithContext()` and performs additional validation, it also requires a context parameter.
* The `Policy` and `Transport` interfaces have had their context parameter removed as the context is associated with the underlying `http.Request`.
* `Pipeline.Do()` will validate the HTTP request before sending it through the pipeline, avoiding retries on a malformed request.
* The `Retrier` interface has been replaced with the `NonRetriableError` interface, and the retry policy updated to test for this.
* `Request.SetBody()` now requires a content type parameter for setting the request's MIME type.
* moved path concatenation into `JoinPaths()` func
## 0.9.6 (2020-08-18)
### Features Added
* Improvements to body download policy
* Always download the response body for error responses, i.e. HTTP status codes >= 400.
* Simplify variable declarations
## 0.9.5 (2020-08-11)
### Features Added
* Set the Content-Length header in `Request.SetBody`
## 0.9.4 (2020-08-03)
### Features Added
* Fix cancellation of per try timeout
* Per try timeout is used to ensure that an HTTP operation doesn't take too long, e.g. that a GET on some URL doesn't take an inordinant amount of time.
* Once the HTTP request returns, the per try timeout should be cancelled, not when the response has been read to completion.
* Do not drain response body if there are no more retries
* Do not retry non-idempotent operations when body download fails
## 0.9.3 (2020-07-28)
### Features Added
* Add support for custom HTTP request headers
* Inserts an internal policy into the pipeline that can extract HTTP header values from the caller's context, adding them to the request.
* Use `azcore.WithHTTPHeader` to add HTTP headers to a context.
* Remove method specific to Go 1.14
## 0.9.2 (2020-07-28)
### Features Added
* Omit read-only content from request payloads
* If any field in a payload's object graph contains `azure:"ro"`, make a clone of the object graph, omitting all fields with this annotation.
* Verify no fields were dropped
* Handle embedded struct types
* Added test for cloning by value
* Add messages to failures
## 0.9.1 (2020-07-22)
### Features Added
* Updated dependency on internal module to fix race condition.
## 0.9.0 (2020-07-09)
### Features Added
* Add `HTTPResponse` interface to be used by callers to access the raw HTTP response from an error in the event of an API call failure.
* Updated `sdk/internal` dependency to latest version.
* Rename package alias
## 0.8.2 (2020-06-29)
### Features Added
* Added missing documentation comments
### Bugs Fixed
* Fixed a bug in body download policy.
## 0.8.1 (2020-06-26)
### Features Added
* Miscellaneous clean-up reported by linters
## 0.8.0 (2020-06-01)
### Features Added
* Differentiate between standard and URL encoding.
## 0.7.1 (2020-05-27)
### Features Added
* Add support for for base64 encoding and decoding of payloads.
## 0.7.0 (2020-05-12)
### Features Added
* Change `RetryAfter()` to a function.
## 0.6.0 (2020-04-29)
### Features Added
* Updating `RetryAfter` to only return the detaion in the RetryAfter header
## 0.5.0 (2020-03-23)
### Features Added
* Export `TransportFunc`
### Breaking Changes
* Removed `IterationDone`
## 0.4.1 (2020-02-25)
### Features Added
* Ensure per-try timeout is properly cancelled
* Explicitly call cancel the per-try timeout when the response body has been read/closed by the body download policy.
* When the response body is returned to the caller for reading/closing, wrap it in a `responseBodyReader` that will cancel the timeout when the body is closed.
* `Logger.Should()` will return false if no listener is set.
## 0.4.0 (2020-02-18)
### Features Added
* Enable custom `RetryOptions` to be specified per API call
* Added `WithRetryOptions()` that adds a custom `RetryOptions` to the provided context, allowing custom settings per API call.
* Remove 429 from the list of default HTTP status codes for retry.
* Change StatusCodesForRetry to a slice so consumers can append to it.
* Added support for retry-after in HTTP-date format.
* Cleaned up some comments specific to storage.
* Remove `Request.SetQueryParam()`
* Renamed `MaxTries` to `MaxRetries`
## 0.3.0 (2020-01-16)
### Features Added
* Added `DefaultRetryOptions` to create initialized default options.
### Breaking Changes
* Removed `Response.CheckStatusCode()`
## 0.2.0 (2020-01-15)
### Features Added
* Add support for marshalling and unmarshalling JSON
* Removed `Response.Payload` field
* Exit early when unmarsahlling if there is no payload
## 0.1.0 (2020-01-10)
### Features Added
* Initial release

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

View File

@ -0,0 +1,39 @@
# Azure Core Client Module for Go
[![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/azcore)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore)
[![Build Status](https://dev.azure.com/azure-sdk/public/_apis/build/status/go/go%20-%20azcore%20-%20ci?branchName=main)](https://dev.azure.com/azure-sdk/public/_build/latest?definitionId=1843&branchName=main)
[![Code Coverage](https://img.shields.io/azure-devops/coverage/azure-sdk/public/1843/main)](https://img.shields.io/azure-devops/coverage/azure-sdk/public/1843/main)
The `azcore` module provides a set of common interfaces and types for Go SDK client modules.
These modules follow the [Azure SDK Design Guidelines for Go](https://azure.github.io/azure-sdk/golang_introduction.html).
## Getting started
This project uses [Go modules](https://github.com/golang/go/wiki/Modules) for versioning and dependency management.
Typically, you will not need to explicitly install `azcore` as it will be installed as a client module dependency.
To add the latest version to your `go.mod` file, execute the following command.
```bash
go get github.com/Azure/azure-sdk-for-go/sdk/azcore
```
General documentation and examples can be found on [pkg.go.dev](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore).
## Contributing
This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution.
For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).
When you submit a pull request, a CLA-bot will automatically determine whether
you need to provide a CLA and decorate the PR appropriately (e.g., label,
comment). Simply follow the instructions provided by the bot. You will only
need to do this once across all repos using our CLA.
This project has adopted the
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information, see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any
additional questions or comments.

View File

@ -0,0 +1,224 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package resource
import (
"fmt"
"strings"
)
const (
providersKey = "providers"
subscriptionsKey = "subscriptions"
resourceGroupsLowerKey = "resourcegroups"
locationsKey = "locations"
builtInResourceNamespace = "Microsoft.Resources"
)
// RootResourceID defines the tenant as the root parent of all other ResourceID.
var RootResourceID = &ResourceID{
Parent: nil,
ResourceType: TenantResourceType,
Name: "",
}
// ResourceID represents a resource ID such as `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg`.
// Don't create this type directly, use ParseResourceID instead.
type ResourceID struct {
// Parent is the parent ResourceID of this instance.
// Can be nil if there is no parent.
Parent *ResourceID
// SubscriptionID is the subscription ID in this resource ID.
// The value can be empty if the resource ID does not contain a subscription ID.
SubscriptionID string
// ResourceGroupName is the resource group name in this resource ID.
// The value can be empty if the resource ID does not contain a resource group name.
ResourceGroupName string
// Provider represents the provider name in this resource ID.
// This is only valid when the resource ID represents a resource provider.
// Example: `/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Insights`
Provider string
// Location is the location in this resource ID.
// The value can be empty if the resource ID does not contain a location name.
Location string
// ResourceType represents the type of this resource ID.
ResourceType ResourceType
// Name is the resource name of this resource ID.
Name string
isChild bool
stringValue string
}
// ParseResourceID parses a string to an instance of ResourceID
func ParseResourceID(id string) (*ResourceID, error) {
if len(id) == 0 {
return nil, fmt.Errorf("invalid resource ID: id cannot be empty")
}
if !strings.HasPrefix(id, "/") {
return nil, fmt.Errorf("invalid resource ID: resource id '%s' must start with '/'", id)
}
parts := splitStringAndOmitEmpty(id, "/")
if len(parts) < 2 {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
if !strings.EqualFold(parts[0], subscriptionsKey) && !strings.EqualFold(parts[0], providersKey) {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
return appendNext(RootResourceID, parts, id)
}
// String returns the string of the ResourceID
func (id *ResourceID) String() string {
if len(id.stringValue) > 0 {
return id.stringValue
}
if id.Parent == nil {
return ""
}
builder := strings.Builder{}
builder.WriteString(id.Parent.String())
if id.isChild {
builder.WriteString(fmt.Sprintf("/%s", id.ResourceType.lastType()))
if len(id.Name) > 0 {
builder.WriteString(fmt.Sprintf("/%s", id.Name))
}
} else {
builder.WriteString(fmt.Sprintf("/providers/%s/%s/%s", id.ResourceType.Namespace, id.ResourceType.Type, id.Name))
}
id.stringValue = builder.String()
return id.stringValue
}
func newResourceID(parent *ResourceID, resourceTypeName string, resourceName string) *ResourceID {
id := &ResourceID{}
id.init(parent, chooseResourceType(resourceTypeName, parent), resourceName, true)
return id
}
func newResourceIDWithResourceType(parent *ResourceID, resourceType ResourceType, resourceName string) *ResourceID {
id := &ResourceID{}
id.init(parent, resourceType, resourceName, true)
return id
}
func newResourceIDWithProvider(parent *ResourceID, providerNamespace, resourceTypeName, resourceName string) *ResourceID {
id := &ResourceID{}
id.init(parent, NewResourceType(providerNamespace, resourceTypeName), resourceName, false)
return id
}
func chooseResourceType(resourceTypeName string, parent *ResourceID) ResourceType {
if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) {
return ResourceGroupResourceType
} else if strings.EqualFold(resourceTypeName, subscriptionsKey) && parent != nil && parent.ResourceType.String() == TenantResourceType.String() {
return SubscriptionResourceType
}
return parent.ResourceType.AppendChild(resourceTypeName)
}
func (id *ResourceID) init(parent *ResourceID, resourceType ResourceType, name string, isChild bool) {
if parent != nil {
id.Provider = parent.Provider
id.SubscriptionID = parent.SubscriptionID
id.ResourceGroupName = parent.ResourceGroupName
id.Location = parent.Location
}
if resourceType.String() == SubscriptionResourceType.String() {
id.SubscriptionID = name
}
if resourceType.lastType() == locationsKey {
id.Location = name
}
if resourceType.String() == ResourceGroupResourceType.String() {
id.ResourceGroupName = name
}
if resourceType.String() == ProviderResourceType.String() {
id.Provider = name
}
if parent == nil {
id.Parent = RootResourceID
} else {
id.Parent = parent
}
id.isChild = isChild
id.ResourceType = resourceType
id.Name = name
}
func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, error) {
if len(parts) == 0 {
return parent, nil
}
if len(parts) == 1 {
// subscriptions and resourceGroups are not valid ids without their names
if strings.EqualFold(parts[0], subscriptionsKey) || strings.EqualFold(parts[0], resourceGroupsLowerKey) {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
// resourceGroup must contain either child or provider resource type
if parent.ResourceType.String() == ResourceGroupResourceType.String() {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
return newResourceID(parent, parts[0], ""), nil
}
if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) {
//provider resource can only be on a tenant or a subscription parent
if parent.ResourceType.String() != SubscriptionResourceType.String() && parent.ResourceType.String() != TenantResourceType.String() {
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
return appendNext(newResourceIDWithResourceType(parent, ProviderResourceType, parts[1]), parts[2:], id)
}
if len(parts) > 3 && strings.EqualFold(parts[0], providersKey) {
return appendNext(newResourceIDWithProvider(parent, parts[1], parts[2], parts[3]), parts[4:], id)
}
if len(parts) > 1 && !strings.EqualFold(parts[0], providersKey) {
return appendNext(newResourceID(parent, parts[0], parts[1]), parts[2:], id)
}
return nil, fmt.Errorf("invalid resource ID: %s", id)
}
func splitStringAndOmitEmpty(v, sep string) []string {
r := make([]string, 0)
for _, s := range strings.Split(v, sep) {
if len(s) == 0 {
continue
}
r = append(r, s)
}
return r
}

View File

@ -0,0 +1,114 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package resource
import (
"fmt"
"strings"
)
// SubscriptionResourceType is the ResourceType of a subscription
var SubscriptionResourceType = NewResourceType(builtInResourceNamespace, "subscriptions")
// ResourceGroupResourceType is the ResourceType of a resource group
var ResourceGroupResourceType = NewResourceType(builtInResourceNamespace, "resourceGroups")
// TenantResourceType is the ResourceType of a tenant
var TenantResourceType = NewResourceType(builtInResourceNamespace, "tenants")
// ProviderResourceType is the ResourceType of a provider
var ProviderResourceType = NewResourceType(builtInResourceNamespace, "providers")
// ResourceType represents an Azure resource type, e.g. "Microsoft.Network/virtualNetworks/subnets".
// Don't create this type directly, use ParseResourceType or NewResourceType instead.
type ResourceType struct {
// Namespace is the namespace of the resource type.
// e.g. "Microsoft.Network" in resource type "Microsoft.Network/virtualNetworks/subnets"
Namespace string
// Type is the full type name of the resource type.
// e.g. "virtualNetworks/subnets" in resource type "Microsoft.Network/virtualNetworks/subnets"
Type string
// Types is the slice of all the sub-types of this resource type.
// e.g. ["virtualNetworks", "subnets"] in resource type "Microsoft.Network/virtualNetworks/subnets"
Types []string
stringValue string
}
// String returns the string of the ResourceType
func (t ResourceType) String() string {
return t.stringValue
}
// IsParentOf returns true when the receiver is the parent resource type of the child.
func (t ResourceType) IsParentOf(child ResourceType) bool {
if !strings.EqualFold(t.Namespace, child.Namespace) {
return false
}
if len(t.Types) >= len(child.Types) {
return false
}
for i := range t.Types {
if !strings.EqualFold(t.Types[i], child.Types[i]) {
return false
}
}
return true
}
// AppendChild creates an instance of ResourceType using the receiver as the parent with childType appended to it.
func (t ResourceType) AppendChild(childType string) ResourceType {
return NewResourceType(t.Namespace, fmt.Sprintf("%s/%s", t.Type, childType))
}
// NewResourceType creates an instance of ResourceType using a provider namespace
// such as "Microsoft.Network" and type such as "virtualNetworks/subnets".
func NewResourceType(providerNamespace, typeName string) ResourceType {
return ResourceType{
Namespace: providerNamespace,
Type: typeName,
Types: splitStringAndOmitEmpty(typeName, "/"),
stringValue: fmt.Sprintf("%s/%s", providerNamespace, typeName),
}
}
// ParseResourceType parses the ResourceType from a resource type string (e.g. Microsoft.Network/virtualNetworks/subsets)
// or a resource identifier string.
// e.g. /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/vnet/subnets/mySubnet)
func ParseResourceType(resourceIDOrType string) (ResourceType, error) {
// split the path into segments
parts := splitStringAndOmitEmpty(resourceIDOrType, "/")
// There must be at least a namespace and type name
if len(parts) < 1 {
return ResourceType{}, fmt.Errorf("invalid resource ID or type: %s", resourceIDOrType)
}
// if the type is just subscriptions, it is a built-in type in the Microsoft.Resources namespace
if len(parts) == 1 {
// Simple resource type
return NewResourceType(builtInResourceNamespace, parts[0]), nil
} else if strings.Contains(parts[0], ".") {
// Handle resource types (Microsoft.Compute/virtualMachines, Microsoft.Network/virtualNetworks/subnets)
// it is a full type name
return NewResourceType(parts[0], strings.Join(parts[1:], "/")), nil
} else {
// Check if ResourceID
id, err := ParseResourceID(resourceIDOrType)
if err != nil {
return ResourceType{}, err
}
return NewResourceType(id.ResourceType.Namespace, id.ResourceType.Type), nil
}
}
func (t ResourceType) lastType() string {
return t.Types[len(t.Types)-1]
}

View File

@ -0,0 +1,98 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package policy
import (
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
)
// BearerTokenOptions configures the bearer token policy's behavior.
type BearerTokenOptions struct {
// AuxiliaryTenants are additional tenant IDs for authenticating cross-tenant requests.
// The policy will add a token from each of these tenants to every request. The
// authenticating user or service principal must be a guest in these tenants, and the
// policy's credential must support multitenant authentication.
AuxiliaryTenants []string
// Scopes contains the list of permission scopes required for the token.
Scopes []string
}
// RegistrationOptions configures the registration policy's behavior.
// All zero-value fields will be initialized with their default values.
type RegistrationOptions struct {
policy.ClientOptions
// MaxAttempts is the total number of times to attempt automatic registration
// in the event that an attempt fails.
// The default value is 3.
// Set to a value less than zero to disable the policy.
MaxAttempts int
// PollingDelay is the amount of time to sleep between polling intervals.
// The default value is 15 seconds.
// A value less than zero means no delay between polling intervals (not recommended).
PollingDelay time.Duration
// PollingDuration is the amount of time to wait before abandoning polling.
// The default valule is 5 minutes.
// NOTE: Setting this to a small value might cause the policy to prematurely fail.
PollingDuration time.Duration
}
// ClientOptions contains configuration settings for a client's pipeline.
type ClientOptions struct {
policy.ClientOptions
// AuxiliaryTenants are additional tenant IDs for authenticating cross-tenant requests.
// The client will add a token from each of these tenants to every request. The
// authenticating user or service principal must be a guest in these tenants, and the
// client's credential must support multitenant authentication.
AuxiliaryTenants []string
// DisableRPRegistration disables the auto-RP registration policy. Defaults to false.
DisableRPRegistration bool
}
// Clone return a deep copy of the current options.
func (o *ClientOptions) Clone() *ClientOptions {
if o == nil {
return nil
}
copiedOptions := *o
copiedOptions.Cloud.Services = copyMap(copiedOptions.Cloud.Services)
copiedOptions.Logging.AllowedHeaders = copyArray(copiedOptions.Logging.AllowedHeaders)
copiedOptions.Logging.AllowedQueryParams = copyArray(copiedOptions.Logging.AllowedQueryParams)
copiedOptions.Retry.StatusCodes = copyArray(copiedOptions.Retry.StatusCodes)
copiedOptions.PerRetryPolicies = copyArray(copiedOptions.PerRetryPolicies)
copiedOptions.PerCallPolicies = copyArray(copiedOptions.PerCallPolicies)
return &copiedOptions
}
// copyMap return a new map with all the key value pair in the src map
func copyMap[K comparable, V any](src map[K]V) map[K]V {
if src == nil {
return nil
}
copiedMap := make(map[K]V)
for k, v := range src {
copiedMap[k] = v
}
return copiedMap
}
// copyMap return a new array with all the elements in the src array
func copyArray[T any](src []T) []T {
if src == nil {
return nil
}
copiedArray := make([]T, len(src))
copy(copiedArray, src)
return copiedArray
}

View File

@ -0,0 +1,65 @@
//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package runtime
import (
"errors"
"reflect"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)
// NewPipeline creates a pipeline from connection options. Policies from ClientOptions are
// placed after policies from PipelineOptions. The telemetry policy, when enabled, will
// use the specified module and version info.
func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azruntime.PipelineOptions, options *armpolicy.ClientOptions) (azruntime.Pipeline, error) {
if options == nil {
options = &armpolicy.ClientOptions{}
}
conf, err := getConfiguration(&options.ClientOptions)
if err != nil {
return azruntime.Pipeline{}, err
}
authPolicy := NewBearerTokenPolicy(cred, &armpolicy.BearerTokenOptions{
AuxiliaryTenants: options.AuxiliaryTenants,
Scopes: []string{conf.Audience + "/.default"},
})
perRetry := make([]azpolicy.Policy, len(plOpts.PerRetry), len(plOpts.PerRetry)+1)
copy(perRetry, plOpts.PerRetry)
plOpts.PerRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy))
if !options.DisableRPRegistration {
regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions}
regPolicy, err := NewRPRegistrationPolicy(cred, &regRPOpts)
if err != nil {
return azruntime.Pipeline{}, err
}
perCall := make([]azpolicy.Policy, len(plOpts.PerCall), len(plOpts.PerCall)+1)
copy(perCall, plOpts.PerCall)
plOpts.PerCall = append(perCall, regPolicy)
}
if plOpts.APIVersion.Name == "" {
plOpts.APIVersion.Name = "api-version"
}
return azruntime.NewPipeline(module, version, plOpts, &options.ClientOptions), nil
}
func getConfiguration(o *azpolicy.ClientOptions) (cloud.ServiceConfiguration, error) {
c := cloud.AzurePublic
if !reflect.ValueOf(o.Cloud).IsZero() {
c = o.Cloud
}
if conf, ok := c.Services[cloud.ResourceManager]; ok && conf.Endpoint != "" && conf.Audience != "" {
return conf, nil
} else {
return conf, errors.New("provided Cloud field is missing Azure Resource Manager configuration")
}
}

Some files were not shown because too many files have changed in this diff Show More