// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.28.1
// 	protoc        v3.20.0
// source: api/mesh/v1alpha1/envoy_admin.proto

package v1alpha1

import (
	reflect "reflect"
	sync "sync"
)

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"

	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type EnvoyAdmin struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// Port on which Envoy Admin API server will be listening
	Port uint32 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"`
}

func (x *EnvoyAdmin) Reset() {
	*x = EnvoyAdmin{}
	if protoimpl.UnsafeEnabled {
		mi := &file_api_mesh_v1alpha1_envoy_admin_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *EnvoyAdmin) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*EnvoyAdmin) ProtoMessage() {}

func (x *EnvoyAdmin) ProtoReflect() protoreflect.Message {
	mi := &file_api_mesh_v1alpha1_envoy_admin_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 EnvoyAdmin.ProtoReflect.Descriptor instead.
func (*EnvoyAdmin) Descriptor() ([]byte, []int) {
	return file_api_mesh_v1alpha1_envoy_admin_proto_rawDescGZIP(), []int{0}
}

func (x *EnvoyAdmin) GetPort() uint32 {
	if x != nil {
		return x.Port
	}
	return 0
}

var File_api_mesh_v1alpha1_envoy_admin_proto protoreflect.FileDescriptor

var file_api_mesh_v1alpha1_envoy_admin_proto_rawDesc = []byte{
	0x0a, 0x23, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70,
	0x68, 0x61, 0x31, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x6d, 0x65, 0x73,
	0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x20, 0x0a, 0x0a, 0x45, 0x6e,
	0x76, 0x6f, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
	0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x36, 0x5a, 0x34,
	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68,
	0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74,
	0x65, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c,
	0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_api_mesh_v1alpha1_envoy_admin_proto_rawDescOnce sync.Once
	file_api_mesh_v1alpha1_envoy_admin_proto_rawDescData = file_api_mesh_v1alpha1_envoy_admin_proto_rawDesc
)

func file_api_mesh_v1alpha1_envoy_admin_proto_rawDescGZIP() []byte {
	file_api_mesh_v1alpha1_envoy_admin_proto_rawDescOnce.Do(func() {
		file_api_mesh_v1alpha1_envoy_admin_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_mesh_v1alpha1_envoy_admin_proto_rawDescData)
	})
	return file_api_mesh_v1alpha1_envoy_admin_proto_rawDescData
}

var file_api_mesh_v1alpha1_envoy_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_api_mesh_v1alpha1_envoy_admin_proto_goTypes = []interface{}{
	(*EnvoyAdmin)(nil), // 0: dubbo.mesh.v1alpha1.EnvoyAdmin
}
var file_api_mesh_v1alpha1_envoy_admin_proto_depIdxs = []int32{
	0, // [0:0] is the sub-list for method output_type
	0, // [0:0] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
}

func init() { file_api_mesh_v1alpha1_envoy_admin_proto_init() }
func file_api_mesh_v1alpha1_envoy_admin_proto_init() {
	if File_api_mesh_v1alpha1_envoy_admin_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_api_mesh_v1alpha1_envoy_admin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*EnvoyAdmin); 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_api_mesh_v1alpha1_envoy_admin_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_api_mesh_v1alpha1_envoy_admin_proto_goTypes,
		DependencyIndexes: file_api_mesh_v1alpha1_envoy_admin_proto_depIdxs,
		MessageInfos:      file_api_mesh_v1alpha1_envoy_admin_proto_msgTypes,
	}.Build()
	File_api_mesh_v1alpha1_envoy_admin_proto = out.File
	file_api_mesh_v1alpha1_envoy_admin_proto_rawDesc = nil
	file_api_mesh_v1alpha1_envoy_admin_proto_goTypes = nil
	file_api_mesh_v1alpha1_envoy_admin_proto_depIdxs = nil
}
