mirror of https://github.com/containers/podman.git
				
				
				
			Merge pull request #22079 from TomSweeneyRedHat/dev/tsweeney/cve-main
CVE-2024-1753 fix for main + pasta setup changes
This commit is contained in:
		
						commit
						e5059fcf19
					
				
							
								
								
									
										12
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										12
									
								
								go.mod
								
								
								
								
							|  | @ -8,10 +8,10 @@ require ( | |||
| 	github.com/blang/semver/v4 v4.0.0 | ||||
| 	github.com/buger/goterm v1.0.4 | ||||
| 	github.com/checkpoint-restore/checkpointctl v1.1.0 | ||||
| 	github.com/checkpoint-restore/go-criu/v7 v7.0.0 | ||||
| 	github.com/checkpoint-restore/go-criu/v7 v7.1.0 | ||||
| 	github.com/containernetworking/plugins v1.4.0 | ||||
| 	github.com/containers/buildah v1.35.0 | ||||
| 	github.com/containers/common v0.58.0 | ||||
| 	github.com/containers/buildah v1.35.1-0.20240318192459-e64e6cc09dfd | ||||
| 	github.com/containers/common v0.58.1-0.20240318131753-6f1c96f53a78 | ||||
| 	github.com/containers/conmon v2.0.20+incompatible | ||||
| 	github.com/containers/gvisor-tap-vsock v0.7.3 | ||||
| 	github.com/containers/image/v5 v5.30.0 | ||||
|  | @ -27,7 +27,7 @@ require ( | |||
| 	github.com/cyphar/filepath-securejoin v0.2.4 | ||||
| 	github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e | ||||
| 	github.com/docker/distribution v2.8.3+incompatible | ||||
| 	github.com/docker/docker v25.0.3+incompatible | ||||
| 	github.com/docker/docker v25.0.4+incompatible | ||||
| 	github.com/docker/go-connections v0.5.0 | ||||
| 	github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 | ||||
| 	github.com/docker/go-units v0.5.0 | ||||
|  | @ -216,8 +216,8 @@ require ( | |||
| 	golang.org/x/time v0.3.0 // indirect | ||||
| 	golang.org/x/tools v0.18.0 // indirect | ||||
| 	google.golang.org/appengine v1.6.8 // indirect | ||||
| 	google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect | ||||
| 	google.golang.org/grpc v1.61.0 // indirect | ||||
| 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect | ||||
| 	google.golang.org/grpc v1.62.0 // indirect | ||||
| 	gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect | ||||
| 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect | ||||
| 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect | ||||
|  |  | |||
							
								
								
									
										28
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										28
									
								
								go.sum
								
								
								
								
							|  | @ -38,8 +38,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA | |||
| github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= | ||||
| github.com/checkpoint-restore/checkpointctl v1.1.0 h1:plS/2zBzbAXO6DH/H+TqD7ZGhz8iQVb+NLgsOJSTWaw= | ||||
| github.com/checkpoint-restore/checkpointctl v1.1.0/go.mod h1:DtPd9M4bt/jdt+7DodFxm0lrzdevabk3cbni/FL4BY0= | ||||
| github.com/checkpoint-restore/go-criu/v7 v7.0.0 h1:R4UF/njKOuq8ooG7naFGsCeKsjv5j+rIhgFgSSeC2KY= | ||||
| github.com/checkpoint-restore/go-criu/v7 v7.0.0/go.mod h1:xD1v3cPww1QYpJR3+XTTdC8hYubPnptIPsT1daXhbr4= | ||||
| github.com/checkpoint-restore/go-criu/v7 v7.1.0 h1:JbQyO4o+P8ycNTMLPiiDqXg49bAcy4WljWCzYQho35A= | ||||
| github.com/checkpoint-restore/go-criu/v7 v7.1.0/go.mod h1:1svAtmbtvX4BKI45OFzgoTTLG7oYFKdColv/Vcsb2A8= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= | ||||
| github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= | ||||
|  | @ -74,10 +74,10 @@ github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl3 | |||
| github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= | ||||
| github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7wwSv9iTbXzzic= | ||||
| github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0= | ||||
| github.com/containers/buildah v1.35.0 h1:ayjY3TLmDG9mF/eqgub6TorEJbrR+H5UVcpWRlBLcas= | ||||
| github.com/containers/buildah v1.35.0/go.mod h1:vVSVUlTu8+99H5j43gBJscpkb/quZvdJg78+6X1HeTM= | ||||
| github.com/containers/common v0.58.0 h1:iQuwMxDD4ubZ9s1tmgdsiaHxMU4TdVBpV6kctJc6Bk8= | ||||
| github.com/containers/common v0.58.0/go.mod h1:l3vMqanJGj7tZ3W/i76gEJ128VXgFUO1tLaohJXPvdk= | ||||
| github.com/containers/buildah v1.35.1-0.20240318192459-e64e6cc09dfd h1:QVUSJsMYYUIQmMi+PU9NYXpbk/lgz0Xx6/naihFHFBQ= | ||||
| github.com/containers/buildah v1.35.1-0.20240318192459-e64e6cc09dfd/go.mod h1:kJEmpENlkUrZ39k4jVJC9RxDNH30qxSsfEOar4la8Ec= | ||||
| github.com/containers/common v0.58.1-0.20240318131753-6f1c96f53a78 h1:EObLO2IA9zAuRp2Qtf6/siVjxlxE2J8KvtS4H2Q47bc= | ||||
| github.com/containers/common v0.58.1-0.20240318131753-6f1c96f53a78/go.mod h1:axvr7QuM6sjs/nwukYpNvSgjE5/T2i6l+UhsKLgOvuI= | ||||
| github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= | ||||
| github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= | ||||
| github.com/containers/gvisor-tap-vsock v0.7.3 h1:yORnf15sP+sLFhxLNLgmB5/lOhldn9dRMHx/tmYtSOQ= | ||||
|  | @ -132,8 +132,8 @@ github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5 | |||
| github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284= | ||||
| github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= | ||||
| github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= | ||||
| github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ= | ||||
| github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/docker v25.0.4+incompatible h1:XITZTrq+52tZyZxUOtFIahUf3aH367FLxJzt9vZeAF8= | ||||
| github.com/docker/docker v25.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= | ||||
| github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= | ||||
| github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= | ||||
| github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= | ||||
|  | @ -788,17 +788,17 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ | |||
| google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||||
| google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | ||||
| google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | ||||
| google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= | ||||
| google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= | ||||
| google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= | ||||
| google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= | ||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= | ||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||
| google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | ||||
| google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= | ||||
| google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | ||||
| google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= | ||||
| google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= | ||||
| google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= | ||||
| google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= | ||||
| google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= | ||||
| 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-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import ( | |||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/containers/common/libnetwork/pasta" | ||||
| 	"github.com/containers/common/libnetwork/types" | ||||
| 	"github.com/containers/common/pkg/config" | ||||
| 	"github.com/containers/common/pkg/secrets" | ||||
|  | @ -127,6 +128,7 @@ type Container struct { | |||
| 	restoreFromCheckpoint bool | ||||
| 
 | ||||
| 	slirp4netnsSubnet *net.IPNet | ||||
| 	pastaResult       *pasta.SetupResult | ||||
| } | ||||
| 
 | ||||
| // ContainerState contains the current state of the container
 | ||||
|  |  | |||
|  | @ -301,29 +301,23 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err | |||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| 	// Now this is a bit of a mess, normally we try to reuse the netns but if a userns
 | ||||
| 	// is used this is not possible as it must be owned by the userns which is created
 | ||||
| 	// by the oci runtime. Thus we need to teardown the netns so that the runtime
 | ||||
| 	// creates the users+netns and then we setup in completeNetworkSetup() again.
 | ||||
| 	if c.config.PostConfigureNetNS { | ||||
| 		if err := c.cleanupNetwork(); err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 	// Always teardown the network, trying to reuse the netns has caused
 | ||||
| 	// a significant amount of bugs in this code here. It also never worked
 | ||||
| 	// for containers with user namespaces. So once and for all simplify this
 | ||||
| 	// by never reusing the netns. Originally this was done to have a faster
 | ||||
| 	// restart of containers but with netavark now we are much faster so it
 | ||||
| 	// shouldn't be that noticeable in practice. It also makes more sense to
 | ||||
| 	// reconfigure the netns as it is likely that the container exited due
 | ||||
| 	// some broken network state in which case reusing would just cause more
 | ||||
| 	// harm than good.
 | ||||
| 	if err := c.cleanupNetwork(); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := c.prepare(); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	// only do this if the container is not in a userns, if we are the cleanupNetwork()
 | ||||
| 	// was called above and a proper network setup is needed which is part of the init() below.
 | ||||
| 	if !c.config.PostConfigureNetNS { | ||||
| 		// set up slirp4netns again because slirp4netns will die when conmon exits
 | ||||
| 		if err := c.setupRootlessNetwork(); err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if c.state.State == define.ContainerStateStopped { | ||||
| 		// Reinitialize the container if we need to
 | ||||
| 		if err := c.reinit(ctx, true); err != nil { | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
|  | @ -2116,8 +2117,8 @@ func (c *Container) addResolvConf() error { | |||
| 		// first add the nameservers from the networks status
 | ||||
| 		nameservers = networkNameServers | ||||
| 
 | ||||
| 		// slirp4netns has a built in DNS forwarder.
 | ||||
| 		nameservers = c.addSlirp4netnsDNS(nameservers) | ||||
| 		// pasta and slirp4netns have a built in DNS forwarder.
 | ||||
| 		nameservers = c.addSpecialDNS(nameservers) | ||||
| 	} | ||||
| 
 | ||||
| 	// Set DNS search domains
 | ||||
|  | @ -2167,6 +2168,10 @@ func (c *Container) checkForIPv6(netStatus map[string]types.StatusBlock) bool { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if c.pastaResult != nil { | ||||
| 		return c.pastaResult.IPv6 | ||||
| 	} | ||||
| 
 | ||||
| 	return c.isSlirp4netnsIPv6() | ||||
| } | ||||
| 
 | ||||
|  | @ -2225,11 +2230,10 @@ func (c *Container) getHostsEntries() (etchosts.HostEntries, error) { | |||
| 	case c.config.NetMode.IsBridge(): | ||||
| 		entries = etchosts.GetNetworkHostEntries(c.state.NetworkStatus, names...) | ||||
| 	case c.config.NetMode.IsPasta(): | ||||
| 		ip, err := getPastaIP(c.state) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		// this should never be the case but check just to be sure and not panic
 | ||||
| 		if len(c.pastaResult.IPAddresses) > 0 { | ||||
| 			entries = etchosts.HostEntries{{IP: c.pastaResult.IPAddresses[0].String(), Names: names}} | ||||
| 		} | ||||
| 		entries = etchosts.HostEntries{{IP: ip.String(), Names: names}} | ||||
| 	case c.config.NetMode.IsSlirp4netns(): | ||||
| 		ip, err := getSlirp4netnsIP(c.slirp4netnsSubnet) | ||||
| 		if err != nil { | ||||
|  | @ -2276,12 +2280,18 @@ func (c *Container) addHosts() error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	var exclude []net.IP | ||||
| 	if c.pastaResult != nil { | ||||
| 		exclude = c.pastaResult.IPAddresses | ||||
| 	} | ||||
| 
 | ||||
| 	return etchosts.New(&etchosts.Params{ | ||||
| 		BaseFile:                 baseHostFile, | ||||
| 		ExtraHosts:               c.config.HostAdd, | ||||
| 		ContainerIPs:             containerIPsEntries, | ||||
| 		HostContainersInternalIP: etchosts.GetHostContainersInternalIP(c.runtime.config, c.state.NetworkStatus, c.runtime.network), | ||||
| 		TargetFile:               targetFile, | ||||
| 		BaseFile:     baseHostFile, | ||||
| 		ExtraHosts:   c.config.HostAdd, | ||||
| 		ContainerIPs: containerIPsEntries, | ||||
| 		HostContainersInternalIP: etchosts.GetHostContainersInternalIPExcluding( | ||||
| 			c.runtime.config, c.state.NetworkStatus, c.runtime.network, exclude), | ||||
| 		TargetFile: targetFile, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -279,7 +279,7 @@ func (c *Container) setCgroupsPath(g *generate.Generator) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *Container) addSlirp4netnsDNS(nameservers []string) []string { | ||||
| func (c *Container) addSpecialDNS(nameservers []string) []string { | ||||
| 	return nameservers | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -413,27 +413,6 @@ func (c *Container) getOCICgroupPath() (string, error) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // If the container is rootless, set up the slirp4netns network
 | ||||
| func (c *Container) setupRootlessNetwork() error { | ||||
| 	// set up slirp4netns again because slirp4netns will die when conmon exits
 | ||||
| 	if c.config.NetMode.IsSlirp4netns() { | ||||
| 		err := c.runtime.setupSlirp4netns(c, c.state.NetNS) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// set up rootlesskit port forwarder again since it dies when conmon exits
 | ||||
| 	// we use rootlesskit port forwarder only as rootless and when bridge network is used
 | ||||
| 	if rootless.IsRootless() && c.config.NetMode.IsBridge() && len(c.config.PortMappings) > 0 { | ||||
| 		err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS, c.state.NetworkStatus) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func openDirectory(path string) (fd int, err error) { | ||||
| 	return unix.Open(path, unix.O_RDONLY|unix.O_PATH, 0) | ||||
| } | ||||
|  | @ -616,7 +595,12 @@ func (c *Container) setCgroupsPath(g *generate.Generator) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *Container) addSlirp4netnsDNS(nameservers []string) []string { | ||||
| // addSpecialDNS adds special dns servers for slirp4netns and pasta
 | ||||
| func (c *Container) addSpecialDNS(nameservers []string) []string { | ||||
| 	if c.pastaResult != nil { | ||||
| 		nameservers = append(nameservers, c.pastaResult.DNSForwardIPs...) | ||||
| 	} | ||||
| 
 | ||||
| 	// slirp4netns has a built in DNS forwarder.
 | ||||
| 	if c.config.NetMode.IsSlirp4netns() { | ||||
| 		slirp4netnsDNS, err := slirp4netns.GetDNS(c.slirp4netnsSubnet) | ||||
|  |  | |||
|  | @ -268,7 +268,3 @@ func (c *Container) reloadRootlessRLKPortMapping() error { | |||
| func (c *Container) setupRootlessNetwork() error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func getPastaIP(state *ContainerState) (net.IP, error) { | ||||
| 	return nil, fmt.Errorf("pasta networking is Linux only") | ||||
| } | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ import ( | |||
| 
 | ||||
| 	"github.com/containernetworking/plugins/pkg/ns" | ||||
| 	"github.com/containers/common/libnetwork/types" | ||||
| 	netUtil "github.com/containers/common/libnetwork/util" | ||||
| 	"github.com/containers/common/pkg/netns" | ||||
| 	"github.com/containers/podman/v5/libpod/define" | ||||
| 	"github.com/containers/podman/v5/pkg/rootless" | ||||
|  | @ -300,13 +299,3 @@ func (c *Container) inspectJoinedNetworkNS(networkns string) (q types.StatusBloc | |||
| 	}) | ||||
| 	return result, err | ||||
| } | ||||
| 
 | ||||
| func getPastaIP(state *ContainerState) (net.IP, error) { | ||||
| 	var ip string | ||||
| 	err := ns.WithNetNSPath(state.NetNS, func(_ ns.NetNS) error { | ||||
| 		// get the first ip in the netns
 | ||||
| 		ip = netUtil.GetLocalIP() | ||||
| 		return nil | ||||
| 	}) | ||||
| 	return net.ParseIP(ip), err | ||||
| } | ||||
|  |  | |||
|  | @ -12,10 +12,15 @@ package libpod | |||
| import "github.com/containers/common/libnetwork/pasta" | ||||
| 
 | ||||
| func (r *Runtime) setupPasta(ctr *Container, netns string) error { | ||||
| 	return pasta.Setup(&pasta.SetupOptions{ | ||||
| 	res, err := pasta.Setup2(&pasta.SetupOptions{ | ||||
| 		Config:       r.config, | ||||
| 		Netns:        netns, | ||||
| 		Ports:        ctr.convertPortMappings(), | ||||
| 		ExtraOptions: ctr.config.NetworkOptions[pasta.BinaryName], | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	ctr.pastaResult = res | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -431,9 +431,12 @@ function pasta_test_do() { | |||
| @test "Local forwarder, IPv4" { | ||||
|     skip_if_no_ipv4 "IPv4 not routable on the host" | ||||
| 
 | ||||
|     run_podman run --dns 198.51.100.1 \ | ||||
|         --net=pasta:--dns-forward,198.51.100.1 $IMAGE nslookup 127.0.0.1 || : | ||||
|     # pasta is the default now so no need to set it | ||||
|     run_podman run --rm $IMAGE grep nameserver /etc/resolv.conf | ||||
|     assert "${lines[0]}" == "nameserver 169.254.0.1" "default dns forward server" | ||||
| 
 | ||||
|     run_podman run --rm --net=pasta:--dns-forward,198.51.100.1 \ | ||||
|         $IMAGE nslookup 127.0.0.1 || : | ||||
|     assert "$output" =~ "1.0.0.127.in-addr.arpa" "No answer from resolver" | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ The following table shows the relation between go-criu and criu versions: | |||
| 
 | ||||
| | Major version  | Latest release | CRIU version | | ||||
| | -------------- | -------------- | ------------ | | ||||
| | v7             | 7.0.0          | 3.18         | | ||||
| | v7             | 7.1.0          | 3.18         | | ||||
| | v6             | 6.3.0          | 3.17         | | ||||
| | v5             | 5.3.0          | 3.16         | | ||||
| | v5             | 5.0.0          | 3.15         | | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| ignore: | ||||
|   - "test" | ||||
|  | @ -1,7 +1,7 @@ | |||
| package criu | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"errors" | ||||
| 
 | ||||
| 	"github.com/checkpoint-restore/go-criu/v7/rpc" | ||||
| ) | ||||
|  | @ -38,7 +38,7 @@ func (c *Criu) FeatureCheck(features *rpc.CriuFeatures) (*rpc.CriuFeatures, erro | |||
| 	} | ||||
| 
 | ||||
| 	if resp.GetType() != rpc.CriuReqType_FEATURE_CHECK { | ||||
| 		return nil, fmt.Errorf("unexpected CRIU RPC response") | ||||
| 		return nil, errors.New("unexpected CRIU RPC response") | ||||
| 	} | ||||
| 
 | ||||
| 	return features, nil | ||||
|  |  | |||
|  | @ -218,7 +218,7 @@ func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) { | |||
| 		return 0, 0, err | ||||
| 	} | ||||
| 
 | ||||
| 	return int(resp.Ps.GetPid()), int(resp.Ps.GetPort()), nil | ||||
| 	return int(resp.GetPs().GetPid()), int(resp.GetPs().GetPort()), nil | ||||
| } | ||||
| 
 | ||||
| // GetCriuVersion executes the VERSION RPC call and returns the version
 | ||||
|  | @ -230,22 +230,22 @@ func (c *Criu) GetCriuVersion() (int, error) { | |||
| 	} | ||||
| 
 | ||||
| 	if resp.GetType() != rpc.CriuReqType_VERSION { | ||||
| 		return 0, fmt.Errorf("unexpected CRIU RPC response") | ||||
| 		return 0, errors.New("unexpected CRIU RPC response") | ||||
| 	} | ||||
| 
 | ||||
| 	version := int(*resp.GetVersion().MajorNumber) * 10000 | ||||
| 	version += int(*resp.GetVersion().MinorNumber) * 100 | ||||
| 	if resp.GetVersion().Sublevel != nil { | ||||
| 		version += int(*resp.GetVersion().Sublevel) | ||||
| 	version := resp.GetVersion().GetMajorNumber() * 10000 | ||||
| 	version += resp.GetVersion().GetMinorNumber() * 100 | ||||
| 	if resp.GetVersion().GetSublevel() != 0 { | ||||
| 		version += resp.GetVersion().GetSublevel() | ||||
| 	} | ||||
| 
 | ||||
| 	if resp.GetVersion().Gitid != nil { | ||||
| 	if resp.GetVersion().GetGitid() != "" { | ||||
| 		// taken from runc: if it is a git release -> increase minor by 1
 | ||||
| 		version -= (version % 100) | ||||
| 		version += 100 | ||||
| 	} | ||||
| 
 | ||||
| 	return version, nil | ||||
| 	return int(version), nil | ||||
| } | ||||
| 
 | ||||
| // IsCriuAtLeast checks if the version is at least the same
 | ||||
|  |  | |||
|  | @ -10,5 +10,5 @@ Dockerfile* | |||
| !/tests/conformance/**/Dockerfile* | ||||
| *.swp | ||||
| /result/ | ||||
| internal/mkcw/embed/entrypoint.o | ||||
| internal/mkcw/embed/entrypoint | ||||
| internal/mkcw/embed/entrypoint_amd64.o | ||||
| internal/mkcw/embed/entrypoint_amd64 | ||||
|  |  | |||
|  | @ -218,5 +218,13 @@ lint: install.tools | |||
| # CAUTION: This is not a replacement for RPMs provided by your distro.
 | ||||
| # Only intended to build and test the latest unreleased changes.
 | ||||
| .PHONY: rpm | ||||
| rpm: | ||||
| 	rpkg local | ||||
| rpm:  ## Build rpm packages
 | ||||
| 	$(MAKE) -C rpm | ||||
| 
 | ||||
| # Remember that rpms install exec to /usr/bin/buildah while a `make install`
 | ||||
| # installs them to /usr/local/bin/buildah which is likely before. Always use
 | ||||
| # a full path to test installed buildah or you risk to call another executable.
 | ||||
| .PHONY: rpm-install | ||||
| rpm-install: package  ## Install rpm packages
 | ||||
| 	$(call err_if_empty,PKG_MANAGER) -y install rpm/RPMS/*/*.rpm | ||||
| 	/usr/bin/buildah version | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ const ( | |||
| 	// identify working containers.
 | ||||
| 	Package = "buildah" | ||||
| 	// Version for the Package. Also used by .packit.sh for Packit builds.
 | ||||
| 	Version = "1.35.0" | ||||
| 	Version = "1.36.0-dev" | ||||
| 
 | ||||
| 	// DefaultRuntime if containers.conf fails.
 | ||||
| 	DefaultRuntime = "runc" | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import ( | |||
| 
 | ||||
| 	"errors" | ||||
| 
 | ||||
| 	"github.com/containers/buildah/copier" | ||||
| 	"github.com/containers/buildah/define" | ||||
| 	"github.com/containers/buildah/internal" | ||||
| 	internalParse "github.com/containers/buildah/internal/parse" | ||||
|  | @ -189,7 +190,11 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st | |||
| 	// buildkit parity: support absolute path for sources from current build context
 | ||||
| 	if contextDir != "" { | ||||
| 		// path should be /contextDir/specified path
 | ||||
| 		newMount.Source = filepath.Join(contextDir, filepath.Clean(string(filepath.Separator)+newMount.Source)) | ||||
| 		evaluated, err := copier.Eval(contextDir, newMount.Source, copier.EvalOptions{}) | ||||
| 		if err != nil { | ||||
| 			return newMount, "", err | ||||
| 		} | ||||
| 		newMount.Source = evaluated | ||||
| 	} else { | ||||
| 		// looks like its coming from `build run --mount=type=bind` allow using absolute path
 | ||||
| 		// error out if no source is set
 | ||||
|  |  | |||
|  | @ -3,10 +3,12 @@ package buildah | |||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/containers/buildah/define" | ||||
| 	"github.com/containers/buildah/internal" | ||||
| 	"github.com/containers/buildah/pkg/sshagent" | ||||
| 	"github.com/containers/common/libnetwork/etchosts" | ||||
| 	"github.com/containers/image/v5/types" | ||||
| 	"github.com/containers/storage/pkg/lockfile" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
|  | @ -207,3 +209,12 @@ type IDMaps struct { | |||
| 	processUID int | ||||
| 	processGID int | ||||
| } | ||||
| 
 | ||||
| // netResult type to hold network info for hosts/resolv.conf
 | ||||
| type netResult struct { | ||||
| 	entries           etchosts.HostEntries | ||||
| 	dnsServers        []string | ||||
| 	excludeIPs        []net.IP | ||||
| 	ipv6              bool | ||||
| 	keepHostResolvers bool | ||||
| } | ||||
|  |  | |||
|  | @ -55,50 +55,13 @@ import ( | |||
| 	"golang.org/x/term" | ||||
| ) | ||||
| 
 | ||||
| // addResolvConf copies files from host and sets them up to bind mount into container
 | ||||
| func (b *Builder) addResolvConf(rdir string, chownOpts *idtools.IDPair, dnsServers, dnsSearch, dnsOptions []string, namespaces []specs.LinuxNamespace) (string, error) { | ||||
| 	defaultConfig, err := config.Default() | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to get config: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	nameservers := make([]string, 0, len(defaultConfig.Containers.DNSServers.Get())+len(dnsServers)) | ||||
| 	nameservers = append(nameservers, defaultConfig.Containers.DNSServers.Get()...) | ||||
| 	nameservers = append(nameservers, dnsServers...) | ||||
| 
 | ||||
| 	keepHostServers := false | ||||
| 	// special check for slirp ip
 | ||||
| 	if len(nameservers) == 0 && b.Isolation == IsolationOCIRootless { | ||||
| 		for _, ns := range namespaces { | ||||
| 			if ns.Type == specs.NetworkNamespace && ns.Path == "" { | ||||
| 				keepHostServers = true | ||||
| 				// if we are using slirp4netns, also add the built-in DNS server.
 | ||||
| 				logrus.Debugf("adding slirp4netns 10.0.2.3 built-in DNS server") | ||||
| 				nameservers = append([]string{"10.0.2.3"}, nameservers...) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	searches := make([]string, 0, len(defaultConfig.Containers.DNSSearches.Get())+len(dnsSearch)) | ||||
| 	searches = append(searches, defaultConfig.Containers.DNSSearches.Get()...) | ||||
| 	searches = append(searches, dnsSearch...) | ||||
| 
 | ||||
| 	options := make([]string, 0, len(defaultConfig.Containers.DNSOptions.Get())+len(dnsOptions)) | ||||
| 	options = append(options, defaultConfig.Containers.DNSOptions.Get()...) | ||||
| 	options = append(options, dnsOptions...) | ||||
| 
 | ||||
| func (b *Builder) createResolvConf(rdir string, chownOpts *idtools.IDPair) (string, error) { | ||||
| 	cfile := filepath.Join(rdir, "resolv.conf") | ||||
| 	if err := resolvconf.New(&resolvconf.Params{ | ||||
| 		Path:            cfile, | ||||
| 		Namespaces:      namespaces, | ||||
| 		IPv6Enabled:     true, // TODO we should check if we have ipv6
 | ||||
| 		KeepHostServers: keepHostServers, | ||||
| 		Nameservers:     nameservers, | ||||
| 		Searches:        searches, | ||||
| 		Options:         options, | ||||
| 	}); err != nil { | ||||
| 		return "", fmt.Errorf("building resolv.conf for container %s: %w", b.ContainerID, err) | ||||
| 	f, err := os.Create(cfile) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 
 | ||||
| 	uid := 0 | ||||
| 	gid := 0 | ||||
|  | @ -106,7 +69,7 @@ func (b *Builder) addResolvConf(rdir string, chownOpts *idtools.IDPair, dnsServe | |||
| 		uid = chownOpts.UID | ||||
| 		gid = chownOpts.GID | ||||
| 	} | ||||
| 	if err = os.Chown(cfile, uid, gid); err != nil { | ||||
| 	if err = f.Chown(uid, gid); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
|  | @ -116,57 +79,61 @@ func (b *Builder) addResolvConf(rdir string, chownOpts *idtools.IDPair, dnsServe | |||
| 	return cfile, nil | ||||
| } | ||||
| 
 | ||||
| // generateHosts creates a containers hosts file
 | ||||
| func (b *Builder) generateHosts(rdir string, chownOpts *idtools.IDPair, imageRoot string, spec *specs.Spec) (string, error) { | ||||
| 	conf, err := config.Default() | ||||
| // addResolvConf copies files from host and sets them up to bind mount into container
 | ||||
| func (b *Builder) addResolvConfEntries(file string, networkNameServer []string, | ||||
| 	namespaces []specs.LinuxNamespace, keepHostServers, ipv6 bool) error { | ||||
| 	defaultConfig, err := config.Default() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 		return fmt.Errorf("failed to get config: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	path, err := etchosts.GetBaseHostFile(conf.Containers.BaseHostsFile, imageRoot) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	dnsServers, dnsSearch, dnsOptions := b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions | ||||
| 	nameservers := make([]string, 0, len(defaultConfig.Containers.DNSServers.Get())+len(dnsServers)) | ||||
| 	nameservers = append(nameservers, defaultConfig.Containers.DNSServers.Get()...) | ||||
| 	nameservers = append(nameservers, dnsServers...) | ||||
| 
 | ||||
| 	searches := make([]string, 0, len(defaultConfig.Containers.DNSSearches.Get())+len(dnsSearch)) | ||||
| 	searches = append(searches, defaultConfig.Containers.DNSSearches.Get()...) | ||||
| 	searches = append(searches, dnsSearch...) | ||||
| 
 | ||||
| 	options := make([]string, 0, len(defaultConfig.Containers.DNSOptions.Get())+len(dnsOptions)) | ||||
| 	options = append(options, defaultConfig.Containers.DNSOptions.Get()...) | ||||
| 	options = append(options, dnsOptions...) | ||||
| 
 | ||||
| 	if len(nameservers) == 0 { | ||||
| 		nameservers = networkNameServer | ||||
| 	} | ||||
| 
 | ||||
| 	var entries etchosts.HostEntries | ||||
| 	isHost := true | ||||
| 	if spec.Linux != nil { | ||||
| 		for _, ns := range spec.Linux.Namespaces { | ||||
| 			if ns.Type == specs.NetworkNamespace { | ||||
| 				isHost = false | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// add host entry for local ip when running in host network
 | ||||
| 	if spec.Hostname != "" && isHost { | ||||
| 		ip := netUtil.GetLocalIP() | ||||
| 		if ip != "" { | ||||
| 			entries = append(entries, etchosts.HostEntry{ | ||||
| 				Names: []string{spec.Hostname}, | ||||
| 				IP:    ip, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	targetfile := filepath.Join(rdir, "hosts") | ||||
| 	if err := etchosts.New(&etchosts.Params{ | ||||
| 		BaseFile:                 path, | ||||
| 		ExtraHosts:               b.CommonBuildOpts.AddHost, | ||||
| 		HostContainersInternalIP: etchosts.GetHostContainersInternalIP(conf, nil, nil), | ||||
| 		TargetFile:               targetfile, | ||||
| 		ContainerIPs:             entries, | ||||
| 	if err := resolvconf.New(&resolvconf.Params{ | ||||
| 		Path:            file, | ||||
| 		Namespaces:      namespaces, | ||||
| 		IPv6Enabled:     ipv6, | ||||
| 		KeepHostServers: keepHostServers, | ||||
| 		Nameservers:     nameservers, | ||||
| 		Searches:        searches, | ||||
| 		Options:         options, | ||||
| 	}); err != nil { | ||||
| 		return "", err | ||||
| 		return fmt.Errorf("building resolv.conf for container %s: %w", b.ContainerID, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // createHostsFile creates a containers hosts file
 | ||||
| func (b *Builder) createHostsFile(rdir string, chownOpts *idtools.IDPair) (string, error) { | ||||
| 	targetfile := filepath.Join(rdir, "hosts") | ||||
| 	f, err := os.Create(targetfile) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	uid := 0 | ||||
| 	gid := 0 | ||||
| 	if chownOpts != nil { | ||||
| 		uid = chownOpts.UID | ||||
| 		gid = chownOpts.GID | ||||
| 	} | ||||
| 	if err = os.Chown(targetfile, uid, gid); err != nil { | ||||
| 	if err := f.Chown(uid, gid); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if err := relabel(targetfile, b.MountLabel, false); err != nil { | ||||
|  | @ -176,6 +143,25 @@ func (b *Builder) generateHosts(rdir string, chownOpts *idtools.IDPair, imageRoo | |||
| 	return targetfile, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) addHostsEntries(file, imageRoot string, entries etchosts.HostEntries, exculde []net.IP) error { | ||||
| 	conf, err := config.Default() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	base, err := etchosts.GetBaseHostFile(conf.Containers.BaseHostsFile, imageRoot) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return etchosts.New(&etchosts.Params{ | ||||
| 		BaseFile:                 base, | ||||
| 		ExtraHosts:               b.CommonBuildOpts.AddHost, | ||||
| 		HostContainersInternalIP: etchosts.GetHostContainersInternalIPExcluding(conf, nil, nil, exculde), | ||||
| 		TargetFile:               file, | ||||
| 		ContainerIPs:             entries, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // generateHostname creates a containers /etc/hostname file
 | ||||
| func (b *Builder) generateHostname(rdir, hostname string, chownOpts *idtools.IDPair) (string, error) { | ||||
| 	var err error | ||||
|  | @ -354,6 +340,27 @@ func getNetworkInterface(store storage.Store, cniConfDir, cniPluginPath string) | |||
| 	return netInt, nil | ||||
| } | ||||
| 
 | ||||
| func netStatusToNetResult(netStatus map[string]netTypes.StatusBlock, hostnames []string) *netResult { | ||||
| 	result := &netResult{ | ||||
| 		keepHostResolvers: false, | ||||
| 	} | ||||
| 	for _, status := range netStatus { | ||||
| 		for _, dns := range status.DNSServerIPs { | ||||
| 			result.dnsServers = append(result.dnsServers, dns.String()) | ||||
| 		} | ||||
| 		for _, netInt := range status.Interfaces { | ||||
| 			for _, netAddress := range netInt.Subnets { | ||||
| 				e := etchosts.HostEntry{IP: netAddress.IPNet.IP.String(), Names: hostnames} | ||||
| 				result.entries = append(result.entries, e) | ||||
| 				if !result.ipv6 && netUtil.IsIPv6(netAddress.IPNet.IP) { | ||||
| 					result.ipv6 = true | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| // DefaultNamespaceOptions returns the default namespace settings from the
 | ||||
| // runtime-tools generator library.
 | ||||
| func DefaultNamespaceOptions() (define.NamespaceOptions, error) { | ||||
|  | @ -1122,7 +1129,7 @@ func runUsingRuntimeMain() { | |||
| } | ||||
| 
 | ||||
| func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options RunOptions, configureNetwork bool, networkString string, | ||||
| 	moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName, buildContainerName, hostsFile string) (err error) { | ||||
| 	moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName, buildContainerName, hostsFile, resolvFile string) (err error) { | ||||
| 	// Lock the caller to a single OS-level thread.
 | ||||
| 	runtime.LockOSThread() | ||||
| 	defer runtime.UnlockOSThread() | ||||
|  | @ -1227,7 +1234,7 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run | |||
| 				return fmt.Errorf("parsing pid %s as a number: %w", string(pidValue), err) | ||||
| 			} | ||||
| 
 | ||||
| 			teardown, netstatus, err := b.runConfigureNetwork(pid, isolation, options, networkString, containerName) | ||||
| 			teardown, netResult, err := b.runConfigureNetwork(pid, isolation, options, networkString, containerName, []string{spec.Hostname, buildContainerName}) | ||||
| 			if teardown != nil { | ||||
| 				defer teardown() | ||||
| 			} | ||||
|  | @ -1237,9 +1244,14 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run | |||
| 
 | ||||
| 			// only add hosts if we manage the hosts file
 | ||||
| 			if hostsFile != "" { | ||||
| 				entries := etchosts.GetNetworkHostEntries(netstatus, spec.Hostname, buildContainerName) | ||||
| 				// make sure to sync this with (b *Builder) generateHosts()
 | ||||
| 				err = etchosts.Add(hostsFile, entries) | ||||
| 				err = b.addHostsEntries(hostsFile, rootPath, netResult.entries, netResult.excludeIPs) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if resolvFile != "" { | ||||
| 				err = b.addResolvConfEntries(resolvFile, netResult.dnsServers, spec.Linux.Namespaces, netResult.keepHostResolvers, netResult.ipv6) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
|  |  | |||
|  | @ -22,8 +22,10 @@ import ( | |||
| 	"github.com/containers/buildah/pkg/parse" | ||||
| 	butil "github.com/containers/buildah/pkg/util" | ||||
| 	"github.com/containers/buildah/util" | ||||
| 	"github.com/containers/common/libnetwork/etchosts" | ||||
| 	"github.com/containers/common/libnetwork/resolvconf" | ||||
| 	nettypes "github.com/containers/common/libnetwork/types" | ||||
| 	netUtil "github.com/containers/common/libnetwork/util" | ||||
| 	"github.com/containers/common/pkg/config" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	"github.com/containers/storage/pkg/lockfile" | ||||
|  | @ -202,21 +204,51 @@ func (b *Builder) Run(command []string, options RunOptions) error { | |||
| 	} | ||||
| 	rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)} | ||||
| 
 | ||||
| 	hostFile := "" | ||||
| 	hostsFile := "" | ||||
| 	if !options.NoHosts && !slices.Contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled { | ||||
| 		hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec) | ||||
| 		hostsFile, err = b.createHostsFile(path, rootIDPair) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		bindFiles[config.DefaultHostsFile] = hostFile | ||||
| 		bindFiles[config.DefaultHostsFile] = hostsFile | ||||
| 
 | ||||
| 		// Only add entries here if we do not have to setup network,
 | ||||
| 		// if we do we have to do it much later after the network setup.
 | ||||
| 		if !configureNetwork { | ||||
| 			var entries etchosts.HostEntries | ||||
| 			// add host entry for local ip when running in host network
 | ||||
| 			if spec.Hostname != "" { | ||||
| 				ip := netUtil.GetLocalIP() | ||||
| 				if ip != "" { | ||||
| 					entries = append(entries, etchosts.HostEntry{ | ||||
| 						Names: []string{spec.Hostname}, | ||||
| 						IP:    ip, | ||||
| 					}) | ||||
| 				} | ||||
| 			} | ||||
| 			err = b.addHostsEntries(hostsFile, mountPoint, entries, nil) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	resolvFile := "" | ||||
| 	if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") { | ||||
| 		resolvFile, err := b.addResolvConf(path, rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions, nil) | ||||
| 		resolvFile, err = b.createResolvConf(path, rootIDPair) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		bindFiles[resolvconf.DefaultResolvConf] = resolvFile | ||||
| 
 | ||||
| 		// Only add entries here if we do not have to do setup network,
 | ||||
| 		// if we do we have to do it much later after the network setup.
 | ||||
| 		if !configureNetwork { | ||||
| 			err = b.addResolvConfEntries(resolvFile, nil, nil, false, true) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	runMountInfo := runMountInfo{ | ||||
|  | @ -290,7 +322,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { | |||
| 		} else { | ||||
| 			moreCreateArgs = nil | ||||
| 		} | ||||
| 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec, mountPoint, path, containerName, b.Container, hostFile) | ||||
| 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec, mountPoint, path, containerName, b.Container, hostsFile, resolvFile) | ||||
| 	case IsolationChroot: | ||||
| 		err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr) | ||||
| 	default: | ||||
|  | @ -417,7 +449,7 @@ func setupCapabilities(g *generate.Generator, defaultCapabilities, adds, drops [ | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, networkString string, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) { | ||||
| func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, networkString string, containerName string, hostnames []string) (func(), *netResult, error) { | ||||
| 	//if isolation == IsolationOCIRootless {
 | ||||
| 	//return setupRootlessNetwork(pid)
 | ||||
| 	//}
 | ||||
|  | @ -451,19 +483,19 @@ func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, optio | |||
| 		ContainerName: containerName, | ||||
| 		Networks:      networks, | ||||
| 	} | ||||
| 	_, err = b.NetworkInterface.Setup(mynetns, nettypes.SetupOptions{NetworkOptions: opts}) | ||||
| 	netStatus, err := b.NetworkInterface.Setup(mynetns, nettypes.SetupOptions{NetworkOptions: opts}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	teardown = func() { | ||||
| 	teardown := func() { | ||||
| 		err := b.NetworkInterface.Teardown(mynetns, nettypes.TeardownOptions{NetworkOptions: opts}) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf("failed to cleanup network: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return teardown, nil, nil | ||||
| 	return teardown, netStatusToNetResult(netStatus, hostnames), nil | ||||
| } | ||||
| 
 | ||||
| func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, networkString string, configureUTS bool, err error) { | ||||
|  |  | |||
|  | @ -7,13 +7,11 @@ import ( | |||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"github.com/containernetworking/plugins/pkg/ns" | ||||
| 	"github.com/containers/buildah/bind" | ||||
| 	"github.com/containers/buildah/chroot" | ||||
| 	"github.com/containers/buildah/copier" | ||||
|  | @ -25,6 +23,7 @@ import ( | |||
| 	"github.com/containers/buildah/pkg/parse" | ||||
| 	butil "github.com/containers/buildah/pkg/util" | ||||
| 	"github.com/containers/buildah/util" | ||||
| 	"github.com/containers/common/libnetwork/etchosts" | ||||
| 	"github.com/containers/common/libnetwork/pasta" | ||||
| 	"github.com/containers/common/libnetwork/resolvconf" | ||||
| 	"github.com/containers/common/libnetwork/slirp4netns" | ||||
|  | @ -260,30 +259,69 @@ func (b *Builder) Run(command []string, options RunOptions) error { | |||
| 	} | ||||
| 	rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)} | ||||
| 
 | ||||
| 	hostFile := "" | ||||
| 	hostsFile := "" | ||||
| 	if !options.NoHosts && !slices.Contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled { | ||||
| 		hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec) | ||||
| 		hostsFile, err = b.createHostsFile(path, rootIDPair) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		bindFiles[config.DefaultHostsFile] = hostFile | ||||
| 		bindFiles[config.DefaultHostsFile] = hostsFile | ||||
| 
 | ||||
| 		// Only add entries here if we do not have to do setup network,
 | ||||
| 		// if we do we have to do it much later after the network setup.
 | ||||
| 		if !configureNetwork { | ||||
| 			var entries etchosts.HostEntries | ||||
| 			isHost := true | ||||
| 			if spec.Linux != nil { | ||||
| 				for _, ns := range spec.Linux.Namespaces { | ||||
| 					if ns.Type == specs.NetworkNamespace { | ||||
| 						isHost = false | ||||
| 						break | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			// add host entry for local ip when running in host network
 | ||||
| 			if spec.Hostname != "" && isHost { | ||||
| 				ip := netUtil.GetLocalIP() | ||||
| 				if ip != "" { | ||||
| 					entries = append(entries, etchosts.HostEntry{ | ||||
| 						Names: []string{spec.Hostname}, | ||||
| 						IP:    ip, | ||||
| 					}) | ||||
| 				} | ||||
| 			} | ||||
| 			err = b.addHostsEntries(hostsFile, mountPoint, entries, nil) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !options.NoHostname && !(slices.Contains(volumes, "/etc/hostname")) { | ||||
| 		hostFile, err := b.generateHostname(path, spec.Hostname, rootIDPair) | ||||
| 		hostnameFile, err := b.generateHostname(path, spec.Hostname, rootIDPair) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		// Bind /etc/hostname
 | ||||
| 		bindFiles["/etc/hostname"] = hostFile | ||||
| 		bindFiles["/etc/hostname"] = hostnameFile | ||||
| 	} | ||||
| 
 | ||||
| 	resolvFile := "" | ||||
| 	if !slices.Contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") { | ||||
| 		resolvFile, err := b.addResolvConf(path, rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions, spec.Linux.Namespaces) | ||||
| 		resolvFile, err = b.createResolvConf(path, rootIDPair) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		bindFiles[resolvconf.DefaultResolvConf] = resolvFile | ||||
| 
 | ||||
| 		// Only add entries here if we do not have to do setup network,
 | ||||
| 		// if we do we have to do it much later after the network setup.
 | ||||
| 		if !configureNetwork { | ||||
| 			err = b.addResolvConfEntries(resolvFile, nil, spec.Linux.Namespaces, false, true) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// Empty file, so no need to recreate if it exists
 | ||||
| 	if _, ok := bindFiles["/run/.containerenv"]; !ok { | ||||
|  | @ -362,7 +400,7 @@ rootless=%d | |||
| 			moreCreateArgs = append(moreCreateArgs, "--no-pivot") | ||||
| 		} | ||||
| 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec, | ||||
| 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) | ||||
| 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostsFile, resolvFile) | ||||
| 	case IsolationChroot: | ||||
| 		err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr) | ||||
| 	case IsolationOCIRootless: | ||||
|  | @ -371,7 +409,7 @@ rootless=%d | |||
| 			moreCreateArgs = append(moreCreateArgs, "--no-pivot") | ||||
| 		} | ||||
| 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec, | ||||
| 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) | ||||
| 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostsFile, resolvFile) | ||||
| 	default: | ||||
| 		err = errors.New("don't know how to run this command") | ||||
| 	} | ||||
|  | @ -470,7 +508,7 @@ func addCommonOptsToSpec(commonOpts *define.CommonBuildOptions, g *generate.Gene | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setupSlirp4netnsNetwork(config *config.Config, netns, cid string, options []string) (func(), map[string]nettypes.StatusBlock, error) { | ||||
| func setupSlirp4netnsNetwork(config *config.Config, netns, cid string, options, hostnames []string) (func(), *netResult, error) { | ||||
| 	// we need the TmpDir for the slirp4netns code
 | ||||
| 	if err := os.MkdirAll(config.Engine.TmpDir, 0o751); err != nil { | ||||
| 		return nil, nil, fmt.Errorf("failed to create tempdir: %w", err) | ||||
|  | @ -491,30 +529,27 @@ func setupSlirp4netnsNetwork(config *config.Config, netns, cid string, options [ | |||
| 		return nil, nil, fmt.Errorf("get slirp4netns ip: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	// create fake status to make sure we get the correct ip in hosts
 | ||||
| 	subnet := nettypes.IPNet{IPNet: net.IPNet{ | ||||
| 		IP:   *ip, | ||||
| 		Mask: res.Subnet.Mask, | ||||
| 	}} | ||||
| 	netStatus := map[string]nettypes.StatusBlock{ | ||||
| 		slirp4netns.BinaryName: { | ||||
| 			Interfaces: map[string]nettypes.NetInterface{ | ||||
| 				"tap0": { | ||||
| 					Subnets: []nettypes.NetAddress{{IPNet: subnet}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	dns, err := slirp4netns.GetDNS(res.Subnet) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, fmt.Errorf("get slirp4netns dns ip: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	result := &netResult{ | ||||
| 		entries:           etchosts.HostEntries{{IP: ip.String(), Names: hostnames}}, | ||||
| 		dnsServers:        []string{dns.String()}, | ||||
| 		ipv6:              res.IPv6, | ||||
| 		keepHostResolvers: true, | ||||
| 	} | ||||
| 
 | ||||
| 	return func() { | ||||
| 		syscall.Kill(res.Pid, syscall.SIGKILL) // nolint:errcheck
 | ||||
| 		var status syscall.WaitStatus | ||||
| 		syscall.Wait4(res.Pid, &status, 0, nil) // nolint:errcheck
 | ||||
| 	}, netStatus, nil | ||||
| 	}, result, nil | ||||
| } | ||||
| 
 | ||||
| func setupPasta(config *config.Config, netns string, options []string) (func(), map[string]nettypes.StatusBlock, error) { | ||||
| 	err := pasta.Setup(&pasta.SetupOptions{ | ||||
| func setupPasta(config *config.Config, netns string, options, hostnames []string) (func(), *netResult, error) { | ||||
| 	res, err := pasta.Setup2(&pasta.SetupOptions{ | ||||
| 		Config:       config, | ||||
| 		Netns:        netns, | ||||
| 		ExtraOptions: options, | ||||
|  | @ -523,35 +558,23 @@ func setupPasta(config *config.Config, netns string, options []string) (func(), | |||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var ip string | ||||
| 	err = ns.WithNetNSPath(netns, func(_ ns.NetNS) error { | ||||
| 		// get the first ip in the netns and use this as our ip for /etc/hosts
 | ||||
| 		ip = netUtil.GetLocalIP() | ||||
| 		return nil | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	var entries etchosts.HostEntries | ||||
| 	if len(res.IPAddresses) > 0 { | ||||
| 		entries = etchosts.HostEntries{{IP: res.IPAddresses[0].String(), Names: hostnames}} | ||||
| 	} | ||||
| 
 | ||||
| 	// create fake status to make sure we get the correct ip in hosts
 | ||||
| 	subnet := nettypes.IPNet{IPNet: net.IPNet{ | ||||
| 		IP:   net.ParseIP(ip), | ||||
| 		Mask: net.IPv4Mask(255, 255, 255, 0), | ||||
| 	}} | ||||
| 	netStatus := map[string]nettypes.StatusBlock{ | ||||
| 		slirp4netns.BinaryName: { | ||||
| 			Interfaces: map[string]nettypes.NetInterface{ | ||||
| 				"tap0": { | ||||
| 					Subnets: []nettypes.NetAddress{{IPNet: subnet}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	result := &netResult{ | ||||
| 		entries:           entries, | ||||
| 		dnsServers:        res.DNSForwardIPs, | ||||
| 		excludeIPs:        res.IPAddresses, | ||||
| 		ipv6:              res.IPv6, | ||||
| 		keepHostResolvers: true, | ||||
| 	} | ||||
| 
 | ||||
| 	return nil, netStatus, nil | ||||
| 	return nil, result, nil | ||||
| } | ||||
| 
 | ||||
| func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, network, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) { | ||||
| func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, network, containerName string, hostnames []string) (func(), *netResult, error) { | ||||
| 	netns := fmt.Sprintf("/proc/%d/ns/net", pid) | ||||
| 	var configureNetworks []string | ||||
| 	defConfig, err := config.Default() | ||||
|  | @ -578,9 +601,9 @@ func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, optio | |||
| 
 | ||||
| 	switch { | ||||
| 	case name == slirp4netns.BinaryName: | ||||
| 		return setupSlirp4netnsNetwork(defConfig, netns, containerName, netOpts) | ||||
| 		return setupSlirp4netnsNetwork(defConfig, netns, containerName, netOpts, hostnames) | ||||
| 	case name == pasta.BinaryName: | ||||
| 		return setupPasta(defConfig, netns, netOpts) | ||||
| 		return setupPasta(defConfig, netns, netOpts, hostnames) | ||||
| 
 | ||||
| 	// Basically default case except we make sure to not split an empty
 | ||||
| 	// name as this would return a slice with one empty string which is
 | ||||
|  | @ -621,19 +644,19 @@ func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, optio | |||
| 		ContainerName: containerName, | ||||
| 		Networks:      networks, | ||||
| 	} | ||||
| 	netStatus, err = b.NetworkInterface.Setup(mynetns, nettypes.SetupOptions{NetworkOptions: opts}) | ||||
| 	netStatus, err := b.NetworkInterface.Setup(mynetns, nettypes.SetupOptions{NetworkOptions: opts}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	teardown = func() { | ||||
| 	teardown := func() { | ||||
| 		err := b.NetworkInterface.Teardown(mynetns, nettypes.TeardownOptions{NetworkOptions: opts}) | ||||
| 		if err != nil { | ||||
| 			options.Logger.Errorf("failed to cleanup network: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return teardown, netStatus, nil | ||||
| 	return teardown, netStatusToNetResult(netStatus, hostnames), nil | ||||
| } | ||||
| 
 | ||||
| // Create pipes to use for relaying stdio.
 | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package etchosts | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/containers/common/libnetwork/types" | ||||
| 	"github.com/containers/common/libnetwork/util" | ||||
| 	"github.com/containers/common/pkg/config" | ||||
|  | @ -8,9 +10,16 @@ import ( | |||
| 	"github.com/containers/storage/pkg/unshare" | ||||
| ) | ||||
| 
 | ||||
| // GetHostContainersInternalIP return the host.containers.internal ip
 | ||||
| // GetHostContainersInternalIP returns the host.containers.internal ip
 | ||||
| // if netStatus is not nil then networkInterface also must be non nil otherwise this function panics
 | ||||
| func GetHostContainersInternalIP(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork) string { | ||||
| 	return GetHostContainersInternalIPExcluding(conf, netStatus, networkInterface, nil) | ||||
| } | ||||
| 
 | ||||
| // GetHostContainersInternalIPExcluding returns the host.containers.internal ip
 | ||||
| // Exclude are ips that should not be returned, this is useful to prevent returning the same ip as in the container.
 | ||||
| // if netStatus is not nil then networkInterface also must be non nil otherwise this function panics
 | ||||
| func GetHostContainersInternalIPExcluding(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork, exclude []net.IP) string { | ||||
| 	switch conf.Containers.HostContainersInternalIP { | ||||
| 	case "": | ||||
| 		// if empty (default) we will automatically choose one below
 | ||||
|  | @ -27,7 +36,7 @@ func GetHostContainersInternalIP(conf *config.Config, netStatus map[string]types | |||
| 	// Only use the bridge ip when root, as rootless the interfaces are created
 | ||||
| 	// inside the special netns and not the host so we cannot use them.
 | ||||
| 	if unshare.IsRootless() { | ||||
| 		return util.GetLocalIP() | ||||
| 		return util.GetLocalIPExcluding(exclude) | ||||
| 	} | ||||
| 	for net, status := range netStatus { | ||||
| 		network, err := networkInterface.NetworkInspect(net) | ||||
|  | @ -51,7 +60,7 @@ func GetHostContainersInternalIP(conf *config.Config, netStatus map[string]types | |||
| 	if ip != "" { | ||||
| 		return ip | ||||
| 	} | ||||
| 	return util.GetLocalIP() | ||||
| 	return util.GetLocalIPExcluding(exclude) | ||||
| } | ||||
| 
 | ||||
| // GetNetworkHostEntries returns HostEntries for all ips in the network status
 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										9
									
								
								vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
								
								
									generated
								
								
									vendored
								
								
							|  | @ -158,7 +158,8 @@ func (n *Netns) setupPasta(nsPath string) error { | |||
| 		Netns:        nsPath, | ||||
| 		ExtraOptions: []string{"--pid", pidPath}, | ||||
| 	} | ||||
| 	if err := pasta.Setup(&pastaOpts); err != nil { | ||||
| 	res, err := pasta.Setup2(&pastaOpts) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("setting up Pasta: %w", err) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -185,11 +186,9 @@ func (n *Netns) setupPasta(nsPath string) error { | |||
| 		Namespaces: []specs.LinuxNamespace{ | ||||
| 			{Type: specs.NetworkNamespace}, | ||||
| 		}, | ||||
| 		// TODO: Need a way to determine if there is a valid v6 address on any
 | ||||
| 		// external interface of the system.
 | ||||
| 		IPv6Enabled:     false, | ||||
| 		IPv6Enabled:     res.IPv6, | ||||
| 		KeepHostServers: true, | ||||
| 		Nameservers:     []string{}, | ||||
| 		Nameservers:     res.DNSForwardIPs, | ||||
| 	}); err != nil { | ||||
| 		return wrapError("create resolv.conf", err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -13,16 +13,23 @@ package pasta | |||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"os/exec" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containernetworking/plugins/pkg/ns" | ||||
| 	"github.com/containers/common/libnetwork/types" | ||||
| 	"github.com/containers/common/libnetwork/util" | ||||
| 	"github.com/containers/common/pkg/config" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	BinaryName = "pasta" | ||||
| 	dnsForwardOpt = "--dns-forward" | ||||
| 
 | ||||
| 	// dnsForwardIpv4 static ip used as nameserver address inside the netns,
 | ||||
| 	// given this is a "link local" ip it should be very unlikely that it causes conflicts
 | ||||
| 	dnsForwardIpv4 = "169.254.0.1" | ||||
| ) | ||||
| 
 | ||||
| type SetupOptions struct { | ||||
|  | @ -37,21 +44,25 @@ type SetupOptions struct { | |||
| 	ExtraOptions []string | ||||
| } | ||||
| 
 | ||||
| // Setup start the pasta process for the given netns.
 | ||||
| // The pasta binary is looked up in the HelperBinariesDir and $PATH.
 | ||||
| // Note that there is no need any special cleanup logic, the pasta process will
 | ||||
| // automatically exit when the netns path is deleted.
 | ||||
| func Setup(opts *SetupOptions) error { | ||||
| 	_, err := Setup2(opts) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Setup2 start the pasta process for the given netns.
 | ||||
| // The pasta binary is looked up in the HelperBinariesDir and $PATH.
 | ||||
| // Note that there is no need for any special cleanup logic, the pasta
 | ||||
| // process will automatically exit when the netns path is deleted.
 | ||||
| func Setup2(opts *SetupOptions) (*SetupResult, error) { | ||||
| 	NoTCPInitPorts := true | ||||
| 	NoUDPInitPorts := true | ||||
| 	NoTCPNamespacePorts := true | ||||
| 	NoUDPNamespacePorts := true | ||||
| 	NoMapGW := true | ||||
| 	NoDNS := true | ||||
| 
 | ||||
| 	path, err := opts.Config.FindHelperBinary(BinaryName, true) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not find pasta, the network namespace can't be configured: %w", err) | ||||
| 		return nil, fmt.Errorf("could not find pasta, the network namespace can't be configured: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	cmdArgs := []string{} | ||||
|  | @ -72,7 +83,7 @@ func Setup(opts *SetupOptions) error { | |||
| 			case "udp": | ||||
| 				cmdArgs = append(cmdArgs, "-u") | ||||
| 			default: | ||||
| 				return fmt.Errorf("can't forward protocol: %s", protocol) | ||||
| 				return nil, fmt.Errorf("can't forward protocol: %s", protocol) | ||||
| 			} | ||||
| 
 | ||||
| 			arg := fmt.Sprintf("%s%d-%d:%d-%d", addr, | ||||
|  | @ -89,6 +100,7 @@ func Setup(opts *SetupOptions) error { | |||
| 	// then append the ones that were set on the cli
 | ||||
| 	cmdArgs = append(cmdArgs, opts.ExtraOptions...) | ||||
| 
 | ||||
| 	var dnsForwardIPs []string | ||||
| 	for i, opt := range cmdArgs { | ||||
| 		switch opt { | ||||
| 		case "-t", "--tcp-ports": | ||||
|  | @ -103,11 +115,20 @@ func Setup(opts *SetupOptions) error { | |||
| 			NoMapGW = false | ||||
| 			// not an actual pasta(1) option
 | ||||
| 			cmdArgs = append(cmdArgs[:i], cmdArgs[i+1:]...) | ||||
| 		case "-D", "--dns", "--dns-forward": | ||||
| 			NoDNS = false | ||||
| 		case dnsForwardOpt: | ||||
| 			// if there is no arg after it pasta will likely error out anyway due invalid cli args
 | ||||
| 			if len(cmdArgs) > i+1 { | ||||
| 				dnsForwardIPs = append(dnsForwardIPs, cmdArgs[i+1]) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(dnsForwardIPs) == 0 { | ||||
| 		// the user did not request custom --dns-forward so add our own.
 | ||||
| 		cmdArgs = append(cmdArgs, dnsForwardOpt, dnsForwardIpv4) | ||||
| 		dnsForwardIPs = append(dnsForwardIPs, dnsForwardIpv4) | ||||
| 	} | ||||
| 
 | ||||
| 	if NoTCPInitPorts { | ||||
| 		cmdArgs = append(cmdArgs, "-t", "none") | ||||
| 	} | ||||
|  | @ -123,12 +144,6 @@ func Setup(opts *SetupOptions) error { | |||
| 	if NoMapGW { | ||||
| 		cmdArgs = append(cmdArgs, "--no-map-gw") | ||||
| 	} | ||||
| 	if NoDNS { | ||||
| 		// disable pasta reading from /etc/resolv.conf which hides the
 | ||||
| 		// "Couldn't get any nameserver address" warning when only
 | ||||
| 		// localhost resolvers are configured.
 | ||||
| 		cmdArgs = append(cmdArgs, "--dns", "none") | ||||
| 	} | ||||
| 
 | ||||
| 	// always pass --quiet to silence the info output from pasta
 | ||||
| 	cmdArgs = append(cmdArgs, "--quiet", "--netns", opts.Netns) | ||||
|  | @ -140,10 +155,10 @@ func Setup(opts *SetupOptions) error { | |||
| 	if err != nil { | ||||
| 		exitErr := &exec.ExitError{} | ||||
| 		if errors.As(err, &exitErr) { | ||||
| 			return fmt.Errorf("pasta failed with exit code %d:\n%s", | ||||
| 			return nil, fmt.Errorf("pasta failed with exit code %d:\n%s", | ||||
| 				exitErr.ExitCode(), string(out)) | ||||
| 		} | ||||
| 		return fmt.Errorf("failed to start pasta: %w", err) | ||||
| 		return nil, fmt.Errorf("failed to start pasta: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(out) > 0 { | ||||
|  | @ -154,5 +169,39 @@ func Setup(opts *SetupOptions) error { | |||
| 		logrus.Infof("pasta logged warnings: %q", string(out)) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| 	var ipv4, ipv6 bool | ||||
| 	result := &SetupResult{} | ||||
| 	err = ns.WithNetNSPath(opts.Netns, func(_ ns.NetNS) error { | ||||
| 		addrs, err := net.InterfaceAddrs() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for _, addr := range addrs { | ||||
| 			// make sure to skip localhost and other special addresses
 | ||||
| 			if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { | ||||
| 				result.IPAddresses = append(result.IPAddresses, ipnet.IP) | ||||
| 				if !ipv4 && util.IsIPv4(ipnet.IP) { | ||||
| 					ipv4 = true | ||||
| 				} | ||||
| 				if !ipv6 && util.IsIPv6(ipnet.IP) { | ||||
| 					ipv6 = true | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	result.IPv6 = ipv6 | ||||
| 	for _, ip := range dnsForwardIPs { | ||||
| 		ipp := net.ParseIP(ip) | ||||
| 		// add the namesever ip only if the address family matches
 | ||||
| 		if ipv4 && util.IsIPv4(ipp) || ipv6 && util.IsIPv6(ipp) { | ||||
| 			result.DNSForwardIPs = append(result.DNSForwardIPs, ip) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return result, nil | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| package pasta | ||||
| 
 | ||||
| import "net" | ||||
| 
 | ||||
| const BinaryName = "pasta" | ||||
| 
 | ||||
| type SetupResult struct { | ||||
| 	// IpAddresses configured by pasta
 | ||||
| 	IPAddresses []net.IP | ||||
| 	// DNSForwardIP is the ip used in --dns-forward, it should be added as first
 | ||||
| 	// entry to resolv.conf in the container.
 | ||||
| 	DNSForwardIPs []string | ||||
| 	// IPv6 says whenever pasta run with ipv6 support
 | ||||
| 	IPv6 bool | ||||
| } | ||||
|  | @ -1,5 +1,7 @@ | |||
| package slirp4netns | ||||
| 
 | ||||
| import "net" | ||||
| 
 | ||||
| const ( | ||||
| 	ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/default/accept_dad" | ||||
| 	BinaryName                     = "slirp4netns" | ||||
|  | @ -10,3 +12,13 @@ const ( | |||
| 	// default slirp4ns subnet
 | ||||
| 	defaultSubnet = "10.0.2.0/24" | ||||
| ) | ||||
| 
 | ||||
| // SetupResult return type from Setup()
 | ||||
| type SetupResult struct { | ||||
| 	// Pid of the created slirp4netns process
 | ||||
| 	Pid int | ||||
| 	// Subnet which is used by slirp4netns
 | ||||
| 	Subnet *net.IPNet | ||||
| 	// IPv6 whenever Ipv6 is enabled in slirp4netns
 | ||||
| 	IPv6 bool | ||||
| } | ||||
|  |  | |||
|  | @ -86,16 +86,6 @@ type SetupOptions struct { | |||
| 	Pdeathsig syscall.Signal | ||||
| } | ||||
| 
 | ||||
| // SetupResult return type from Setup()
 | ||||
| type SetupResult struct { | ||||
| 	// Pid of the created slirp4netns process
 | ||||
| 	Pid int | ||||
| 	// Subnet which is used by slirp4netns
 | ||||
| 	Subnet *net.IPNet | ||||
| 	// IPv6 whenever Ipv6 is enabled in slirp4netns
 | ||||
| 	IPv6 bool | ||||
| } | ||||
| 
 | ||||
| type logrusDebugWriter struct { | ||||
| 	prefix string | ||||
| } | ||||
|  |  | |||
|  | @ -59,14 +59,31 @@ func NormalizeIP(ip *net.IP) { | |||
| // If no ipv4 address is found it may return an ipv6 address.
 | ||||
| // When no ip is found and empty string is returned.
 | ||||
| func GetLocalIP() string { | ||||
| 	return GetLocalIPExcluding(nil) | ||||
| } | ||||
| 
 | ||||
| // GetLocalIPExcluding returns the first non loopback local IPv4 of the host.
 | ||||
| // If no ipv4 address is found it may return an ipv6 address.
 | ||||
| // Additionally you can specify a list of ips that should not be returned.
 | ||||
| // When no ip is found and empty string is returned.
 | ||||
| func GetLocalIPExcluding(exclude []net.IP) string { | ||||
| 	addrs, err := net.InterfaceAddrs() | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	ip := "" | ||||
| outer: | ||||
| 	for _, address := range addrs { | ||||
| 		// check the address type and if it is not a loopback the display it
 | ||||
| 		if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { | ||||
| 			// cannot use slices.Contains for net.IP
 | ||||
| 			for _, eip := range exclude { | ||||
| 				if eip.Equal(ipnet.IP) { | ||||
| 					// ip should be excluded skip to next one
 | ||||
| 					continue outer | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if IsIPv4(ipnet.IP) { | ||||
| 				return ipnet.IP.String() | ||||
| 			} | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| package version | ||||
| 
 | ||||
| // Version is the version of the build.
 | ||||
| const Version = "0.58.0" | ||||
| const Version = "0.59.0-dev" | ||||
|  |  | |||
|  | @ -391,7 +391,11 @@ definitions: | |||
|           ReadOnlyNonRecursive: | ||||
|             description: | | ||||
|                Make the mount non-recursively read-only, but still leave the mount recursive | ||||
|                (unless NonRecursive is set to true in conjunction). | ||||
|                (unless NonRecursive is set to `true` in conjunction). | ||||
| 
 | ||||
|                Addded in v1.44, before that version all read-only mounts were | ||||
|                non-recursive by default. To match the previous behaviour this | ||||
|                will default to `true` for clients on versions prior to v1.44. | ||||
|             type: "boolean" | ||||
|             default: false | ||||
|           ReadOnlyForceRecursive: | ||||
|  | @ -1743,8 +1747,12 @@ definitions: | |||
|         description: | | ||||
|           Date and time at which the image was created, formatted in | ||||
|           [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. | ||||
| 
 | ||||
|           This information is only available if present in the image, | ||||
|           and omitted otherwise. | ||||
|         type: "string" | ||||
|         x-nullable: false | ||||
|         format: "dateTime" | ||||
|         x-nullable: true | ||||
|         example: "2022-02-04T21:20:12.497794809Z" | ||||
|       Container: | ||||
|         description: | | ||||
|  |  | |||
|  | @ -13,12 +13,13 @@ import ( | |||
| 
 | ||||
| // ContainerCreateConfig is the parameter set to ContainerCreate()
 | ||||
| type ContainerCreateConfig struct { | ||||
| 	Name             string | ||||
| 	Config           *container.Config | ||||
| 	HostConfig       *container.HostConfig | ||||
| 	NetworkingConfig *network.NetworkingConfig | ||||
| 	Platform         *ocispec.Platform | ||||
| 	AdjustCPUShares  bool | ||||
| 	Name                        string | ||||
| 	Config                      *container.Config | ||||
| 	HostConfig                  *container.HostConfig | ||||
| 	NetworkingConfig            *network.NetworkingConfig | ||||
| 	Platform                    *ocispec.Platform | ||||
| 	AdjustCPUShares             bool | ||||
| 	DefaultReadOnlyNonRecursive bool | ||||
| } | ||||
| 
 | ||||
| // ContainerRmConfig holds arguments for the container remove
 | ||||
|  |  | |||
|  | @ -72,7 +72,10 @@ type ImageInspect struct { | |||
| 
 | ||||
| 	// Created is the date and time at which the image was created, formatted in
 | ||||
| 	// RFC 3339 nano-seconds (time.RFC3339Nano).
 | ||||
| 	Created string | ||||
| 	//
 | ||||
| 	// This information is only available if present in the image,
 | ||||
| 	// and omitted otherwise.
 | ||||
| 	Created string `json:",omitempty"` | ||||
| 
 | ||||
| 	// Container is the ID of the container that was used to create the image.
 | ||||
| 	//
 | ||||
|  |  | |||
|  | @ -265,17 +265,22 @@ func (cli *Client) Close() error { | |||
| // This allows for version-dependent code to use the same version as will
 | ||||
| // be negotiated when making the actual requests, and for which cases
 | ||||
| // we cannot do the negotiation lazily.
 | ||||
| func (cli *Client) checkVersion(ctx context.Context) { | ||||
| 	if cli.negotiateVersion && !cli.negotiated { | ||||
| 		cli.NegotiateAPIVersion(ctx) | ||||
| func (cli *Client) checkVersion(ctx context.Context) error { | ||||
| 	if !cli.manualOverride && cli.negotiateVersion && !cli.negotiated { | ||||
| 		ping, err := cli.Ping(ctx) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		cli.negotiateAPIVersionPing(ping) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // getAPIPath returns the versioned request path to call the API.
 | ||||
| // It appends the query parameters to the path if they are not empty.
 | ||||
| func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string { | ||||
| 	var apiPath string | ||||
| 	cli.checkVersion(ctx) | ||||
| 	_ = cli.checkVersion(ctx) | ||||
| 	if cli.version != "" { | ||||
| 		v := strings.TrimPrefix(cli.version, "v") | ||||
| 		apiPath = path.Join(cli.basePath, "/v"+v, p) | ||||
|  | @ -307,7 +312,11 @@ func (cli *Client) ClientVersion() string { | |||
| // added (1.24).
 | ||||
| func (cli *Client) NegotiateAPIVersion(ctx context.Context) { | ||||
| 	if !cli.manualOverride { | ||||
| 		ping, _ := cli.Ping(ctx) | ||||
| 		ping, err := cli.Ping(ctx) | ||||
| 		if err != nil { | ||||
| 			// FIXME(thaJeztah): Ping returns an error when failing to connect to the API; we should not swallow the error here, and instead returning it.
 | ||||
| 			return | ||||
| 		} | ||||
| 		cli.negotiateAPIVersionPing(ping) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -28,7 +28,9 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config | |||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return response, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := cli.NewVersionError(ctx, "1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil { | ||||
| 		return response, err | ||||
|  |  | |||
|  | @ -18,7 +18,9 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co | |||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return response, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil { | ||||
| 		return response, err | ||||
|  |  | |||
|  | @ -23,7 +23,9 @@ func (cli *Client) ContainerRestart(ctx context.Context, containerID string, opt | |||
| 		//
 | ||||
| 		// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 		// the API request is made.
 | ||||
| 		cli.checkVersion(ctx) | ||||
| 		if err := cli.checkVersion(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if versions.GreaterThanOrEqualTo(cli.version, "1.42") { | ||||
| 			query.Set("signal", options.Signal) | ||||
| 		} | ||||
|  |  | |||
|  | @ -27,7 +27,9 @@ func (cli *Client) ContainerStop(ctx context.Context, containerID string, option | |||
| 		//
 | ||||
| 		// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 		// the API request is made.
 | ||||
| 		cli.checkVersion(ctx) | ||||
| 		if err := cli.checkVersion(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if versions.GreaterThanOrEqualTo(cli.version, "1.42") { | ||||
| 			query.Set("signal", options.Signal) | ||||
| 		} | ||||
|  |  | |||
|  | @ -30,19 +30,22 @@ const containerWaitErrorMsgLimit = 2 * 1024 /* Max: 2KiB */ | |||
| // synchronize ContainerWait with other calls, such as specifying a
 | ||||
| // "next-exit" condition before issuing a ContainerStart request.
 | ||||
| func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { | ||||
| 	resultC := make(chan container.WaitResponse) | ||||
| 	errC := make(chan error, 1) | ||||
| 
 | ||||
| 	// Make sure we negotiated (if the client is configured to do so),
 | ||||
| 	// as code below contains API-version specific handling of options.
 | ||||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		errC <- err | ||||
| 		return resultC, errC | ||||
| 	} | ||||
| 	if versions.LessThan(cli.ClientVersion(), "1.30") { | ||||
| 		return cli.legacyContainerWait(ctx, containerID) | ||||
| 	} | ||||
| 
 | ||||
| 	resultC := make(chan container.WaitResponse) | ||||
| 	errC := make(chan error, 1) | ||||
| 
 | ||||
| 	query := url.Values{} | ||||
| 	if condition != "" { | ||||
| 		query.Set("condition", string(condition)) | ||||
|  |  | |||
|  | @ -11,15 +11,16 @@ import ( | |||
| 
 | ||||
| // errConnectionFailed implements an error returned when connection failed.
 | ||||
| type errConnectionFailed struct { | ||||
| 	host string | ||||
| 	error | ||||
| } | ||||
| 
 | ||||
| // Error returns a string representation of an errConnectionFailed
 | ||||
| func (err errConnectionFailed) Error() string { | ||||
| 	if err.host == "" { | ||||
| 		return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?" | ||||
| 	} | ||||
| 	return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host) | ||||
| func (e errConnectionFailed) Error() string { | ||||
| 	return e.error.Error() | ||||
| } | ||||
| 
 | ||||
| func (e errConnectionFailed) Unwrap() error { | ||||
| 	return e.error | ||||
| } | ||||
| 
 | ||||
| // IsErrConnectionFailed returns true if the error is caused by connection failed.
 | ||||
|  | @ -29,7 +30,13 @@ func IsErrConnectionFailed(err error) bool { | |||
| 
 | ||||
| // ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed.
 | ||||
| func ErrorConnectionFailed(host string) error { | ||||
| 	return errConnectionFailed{host: host} | ||||
| 	var err error | ||||
| 	if host == "" { | ||||
| 		err = fmt.Errorf("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") | ||||
| 	} else { | ||||
| 		err = fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host) | ||||
| 	} | ||||
| 	return errConnectionFailed{error: err} | ||||
| } | ||||
| 
 | ||||
| // IsErrNotFound returns true if the error is a NotFound error, which is returned
 | ||||
|  | @ -60,7 +67,9 @@ func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature str | |||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if cli.version != "" && versions.LessThan(cli.version, APIrequired) { | ||||
| 		return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version) | ||||
| 	} | ||||
|  |  | |||
|  | @ -13,14 +13,17 @@ import ( | |||
| 
 | ||||
| // ImageList returns a list of images in the docker host.
 | ||||
| func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]image.Summary, error) { | ||||
| 	var images []image.Summary | ||||
| 
 | ||||
| 	// Make sure we negotiated (if the client is configured to do so),
 | ||||
| 	// as code below contains API-version specific handling of options.
 | ||||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return images, err | ||||
| 	} | ||||
| 
 | ||||
| 	var images []image.Summary | ||||
| 	query := url.Values{} | ||||
| 
 | ||||
| 	optionFilters := options.Filters | ||||
|  |  | |||
|  | @ -10,12 +10,16 @@ import ( | |||
| 
 | ||||
| // NetworkCreate creates a new network in the docker host.
 | ||||
| func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { | ||||
| 	var response types.NetworkCreateResponse | ||||
| 
 | ||||
| 	// Make sure we negotiated (if the client is configured to do so),
 | ||||
| 	// as code below contains API-version specific handling of options.
 | ||||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return response, err | ||||
| 	} | ||||
| 
 | ||||
| 	networkCreateRequest := types.NetworkCreateRequest{ | ||||
| 		NetworkCreate: options, | ||||
|  | @ -25,7 +29,6 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types | |||
| 		networkCreateRequest.CheckDuplicate = true //nolint:staticcheck // ignore SA1019: CheckDuplicate is deprecated since API v1.44.
 | ||||
| 	} | ||||
| 
 | ||||
| 	var response types.NetworkCreateResponse | ||||
| 	serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) | ||||
| 	defer ensureReaderClosed(serverResp) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -14,7 +14,10 @@ import ( | |||
| // Ping pings the server and returns the value of the "Docker-Experimental",
 | ||||
| // "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
 | ||||
| // a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
 | ||||
| // by the daemon.
 | ||||
| // by the daemon. It ignores internal server errors returned by the API, which
 | ||||
| // may be returned if the daemon is in an unhealthy state, but returns errors
 | ||||
| // for other non-success status codes, failing to connect to the API, or failing
 | ||||
| // to parse the API response.
 | ||||
| func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { | ||||
| 	var ping types.Ping | ||||
| 
 | ||||
|  |  | |||
|  | @ -134,17 +134,18 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u | |||
| 	return resp, errdefs.FromStatusCode(err, resp.statusCode) | ||||
| } | ||||
| 
 | ||||
| // FIXME(thaJeztah): Should this actually return a serverResp when a connection error occurred?
 | ||||
| func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { | ||||
| 	serverResp := serverResponse{statusCode: -1, reqURL: req.URL} | ||||
| 
 | ||||
| 	resp, err := cli.client.Do(req) | ||||
| 	if err != nil { | ||||
| 		if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { | ||||
| 			return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) | ||||
| 			return serverResp, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)} | ||||
| 		} | ||||
| 
 | ||||
| 		if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") { | ||||
| 			return serverResp, errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings") | ||||
| 			return serverResp, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")} | ||||
| 		} | ||||
| 
 | ||||
| 		// Don't decorate context sentinel errors; users may be comparing to
 | ||||
|  | @ -156,12 +157,13 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { | |||
| 		if uErr, ok := err.(*url.Error); ok { | ||||
| 			if nErr, ok := uErr.Err.(*net.OpError); ok { | ||||
| 				if os.IsPermission(nErr.Err) { | ||||
| 					return serverResp, errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host) | ||||
| 					return serverResp, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if nErr, ok := err.(net.Error); ok { | ||||
| 			// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
 | ||||
| 			if nErr.Timeout() { | ||||
| 				return serverResp, ErrorConnectionFailed(cli.host) | ||||
| 			} | ||||
|  | @ -190,7 +192,7 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return serverResp, errors.Wrap(err, "error during connect") | ||||
| 		return serverResp, errConnectionFailed{errors.Wrap(err, "error during connect")} | ||||
| 	} | ||||
| 
 | ||||
| 	if resp != nil { | ||||
|  |  | |||
|  | @ -25,7 +25,9 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, | |||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return response, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
 | ||||
| 	if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) { | ||||
|  |  | |||
|  | @ -16,18 +16,18 @@ import ( | |||
| // It should be the value as set *before* the update. You can find this value in the Meta field
 | ||||
| // of swarm.Service, which can be found using ServiceInspectWithRaw.
 | ||||
| func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { | ||||
| 	response := swarm.ServiceUpdateResponse{} | ||||
| 
 | ||||
| 	// Make sure we negotiated (if the client is configured to do so),
 | ||||
| 	// as code below contains API-version specific handling of options.
 | ||||
| 	//
 | ||||
| 	// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 	// the API request is made.
 | ||||
| 	cli.checkVersion(ctx) | ||||
| 
 | ||||
| 	var ( | ||||
| 		query    = url.Values{} | ||||
| 		response = swarm.ServiceUpdateResponse{} | ||||
| 	) | ||||
| 	if err := cli.checkVersion(ctx); err != nil { | ||||
| 		return response, err | ||||
| 	} | ||||
| 
 | ||||
| 	query := url.Values{} | ||||
| 	if options.RegistryAuthFrom != "" { | ||||
| 		query.Set("registryAuthFrom", options.RegistryAuthFrom) | ||||
| 	} | ||||
|  |  | |||
|  | @ -16,7 +16,9 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool | |||
| 		//
 | ||||
| 		// Normally, version-negotiation (if enabled) would not happen until
 | ||||
| 		// the API request is made.
 | ||||
| 		cli.checkVersion(ctx) | ||||
| 		if err := cli.checkVersion(ctx); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if versions.GreaterThanOrEqualTo(cli.version, "1.25") { | ||||
| 			query.Set("force", "1") | ||||
| 		} | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/docker/docker/pkg/jsonmessage" | ||||
| 	"github.com/docker/docker/pkg/progress" | ||||
|  | @ -109,6 +110,7 @@ type progressOutput struct { | |||
| 	sf       formatProgress | ||||
| 	out      io.Writer | ||||
| 	newLines bool | ||||
| 	mu       sync.Mutex | ||||
| } | ||||
| 
 | ||||
| // WriteProgress formats progress information from a ProgressReader.
 | ||||
|  | @ -120,6 +122,9 @@ func (out *progressOutput) WriteProgress(prog progress.Progress) error { | |||
| 		jsonProgress := jsonmessage.JSONProgress{Current: prog.Current, Total: prog.Total, HideCounts: prog.HideCounts, Units: prog.Units} | ||||
| 		formatted = out.sf.formatProgress(prog.ID, prog.Action, &jsonProgress, prog.Aux) | ||||
| 	} | ||||
| 
 | ||||
| 	out.mu.Lock() | ||||
| 	defer out.mu.Unlock() | ||||
| 	_, err := out.out.Write(formatted) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  |  | |||
|  | @ -1,530 +0,0 @@ | |||
| // Copyright 2015 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 jsonpb | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/encoding/protojson" | ||||
| 	protoV2 "google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	"google.golang.org/protobuf/reflect/protoregistry" | ||||
| ) | ||||
| 
 | ||||
| const wrapJSONUnmarshalV2 = false | ||||
| 
 | ||||
| // UnmarshalNext unmarshals the next JSON object from d into m.
 | ||||
| func UnmarshalNext(d *json.Decoder, m proto.Message) error { | ||||
| 	return new(Unmarshaler).UnmarshalNext(d, m) | ||||
| } | ||||
| 
 | ||||
| // Unmarshal unmarshals a JSON object from r into m.
 | ||||
| func Unmarshal(r io.Reader, m proto.Message) error { | ||||
| 	return new(Unmarshaler).Unmarshal(r, m) | ||||
| } | ||||
| 
 | ||||
| // UnmarshalString unmarshals a JSON object from s into m.
 | ||||
| func UnmarshalString(s string, m proto.Message) error { | ||||
| 	return new(Unmarshaler).Unmarshal(strings.NewReader(s), m) | ||||
| } | ||||
| 
 | ||||
| // Unmarshaler is a configurable object for converting from a JSON
 | ||||
| // representation to a protocol buffer object.
 | ||||
| type Unmarshaler struct { | ||||
| 	// AllowUnknownFields specifies whether to allow messages to contain
 | ||||
| 	// unknown JSON fields, as opposed to failing to unmarshal.
 | ||||
| 	AllowUnknownFields bool | ||||
| 
 | ||||
| 	// AnyResolver is used to resolve the google.protobuf.Any well-known type.
 | ||||
| 	// If unset, the global registry is used by default.
 | ||||
| 	AnyResolver AnyResolver | ||||
| } | ||||
| 
 | ||||
| // JSONPBUnmarshaler is implemented by protobuf messages that customize the way
 | ||||
| // they are unmarshaled from JSON. Messages that implement this should also
 | ||||
| // implement JSONPBMarshaler so that the custom format can be produced.
 | ||||
| //
 | ||||
| // The JSON unmarshaling must follow the JSON to proto specification:
 | ||||
| //	https://developers.google.com/protocol-buffers/docs/proto3#json
 | ||||
| //
 | ||||
| // Deprecated: Custom types should implement protobuf reflection instead.
 | ||||
| type JSONPBUnmarshaler interface { | ||||
| 	UnmarshalJSONPB(*Unmarshaler, []byte) error | ||||
| } | ||||
| 
 | ||||
| // Unmarshal unmarshals a JSON object from r into m.
 | ||||
| func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error { | ||||
| 	return u.UnmarshalNext(json.NewDecoder(r), m) | ||||
| } | ||||
| 
 | ||||
| // UnmarshalNext unmarshals the next JSON object from d into m.
 | ||||
| func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error { | ||||
| 	if m == nil { | ||||
| 		return errors.New("invalid nil message") | ||||
| 	} | ||||
| 
 | ||||
| 	// Parse the next JSON object from the stream.
 | ||||
| 	raw := json.RawMessage{} | ||||
| 	if err := d.Decode(&raw); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Check for custom unmarshalers first since they may not properly
 | ||||
| 	// implement protobuf reflection that the logic below relies on.
 | ||||
| 	if jsu, ok := m.(JSONPBUnmarshaler); ok { | ||||
| 		return jsu.UnmarshalJSONPB(u, raw) | ||||
| 	} | ||||
| 
 | ||||
| 	mr := proto.MessageReflect(m) | ||||
| 
 | ||||
| 	// NOTE: For historical reasons, a top-level null is treated as a noop.
 | ||||
| 	// This is incorrect, but kept for compatibility.
 | ||||
| 	if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if wrapJSONUnmarshalV2 { | ||||
| 		// NOTE: If input message is non-empty, we need to preserve merge semantics
 | ||||
| 		// of the old jsonpb implementation. These semantics are not supported by
 | ||||
| 		// the protobuf JSON specification.
 | ||||
| 		isEmpty := true | ||||
| 		mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { | ||||
| 			isEmpty = false // at least one iteration implies non-empty
 | ||||
| 			return false | ||||
| 		}) | ||||
| 		if !isEmpty { | ||||
| 			// Perform unmarshaling into a newly allocated, empty message.
 | ||||
| 			mr = mr.New() | ||||
| 
 | ||||
| 			// Use a defer to copy all unmarshaled fields into the original message.
 | ||||
| 			dst := proto.MessageReflect(m) | ||||
| 			defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { | ||||
| 				dst.Set(fd, v) | ||||
| 				return true | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 		// Unmarshal using the v2 JSON unmarshaler.
 | ||||
| 		opts := protojson.UnmarshalOptions{ | ||||
| 			DiscardUnknown: u.AllowUnknownFields, | ||||
| 		} | ||||
| 		if u.AnyResolver != nil { | ||||
| 			opts.Resolver = anyResolver{u.AnyResolver} | ||||
| 		} | ||||
| 		return opts.Unmarshal(raw, mr.Interface()) | ||||
| 	} else { | ||||
| 		if err := u.unmarshalMessage(mr, raw); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return protoV2.CheckInitialized(mr.Interface()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error { | ||||
| 	md := m.Descriptor() | ||||
| 	fds := md.Fields() | ||||
| 
 | ||||
| 	if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { | ||||
| 		return jsu.UnmarshalJSONPB(u, in) | ||||
| 	} | ||||
| 
 | ||||
| 	if string(in) == "null" && md.FullName() != "google.protobuf.Value" { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	switch wellKnownType(md.FullName()) { | ||||
| 	case "Any": | ||||
| 		var jsonObject map[string]json.RawMessage | ||||
| 		if err := json.Unmarshal(in, &jsonObject); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		rawTypeURL, ok := jsonObject["@type"] | ||||
| 		if !ok { | ||||
| 			return errors.New("Any JSON doesn't have '@type'") | ||||
| 		} | ||||
| 		typeURL, err := unquoteString(string(rawTypeURL)) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL) | ||||
| 		} | ||||
| 		m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL)) | ||||
| 
 | ||||
| 		var m2 protoreflect.Message | ||||
| 		if u.AnyResolver != nil { | ||||
| 			mi, err := u.AnyResolver.Resolve(typeURL) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			m2 = proto.MessageReflect(mi) | ||||
| 		} else { | ||||
| 			mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) | ||||
| 			if err != nil { | ||||
| 				if err == protoregistry.NotFound { | ||||
| 					return fmt.Errorf("could not resolve Any message type: %v", typeURL) | ||||
| 				} | ||||
| 				return err | ||||
| 			} | ||||
| 			m2 = mt.New() | ||||
| 		} | ||||
| 
 | ||||
| 		if wellKnownType(m2.Descriptor().FullName()) != "" { | ||||
| 			rawValue, ok := jsonObject["value"] | ||||
| 			if !ok { | ||||
| 				return errors.New("Any JSON doesn't have 'value'") | ||||
| 			} | ||||
| 			if err := u.unmarshalMessage(m2, rawValue); err != nil { | ||||
| 				return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) | ||||
| 			} | ||||
| 		} else { | ||||
| 			delete(jsonObject, "@type") | ||||
| 			rawJSON, err := json.Marshal(jsonObject) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) | ||||
| 			} | ||||
| 			if err = u.unmarshalMessage(m2, rawJSON); err != nil { | ||||
| 				return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		rawWire, err := protoV2.Marshal(m2.Interface()) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err) | ||||
| 		} | ||||
| 		m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire)) | ||||
| 		return nil | ||||
| 	case "BoolValue", "BytesValue", "StringValue", | ||||
| 		"Int32Value", "UInt32Value", "FloatValue", | ||||
| 		"Int64Value", "UInt64Value", "DoubleValue": | ||||
| 		fd := fds.ByNumber(1) | ||||
| 		v, err := u.unmarshalValue(m.NewField(fd), in, fd) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		m.Set(fd, v) | ||||
| 		return nil | ||||
| 	case "Duration": | ||||
| 		v, err := unquoteString(string(in)) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		d, err := time.ParseDuration(v) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("bad Duration: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		sec := d.Nanoseconds() / 1e9 | ||||
| 		nsec := d.Nanoseconds() % 1e9 | ||||
| 		m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) | ||||
| 		m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) | ||||
| 		return nil | ||||
| 	case "Timestamp": | ||||
| 		v, err := unquoteString(string(in)) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		t, err := time.Parse(time.RFC3339Nano, v) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("bad Timestamp: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		sec := t.Unix() | ||||
| 		nsec := t.Nanosecond() | ||||
| 		m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) | ||||
| 		m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) | ||||
| 		return nil | ||||
| 	case "Value": | ||||
| 		switch { | ||||
| 		case string(in) == "null": | ||||
| 			m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0)) | ||||
| 		case string(in) == "true": | ||||
| 			m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true)) | ||||
| 		case string(in) == "false": | ||||
| 			m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false)) | ||||
| 		case hasPrefixAndSuffix('"', in, '"'): | ||||
| 			s, err := unquoteString(string(in)) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("unrecognized type for Value %q", in) | ||||
| 			} | ||||
| 			m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s)) | ||||
| 		case hasPrefixAndSuffix('[', in, ']'): | ||||
| 			v := m.Mutable(fds.ByNumber(6)) | ||||
| 			return u.unmarshalMessage(v.Message(), in) | ||||
| 		case hasPrefixAndSuffix('{', in, '}'): | ||||
| 			v := m.Mutable(fds.ByNumber(5)) | ||||
| 			return u.unmarshalMessage(v.Message(), in) | ||||
| 		default: | ||||
| 			f, err := strconv.ParseFloat(string(in), 0) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("unrecognized type for Value %q", in) | ||||
| 			} | ||||
| 			m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f)) | ||||
| 		} | ||||
| 		return nil | ||||
| 	case "ListValue": | ||||
| 		var jsonArray []json.RawMessage | ||||
| 		if err := json.Unmarshal(in, &jsonArray); err != nil { | ||||
| 			return fmt.Errorf("bad ListValue: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		lv := m.Mutable(fds.ByNumber(1)).List() | ||||
| 		for _, raw := range jsonArray { | ||||
| 			ve := lv.NewElement() | ||||
| 			if err := u.unmarshalMessage(ve.Message(), raw); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			lv.Append(ve) | ||||
| 		} | ||||
| 		return nil | ||||
| 	case "Struct": | ||||
| 		var jsonObject map[string]json.RawMessage | ||||
| 		if err := json.Unmarshal(in, &jsonObject); err != nil { | ||||
| 			return fmt.Errorf("bad StructValue: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		mv := m.Mutable(fds.ByNumber(1)).Map() | ||||
| 		for key, raw := range jsonObject { | ||||
| 			kv := protoreflect.ValueOf(key).MapKey() | ||||
| 			vv := mv.NewValue() | ||||
| 			if err := u.unmarshalMessage(vv.Message(), raw); err != nil { | ||||
| 				return fmt.Errorf("bad value in StructValue for key %q: %v", key, err) | ||||
| 			} | ||||
| 			mv.Set(kv, vv) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	var jsonObject map[string]json.RawMessage | ||||
| 	if err := json.Unmarshal(in, &jsonObject); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Handle known fields.
 | ||||
| 	for i := 0; i < fds.Len(); i++ { | ||||
| 		fd := fds.Get(i) | ||||
| 		if fd.IsWeak() && fd.Message().IsPlaceholder() { | ||||
| 			continue //  weak reference is not linked in
 | ||||
| 		} | ||||
| 
 | ||||
| 		// Search for any raw JSON value associated with this field.
 | ||||
| 		var raw json.RawMessage | ||||
| 		name := string(fd.Name()) | ||||
| 		if fd.Kind() == protoreflect.GroupKind { | ||||
| 			name = string(fd.Message().Name()) | ||||
| 		} | ||||
| 		if v, ok := jsonObject[name]; ok { | ||||
| 			delete(jsonObject, name) | ||||
| 			raw = v | ||||
| 		} | ||||
| 		name = string(fd.JSONName()) | ||||
| 		if v, ok := jsonObject[name]; ok { | ||||
| 			delete(jsonObject, name) | ||||
| 			raw = v | ||||
| 		} | ||||
| 
 | ||||
| 		field := m.NewField(fd) | ||||
| 		// Unmarshal the field value.
 | ||||
| 		if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { | ||||
| 			continue | ||||
| 		} | ||||
| 		v, err := u.unmarshalValue(field, raw, fd) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		m.Set(fd, v) | ||||
| 	} | ||||
| 
 | ||||
| 	// Handle extension fields.
 | ||||
| 	for name, raw := range jsonObject { | ||||
| 		if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		// Resolve the extension field by name.
 | ||||
| 		xname := protoreflect.FullName(name[len("[") : len(name)-len("]")]) | ||||
| 		xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname) | ||||
| 		if xt == nil && isMessageSet(md) { | ||||
| 			xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension")) | ||||
| 		} | ||||
| 		if xt == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		delete(jsonObject, name) | ||||
| 		fd := xt.TypeDescriptor() | ||||
| 		if fd.ContainingMessage().FullName() != m.Descriptor().FullName() { | ||||
| 			return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) | ||||
| 		} | ||||
| 
 | ||||
| 		field := m.NewField(fd) | ||||
| 		// Unmarshal the field value.
 | ||||
| 		if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { | ||||
| 			continue | ||||
| 		} | ||||
| 		v, err := u.unmarshalValue(field, raw, fd) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		m.Set(fd, v) | ||||
| 	} | ||||
| 
 | ||||
| 	if !u.AllowUnknownFields && len(jsonObject) > 0 { | ||||
| 		for name := range jsonObject { | ||||
| 			return fmt.Errorf("unknown field %q in %v", name, md.FullName()) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { | ||||
| 	if fd.Cardinality() == protoreflect.Repeated { | ||||
| 		return false | ||||
| 	} | ||||
| 	if md := fd.Message(); md != nil { | ||||
| 		return md.FullName() == "google.protobuf.Value" | ||||
| 	} | ||||
| 	if ed := fd.Enum(); ed != nil { | ||||
| 		return ed.FullName() == "google.protobuf.NullValue" | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { | ||||
| 	if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { | ||||
| 		_, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) | ||||
| 		return ok | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { | ||||
| 	switch { | ||||
| 	case fd.IsList(): | ||||
| 		var jsonArray []json.RawMessage | ||||
| 		if err := json.Unmarshal(in, &jsonArray); err != nil { | ||||
| 			return v, err | ||||
| 		} | ||||
| 		lv := v.List() | ||||
| 		for _, raw := range jsonArray { | ||||
| 			ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd) | ||||
| 			if err != nil { | ||||
| 				return v, err | ||||
| 			} | ||||
| 			lv.Append(ve) | ||||
| 		} | ||||
| 		return v, nil | ||||
| 	case fd.IsMap(): | ||||
| 		var jsonObject map[string]json.RawMessage | ||||
| 		if err := json.Unmarshal(in, &jsonObject); err != nil { | ||||
| 			return v, err | ||||
| 		} | ||||
| 		kfd := fd.MapKey() | ||||
| 		vfd := fd.MapValue() | ||||
| 		mv := v.Map() | ||||
| 		for key, raw := range jsonObject { | ||||
| 			var kv protoreflect.MapKey | ||||
| 			if kfd.Kind() == protoreflect.StringKind { | ||||
| 				kv = protoreflect.ValueOf(key).MapKey() | ||||
| 			} else { | ||||
| 				v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd) | ||||
| 				if err != nil { | ||||
| 					return v, err | ||||
| 				} | ||||
| 				kv = v.MapKey() | ||||
| 			} | ||||
| 
 | ||||
| 			vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd) | ||||
| 			if err != nil { | ||||
| 				return v, err | ||||
| 			} | ||||
| 			mv.Set(kv, vv) | ||||
| 		} | ||||
| 		return v, nil | ||||
| 	default: | ||||
| 		return u.unmarshalSingularValue(v, in, fd) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var nonFinite = map[string]float64{ | ||||
| 	`"NaN"`:       math.NaN(), | ||||
| 	`"Infinity"`:  math.Inf(+1), | ||||
| 	`"-Infinity"`: math.Inf(-1), | ||||
| } | ||||
| 
 | ||||
| func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { | ||||
| 	switch fd.Kind() { | ||||
| 	case protoreflect.BoolKind: | ||||
| 		return unmarshalValue(in, new(bool)) | ||||
| 	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: | ||||
| 		return unmarshalValue(trimQuote(in), new(int32)) | ||||
| 	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: | ||||
| 		return unmarshalValue(trimQuote(in), new(int64)) | ||||
| 	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: | ||||
| 		return unmarshalValue(trimQuote(in), new(uint32)) | ||||
| 	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: | ||||
| 		return unmarshalValue(trimQuote(in), new(uint64)) | ||||
| 	case protoreflect.FloatKind: | ||||
| 		if f, ok := nonFinite[string(in)]; ok { | ||||
| 			return protoreflect.ValueOfFloat32(float32(f)), nil | ||||
| 		} | ||||
| 		return unmarshalValue(trimQuote(in), new(float32)) | ||||
| 	case protoreflect.DoubleKind: | ||||
| 		if f, ok := nonFinite[string(in)]; ok { | ||||
| 			return protoreflect.ValueOfFloat64(float64(f)), nil | ||||
| 		} | ||||
| 		return unmarshalValue(trimQuote(in), new(float64)) | ||||
| 	case protoreflect.StringKind: | ||||
| 		return unmarshalValue(in, new(string)) | ||||
| 	case protoreflect.BytesKind: | ||||
| 		return unmarshalValue(in, new([]byte)) | ||||
| 	case protoreflect.EnumKind: | ||||
| 		if hasPrefixAndSuffix('"', in, '"') { | ||||
| 			vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in))) | ||||
| 			if vd == nil { | ||||
| 				return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName()) | ||||
| 			} | ||||
| 			return protoreflect.ValueOfEnum(vd.Number()), nil | ||||
| 		} | ||||
| 		return unmarshalValue(in, new(protoreflect.EnumNumber)) | ||||
| 	case protoreflect.MessageKind, protoreflect.GroupKind: | ||||
| 		err := u.unmarshalMessage(v.Message(), in) | ||||
| 		return v, err | ||||
| 	default: | ||||
| 		panic(fmt.Sprintf("invalid kind %v", fd.Kind())) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) { | ||||
| 	err := json.Unmarshal(in, v) | ||||
| 	return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err | ||||
| } | ||||
| 
 | ||||
| func unquoteString(in string) (out string, err error) { | ||||
| 	err = json.Unmarshal([]byte(in), &out) | ||||
| 	return out, err | ||||
| } | ||||
| 
 | ||||
| func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool { | ||||
| 	if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix { | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // trimQuote is like unquoteString but simply strips surrounding quotes.
 | ||||
| // This is incorrect, but is behavior done by the legacy implementation.
 | ||||
| func trimQuote(in []byte) []byte { | ||||
| 	if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' { | ||||
| 		in = in[1 : len(in)-1] | ||||
| 	} | ||||
| 	return in | ||||
| } | ||||
|  | @ -1,559 +0,0 @@ | |||
| // Copyright 2015 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 jsonpb | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/encoding/protojson" | ||||
| 	protoV2 "google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	"google.golang.org/protobuf/reflect/protoregistry" | ||||
| ) | ||||
| 
 | ||||
| const wrapJSONMarshalV2 = false | ||||
| 
 | ||||
| // Marshaler is a configurable object for marshaling protocol buffer messages
 | ||||
| // to the specified JSON representation.
 | ||||
| type Marshaler struct { | ||||
| 	// OrigName specifies whether to use the original protobuf name for fields.
 | ||||
| 	OrigName bool | ||||
| 
 | ||||
| 	// EnumsAsInts specifies whether to render enum values as integers,
 | ||||
| 	// as opposed to string values.
 | ||||
| 	EnumsAsInts bool | ||||
| 
 | ||||
| 	// EmitDefaults specifies whether to render fields with zero values.
 | ||||
| 	EmitDefaults bool | ||||
| 
 | ||||
| 	// Indent controls whether the output is compact or not.
 | ||||
| 	// If empty, the output is compact JSON. Otherwise, every JSON object
 | ||||
| 	// entry and JSON array value will be on its own line.
 | ||||
| 	// Each line will be preceded by repeated copies of Indent, where the
 | ||||
| 	// number of copies is the current indentation depth.
 | ||||
| 	Indent string | ||||
| 
 | ||||
| 	// AnyResolver is used to resolve the google.protobuf.Any well-known type.
 | ||||
| 	// If unset, the global registry is used by default.
 | ||||
| 	AnyResolver AnyResolver | ||||
| } | ||||
| 
 | ||||
| // JSONPBMarshaler is implemented by protobuf messages that customize the
 | ||||
| // way they are marshaled to JSON. Messages that implement this should also
 | ||||
| // implement JSONPBUnmarshaler so that the custom format can be parsed.
 | ||||
| //
 | ||||
| // The JSON marshaling must follow the proto to JSON specification:
 | ||||
| //	https://developers.google.com/protocol-buffers/docs/proto3#json
 | ||||
| //
 | ||||
| // Deprecated: Custom types should implement protobuf reflection instead.
 | ||||
| type JSONPBMarshaler interface { | ||||
| 	MarshalJSONPB(*Marshaler) ([]byte, error) | ||||
| } | ||||
| 
 | ||||
| // Marshal serializes a protobuf message as JSON into w.
 | ||||
| func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error { | ||||
| 	b, err := jm.marshal(m) | ||||
| 	if len(b) > 0 { | ||||
| 		if _, err := w.Write(b); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // MarshalToString serializes a protobuf message as JSON in string form.
 | ||||
| func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) { | ||||
| 	b, err := jm.marshal(m) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return string(b), nil | ||||
| } | ||||
| 
 | ||||
| func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) { | ||||
| 	v := reflect.ValueOf(m) | ||||
| 	if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { | ||||
| 		return nil, errors.New("Marshal called with nil") | ||||
| 	} | ||||
| 
 | ||||
| 	// Check for custom marshalers first since they may not properly
 | ||||
| 	// implement protobuf reflection that the logic below relies on.
 | ||||
| 	if jsm, ok := m.(JSONPBMarshaler); ok { | ||||
| 		return jsm.MarshalJSONPB(jm) | ||||
| 	} | ||||
| 
 | ||||
| 	if wrapJSONMarshalV2 { | ||||
| 		opts := protojson.MarshalOptions{ | ||||
| 			UseProtoNames:   jm.OrigName, | ||||
| 			UseEnumNumbers:  jm.EnumsAsInts, | ||||
| 			EmitUnpopulated: jm.EmitDefaults, | ||||
| 			Indent:          jm.Indent, | ||||
| 		} | ||||
| 		if jm.AnyResolver != nil { | ||||
| 			opts.Resolver = anyResolver{jm.AnyResolver} | ||||
| 		} | ||||
| 		return opts.Marshal(proto.MessageReflect(m).Interface()) | ||||
| 	} else { | ||||
| 		// Check for unpopulated required fields first.
 | ||||
| 		m2 := proto.MessageReflect(m) | ||||
| 		if err := protoV2.CheckInitialized(m2.Interface()); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		w := jsonWriter{Marshaler: jm} | ||||
| 		err := w.marshalMessage(m2, "", "") | ||||
| 		return w.buf, err | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type jsonWriter struct { | ||||
| 	*Marshaler | ||||
| 	buf []byte | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) write(s string) { | ||||
| 	w.buf = append(w.buf, s...) | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error { | ||||
| 	if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok { | ||||
| 		b, err := jsm.MarshalJSONPB(w.Marshaler) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if typeURL != "" { | ||||
| 			// we are marshaling this object to an Any type
 | ||||
| 			var js map[string]*json.RawMessage | ||||
| 			if err = json.Unmarshal(b, &js); err != nil { | ||||
| 				return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err) | ||||
| 			} | ||||
| 			turl, err := json.Marshal(typeURL) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) | ||||
| 			} | ||||
| 			js["@type"] = (*json.RawMessage)(&turl) | ||||
| 			if b, err = json.Marshal(js); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		w.write(string(b)) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	md := m.Descriptor() | ||||
| 	fds := md.Fields() | ||||
| 
 | ||||
| 	// Handle well-known types.
 | ||||
| 	const secondInNanos = int64(time.Second / time.Nanosecond) | ||||
| 	switch wellKnownType(md.FullName()) { | ||||
| 	case "Any": | ||||
| 		return w.marshalAny(m, indent) | ||||
| 	case "BoolValue", "BytesValue", "StringValue", | ||||
| 		"Int32Value", "UInt32Value", "FloatValue", | ||||
| 		"Int64Value", "UInt64Value", "DoubleValue": | ||||
| 		fd := fds.ByNumber(1) | ||||
| 		return w.marshalValue(fd, m.Get(fd), indent) | ||||
| 	case "Duration": | ||||
| 		const maxSecondsInDuration = 315576000000 | ||||
| 		// "Generated output always contains 0, 3, 6, or 9 fractional digits,
 | ||||
| 		//  depending on required precision."
 | ||||
| 		s := m.Get(fds.ByNumber(1)).Int() | ||||
| 		ns := m.Get(fds.ByNumber(2)).Int() | ||||
| 		if s < -maxSecondsInDuration || s > maxSecondsInDuration { | ||||
| 			return fmt.Errorf("seconds out of range %v", s) | ||||
| 		} | ||||
| 		if ns <= -secondInNanos || ns >= secondInNanos { | ||||
| 			return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) | ||||
| 		} | ||||
| 		if (s > 0 && ns < 0) || (s < 0 && ns > 0) { | ||||
| 			return errors.New("signs of seconds and nanos do not match") | ||||
| 		} | ||||
| 		var sign string | ||||
| 		if s < 0 || ns < 0 { | ||||
| 			sign, s, ns = "-", -1*s, -1*ns | ||||
| 		} | ||||
| 		x := fmt.Sprintf("%s%d.%09d", sign, s, ns) | ||||
| 		x = strings.TrimSuffix(x, "000") | ||||
| 		x = strings.TrimSuffix(x, "000") | ||||
| 		x = strings.TrimSuffix(x, ".000") | ||||
| 		w.write(fmt.Sprintf(`"%vs"`, x)) | ||||
| 		return nil | ||||
| 	case "Timestamp": | ||||
| 		// "RFC 3339, where generated output will always be Z-normalized
 | ||||
| 		//  and uses 0, 3, 6 or 9 fractional digits."
 | ||||
| 		s := m.Get(fds.ByNumber(1)).Int() | ||||
| 		ns := m.Get(fds.ByNumber(2)).Int() | ||||
| 		if ns < 0 || ns >= secondInNanos { | ||||
| 			return fmt.Errorf("ns out of range [0, %v)", secondInNanos) | ||||
| 		} | ||||
| 		t := time.Unix(s, ns).UTC() | ||||
| 		// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
 | ||||
| 		x := t.Format("2006-01-02T15:04:05.000000000") | ||||
| 		x = strings.TrimSuffix(x, "000") | ||||
| 		x = strings.TrimSuffix(x, "000") | ||||
| 		x = strings.TrimSuffix(x, ".000") | ||||
| 		w.write(fmt.Sprintf(`"%vZ"`, x)) | ||||
| 		return nil | ||||
| 	case "Value": | ||||
| 		// JSON value; which is a null, number, string, bool, object, or array.
 | ||||
| 		od := md.Oneofs().Get(0) | ||||
| 		fd := m.WhichOneof(od) | ||||
| 		if fd == nil { | ||||
| 			return errors.New("nil Value") | ||||
| 		} | ||||
| 		return w.marshalValue(fd, m.Get(fd), indent) | ||||
| 	case "Struct", "ListValue": | ||||
| 		// JSON object or array.
 | ||||
| 		fd := fds.ByNumber(1) | ||||
| 		return w.marshalValue(fd, m.Get(fd), indent) | ||||
| 	} | ||||
| 
 | ||||
| 	w.write("{") | ||||
| 	if w.Indent != "" { | ||||
| 		w.write("\n") | ||||
| 	} | ||||
| 
 | ||||
| 	firstField := true | ||||
| 	if typeURL != "" { | ||||
| 		if err := w.marshalTypeURL(indent, typeURL); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		firstField = false | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < fds.Len(); { | ||||
| 		fd := fds.Get(i) | ||||
| 		if od := fd.ContainingOneof(); od != nil { | ||||
| 			fd = m.WhichOneof(od) | ||||
| 			i += od.Fields().Len() | ||||
| 			if fd == nil { | ||||
| 				continue | ||||
| 			} | ||||
| 		} else { | ||||
| 			i++ | ||||
| 		} | ||||
| 
 | ||||
| 		v := m.Get(fd) | ||||
| 
 | ||||
| 		if !m.Has(fd) { | ||||
| 			if !w.EmitDefaults || fd.ContainingOneof() != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) { | ||||
| 				v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
 | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if !firstField { | ||||
| 			w.writeComma() | ||||
| 		} | ||||
| 		if err := w.marshalField(fd, v, indent); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		firstField = false | ||||
| 	} | ||||
| 
 | ||||
| 	// Handle proto2 extensions.
 | ||||
| 	if md.ExtensionRanges().Len() > 0 { | ||||
| 		// Collect a sorted list of all extension descriptor and values.
 | ||||
| 		type ext struct { | ||||
| 			desc protoreflect.FieldDescriptor | ||||
| 			val  protoreflect.Value | ||||
| 		} | ||||
| 		var exts []ext | ||||
| 		m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { | ||||
| 			if fd.IsExtension() { | ||||
| 				exts = append(exts, ext{fd, v}) | ||||
| 			} | ||||
| 			return true | ||||
| 		}) | ||||
| 		sort.Slice(exts, func(i, j int) bool { | ||||
| 			return exts[i].desc.Number() < exts[j].desc.Number() | ||||
| 		}) | ||||
| 
 | ||||
| 		for _, ext := range exts { | ||||
| 			if !firstField { | ||||
| 				w.writeComma() | ||||
| 			} | ||||
| 			if err := w.marshalField(ext.desc, ext.val, indent); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			firstField = false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if w.Indent != "" { | ||||
| 		w.write("\n") | ||||
| 		w.write(indent) | ||||
| 	} | ||||
| 	w.write("}") | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) writeComma() { | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(",\n") | ||||
| 	} else { | ||||
| 		w.write(",") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error { | ||||
| 	// "If the Any contains a value that has a special JSON mapping,
 | ||||
| 	//  it will be converted as follows: {"@type": xxx, "value": yyy}.
 | ||||
| 	//  Otherwise, the value will be converted into a JSON object,
 | ||||
| 	//  and the "@type" field will be inserted to indicate the actual data type."
 | ||||
| 	md := m.Descriptor() | ||||
| 	typeURL := m.Get(md.Fields().ByNumber(1)).String() | ||||
| 	rawVal := m.Get(md.Fields().ByNumber(2)).Bytes() | ||||
| 
 | ||||
| 	var m2 protoreflect.Message | ||||
| 	if w.AnyResolver != nil { | ||||
| 		mi, err := w.AnyResolver.Resolve(typeURL) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		m2 = proto.MessageReflect(mi) | ||||
| 	} else { | ||||
| 		mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		m2 = mt.New() | ||||
| 	} | ||||
| 
 | ||||
| 	if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if wellKnownType(m2.Descriptor().FullName()) == "" { | ||||
| 		return w.marshalMessage(m2, indent, typeURL) | ||||
| 	} | ||||
| 
 | ||||
| 	w.write("{") | ||||
| 	if w.Indent != "" { | ||||
| 		w.write("\n") | ||||
| 	} | ||||
| 	if err := w.marshalTypeURL(indent, typeURL); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	w.writeComma() | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(indent) | ||||
| 		w.write(w.Indent) | ||||
| 		w.write(`"value": `) | ||||
| 	} else { | ||||
| 		w.write(`"value":`) | ||||
| 	} | ||||
| 	if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if w.Indent != "" { | ||||
| 		w.write("\n") | ||||
| 		w.write(indent) | ||||
| 	} | ||||
| 	w.write("}") | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error { | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(indent) | ||||
| 		w.write(w.Indent) | ||||
| 	} | ||||
| 	w.write(`"@type":`) | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(" ") | ||||
| 	} | ||||
| 	b, err := json.Marshal(typeURL) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	w.write(string(b)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // marshalField writes field description and value to the Writer.
 | ||||
| func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(indent) | ||||
| 		w.write(w.Indent) | ||||
| 	} | ||||
| 	w.write(`"`) | ||||
| 	switch { | ||||
| 	case fd.IsExtension(): | ||||
| 		// For message set, use the fname of the message as the extension name.
 | ||||
| 		name := string(fd.FullName()) | ||||
| 		if isMessageSet(fd.ContainingMessage()) { | ||||
| 			name = strings.TrimSuffix(name, ".message_set_extension") | ||||
| 		} | ||||
| 
 | ||||
| 		w.write("[" + name + "]") | ||||
| 	case w.OrigName: | ||||
| 		name := string(fd.Name()) | ||||
| 		if fd.Kind() == protoreflect.GroupKind { | ||||
| 			name = string(fd.Message().Name()) | ||||
| 		} | ||||
| 		w.write(name) | ||||
| 	default: | ||||
| 		w.write(string(fd.JSONName())) | ||||
| 	} | ||||
| 	w.write(`":`) | ||||
| 	if w.Indent != "" { | ||||
| 		w.write(" ") | ||||
| 	} | ||||
| 	return w.marshalValue(fd, v, indent) | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { | ||||
| 	switch { | ||||
| 	case fd.IsList(): | ||||
| 		w.write("[") | ||||
| 		comma := "" | ||||
| 		lv := v.List() | ||||
| 		for i := 0; i < lv.Len(); i++ { | ||||
| 			w.write(comma) | ||||
| 			if w.Indent != "" { | ||||
| 				w.write("\n") | ||||
| 				w.write(indent) | ||||
| 				w.write(w.Indent) | ||||
| 				w.write(w.Indent) | ||||
| 			} | ||||
| 			if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			comma = "," | ||||
| 		} | ||||
| 		if w.Indent != "" { | ||||
| 			w.write("\n") | ||||
| 			w.write(indent) | ||||
| 			w.write(w.Indent) | ||||
| 		} | ||||
| 		w.write("]") | ||||
| 		return nil | ||||
| 	case fd.IsMap(): | ||||
| 		kfd := fd.MapKey() | ||||
| 		vfd := fd.MapValue() | ||||
| 		mv := v.Map() | ||||
| 
 | ||||
| 		// Collect a sorted list of all map keys and values.
 | ||||
| 		type entry struct{ key, val protoreflect.Value } | ||||
| 		var entries []entry | ||||
| 		mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { | ||||
| 			entries = append(entries, entry{k.Value(), v}) | ||||
| 			return true | ||||
| 		}) | ||||
| 		sort.Slice(entries, func(i, j int) bool { | ||||
| 			switch kfd.Kind() { | ||||
| 			case protoreflect.BoolKind: | ||||
| 				return !entries[i].key.Bool() && entries[j].key.Bool() | ||||
| 			case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: | ||||
| 				return entries[i].key.Int() < entries[j].key.Int() | ||||
| 			case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: | ||||
| 				return entries[i].key.Uint() < entries[j].key.Uint() | ||||
| 			case protoreflect.StringKind: | ||||
| 				return entries[i].key.String() < entries[j].key.String() | ||||
| 			default: | ||||
| 				panic("invalid kind") | ||||
| 			} | ||||
| 		}) | ||||
| 
 | ||||
| 		w.write(`{`) | ||||
| 		comma := "" | ||||
| 		for _, entry := range entries { | ||||
| 			w.write(comma) | ||||
| 			if w.Indent != "" { | ||||
| 				w.write("\n") | ||||
| 				w.write(indent) | ||||
| 				w.write(w.Indent) | ||||
| 				w.write(w.Indent) | ||||
| 			} | ||||
| 
 | ||||
| 			s := fmt.Sprint(entry.key.Interface()) | ||||
| 			b, err := json.Marshal(s) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			w.write(string(b)) | ||||
| 
 | ||||
| 			w.write(`:`) | ||||
| 			if w.Indent != "" { | ||||
| 				w.write(` `) | ||||
| 			} | ||||
| 
 | ||||
| 			if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			comma = "," | ||||
| 		} | ||||
| 		if w.Indent != "" { | ||||
| 			w.write("\n") | ||||
| 			w.write(indent) | ||||
| 			w.write(w.Indent) | ||||
| 		} | ||||
| 		w.write(`}`) | ||||
| 		return nil | ||||
| 	default: | ||||
| 		return w.marshalSingularValue(fd, v, indent) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { | ||||
| 	switch { | ||||
| 	case !v.IsValid(): | ||||
| 		w.write("null") | ||||
| 		return nil | ||||
| 	case fd.Message() != nil: | ||||
| 		return w.marshalMessage(v.Message(), indent+w.Indent, "") | ||||
| 	case fd.Enum() != nil: | ||||
| 		if fd.Enum().FullName() == "google.protobuf.NullValue" { | ||||
| 			w.write("null") | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		vd := fd.Enum().Values().ByNumber(v.Enum()) | ||||
| 		if vd == nil || w.EnumsAsInts { | ||||
| 			w.write(strconv.Itoa(int(v.Enum()))) | ||||
| 		} else { | ||||
| 			w.write(`"` + string(vd.Name()) + `"`) | ||||
| 		} | ||||
| 		return nil | ||||
| 	default: | ||||
| 		switch v.Interface().(type) { | ||||
| 		case float32, float64: | ||||
| 			switch { | ||||
| 			case math.IsInf(v.Float(), +1): | ||||
| 				w.write(`"Infinity"`) | ||||
| 				return nil | ||||
| 			case math.IsInf(v.Float(), -1): | ||||
| 				w.write(`"-Infinity"`) | ||||
| 				return nil | ||||
| 			case math.IsNaN(v.Float()): | ||||
| 				w.write(`"NaN"`) | ||||
| 				return nil | ||||
| 			} | ||||
| 		case int64, uint64: | ||||
| 			w.write(fmt.Sprintf(`"%d"`, v.Interface())) | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		b, err := json.Marshal(v.Interface()) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		w.write(string(b)) | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | @ -1,69 +0,0 @@ | |||
| // Copyright 2015 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 jsonpb provides functionality to marshal and unmarshal between a
 | ||||
| // protocol buffer message and JSON. It follows the specification at
 | ||||
| // https://developers.google.com/protocol-buffers/docs/proto3#json.
 | ||||
| //
 | ||||
| // Do not rely on the default behavior of the standard encoding/json package
 | ||||
| // when called on generated message types as it does not operate correctly.
 | ||||
| //
 | ||||
| // Deprecated: Use the "google.golang.org/protobuf/encoding/protojson"
 | ||||
| // package instead.
 | ||||
| package jsonpb | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	"google.golang.org/protobuf/reflect/protoregistry" | ||||
| 	"google.golang.org/protobuf/runtime/protoimpl" | ||||
| ) | ||||
| 
 | ||||
| // AnyResolver takes a type URL, present in an Any message,
 | ||||
| // and resolves it into an instance of the associated message.
 | ||||
| type AnyResolver interface { | ||||
| 	Resolve(typeURL string) (proto.Message, error) | ||||
| } | ||||
| 
 | ||||
| type anyResolver struct{ AnyResolver } | ||||
| 
 | ||||
| func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { | ||||
| 	return r.FindMessageByURL(string(message)) | ||||
| } | ||||
| 
 | ||||
| func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) { | ||||
| 	m, err := r.Resolve(url) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return protoimpl.X.MessageTypeOf(m), nil | ||||
| } | ||||
| 
 | ||||
| func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { | ||||
| 	return protoregistry.GlobalTypes.FindExtensionByName(field) | ||||
| } | ||||
| 
 | ||||
| func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { | ||||
| 	return protoregistry.GlobalTypes.FindExtensionByNumber(message, field) | ||||
| } | ||||
| 
 | ||||
| func wellKnownType(s protoreflect.FullName) string { | ||||
| 	if s.Parent() == "google.protobuf" { | ||||
| 		switch s.Name() { | ||||
| 		case "Empty", "Any", | ||||
| 			"BoolValue", "BytesValue", "StringValue", | ||||
| 			"Int32Value", "UInt32Value", "FloatValue", | ||||
| 			"Int64Value", "UInt64Value", "DoubleValue", | ||||
| 			"Duration", "Timestamp", | ||||
| 			"NullValue", "Struct", "Value", "ListValue": | ||||
| 			return string(s.Name()) | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
| 
 | ||||
| func isMessageSet(md protoreflect.MessageDescriptor) bool { | ||||
| 	ms, ok := md.(interface{ IsMessageSet() bool }) | ||||
| 	return ok && ms.IsMessageSet() | ||||
| } | ||||
|  | @ -1,179 +0,0 @@ | |||
| // Copyright 2016 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 ptypes | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	"google.golang.org/protobuf/reflect/protoregistry" | ||||
| 
 | ||||
| 	anypb "github.com/golang/protobuf/ptypes/any" | ||||
| ) | ||||
| 
 | ||||
| const urlPrefix = "type.googleapis.com/" | ||||
| 
 | ||||
| // AnyMessageName returns the message name contained in an anypb.Any message.
 | ||||
| // Most type assertions should use the Is function instead.
 | ||||
| //
 | ||||
| // Deprecated: Call the any.MessageName method instead.
 | ||||
| func AnyMessageName(any *anypb.Any) (string, error) { | ||||
| 	name, err := anyMessageName(any) | ||||
| 	return string(name), err | ||||
| } | ||||
| func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) { | ||||
| 	if any == nil { | ||||
| 		return "", fmt.Errorf("message is nil") | ||||
| 	} | ||||
| 	name := protoreflect.FullName(any.TypeUrl) | ||||
| 	if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 { | ||||
| 		name = name[i+len("/"):] | ||||
| 	} | ||||
| 	if !name.IsValid() { | ||||
| 		return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) | ||||
| 	} | ||||
| 	return name, nil | ||||
| } | ||||
| 
 | ||||
| // MarshalAny marshals the given message m into an anypb.Any message.
 | ||||
| //
 | ||||
| // Deprecated: Call the anypb.New function instead.
 | ||||
| func MarshalAny(m proto.Message) (*anypb.Any, error) { | ||||
| 	switch dm := m.(type) { | ||||
| 	case DynamicAny: | ||||
| 		m = dm.Message | ||||
| 	case *DynamicAny: | ||||
| 		if dm == nil { | ||||
| 			return nil, proto.ErrNil | ||||
| 		} | ||||
| 		m = dm.Message | ||||
| 	} | ||||
| 	b, err := proto.Marshal(m) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil | ||||
| } | ||||
| 
 | ||||
| // Empty returns a new message of the type specified in an anypb.Any message.
 | ||||
| // It returns protoregistry.NotFound if the corresponding message type could not
 | ||||
| // be resolved in the global registry.
 | ||||
| //
 | ||||
| // Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
 | ||||
| // to resolve the message name and create a new instance of it.
 | ||||
| func Empty(any *anypb.Any) (proto.Message, error) { | ||||
| 	name, err := anyMessageName(any) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	mt, err := protoregistry.GlobalTypes.FindMessageByName(name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return proto.MessageV1(mt.New().Interface()), nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalAny unmarshals the encoded value contained in the anypb.Any message
 | ||||
| // into the provided message m. It returns an error if the target message
 | ||||
| // does not match the type in the Any message or if an unmarshal error occurs.
 | ||||
| //
 | ||||
| // The target message m may be a *DynamicAny message. If the underlying message
 | ||||
| // type could not be resolved, then this returns protoregistry.NotFound.
 | ||||
| //
 | ||||
| // Deprecated: Call the any.UnmarshalTo method instead.
 | ||||
| func UnmarshalAny(any *anypb.Any, m proto.Message) error { | ||||
| 	if dm, ok := m.(*DynamicAny); ok { | ||||
| 		if dm.Message == nil { | ||||
| 			var err error | ||||
| 			dm.Message, err = Empty(any) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		m = dm.Message | ||||
| 	} | ||||
| 
 | ||||
| 	anyName, err := AnyMessageName(any) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	msgName := proto.MessageName(m) | ||||
| 	if anyName != msgName { | ||||
| 		return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName) | ||||
| 	} | ||||
| 	return proto.Unmarshal(any.Value, m) | ||||
| } | ||||
| 
 | ||||
| // Is reports whether the Any message contains a message of the specified type.
 | ||||
| //
 | ||||
| // Deprecated: Call the any.MessageIs method instead.
 | ||||
| func Is(any *anypb.Any, m proto.Message) bool { | ||||
| 	if any == nil || m == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	name := proto.MessageName(m) | ||||
| 	if !strings.HasSuffix(any.TypeUrl, name) { | ||||
| 		return false | ||||
| 	} | ||||
| 	return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/' | ||||
| } | ||||
| 
 | ||||
| // DynamicAny is a value that can be passed to UnmarshalAny to automatically
 | ||||
| // allocate a proto.Message for the type specified in an anypb.Any message.
 | ||||
| // The allocated message is stored in the embedded proto.Message.
 | ||||
| //
 | ||||
| // Example:
 | ||||
| //   var x ptypes.DynamicAny
 | ||||
| //   if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
 | ||||
| //   fmt.Printf("unmarshaled message: %v", x.Message)
 | ||||
| //
 | ||||
| // Deprecated: Use the any.UnmarshalNew method instead to unmarshal
 | ||||
| // the any message contents into a new instance of the underlying message.
 | ||||
| type DynamicAny struct{ proto.Message } | ||||
| 
 | ||||
| func (m DynamicAny) String() string { | ||||
| 	if m.Message == nil { | ||||
| 		return "<nil>" | ||||
| 	} | ||||
| 	return m.Message.String() | ||||
| } | ||||
| func (m DynamicAny) Reset() { | ||||
| 	if m.Message == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	m.Message.Reset() | ||||
| } | ||||
| func (m DynamicAny) ProtoMessage() { | ||||
| 	return | ||||
| } | ||||
| func (m DynamicAny) ProtoReflect() protoreflect.Message { | ||||
| 	if m.Message == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return dynamicAny{proto.MessageReflect(m.Message)} | ||||
| } | ||||
| 
 | ||||
| type dynamicAny struct{ protoreflect.Message } | ||||
| 
 | ||||
| func (m dynamicAny) Type() protoreflect.MessageType { | ||||
| 	return dynamicAnyType{m.Message.Type()} | ||||
| } | ||||
| func (m dynamicAny) New() protoreflect.Message { | ||||
| 	return dynamicAnyType{m.Message.Type()}.New() | ||||
| } | ||||
| func (m dynamicAny) Interface() protoreflect.ProtoMessage { | ||||
| 	return DynamicAny{proto.MessageV1(m.Message.Interface())} | ||||
| } | ||||
| 
 | ||||
| type dynamicAnyType struct{ protoreflect.MessageType } | ||||
| 
 | ||||
| func (t dynamicAnyType) New() protoreflect.Message { | ||||
| 	return dynamicAny{t.MessageType.New()} | ||||
| } | ||||
| func (t dynamicAnyType) Zero() protoreflect.Message { | ||||
| 	return dynamicAny{t.MessageType.Zero()} | ||||
| } | ||||
|  | @ -1,62 +0,0 @@ | |||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||
| // source: github.com/golang/protobuf/ptypes/any/any.proto
 | ||||
| 
 | ||||
| package any | ||||
| 
 | ||||
| import ( | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	anypb "google.golang.org/protobuf/types/known/anypb" | ||||
| 	reflect "reflect" | ||||
| ) | ||||
| 
 | ||||
| // Symbols defined in public import of google/protobuf/any.proto.
 | ||||
| 
 | ||||
| type Any = anypb.Any | ||||
| 
 | ||||
| var File_github_com_golang_protobuf_ptypes_any_any_proto protoreflect.FileDescriptor | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | ||||
| 	0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | ||||
| 	0x70, 0x65, 0x73, 0x2f, 0x61, 0x6e, 0x79, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, | ||||
| 	0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x2b, 0x5a, 0x29, | ||||
| 	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, | ||||
| 	0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, | ||||
| 	0x73, 0x2f, 0x61, 0x6e, 0x79, 0x3b, 0x61, 0x6e, 0x79, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, | ||||
| 	0x74, 0x6f, 0x33, | ||||
| } | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = []interface{}{} | ||||
| var file_github_com_golang_protobuf_ptypes_any_any_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_github_com_golang_protobuf_ptypes_any_any_proto_init() } | ||||
| func file_github_com_golang_protobuf_ptypes_any_any_proto_init() { | ||||
| 	if File_github_com_golang_protobuf_ptypes_any_any_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   0, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   0, | ||||
| 		}, | ||||
| 		GoTypes:           file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes, | ||||
| 		DependencyIndexes: file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs, | ||||
| 	}.Build() | ||||
| 	File_github_com_golang_protobuf_ptypes_any_any_proto = out.File | ||||
| 	file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = nil | ||||
| } | ||||
|  | @ -1,10 +0,0 @@ | |||
| // Copyright 2016 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 ptypes provides functionality for interacting with well-known types.
 | ||||
| //
 | ||||
| // Deprecated: Well-known types have specialized functionality directly
 | ||||
| // injected into the generated packages for each message type.
 | ||||
| // See the deprecation notice for each function for the suggested alternative.
 | ||||
| package ptypes | ||||
|  | @ -1,76 +0,0 @@ | |||
| // Copyright 2016 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 ptypes | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	durationpb "github.com/golang/protobuf/ptypes/duration" | ||||
| ) | ||||
| 
 | ||||
| // Range of google.protobuf.Duration as specified in duration.proto.
 | ||||
| // This is about 10,000 years in seconds.
 | ||||
| const ( | ||||
| 	maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) | ||||
| 	minSeconds = -maxSeconds | ||||
| ) | ||||
| 
 | ||||
| // Duration converts a durationpb.Duration to a time.Duration.
 | ||||
| // Duration returns an error if dur is invalid or overflows a time.Duration.
 | ||||
| //
 | ||||
| // Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead.
 | ||||
| func Duration(dur *durationpb.Duration) (time.Duration, error) { | ||||
| 	if err := validateDuration(dur); err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	d := time.Duration(dur.Seconds) * time.Second | ||||
| 	if int64(d/time.Second) != dur.Seconds { | ||||
| 		return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) | ||||
| 	} | ||||
| 	if dur.Nanos != 0 { | ||||
| 		d += time.Duration(dur.Nanos) * time.Nanosecond | ||||
| 		if (d < 0) != (dur.Nanos < 0) { | ||||
| 			return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) | ||||
| 		} | ||||
| 	} | ||||
| 	return d, nil | ||||
| } | ||||
| 
 | ||||
| // DurationProto converts a time.Duration to a durationpb.Duration.
 | ||||
| //
 | ||||
| // Deprecated: Call the durationpb.New function instead.
 | ||||
| func DurationProto(d time.Duration) *durationpb.Duration { | ||||
| 	nanos := d.Nanoseconds() | ||||
| 	secs := nanos / 1e9 | ||||
| 	nanos -= secs * 1e9 | ||||
| 	return &durationpb.Duration{ | ||||
| 		Seconds: int64(secs), | ||||
| 		Nanos:   int32(nanos), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // validateDuration determines whether the durationpb.Duration is valid
 | ||||
| // according to the definition in google/protobuf/duration.proto.
 | ||||
| // A valid durpb.Duration may still be too large to fit into a time.Duration
 | ||||
| // Note that the range of durationpb.Duration is about 10,000 years,
 | ||||
| // while the range of time.Duration is about 290 years.
 | ||||
| func validateDuration(dur *durationpb.Duration) error { | ||||
| 	if dur == nil { | ||||
| 		return errors.New("duration: nil Duration") | ||||
| 	} | ||||
| 	if dur.Seconds < minSeconds || dur.Seconds > maxSeconds { | ||||
| 		return fmt.Errorf("duration: %v: seconds out of range", dur) | ||||
| 	} | ||||
| 	if dur.Nanos <= -1e9 || dur.Nanos >= 1e9 { | ||||
| 		return fmt.Errorf("duration: %v: nanos out of range", dur) | ||||
| 	} | ||||
| 	// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
 | ||||
| 	if (dur.Seconds < 0 && dur.Nanos > 0) || (dur.Seconds > 0 && dur.Nanos < 0) { | ||||
| 		return fmt.Errorf("duration: %v: seconds and nanos have different signs", dur) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,63 +0,0 @@ | |||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||
| // source: github.com/golang/protobuf/ptypes/duration/duration.proto
 | ||||
| 
 | ||||
| package duration | ||||
| 
 | ||||
| import ( | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	durationpb "google.golang.org/protobuf/types/known/durationpb" | ||||
| 	reflect "reflect" | ||||
| ) | ||||
| 
 | ||||
| // Symbols defined in public import of google/protobuf/duration.proto.
 | ||||
| 
 | ||||
| type Duration = durationpb.Duration | ||||
| 
 | ||||
| var File_github_com_golang_protobuf_ptypes_duration_duration_proto protoreflect.FileDescriptor | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | ||||
| 	0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | ||||
| 	0x70, 0x65, 0x73, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x75, 0x72, | ||||
| 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, | ||||
| 	0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, | ||||
| 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67, | ||||
| 	0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, | ||||
| 	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, | ||||
| 	0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, | ||||
| 	0x6f, 0x6e, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||
| } | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = []interface{}{} | ||||
| var file_github_com_golang_protobuf_ptypes_duration_duration_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_github_com_golang_protobuf_ptypes_duration_duration_proto_init() } | ||||
| func file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() { | ||||
| 	if File_github_com_golang_protobuf_ptypes_duration_duration_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   0, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   0, | ||||
| 		}, | ||||
| 		GoTypes:           file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes, | ||||
| 		DependencyIndexes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs, | ||||
| 	}.Build() | ||||
| 	File_github_com_golang_protobuf_ptypes_duration_duration_proto = out.File | ||||
| 	file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = nil | ||||
| } | ||||
|  | @ -1,112 +0,0 @@ | |||
| // Copyright 2016 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 ptypes | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	timestamppb "github.com/golang/protobuf/ptypes/timestamp" | ||||
| ) | ||||
| 
 | ||||
| // Range of google.protobuf.Duration as specified in timestamp.proto.
 | ||||
| const ( | ||||
| 	// Seconds field of the earliest valid Timestamp.
 | ||||
| 	// This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
 | ||||
| 	minValidSeconds = -62135596800 | ||||
| 	// Seconds field just after the latest valid Timestamp.
 | ||||
| 	// This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
 | ||||
| 	maxValidSeconds = 253402300800 | ||||
| ) | ||||
| 
 | ||||
| // Timestamp converts a timestamppb.Timestamp to a time.Time.
 | ||||
| // It returns an error if the argument is invalid.
 | ||||
| //
 | ||||
| // Unlike most Go functions, if Timestamp returns an error, the first return
 | ||||
| // value is not the zero time.Time. Instead, it is the value obtained from the
 | ||||
| // time.Unix function when passed the contents of the Timestamp, in the UTC
 | ||||
| // locale. This may or may not be a meaningful time; many invalid Timestamps
 | ||||
| // do map to valid time.Times.
 | ||||
| //
 | ||||
| // A nil Timestamp returns an error. The first return value in that case is
 | ||||
| // undefined.
 | ||||
| //
 | ||||
| // Deprecated: Call the ts.AsTime and ts.CheckValid methods instead.
 | ||||
| func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { | ||||
| 	// Don't return the zero value on error, because corresponds to a valid
 | ||||
| 	// timestamp. Instead return whatever time.Unix gives us.
 | ||||
| 	var t time.Time | ||||
| 	if ts == nil { | ||||
| 		t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
 | ||||
| 	} else { | ||||
| 		t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() | ||||
| 	} | ||||
| 	return t, validateTimestamp(ts) | ||||
| } | ||||
| 
 | ||||
| // TimestampNow returns a google.protobuf.Timestamp for the current time.
 | ||||
| //
 | ||||
| // Deprecated: Call the timestamppb.Now function instead.
 | ||||
| func TimestampNow() *timestamppb.Timestamp { | ||||
| 	ts, err := TimestampProto(time.Now()) | ||||
| 	if err != nil { | ||||
| 		panic("ptypes: time.Now() out of Timestamp range") | ||||
| 	} | ||||
| 	return ts | ||||
| } | ||||
| 
 | ||||
| // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
 | ||||
| // It returns an error if the resulting Timestamp is invalid.
 | ||||
| //
 | ||||
| // Deprecated: Call the timestamppb.New function instead.
 | ||||
| func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { | ||||
| 	ts := ×tamppb.Timestamp{ | ||||
| 		Seconds: t.Unix(), | ||||
| 		Nanos:   int32(t.Nanosecond()), | ||||
| 	} | ||||
| 	if err := validateTimestamp(ts); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ts, nil | ||||
| } | ||||
| 
 | ||||
| // TimestampString returns the RFC 3339 string for valid Timestamps.
 | ||||
| // For invalid Timestamps, it returns an error message in parentheses.
 | ||||
| //
 | ||||
| // Deprecated: Call the ts.AsTime method instead,
 | ||||
| // followed by a call to the Format method on the time.Time value.
 | ||||
| func TimestampString(ts *timestamppb.Timestamp) string { | ||||
| 	t, err := Timestamp(ts) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("(%v)", err) | ||||
| 	} | ||||
| 	return t.Format(time.RFC3339Nano) | ||||
| } | ||||
| 
 | ||||
| // validateTimestamp determines whether a Timestamp is valid.
 | ||||
| // A valid timestamp represents a time in the range [0001-01-01, 10000-01-01)
 | ||||
| // and has a Nanos field in the range [0, 1e9).
 | ||||
| //
 | ||||
| // If the Timestamp is valid, validateTimestamp returns nil.
 | ||||
| // Otherwise, it returns an error that describes the problem.
 | ||||
| //
 | ||||
| // Every valid Timestamp can be represented by a time.Time,
 | ||||
| // but the converse is not true.
 | ||||
| func validateTimestamp(ts *timestamppb.Timestamp) error { | ||||
| 	if ts == nil { | ||||
| 		return errors.New("timestamp: nil Timestamp") | ||||
| 	} | ||||
| 	if ts.Seconds < minValidSeconds { | ||||
| 		return fmt.Errorf("timestamp: %v before 0001-01-01", ts) | ||||
| 	} | ||||
| 	if ts.Seconds >= maxValidSeconds { | ||||
| 		return fmt.Errorf("timestamp: %v after 10000-01-01", ts) | ||||
| 	} | ||||
| 	if ts.Nanos < 0 || ts.Nanos >= 1e9 { | ||||
| 		return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1,64 +0,0 @@ | |||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||
| // source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
 | ||||
| 
 | ||||
| package timestamp | ||||
| 
 | ||||
| import ( | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	timestamppb "google.golang.org/protobuf/types/known/timestamppb" | ||||
| 	reflect "reflect" | ||||
| ) | ||||
| 
 | ||||
| // Symbols defined in public import of google/protobuf/timestamp.proto.
 | ||||
| 
 | ||||
| type Timestamp = timestamppb.Timestamp | ||||
| 
 | ||||
| var File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto protoreflect.FileDescriptor | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | ||||
| 	0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | ||||
| 	0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x74, 0x69, | ||||
| 	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, | ||||
| 	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, | ||||
| 	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x37, | ||||
| 	0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, | ||||
| 	0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, | ||||
| 	0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x3b, 0x74, 0x69, | ||||
| 	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x33, | ||||
| } | ||||
| 
 | ||||
| var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = []interface{}{} | ||||
| var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_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_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() } | ||||
| func file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() { | ||||
| 	if File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   0, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   0, | ||||
| 		}, | ||||
| 		GoTypes:           file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes, | ||||
| 		DependencyIndexes: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs, | ||||
| 	}.Build() | ||||
| 	File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto = out.File | ||||
| 	file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = nil | ||||
| 	file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs = nil | ||||
| } | ||||
|  | @ -18,8 +18,8 @@ | |||
| 
 | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||
| // versions:
 | ||||
| // 	protoc-gen-go v1.31.0
 | ||||
| // 	protoc        v4.22.0
 | ||||
| // 	protoc-gen-go v1.32.0
 | ||||
| // 	protoc        v4.25.2
 | ||||
| // source: grpc/binlog/v1/binarylog.proto
 | ||||
| 
 | ||||
| package grpc_binarylog_v1 | ||||
|  |  | |||
|  | @ -23,8 +23,9 @@ package proto | |||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/protoadapt" | ||||
| ) | ||||
| 
 | ||||
| // Name is the name registered for the proto compressor.
 | ||||
|  | @ -38,21 +39,34 @@ func init() { | |||
| type codec struct{} | ||||
| 
 | ||||
| func (codec) Marshal(v any) ([]byte, error) { | ||||
| 	vv, ok := v.(proto.Message) | ||||
| 	if !ok { | ||||
| 	vv := messageV2Of(v) | ||||
| 	if vv == nil { | ||||
| 		return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) | ||||
| 	} | ||||
| 
 | ||||
| 	return proto.Marshal(vv) | ||||
| } | ||||
| 
 | ||||
| func (codec) Unmarshal(data []byte, v any) error { | ||||
| 	vv, ok := v.(proto.Message) | ||||
| 	if !ok { | ||||
| 	vv := messageV2Of(v) | ||||
| 	if vv == nil { | ||||
| 		return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) | ||||
| 	} | ||||
| 
 | ||||
| 	return proto.Unmarshal(data, vv) | ||||
| } | ||||
| 
 | ||||
| func messageV2Of(v any) proto.Message { | ||||
| 	switch v := v.(type) { | ||||
| 	case protoadapt.MessageV1: | ||||
| 		return protoadapt.MessageV2Of(v) | ||||
| 	case protoadapt.MessageV2: | ||||
| 		return v | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (codec) Name() string { | ||||
| 	return Name | ||||
| } | ||||
|  |  | |||
|  | @ -25,11 +25,12 @@ import ( | |||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"github.com/golang/protobuf/ptypes" | ||||
| 	binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/types/known/durationpb" | ||||
| 	"google.golang.org/protobuf/types/known/timestamppb" | ||||
| ) | ||||
| 
 | ||||
| type callIDGenerator struct { | ||||
|  | @ -88,7 +89,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger { | |||
| // in TruncatingMethodLogger as possible.
 | ||||
| func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry { | ||||
| 	m := c.toProto() | ||||
| 	timestamp, _ := ptypes.TimestampProto(time.Now()) | ||||
| 	timestamp := timestamppb.Now() | ||||
| 	m.Timestamp = timestamp | ||||
| 	m.CallId = ml.callID | ||||
| 	m.SequenceIdWithinCall = ml.idWithinCallGen.next() | ||||
|  | @ -178,7 +179,7 @@ func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry { | |||
| 		Authority:  c.Authority, | ||||
| 	} | ||||
| 	if c.Timeout > 0 { | ||||
| 		clientHeader.Timeout = ptypes.DurationProto(c.Timeout) | ||||
| 		clientHeader.Timeout = durationpb.New(c.Timeout) | ||||
| 	} | ||||
| 	ret := &binlogpb.GrpcLogEntry{ | ||||
| 		Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ import ( | |||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  |  | |||
|  | @ -1,3 +1,8 @@ | |||
| //go:build !go1.21
 | ||||
| 
 | ||||
| // TODO: when this file is deleted (after Go 1.20 support is dropped), delete
 | ||||
| // all of grpcrand and call the rand package directly.
 | ||||
| 
 | ||||
| /* | ||||
|  * | ||||
|  * Copyright 2018 gRPC authors. | ||||
|  |  | |||
							
								
								
									
										73
									
								
								vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										73
									
								
								vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,73 @@ | |||
| //go:build go1.21
 | ||||
| 
 | ||||
| /* | ||||
|  * | ||||
|  * Copyright 2024 gRPC authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| // Package grpcrand implements math/rand functions in a concurrent-safe way
 | ||||
| // with a global random source, independent of math/rand's global source.
 | ||||
| package grpcrand | ||||
| 
 | ||||
| import "math/rand" | ||||
| 
 | ||||
| // This implementation will be used for Go version 1.21 or newer.
 | ||||
| // For older versions, the original implementation with mutex will be used.
 | ||||
| 
 | ||||
| // Int implements rand.Int on the grpcrand global source.
 | ||||
| func Int() int { | ||||
| 	return rand.Int() | ||||
| } | ||||
| 
 | ||||
| // Int63n implements rand.Int63n on the grpcrand global source.
 | ||||
| func Int63n(n int64) int64 { | ||||
| 	return rand.Int63n(n) | ||||
| } | ||||
| 
 | ||||
| // Intn implements rand.Intn on the grpcrand global source.
 | ||||
| func Intn(n int) int { | ||||
| 	return rand.Intn(n) | ||||
| } | ||||
| 
 | ||||
| // Int31n implements rand.Int31n on the grpcrand global source.
 | ||||
| func Int31n(n int32) int32 { | ||||
| 	return rand.Int31n(n) | ||||
| } | ||||
| 
 | ||||
| // Float64 implements rand.Float64 on the grpcrand global source.
 | ||||
| func Float64() float64 { | ||||
| 	return rand.Float64() | ||||
| } | ||||
| 
 | ||||
| // Uint64 implements rand.Uint64 on the grpcrand global source.
 | ||||
| func Uint64() uint64 { | ||||
| 	return rand.Uint64() | ||||
| } | ||||
| 
 | ||||
| // Uint32 implements rand.Uint32 on the grpcrand global source.
 | ||||
| func Uint32() uint32 { | ||||
| 	return rand.Uint32() | ||||
| } | ||||
| 
 | ||||
| // ExpFloat64 implements rand.ExpFloat64 on the grpcrand global source.
 | ||||
| func ExpFloat64() float64 { | ||||
| 	return rand.ExpFloat64() | ||||
| } | ||||
| 
 | ||||
| // Shuffle implements rand.Shuffle on the grpcrand global source.
 | ||||
| var Shuffle = func(n int, f func(int, int)) { | ||||
| 	rand.Shuffle(n, f) | ||||
| } | ||||
|  | @ -24,7 +24,6 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/jsonpb" | ||||
| 	protov1 "github.com/golang/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/encoding/protojson" | ||||
| 	protov2 "google.golang.org/protobuf/proto" | ||||
|  | @ -38,15 +37,15 @@ const jsonIndent = "  " | |||
| func ToJSON(e any) string { | ||||
| 	switch ee := e.(type) { | ||||
| 	case protov1.Message: | ||||
| 		mm := jsonpb.Marshaler{Indent: jsonIndent} | ||||
| 		ret, err := mm.MarshalToString(ee) | ||||
| 		mm := protojson.MarshalOptions{Indent: jsonIndent} | ||||
| 		ret, err := mm.Marshal(protov1.MessageV2(ee)) | ||||
| 		if err != nil { | ||||
| 			// This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2
 | ||||
| 			// messages are not imported, and this will fail because the message
 | ||||
| 			// is not found.
 | ||||
| 			return fmt.Sprintf("%+v", ee) | ||||
| 		} | ||||
| 		return ret | ||||
| 		return string(ret) | ||||
| 	case protov2.Message: | ||||
| 		mm := protojson.MarshalOptions{ | ||||
| 			Multiline: true, | ||||
|  |  | |||
|  | @ -31,10 +31,11 @@ import ( | |||
| 	"errors" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"github.com/golang/protobuf/ptypes" | ||||
| 	spb "google.golang.org/genproto/googleapis/rpc/status" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/protoadapt" | ||||
| 	"google.golang.org/protobuf/types/known/anypb" | ||||
| ) | ||||
| 
 | ||||
| // Status represents an RPC status code, message, and details.  It is immutable
 | ||||
|  | @ -130,14 +131,14 @@ func (s *Status) Err() error { | |||
| 
 | ||||
| // WithDetails returns a new status with the provided details messages appended to the status.
 | ||||
| // If any errors are encountered, it returns nil and the first error encountered.
 | ||||
| func (s *Status) WithDetails(details ...proto.Message) (*Status, error) { | ||||
| func (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) { | ||||
| 	if s.Code() == codes.OK { | ||||
| 		return nil, errors.New("no error details for status with code OK") | ||||
| 	} | ||||
| 	// s.Code() != OK implies that s.Proto() != nil.
 | ||||
| 	p := s.Proto() | ||||
| 	for _, detail := range details { | ||||
| 		any, err := ptypes.MarshalAny(detail) | ||||
| 		any, err := anypb.New(protoadapt.MessageV2Of(detail)) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | @ -154,12 +155,12 @@ func (s *Status) Details() []any { | |||
| 	} | ||||
| 	details := make([]any, 0, len(s.s.Details)) | ||||
| 	for _, any := range s.s.Details { | ||||
| 		detail := &ptypes.DynamicAny{} | ||||
| 		if err := ptypes.UnmarshalAny(any, detail); err != nil { | ||||
| 		detail, err := any.UnmarshalNew() | ||||
| 		if err != nil { | ||||
| 			details = append(details, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		details = append(details, detail.Message) | ||||
| 		details = append(details, detail) | ||||
| 	} | ||||
| 	return details | ||||
| } | ||||
|  |  | |||
|  | @ -535,8 +535,8 @@ const minBatchSize = 1000 | |||
| // size is too low to give stream goroutines a chance to fill it up.
 | ||||
| //
 | ||||
| // Upon exiting, if the error causing the exit is not an I/O error, run()
 | ||||
| // flushes and closes the underlying connection.  Otherwise, the connection is
 | ||||
| // left open to allow the I/O error to be encountered by the reader instead.
 | ||||
| // flushes the underlying connection.  The connection is always left open to
 | ||||
| // allow different closing behavior on the client and server.
 | ||||
| func (l *loopyWriter) run() (err error) { | ||||
| 	defer func() { | ||||
| 		if l.logger.V(logLevel) { | ||||
|  | @ -544,7 +544,6 @@ func (l *loopyWriter) run() (err error) { | |||
| 		} | ||||
| 		if !isIOError(err) { | ||||
| 			l.framer.writer.Flush() | ||||
| 			l.conn.Close() | ||||
| 		} | ||||
| 		l.cbuf.finish() | ||||
| 	}() | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ import ( | |||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"golang.org/x/net/http2" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/credentials" | ||||
|  | @ -45,6 +44,7 @@ import ( | |||
| 	"google.golang.org/grpc/peer" | ||||
| 	"google.golang.org/grpc/stats" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
| 
 | ||||
| // NewServerHandlerTransport returns a ServerTransport handling gRPC from
 | ||||
|  |  | |||
|  | @ -451,7 +451,13 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts | |||
| 	} | ||||
| 	go func() { | ||||
| 		t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) | ||||
| 		t.loopy.run() | ||||
| 		if err := t.loopy.run(); !isIOError(err) { | ||||
| 			// Immediately close the connection, as the loopy writer returns
 | ||||
| 			// when there are no more active streams and we were draining (the
 | ||||
| 			// server sent a GOAWAY).  For I/O errors, the reader will hit it
 | ||||
| 			// after draining any remaining incoming data.
 | ||||
| 			t.conn.Close() | ||||
| 		} | ||||
| 		close(t.writerDone) | ||||
| 	}() | ||||
| 	return t, nil | ||||
|  |  | |||
|  | @ -32,13 +32,13 @@ import ( | |||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"golang.org/x/net/http2" | ||||
| 	"golang.org/x/net/http2/hpack" | ||||
| 	"google.golang.org/grpc/internal/grpclog" | ||||
| 	"google.golang.org/grpc/internal/grpcutil" | ||||
| 	"google.golang.org/grpc/internal/pretty" | ||||
| 	"google.golang.org/grpc/internal/syscall" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 
 | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/credentials" | ||||
|  | @ -322,8 +322,24 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, | |||
| 	go func() { | ||||
| 		t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) | ||||
| 		t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler | ||||
| 		t.loopy.run() | ||||
| 		err := t.loopy.run() | ||||
| 		close(t.loopyWriterDone) | ||||
| 		if !isIOError(err) { | ||||
| 			// Close the connection if a non-I/O error occurs (for I/O errors
 | ||||
| 			// the reader will also encounter the error and close).  Wait 1
 | ||||
| 			// second before closing the connection, or when the reader is done
 | ||||
| 			// (i.e. the client already closed the connection or a connection
 | ||||
| 			// error occurred).  This avoids the potential problem where there
 | ||||
| 			// is unread data on the receive side of the connection, which, if
 | ||||
| 			// closed, would lead to a TCP RST instead of FIN, and the client
 | ||||
| 			// encountering errors.  For more info:
 | ||||
| 			// https://github.com/grpc/grpc-go/issues/5358
 | ||||
| 			select { | ||||
| 			case <-t.readerDone: | ||||
| 			case <-time.After(time.Second): | ||||
| 			} | ||||
| 			t.conn.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	go t.keepalive() | ||||
| 	return t, nil | ||||
|  | @ -609,8 +625,8 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade | |||
| // traceCtx attaches trace to ctx and returns the new context.
 | ||||
| func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) { | ||||
| 	defer func() { | ||||
| 		<-t.loopyWriterDone | ||||
| 		close(t.readerDone) | ||||
| 		<-t.loopyWriterDone | ||||
| 	}() | ||||
| 	for { | ||||
| 		t.controlBuf.throttle() | ||||
|  | @ -636,10 +652,6 @@ func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) { | |||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			if err == io.EOF || err == io.ErrUnexpectedEOF { | ||||
| 				t.Close(err) | ||||
| 				return | ||||
| 			} | ||||
| 			t.Close(err) | ||||
| 			return | ||||
| 		} | ||||
|  | @ -1329,6 +1341,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { | |||
| 		if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		t.framer.writer.Flush() | ||||
| 		if retErr != nil { | ||||
| 			return false, retErr | ||||
| 		} | ||||
|  | @ -1349,7 +1362,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { | |||
| 		return false, err | ||||
| 	} | ||||
| 	go func() { | ||||
| 		timer := time.NewTimer(time.Minute) | ||||
| 		timer := time.NewTimer(5 * time.Second) | ||||
| 		defer timer.Stop() | ||||
| 		select { | ||||
| 		case <-t.drainEvent.Done(): | ||||
|  |  | |||
|  | @ -189,6 +189,20 @@ type EmptyCallOption struct{} | |||
| func (EmptyCallOption) before(*callInfo) error      { return nil } | ||||
| func (EmptyCallOption) after(*callInfo, *csAttempt) {} | ||||
| 
 | ||||
| // StaticMethod returns a CallOption which specifies that a call is being made
 | ||||
| // to a method that is static, which means the method is known at compile time
 | ||||
| // and doesn't change at runtime. This can be used as a signal to stats plugins
 | ||||
| // that this method is safe to include as a key to a measurement.
 | ||||
| func StaticMethod() CallOption { | ||||
| 	return StaticMethodCallOption{} | ||||
| } | ||||
| 
 | ||||
| // StaticMethodCallOption is a CallOption that specifies that a call comes
 | ||||
| // from a static method.
 | ||||
| type StaticMethodCallOption struct { | ||||
| 	EmptyCallOption | ||||
| } | ||||
| 
 | ||||
| // Header returns a CallOptions that retrieves the header metadata
 | ||||
| // for a unary RPC.
 | ||||
| func Header(md *metadata.MD) CallOption { | ||||
|  | @ -958,6 +972,7 @@ const ( | |||
| 	SupportPackageIsVersion5 = true | ||||
| 	SupportPackageIsVersion6 = true | ||||
| 	SupportPackageIsVersion7 = true | ||||
| 	SupportPackageIsVersion8 = true | ||||
| ) | ||||
| 
 | ||||
| const grpcUA = "grpc-go/" + Version | ||||
|  |  | |||
|  | @ -33,8 +33,6 @@ import ( | |||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"golang.org/x/net/trace" | ||||
| 
 | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/credentials" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
|  | @ -131,7 +129,7 @@ type Server struct { | |||
| 	drain    bool | ||||
| 	cv       *sync.Cond              // signaled when connections close for GracefulStop
 | ||||
| 	services map[string]*serviceInfo // service name -> service info
 | ||||
| 	events   trace.EventLog | ||||
| 	events   traceEventLog | ||||
| 
 | ||||
| 	quit               *grpcsync.Event | ||||
| 	done               *grpcsync.Event | ||||
|  | @ -670,7 +668,7 @@ func NewServer(opt ...ServerOption) *Server { | |||
| 	s.cv = sync.NewCond(&s.mu) | ||||
| 	if EnableTracing { | ||||
| 		_, file, line, _ := runtime.Caller(1) | ||||
| 		s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) | ||||
| 		s.events = newTraceEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) | ||||
| 	} | ||||
| 
 | ||||
| 	if s.opts.numServerWorkers > 0 { | ||||
|  | @ -1734,8 +1732,8 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str | |||
| 	ctx = contextWithServer(ctx, s) | ||||
| 	var ti *traceInfo | ||||
| 	if EnableTracing { | ||||
| 		tr := trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) | ||||
| 		ctx = trace.NewContext(ctx, tr) | ||||
| 		tr := newTrace("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) | ||||
| 		ctx = newTraceContext(ctx, tr) | ||||
| 		ti = &traceInfo{ | ||||
| 			tr: tr, | ||||
| 			firstLine: firstLine{ | ||||
|  |  | |||
|  | @ -27,7 +27,6 @@ import ( | |||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"golang.org/x/net/trace" | ||||
| 	"google.golang.org/grpc/balancer" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
|  | @ -431,7 +430,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) | |||
| 	var trInfo *traceInfo | ||||
| 	if EnableTracing { | ||||
| 		trInfo = &traceInfo{ | ||||
| 			tr: trace.New("grpc.Sent."+methodFamily(method), method), | ||||
| 			tr: newTrace("grpc.Sent."+methodFamily(method), method), | ||||
| 			firstLine: firstLine{ | ||||
| 				client: true, | ||||
| 			}, | ||||
|  | @ -440,7 +439,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) | |||
| 			trInfo.firstLine.deadline = time.Until(deadline) | ||||
| 		} | ||||
| 		trInfo.tr.LazyLog(&trInfo.firstLine, false) | ||||
| 		ctx = trace.NewContext(ctx, trInfo.tr) | ||||
| 		ctx = newTraceContext(ctx, trInfo.tr) | ||||
| 	} | ||||
| 
 | ||||
| 	if cs.cc.parsedTarget.URL.Scheme == internal.GRPCResolverSchemeExtraMetadata { | ||||
|  |  | |||
|  | @ -26,8 +26,6 @@ import ( | |||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"golang.org/x/net/trace" | ||||
| ) | ||||
| 
 | ||||
| // EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package.
 | ||||
|  | @ -44,9 +42,31 @@ func methodFamily(m string) string { | |||
| 	return m | ||||
| } | ||||
| 
 | ||||
| // traceEventLog mirrors golang.org/x/net/trace.EventLog.
 | ||||
| //
 | ||||
| // It exists in order to avoid importing x/net/trace on grpcnotrace builds.
 | ||||
| type traceEventLog interface { | ||||
| 	Printf(format string, a ...any) | ||||
| 	Errorf(format string, a ...any) | ||||
| 	Finish() | ||||
| } | ||||
| 
 | ||||
| // traceLog mirrors golang.org/x/net/trace.Trace.
 | ||||
| //
 | ||||
| // It exists in order to avoid importing x/net/trace on grpcnotrace builds.
 | ||||
| type traceLog interface { | ||||
| 	LazyLog(x fmt.Stringer, sensitive bool) | ||||
| 	LazyPrintf(format string, a ...any) | ||||
| 	SetError() | ||||
| 	SetRecycler(f func(any)) | ||||
| 	SetTraceInfo(traceID, spanID uint64) | ||||
| 	SetMaxEvents(m int) | ||||
| 	Finish() | ||||
| } | ||||
| 
 | ||||
| // traceInfo contains tracing information for an RPC.
 | ||||
| type traceInfo struct { | ||||
| 	tr        trace.Trace | ||||
| 	tr        traceLog | ||||
| 	firstLine firstLine | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,52 @@ | |||
| //go:build grpcnotrace
 | ||||
| 
 | ||||
| /* | ||||
|  * | ||||
|  * Copyright 2024 gRPC authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| package grpc | ||||
| 
 | ||||
| // grpcnotrace can be used to avoid importing golang.org/x/net/trace, which in
 | ||||
| // turn enables binaries using gRPC-Go for dead code elimination, which can
 | ||||
| // yield 10-15% improvements in binary size when tracing is not needed.
 | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| type notrace struct{} | ||||
| 
 | ||||
| func (notrace) LazyLog(x fmt.Stringer, sensitive bool) {} | ||||
| func (notrace) LazyPrintf(format string, a ...any)     {} | ||||
| func (notrace) SetError()                              {} | ||||
| func (notrace) SetRecycler(f func(any))                {} | ||||
| func (notrace) SetTraceInfo(traceID, spanID uint64)    {} | ||||
| func (notrace) SetMaxEvents(m int)                     {} | ||||
| func (notrace) Finish()                                {} | ||||
| 
 | ||||
| func newTrace(family, title string) traceLog { | ||||
| 	return notrace{} | ||||
| } | ||||
| 
 | ||||
| func newTraceContext(ctx context.Context, tr traceLog) context.Context { | ||||
| 	return ctx | ||||
| } | ||||
| 
 | ||||
| func newTraceEventLog(family, title string) traceEventLog { | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,39 @@ | |||
| //go:build !grpcnotrace
 | ||||
| 
 | ||||
| /* | ||||
|  * | ||||
|  * Copyright 2024 gRPC authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| package grpc | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	t "golang.org/x/net/trace" | ||||
| ) | ||||
| 
 | ||||
| func newTrace(family, title string) traceLog { | ||||
| 	return t.New(family, title) | ||||
| } | ||||
| 
 | ||||
| func newTraceContext(ctx context.Context, tr traceLog) context.Context { | ||||
| 	return t.NewContext(ctx, tr) | ||||
| } | ||||
| 
 | ||||
| func newTraceEventLog(family, title string) traceEventLog { | ||||
| 	return t.NewEventLog(family, title) | ||||
| } | ||||
|  | @ -19,4 +19,4 @@ | |||
| package grpc | ||||
| 
 | ||||
| // Version is the current grpc version.
 | ||||
| const Version = "1.61.0" | ||||
| const Version = "1.62.0" | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ if [[ "$1" = "-install" ]]; then | |||
|   popd | ||||
|   if [[ -z "${VET_SKIP_PROTO}" ]]; then | ||||
|     if [[ "${GITHUB_ACTIONS}" = "true" ]]; then | ||||
|       PROTOBUF_VERSION=22.0 # a.k.a v4.22.0 in pb.go files. | ||||
|       PROTOBUF_VERSION=25.2 # a.k.a. v4.22.0 in pb.go files. | ||||
|       PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip | ||||
|       pushd /home/runner/go | ||||
|       wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME} | ||||
|  |  | |||
|  | @ -0,0 +1,31 @@ | |||
| // Copyright 2023 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 protoadapt bridges the original and new proto APIs.
 | ||||
| package protoadapt | ||||
| 
 | ||||
| import ( | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| 	"google.golang.org/protobuf/runtime/protoiface" | ||||
| 	"google.golang.org/protobuf/runtime/protoimpl" | ||||
| ) | ||||
| 
 | ||||
| // MessageV1 is the original [github.com/golang/protobuf/proto.Message] type.
 | ||||
| type MessageV1 = protoiface.MessageV1 | ||||
| 
 | ||||
| // MessageV2 is the [google.golang.org/protobuf/proto.Message] type used by the
 | ||||
| // current [google.golang.org/protobuf] module, adding support for reflection.
 | ||||
| type MessageV2 = proto.Message | ||||
| 
 | ||||
| // MessageV1Of converts a v2 message to a v1 message.
 | ||||
| // It returns nil if m is nil.
 | ||||
| func MessageV1Of(m MessageV2) MessageV1 { | ||||
| 	return protoimpl.X.ProtoMessageV1Of(m) | ||||
| } | ||||
| 
 | ||||
| // MessageV2Of converts a v1 message to a v2 message.
 | ||||
| // It returns nil if m is nil.
 | ||||
| func MessageV2Of(m MessageV1) MessageV2 { | ||||
| 	return protoimpl.X.ProtoMessageV2Of(m) | ||||
| } | ||||
|  | @ -89,7 +89,7 @@ github.com/bytedance/sonic/utf8 | |||
| # github.com/checkpoint-restore/checkpointctl v1.1.0 | ||||
| ## explicit; go 1.18 | ||||
| github.com/checkpoint-restore/checkpointctl/lib | ||||
| # github.com/checkpoint-restore/go-criu/v7 v7.0.0 | ||||
| # github.com/checkpoint-restore/go-criu/v7 v7.1.0 | ||||
| ## explicit; go 1.18 | ||||
| github.com/checkpoint-restore/go-criu/v7 | ||||
| github.com/checkpoint-restore/go-criu/v7/rpc | ||||
|  | @ -141,7 +141,7 @@ github.com/containernetworking/cni/pkg/version | |||
| # github.com/containernetworking/plugins v1.4.0 | ||||
| ## explicit; go 1.20 | ||||
| github.com/containernetworking/plugins/pkg/ns | ||||
| # github.com/containers/buildah v1.35.0 | ||||
| # github.com/containers/buildah v1.35.1-0.20240318192459-e64e6cc09dfd | ||||
| ## explicit; go 1.20 | ||||
| github.com/containers/buildah | ||||
| github.com/containers/buildah/bind | ||||
|  | @ -171,7 +171,7 @@ github.com/containers/buildah/pkg/sshagent | |||
| github.com/containers/buildah/pkg/util | ||||
| github.com/containers/buildah/pkg/volumes | ||||
| github.com/containers/buildah/util | ||||
| # github.com/containers/common v0.58.0 | ||||
| # github.com/containers/common v0.58.1-0.20240318131753-6f1c96f53a78 | ||||
| ## explicit; go 1.20 | ||||
| github.com/containers/common/internal | ||||
| github.com/containers/common/internal/attributedstring | ||||
|  | @ -470,7 +470,7 @@ github.com/distribution/reference | |||
| github.com/docker/distribution/registry/api/errcode | ||||
| github.com/docker/distribution/registry/api/v2 | ||||
| github.com/docker/distribution/registry/client/auth/challenge | ||||
| # github.com/docker/docker v25.0.3+incompatible | ||||
| # github.com/docker/docker v25.0.4+incompatible | ||||
| ## explicit | ||||
| github.com/docker/docker/api | ||||
| github.com/docker/docker/api/types | ||||
|  | @ -646,12 +646,7 @@ github.com/gogo/protobuf/proto | |||
| github.com/golang/groupcache/lru | ||||
| # github.com/golang/protobuf v1.5.3 | ||||
| ## explicit; go 1.9 | ||||
| github.com/golang/protobuf/jsonpb | ||||
| github.com/golang/protobuf/proto | ||||
| github.com/golang/protobuf/ptypes | ||||
| github.com/golang/protobuf/ptypes/any | ||||
| github.com/golang/protobuf/ptypes/duration | ||||
| github.com/golang/protobuf/ptypes/timestamp | ||||
| # github.com/google/go-cmp v0.6.0 | ||||
| ## explicit; go 1.13 | ||||
| github.com/google/go-cmp/cmp | ||||
|  | @ -1282,10 +1277,10 @@ google.golang.org/appengine/internal/log | |||
| google.golang.org/appengine/internal/remote_api | ||||
| google.golang.org/appengine/internal/urlfetch | ||||
| google.golang.org/appengine/urlfetch | ||||
| # google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 | ||||
| # google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 | ||||
| ## explicit; go 1.19 | ||||
| google.golang.org/genproto/googleapis/rpc/status | ||||
| # google.golang.org/grpc v1.61.0 | ||||
| # google.golang.org/grpc v1.62.0 | ||||
| ## explicit; go 1.19 | ||||
| google.golang.org/grpc | ||||
| google.golang.org/grpc/attributes | ||||
|  | @ -1364,6 +1359,7 @@ google.golang.org/protobuf/internal/set | |||
| google.golang.org/protobuf/internal/strs | ||||
| google.golang.org/protobuf/internal/version | ||||
| google.golang.org/protobuf/proto | ||||
| google.golang.org/protobuf/protoadapt | ||||
| google.golang.org/protobuf/reflect/protodesc | ||||
| google.golang.org/protobuf/reflect/protoreflect | ||||
| google.golang.org/protobuf/reflect/protoregistry | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue