You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	OS description attribute detector (#1840)
* Added Linux-specific detector for the os.description attribute * Generalized OS description detector with placeholder function for unimplemented OSes * Extended osDescription function to *nix OSes based on golang.org/x/sys/unix * Added WithOS resource configuration function to configure all of the OS resource attributes * Implemented osDescription funtion for Windows OS * Improved documentation header for *nix version of the osDescription function * Added support for reading os-release file * Added/updated documentation headers for *nix implementation of osDescription and related functions * Changelog update * Added support for reading macOS version information * Mock approach to test OS description attribute * Extracted common function getFirstAvailableFile to read the first available file from a list of candidates * Upgraded golang.org/x/sys * Changelog update * Fixed wrong function name in documentation header for WithOSDescription * Updated documentation header for platformOSDescription function * Renamed restoreProcessAttributesProviders test helper function The function restoreProcessAttributesProviders was renamed to simply restoreAttributesProviders to better reflect its broader scope, which not only applies to process attribute's providers. * Fixed os_linux.go overriding build tags defined inside the file The suffix on os_linux.go was overriding the build tags already defined in that file. The file was renamed to os_release_unix.go, reflecting the main function defined in the file. For consistency, os_darwin.go was renamed to os_release_darwing.go, as its primary purpose is to also define the osRelease function. * Removed use of discontinued function resource.WithoutBuiltin * Added PR number to changelog entries * Updated go.sum files after run of make lint * Linux implementation: ignore lines with an empty key * Linux implementation: avoid unquoting strings less than two chars * WIP: added tests for Linux support functions * WIP: added tests for charsToString and getFirstAvailableFile functions * Replaced os.CreateTemp with ioutil.TempFile as the former only exists in Go 1.16 * Added unameProvider type to decouple direct reference to unix.Uname function inside Uname() * Added tests for Uname() function * Replaced *os.File with io.Reader in parseOSReleaseFile to ease testing * Added tests for parseOSReleaseFile function * Darwin implementation: added tests for buildOSRelease function * Replaced *os.File with io.Reader in parsePlistFile to ease testing * Darwin implementation: added tests for parsePlistFile function * Type in documentation header for Linux osRelease function * Extracted logic for reading specific registry values into helper functions * Added basic tests for Windows version of platformOSDescription and helper functions * Manually formatted uint64 to strings to have an uniform interface for test assertions * Asserts there's no error when opening registry key for testing Co-authored-by: Robert Pająk <pellared@hotmail.com> * Simplified subtests by using a single test with multiple asserts * go.sum update after running make * Fix typo Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> * WIP: added placeholder implementation of platformOSDescription for unsupported OSes * Fixed typo on osRelease documentation header Co-authored-by: Chris Bandy <bandy.chris@gmail.com> * Fixed typo on test case name for ParsePlistFile tests Co-authored-by: Chris Bandy <bandy.chris@gmail.com> * Linter fix in changelog * go.sum updates after running make * Used strings.Replacer instead of multiple strings.ReplaceAll calls * Optimized implementation of charsToString * Safer temporary file deletion with t.TempDir() * Used t.Cleanup() for safer mocking of runtime providers in OS resource tests * Handled optionality of DisplayVersion registry key. For example, CI machine runs on: Windows Server 2019 Datacenter (1809) [Version 10.0.17763.1999] So, to not add an extra white space due to missing DisplayVersion, this value is checked to be not empty, and only in such case a trailing space is added for that component. * Workaround to handle the case of DisplayVersion registry key not present * Excluded unsupported GOOSes by negation of supported ones * go.sum update after running make Co-authored-by: Anthony Mirabella <a9@aneurysm9.com> Co-authored-by: Robert Pająk <pellared@hotmail.com> Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Chris Bandy <bandy.chris@gmail.com>
This commit is contained in:
		| @@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm | |||||||
| ### Added | ### Added | ||||||
|  |  | ||||||
| - Adds HTTP support for OTLP metrics exporter. (#2022) | - Adds HTTP support for OTLP metrics exporter. (#2022) | ||||||
|  | - Added `WithOSDescription` resource configuration option to set OS (Operating System) description resource attribute (`os.description`). (#1840) | ||||||
|  | - Added `WithOS` resource configuration option to set all OS (Operating System) resource attributes at once. (#1840) | ||||||
|  |  | ||||||
| ### Changed | ### Changed | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,6 +37,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -39,6 +39,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -121,6 +121,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w | |||||||
| golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | ||||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
|   | |||||||
| @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -82,8 +82,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -82,8 +82,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -81,8 +81,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -80,8 +80,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -79,8 +79,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= |  | ||||||
| golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
|   | |||||||
| @@ -121,6 +121,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w | |||||||
| golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= | ||||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -71,6 +71,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ require ( | |||||||
| 	go.opentelemetry.io/otel v1.0.0-RC1 | 	go.opentelemetry.io/otel v1.0.0-RC1 | ||||||
| 	go.opentelemetry.io/otel/oteltest v1.0.0-RC1 | 	go.opentelemetry.io/otel/oteltest v1.0.0-RC1 | ||||||
| 	go.opentelemetry.io/otel/trace v1.0.0-RC1 | 	go.opentelemetry.io/otel/trace v1.0.0-RC1 | ||||||
|  | 	golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| replace go.opentelemetry.io/otel/bridge/opencensus => ../bridge/opencensus | replace go.opentelemetry.io/otel/bridge/opencensus => ../bridge/opencensus | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN | |||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= | ||||||
|  | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								sdk/resource/export_common_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								sdk/resource/export_common_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	Uname                 = uname | ||||||
|  | 	CharsToString         = charsToString | ||||||
|  | 	GetFirstAvailableFile = getFirstAvailableFile | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	SetUnameProvider        = setUnameProvider | ||||||
|  | 	SetDefaultUnameProvider = setDefaultUnameProvider | ||||||
|  | ) | ||||||
							
								
								
									
										20
									
								
								sdk/resource/export_os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								sdk/resource/export_os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	ParsePlistFile = parsePlistFile | ||||||
|  | 	BuildOSRelease = buildOSRelease | ||||||
|  | ) | ||||||
| @@ -15,12 +15,14 @@ | |||||||
| package resource // import "go.opentelemetry.io/otel/sdk/resource" | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	SetDefaultOSProviders      = setDefaultOSProviders | 	SetDefaultOSProviders           = setDefaultOSProviders | ||||||
| 	SetOSProviders             = setOSProviders | 	SetOSProviders                  = setOSProviders | ||||||
| 	SetDefaultRuntimeProviders = setDefaultRuntimeProviders | 	SetDefaultRuntimeProviders      = setDefaultRuntimeProviders | ||||||
| 	SetRuntimeProviders        = setRuntimeProviders | 	SetRuntimeProviders             = setRuntimeProviders | ||||||
| 	SetDefaultUserProviders    = setDefaultUserProviders | 	SetDefaultUserProviders         = setDefaultUserProviders | ||||||
| 	SetUserProviders           = setUserProviders | 	SetUserProviders                = setUserProviders | ||||||
|  | 	SetDefaultOSDescriptionProvider = setDefaultOSDescriptionProvider | ||||||
|  | 	SetOSDescriptionProvider        = setOSDescriptionProvider | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								sdk/resource/export_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								sdk/resource/export_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	ParseOSReleaseFile = parseOSReleaseFile | ||||||
|  | 	Skip               = skip | ||||||
|  | 	Parse              = parse | ||||||
|  | 	Unquote            = unquote | ||||||
|  | 	Unescape           = unescape | ||||||
|  | 	BuildOSRelease     = buildOSRelease | ||||||
|  | ) | ||||||
							
								
								
									
										26
									
								
								sdk/resource/export_windows_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								sdk/resource/export_windows_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	PlatformOSDescription         = platformOSDescription | ||||||
|  | 	ReadProductName               = readProductName | ||||||
|  | 	ReadDisplayVersion            = readDisplayVersion | ||||||
|  | 	ReadReleaseID                 = readReleaseID | ||||||
|  | 	ReadCurrentMajorVersionNumber = readCurrentMajorVersionNumber | ||||||
|  | 	ReadCurrentMinorVersionNumber = readCurrentMinorVersionNumber | ||||||
|  | 	ReadCurrentBuildNumber        = readCurrentBuildNumber | ||||||
|  | 	ReadUBR                       = readUBR | ||||||
|  | ) | ||||||
| @@ -21,7 +21,22 @@ import ( | |||||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.4.0" | 	semconv "go.opentelemetry.io/otel/semconv/v1.4.0" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type osDescriptionProvider func() (string, error) | ||||||
|  |  | ||||||
|  | var defaultOSDescriptionProvider osDescriptionProvider = platformOSDescription | ||||||
|  |  | ||||||
|  | var osDescription = defaultOSDescriptionProvider | ||||||
|  |  | ||||||
|  | func setDefaultOSDescriptionProvider() { | ||||||
|  | 	setOSDescriptionProvider(defaultOSDescriptionProvider) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func setOSDescriptionProvider(osDescriptionProvider osDescriptionProvider) { | ||||||
|  | 	osDescription = osDescriptionProvider | ||||||
|  | } | ||||||
|  |  | ||||||
| type osTypeDetector struct{} | type osTypeDetector struct{} | ||||||
|  | type osDescriptionDetector struct{} | ||||||
|  |  | ||||||
| // Detect returns a *Resource that describes the operating system type the | // Detect returns a *Resource that describes the operating system type the | ||||||
| // service is running on. | // service is running on. | ||||||
| @@ -34,7 +49,38 @@ func (osTypeDetector) Detect(ctx context.Context) (*Resource, error) { | |||||||
| 	), nil | 	), nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Detect returns a *Resource that describes the operating system the | ||||||
|  | // service is running on. | ||||||
|  | func (osDescriptionDetector) Detect(ctx context.Context) (*Resource, error) { | ||||||
|  | 	description, err := osDescription() | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NewWithAttributes( | ||||||
|  | 		semconv.SchemaURL, | ||||||
|  | 		semconv.OSDescriptionKey.String(description), | ||||||
|  | 	), nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // WithOSType adds an attribute with the operating system type to the configured Resource. | // WithOSType adds an attribute with the operating system type to the configured Resource. | ||||||
| func WithOSType() Option { | func WithOSType() Option { | ||||||
| 	return WithDetectors(osTypeDetector{}) | 	return WithDetectors(osTypeDetector{}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // WithOSDescription adds an attribute with the operating system description to the | ||||||
|  | // configured Resource. The formatted string is equivalent to the output of the | ||||||
|  | // `uname -snrvm` command. | ||||||
|  | func WithOSDescription() Option { | ||||||
|  | 	return WithDetectors(osDescriptionDetector{}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // WithOS adds all the OS attributes to the configured Resource. | ||||||
|  | // See individual WithOS* functions to configure specific attributes. | ||||||
|  | func WithOS() Option { | ||||||
|  | 	return WithDetectors( | ||||||
|  | 		osTypeDetector{}, | ||||||
|  | 		osDescriptionDetector{}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										102
									
								
								sdk/resource/os_release_darwin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								sdk/resource/os_release_darwin.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/xml" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type plist struct { | ||||||
|  | 	XMLName xml.Name `xml:"plist"` | ||||||
|  | 	Dict    dict     `xml:"dict"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type dict struct { | ||||||
|  | 	Key    []string `xml:"key"` | ||||||
|  | 	String []string `xml:"string"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // osRelease builds a string describing the operating system release based on the | ||||||
|  | // contents of the property list (.plist) system files. If no .plist files are found, | ||||||
|  | // or if the required properties to build the release description string are missing, | ||||||
|  | // an empty string is returned instead. The generated string resembles the output of | ||||||
|  | // the `sw_vers` commandline program, but in a single-line string. For more information | ||||||
|  | // about the `sw_vers` program, see: https://www.unix.com/man-page/osx/1/SW_VERS. | ||||||
|  | func osRelease() string { | ||||||
|  | 	file, err := getPlistFile() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	defer file.Close() | ||||||
|  |  | ||||||
|  | 	values, err := parsePlistFile(file) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return buildOSRelease(values) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getPlistFile returns a *os.File pointing to one of the well-known .plist files | ||||||
|  | // available on macOS. If no file can be opened, it returns an error. | ||||||
|  | func getPlistFile() (*os.File, error) { | ||||||
|  | 	return getFirstAvailableFile([]string{ | ||||||
|  | 		"/System/Library/CoreServices/SystemVersion.plist", | ||||||
|  | 		"/System/Library/CoreServices/ServerVersion.plist", | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // parsePlistFile process the file pointed by `file` as a .plist file and returns | ||||||
|  | // a map with the key-values for each pair of correlated <key> and <string> elements | ||||||
|  | // contained in it. | ||||||
|  | func parsePlistFile(file io.Reader) (map[string]string, error) { | ||||||
|  | 	var v plist | ||||||
|  |  | ||||||
|  | 	err := xml.NewDecoder(file).Decode(&v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(v.Dict.Key) != len(v.Dict.String) { | ||||||
|  | 		return nil, fmt.Errorf("the number of <key> and <string> elements doesn't match") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	properties := make(map[string]string, len(v.Dict.Key)) | ||||||
|  | 	for i, key := range v.Dict.Key { | ||||||
|  | 		properties[key] = v.Dict.String[i] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return properties, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // buildOSRelease builds a string describing the OS release based on the properties | ||||||
|  | // available on the provided map. It tries to find the `ProductName`, `ProductVersion` | ||||||
|  | // and `ProductBuildVersion` properties. If some of these properties are not found, | ||||||
|  | // it returns an empty string. | ||||||
|  | func buildOSRelease(properties map[string]string) string { | ||||||
|  | 	productName := properties["ProductName"] | ||||||
|  | 	productVersion := properties["ProductVersion"] | ||||||
|  | 	productBuildVersion := properties["ProductBuildVersion"] | ||||||
|  |  | ||||||
|  | 	if productName == "" || productVersion == "" || productBuildVersion == "" { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return fmt.Sprintf("%s %s (%s)", productName, productVersion, productBuildVersion) | ||||||
|  | } | ||||||
							
								
								
									
										176
									
								
								sdk/resource/os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								sdk/resource/os_release_darwin_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"io" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  |  | ||||||
|  | 	"go.opentelemetry.io/otel/sdk/resource" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestParsePlistFile(t *testing.T) { | ||||||
|  | 	standardPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<key>ProductBuildVersion</key> | ||||||
|  | 	<string>20E232</string> | ||||||
|  | 	<key>ProductCopyright</key> | ||||||
|  | 	<string>1983-2021 Apple Inc.</string> | ||||||
|  | 	<key>ProductName</key> | ||||||
|  | 	<string>macOS</string> | ||||||
|  | 	<key>ProductUserVisibleVersion</key> | ||||||
|  | 	<string>11.3</string> | ||||||
|  | 	<key>ProductVersion</key> | ||||||
|  | 	<string>11.3</string> | ||||||
|  | 	<key>iOSSupportVersion</key> | ||||||
|  | 	<string>14.5</string> | ||||||
|  | </dict> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	parsedPlist := map[string]string{ | ||||||
|  | 		"ProductBuildVersion":       "20E232", | ||||||
|  | 		"ProductCopyright":          "1983-2021 Apple Inc.", | ||||||
|  | 		"ProductName":               "macOS", | ||||||
|  | 		"ProductUserVisibleVersion": "11.3", | ||||||
|  | 		"ProductVersion":            "11.3", | ||||||
|  | 		"iOSSupportVersion":         "14.5", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	emptyPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | </dict> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	missingDictPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	unknownElementsPlist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<a> | ||||||
|  | 		<b>123</b> | ||||||
|  | 	</a> | ||||||
|  | 	<key>ProductBuildVersion</key> | ||||||
|  | 	<c>Value</c> | ||||||
|  | 	<string>20E232</string> | ||||||
|  | 	<d attr="1"></d> | ||||||
|  | </dict> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	parsedUnknownElementsPlist := map[string]string{ | ||||||
|  | 		"ProductBuildVersion": "20E232", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name   string | ||||||
|  | 		Plist  io.Reader | ||||||
|  | 		Parsed map[string]string | ||||||
|  | 	}{ | ||||||
|  | 		{"Standard", standardPlist, parsedPlist}, | ||||||
|  | 		{"Empty", emptyPlist, map[string]string{}}, | ||||||
|  | 		{"Missing dict", missingDictPlist, map[string]string{}}, | ||||||
|  | 		{"Unknown elements", unknownElementsPlist, parsedUnknownElementsPlist}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result, err := resource.ParsePlistFile(tc.Plist) | ||||||
|  |  | ||||||
|  | 			require.Equal(t, tc.Parsed, result) | ||||||
|  | 			require.NoError(t, err) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestParsePlistFileUnevenKeys(t *testing.T) { | ||||||
|  | 	plist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<key>ProductBuildVersion</key> | ||||||
|  | 	<string>20E232</string> | ||||||
|  | 	<key>ProductCopyright</key> | ||||||
|  | </dict> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	result, err := resource.ParsePlistFile(plist) | ||||||
|  |  | ||||||
|  | 	require.Nil(t, result) | ||||||
|  | 	require.Error(t, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestParsePlistFileMalformed(t *testing.T) { | ||||||
|  | 	plist := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<key>Product | ||||||
|  | </dict> | ||||||
|  | </plist>`) | ||||||
|  |  | ||||||
|  | 	result, err := resource.ParsePlistFile(plist) | ||||||
|  |  | ||||||
|  | 	require.Nil(t, result) | ||||||
|  | 	require.Error(t, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestBuildOSRelease(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name       string | ||||||
|  | 		Properties map[string]string | ||||||
|  | 		OSRelease  string | ||||||
|  | 	}{ | ||||||
|  | 		{"Empty properties", map[string]string{}, ""}, | ||||||
|  | 		{"Empty properties (nil)", nil, ""}, | ||||||
|  | 		{"Missing product name", map[string]string{ | ||||||
|  | 			"ProductVersion":      "11.3", | ||||||
|  | 			"ProductBuildVersion": "20E232", | ||||||
|  | 		}, ""}, | ||||||
|  | 		{"Missing product version", map[string]string{ | ||||||
|  | 			"ProductName":         "macOS", | ||||||
|  | 			"ProductBuildVersion": "20E232", | ||||||
|  | 		}, ""}, | ||||||
|  | 		{"Missing product build version", map[string]string{ | ||||||
|  | 			"ProductName":    "macOS", | ||||||
|  | 			"ProductVersion": "11.3", | ||||||
|  | 		}, ""}, | ||||||
|  | 		{"All properties available", map[string]string{ | ||||||
|  | 			"ProductName":         "macOS", | ||||||
|  | 			"ProductVersion":      "11.3", | ||||||
|  | 			"ProductBuildVersion": "20E232", | ||||||
|  | 		}, "macOS 11.3 (20E232)"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.BuildOSRelease(tc.Properties) | ||||||
|  | 			require.Equal(t, tc.OSRelease, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								sdk/resource/os_release_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								sdk/resource/os_release_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // osRelease builds a string describing the operating system release based on the | ||||||
|  | // properties of the os-release file. If no os-release file is found, or if the | ||||||
|  | // required properties to build the release description string are missing, an empty | ||||||
|  | // string is returned instead. For more information about os-release files, see: | ||||||
|  | // https://www.freedesktop.org/software/systemd/man/os-release.html | ||||||
|  | func osRelease() string { | ||||||
|  | 	file, err := getOSReleaseFile() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	defer file.Close() | ||||||
|  |  | ||||||
|  | 	values := parseOSReleaseFile(file) | ||||||
|  |  | ||||||
|  | 	return buildOSRelease(values) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getOSReleaseFile returns a *os.File pointing to one of the well-known os-release | ||||||
|  | // files, according to their order of preference. If no file can be opened, it | ||||||
|  | // returns an error. | ||||||
|  | func getOSReleaseFile() (*os.File, error) { | ||||||
|  | 	return getFirstAvailableFile([]string{"/etc/os-release", "/usr/lib/os-release"}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // parseOSReleaseFile process the file pointed by `file` as an os-release file and | ||||||
|  | // returns a map with the key-values contained in it. Empty lines or lines starting | ||||||
|  | // with a '#' character are ignored, as well as lines with the missing key=value | ||||||
|  | // separator. Values are unquoted and unescaped. | ||||||
|  | func parseOSReleaseFile(file io.Reader) map[string]string { | ||||||
|  | 	values := make(map[string]string) | ||||||
|  | 	scanner := bufio.NewScanner(file) | ||||||
|  |  | ||||||
|  | 	for scanner.Scan() { | ||||||
|  | 		line := scanner.Text() | ||||||
|  |  | ||||||
|  | 		if skip(line) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		key, value, ok := parse(line) | ||||||
|  | 		if ok { | ||||||
|  | 			values[key] = value | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return values | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // skip returns true if the line is blank or starts with a '#' character, and | ||||||
|  | // therefore should be skipped from processing. | ||||||
|  | func skip(line string) bool { | ||||||
|  | 	line = strings.TrimSpace(line) | ||||||
|  |  | ||||||
|  | 	return len(line) == 0 || strings.HasPrefix(line, "#") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // parse attempts to split the provided line on the first '=' character, and then | ||||||
|  | // sanitize each side of the split before returning them as a key-value pair. | ||||||
|  | func parse(line string) (string, string, bool) { | ||||||
|  | 	parts := strings.SplitN(line, "=", 2) | ||||||
|  |  | ||||||
|  | 	if len(parts) != 2 || len(parts[0]) == 0 { | ||||||
|  | 		return "", "", false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	key := strings.TrimSpace(parts[0]) | ||||||
|  | 	value := unescape(unquote(strings.TrimSpace(parts[1]))) | ||||||
|  |  | ||||||
|  | 	return key, value, true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // unquote checks whether the string `s` is quoted with double or single quotes | ||||||
|  | // and, if so, returns a version of the string without them. Otherwise it returns | ||||||
|  | // the provided string unchanged. | ||||||
|  | func unquote(s string) string { | ||||||
|  | 	if len(s) < 2 { | ||||||
|  | 		return s | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (s[0] == '"' || s[0] == '\'') && s[0] == s[len(s)-1] { | ||||||
|  | 		return s[1 : len(s)-1] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // unescape removes the `\` prefix from some characters that are expected | ||||||
|  | // to have it added in front of them for escaping purposes. | ||||||
|  | func unescape(s string) string { | ||||||
|  | 	return strings.NewReplacer( | ||||||
|  | 		`\$`, `$`, | ||||||
|  | 		`\"`, `"`, | ||||||
|  | 		`\'`, `'`, | ||||||
|  | 		`\\`, `\`, | ||||||
|  | 		"\\`", "`", | ||||||
|  | 	).Replace(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // buildOSRelease builds a string describing the OS release based on the properties | ||||||
|  | // available on the provided map. It favors a combination of the `NAME` and `VERSION` | ||||||
|  | // properties as first option (falling back to `VERSION_ID` if `VERSION` isn't | ||||||
|  | // found), and using `PRETTY_NAME` alone if some of the previous are not present. If | ||||||
|  | // none of these properties are found, it returns an empty string. | ||||||
|  | // | ||||||
|  | // The rationale behind not using `PRETTY_NAME` as first choice was that, for some | ||||||
|  | // Linux distributions, it doesn't include the same detail that can be found on the | ||||||
|  | // individual `NAME` and `VERSION` properties, and combining `PRETTY_NAME` with | ||||||
|  | // other properties can produce "pretty" redundant strings in some cases. | ||||||
|  | func buildOSRelease(values map[string]string) string { | ||||||
|  | 	var osRelease string | ||||||
|  |  | ||||||
|  | 	name := values["NAME"] | ||||||
|  | 	version := values["VERSION"] | ||||||
|  |  | ||||||
|  | 	if version == "" { | ||||||
|  | 		version = values["VERSION_ID"] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if name != "" && version != "" { | ||||||
|  | 		osRelease = fmt.Sprintf("%s %s", name, version) | ||||||
|  | 	} else { | ||||||
|  | 		osRelease = values["PRETTY_NAME"] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return osRelease | ||||||
|  | } | ||||||
							
								
								
									
										306
									
								
								sdk/resource/os_release_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								sdk/resource/os_release_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"io" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  |  | ||||||
|  | 	"go.opentelemetry.io/otel/sdk/resource" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestParseOSReleaseFile(t *testing.T) { | ||||||
|  | 	osReleaseUbuntu := bytes.NewBufferString(`NAME="Ubuntu" | ||||||
|  | VERSION="20.04.2 LTS (Focal Fossa)" | ||||||
|  | ID=ubuntu | ||||||
|  | ID_LIKE=debian | ||||||
|  | PRETTY_NAME="Ubuntu 20.04.2 LTS" | ||||||
|  | VERSION_ID="20.04" | ||||||
|  | HOME_URL="https://www.ubuntu.com/" | ||||||
|  | SUPPORT_URL="https://help.ubuntu.com/" | ||||||
|  | BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" | ||||||
|  | PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" | ||||||
|  | VERSION_CODENAME=focal | ||||||
|  | UBUNTU_CODENAME=focal`) | ||||||
|  |  | ||||||
|  | 	parsedUbuntu := map[string]string{ | ||||||
|  | 		"NAME":               "Ubuntu", | ||||||
|  | 		"VERSION":            "20.04.2 LTS (Focal Fossa)", | ||||||
|  | 		"ID":                 "ubuntu", | ||||||
|  | 		"ID_LIKE":            "debian", | ||||||
|  | 		"PRETTY_NAME":        "Ubuntu 20.04.2 LTS", | ||||||
|  | 		"VERSION_ID":         "20.04", | ||||||
|  | 		"HOME_URL":           "https://www.ubuntu.com/", | ||||||
|  | 		"SUPPORT_URL":        "https://help.ubuntu.com/", | ||||||
|  | 		"BUG_REPORT_URL":     "https://bugs.launchpad.net/ubuntu/", | ||||||
|  | 		"PRIVACY_POLICY_URL": "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy", | ||||||
|  | 		"VERSION_CODENAME":   "focal", | ||||||
|  | 		"UBUNTU_CODENAME":    "focal", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	osReleaseDebian := bytes.NewBufferString(`PRETTY_NAME="Debian GNU/Linux 10 (buster)" | ||||||
|  | NAME="Debian GNU/Linux" | ||||||
|  | VERSION_ID="10" | ||||||
|  | VERSION="10 (buster)" | ||||||
|  | VERSION_CODENAME=buster | ||||||
|  | ID=debian | ||||||
|  | HOME_URL="https://www.debian.org/" | ||||||
|  | SUPPORT_URL="https://www.debian.org/support" | ||||||
|  | BUG_REPORT_URL="https://bugs.debian.org/"`) | ||||||
|  |  | ||||||
|  | 	parsedDebian := map[string]string{ | ||||||
|  | 		"PRETTY_NAME":      "Debian GNU/Linux 10 (buster)", | ||||||
|  | 		"NAME":             "Debian GNU/Linux", | ||||||
|  | 		"VERSION_ID":       "10", | ||||||
|  | 		"VERSION":          "10 (buster)", | ||||||
|  | 		"VERSION_CODENAME": "buster", | ||||||
|  | 		"ID":               "debian", | ||||||
|  | 		"HOME_URL":         "https://www.debian.org/", | ||||||
|  | 		"SUPPORT_URL":      "https://www.debian.org/support", | ||||||
|  | 		"BUG_REPORT_URL":   "https://bugs.debian.org/", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	osReleaseAlpine := bytes.NewBufferString(`NAME="Alpine Linux" | ||||||
|  | ID=alpine | ||||||
|  | VERSION_ID=3.13.4 | ||||||
|  | PRETTY_NAME="Alpine Linux v3.13" | ||||||
|  | HOME_URL="https://alpinelinux.org/" | ||||||
|  | BUG_REPORT_URL="https://bugs.alpinelinux.org/"`) | ||||||
|  |  | ||||||
|  | 	parsedAlpine := map[string]string{ | ||||||
|  | 		"NAME":           "Alpine Linux", | ||||||
|  | 		"ID":             "alpine", | ||||||
|  | 		"VERSION_ID":     "3.13.4", | ||||||
|  | 		"PRETTY_NAME":    "Alpine Linux v3.13", | ||||||
|  | 		"HOME_URL":       "https://alpinelinux.org/", | ||||||
|  | 		"BUG_REPORT_URL": "https://bugs.alpinelinux.org/", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	osReleaseMock := bytes.NewBufferString(` | ||||||
|  | # This line should be skipped | ||||||
|  |  | ||||||
|  | QUOTED1="Quoted value 1" | ||||||
|  | QUOTED2='Quoted value 2' | ||||||
|  | ESCAPED1="\$HOME" | ||||||
|  | ESCAPED2="\"release\"" | ||||||
|  | ESCAPED3="rock\'n\'roll" | ||||||
|  | ESCAPED4="\\var" | ||||||
|  |  | ||||||
|  | =line with missing key should be skipped | ||||||
|  |  | ||||||
|  | PROP1=name=john | ||||||
|  | 	PROP2  =  Value   | ||||||
|  | PROP3='This value will be overwritten by the next one' | ||||||
|  | PROP3='Final value'`) | ||||||
|  |  | ||||||
|  | 	parsedMock := map[string]string{ | ||||||
|  | 		"QUOTED1":  "Quoted value 1", | ||||||
|  | 		"QUOTED2":  "Quoted value 2", | ||||||
|  | 		"ESCAPED1": "$HOME", | ||||||
|  | 		"ESCAPED2": `"release"`, | ||||||
|  | 		"ESCAPED3": "rock'n'roll", | ||||||
|  | 		"ESCAPED4": `\var`, | ||||||
|  | 		"PROP1":    "name=john", | ||||||
|  | 		"PROP2":    "Value", | ||||||
|  | 		"PROP3":    "Final value", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name      string | ||||||
|  | 		OSRelease io.Reader | ||||||
|  | 		Parsed    map[string]string | ||||||
|  | 	}{ | ||||||
|  | 		{"Ubuntu", osReleaseUbuntu, parsedUbuntu}, | ||||||
|  | 		{"Debian", osReleaseDebian, parsedDebian}, | ||||||
|  | 		{"Alpine", osReleaseAlpine, parsedAlpine}, | ||||||
|  | 		{"Mock", osReleaseMock, parsedMock}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.ParseOSReleaseFile(tc.OSRelease) | ||||||
|  | 			require.EqualValues(t, tc.Parsed, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestSkip(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name     string | ||||||
|  | 		Line     string | ||||||
|  | 		Expected bool | ||||||
|  | 	}{ | ||||||
|  | 		{"Empty string", "", true}, | ||||||
|  | 		{"Only whitespace", "   ", true}, | ||||||
|  | 		{"Hashtag prefix 1", "# Sample text", true}, | ||||||
|  | 		{"Hashtag prefix 2", "  # Sample text", true}, | ||||||
|  | 		{"Hashtag and whitespace 1", "#  ", true}, | ||||||
|  | 		{"Hashtag and whitespace 2", "  #", true}, | ||||||
|  | 		{"Hashtag and whitespace 3", "  #  ", true}, | ||||||
|  | 		{"Nonempty string", "Sample text", false}, | ||||||
|  | 		{"Nonempty string with whitespace around", " Sample text ", false}, | ||||||
|  | 		{"Nonempty string with middle hashtag", "Sample #text", false}, | ||||||
|  | 		{"Nonempty string with ending hashtag", "Sample text #", false}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.Skip(tc.Line) | ||||||
|  | 			require.EqualValues(t, tc.Expected, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestParse(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name          string | ||||||
|  | 		Line          string | ||||||
|  | 		ExpectedKey   string | ||||||
|  | 		ExpectedValue string | ||||||
|  | 		OK            bool | ||||||
|  | 	}{ | ||||||
|  | 		{"Empty string", "", "", "", false}, | ||||||
|  | 		{"No separator", "wrong", "", "", false}, | ||||||
|  | 		{"Empty key", "=john", "", "", false}, | ||||||
|  | 		{"Empty key value", "=", "", "", false}, | ||||||
|  | 		{"Empty value", "name=", "name", "", true}, | ||||||
|  | 		{"Key value 1", "name=john", "name", "john", true}, | ||||||
|  | 		{"Key value 2", "name=john=dev", "name", "john=dev", true}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			key, value, ok := resource.Parse(tc.Line) | ||||||
|  | 			require.EqualValues(t, tc.ExpectedKey, key) | ||||||
|  | 			require.EqualValues(t, tc.ExpectedValue, value) | ||||||
|  | 			require.EqualValues(t, tc.OK, ok) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestUnquote(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name     string | ||||||
|  | 		Text     string | ||||||
|  | 		Expected string | ||||||
|  | 	}{ | ||||||
|  | 		{"Empty string", ``, ``}, | ||||||
|  | 		{"Single double quote", `"`, `"`}, | ||||||
|  | 		{"Single single quote", `'`, `'`}, | ||||||
|  | 		{"Empty double quotes", `""`, ``}, | ||||||
|  | 		{"Empty single quotes", `''`, ``}, | ||||||
|  | 		{"Empty mixed quotes 1", `"'`, `"'`}, | ||||||
|  | 		{"Empty mixed quotes 2", `'"`, `'"`}, | ||||||
|  | 		{"Double quotes", `"Sample text"`, `Sample text`}, | ||||||
|  | 		{"Single quotes", `'Sample text'`, `Sample text`}, | ||||||
|  | 		{"Half-open starting double quote", `"Sample text`, `"Sample text`}, | ||||||
|  | 		{"Half-open ending double quote", `Sample text"`, `Sample text"`}, | ||||||
|  | 		{"Half-open starting single quote", `'Sample text`, `'Sample text`}, | ||||||
|  | 		{"Half-open ending single quote", `Sample text'`, `Sample text'`}, | ||||||
|  | 		{"Double double quotes", `""Sample text""`, `"Sample text"`}, | ||||||
|  | 		{"Double single quotes", `''Sample text''`, `'Sample text'`}, | ||||||
|  | 		{"Mismatch quotes 1", `"Sample text'`, `"Sample text'`}, | ||||||
|  | 		{"Mismatch quotes 2", `'Sample text"`, `'Sample text"`}, | ||||||
|  | 		{"No quotes", `Sample text`, `Sample text`}, | ||||||
|  | 		{"Internal double quote", `Sample "text"`, `Sample "text"`}, | ||||||
|  | 		{"Internal single quote", `Sample 'text'`, `Sample 'text'`}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.Unquote(tc.Text) | ||||||
|  | 			require.EqualValues(t, tc.Expected, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestUnescape(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name     string | ||||||
|  | 		Text     string | ||||||
|  | 		Expected string | ||||||
|  | 	}{ | ||||||
|  | 		{"Empty string", ``, ``}, | ||||||
|  | 		{"Escaped dollar sign", `\$var`, `$var`}, | ||||||
|  | 		{"Escaped double quote", `\"var`, `"var`}, | ||||||
|  | 		{"Escaped single quote", `\'var`, `'var`}, | ||||||
|  | 		{"Escaped backslash", `\\var`, `\var`}, | ||||||
|  | 		{"Escaped backtick", "\\`var", "`var"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.Unescape(tc.Text) | ||||||
|  | 			require.EqualValues(t, tc.Expected, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestBuildOSRelease(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name     string | ||||||
|  | 		Values   map[string]string | ||||||
|  | 		Expected string | ||||||
|  | 	}{ | ||||||
|  | 		{"Nil values", nil, ""}, | ||||||
|  | 		{"Empty values", map[string]string{}, ""}, | ||||||
|  | 		{"Name and version only", map[string]string{ | ||||||
|  | 			"NAME":    "Ubuntu", | ||||||
|  | 			"VERSION": "20.04.2 LTS (Focal Fossa)", | ||||||
|  | 		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"}, | ||||||
|  | 		{"Name and version preferred", map[string]string{ | ||||||
|  | 			"NAME":        "Ubuntu", | ||||||
|  | 			"VERSION":     "20.04.2 LTS (Focal Fossa)", | ||||||
|  | 			"VERSION_ID":  "20.04", | ||||||
|  | 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||||
|  | 		}, "Ubuntu 20.04.2 LTS (Focal Fossa)"}, | ||||||
|  | 		{"Version ID fallback", map[string]string{ | ||||||
|  | 			"NAME":       "Ubuntu", | ||||||
|  | 			"VERSION_ID": "20.04", | ||||||
|  | 		}, "Ubuntu 20.04"}, | ||||||
|  | 		{"Pretty name fallback due to missing name", map[string]string{ | ||||||
|  | 			"VERSION":     "20.04.2 LTS (Focal Fossa)", | ||||||
|  | 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||||
|  | 		}, "Ubuntu 20.04.2 LTS"}, | ||||||
|  | 		{"Pretty name fallback due to missing version", map[string]string{ | ||||||
|  | 			"NAME":        "Ubuntu", | ||||||
|  | 			"PRETTY_NAME": "Ubuntu 20.04.2 LTS", | ||||||
|  | 		}, "Ubuntu 20.04.2 LTS"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.BuildOSRelease(tc.Values) | ||||||
|  | 			require.EqualValues(t, tc.Expected, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -30,10 +30,15 @@ func mockRuntimeProviders() { | |||||||
| 		func() string { return "LINUX" }, | 		func() string { return "LINUX" }, | ||||||
| 		fakeRuntimeArchProvider, | 		fakeRuntimeArchProvider, | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
|  | 	resource.SetOSDescriptionProvider( | ||||||
|  | 		func() (string, error) { return "Test", nil }, | ||||||
|  | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestWithOSType(t *testing.T) { | func TestWithOSType(t *testing.T) { | ||||||
| 	mockRuntimeProviders() | 	mockRuntimeProviders() | ||||||
|  | 	t.Cleanup(restoreAttributesProviders) | ||||||
|  |  | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
|  |  | ||||||
| @@ -45,6 +50,37 @@ func TestWithOSType(t *testing.T) { | |||||||
| 	require.EqualValues(t, map[string]string{ | 	require.EqualValues(t, map[string]string{ | ||||||
| 		"os.type": "linux", | 		"os.type": "linux", | ||||||
| 	}, toMap(res)) | 	}, toMap(res)) | ||||||
|  | } | ||||||
| 	restoreProcessAttributesProviders() |  | ||||||
|  | func TestWithOSDescription(t *testing.T) { | ||||||
|  | 	mockRuntimeProviders() | ||||||
|  | 	t.Cleanup(restoreAttributesProviders) | ||||||
|  |  | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	res, err := resource.New(ctx, | ||||||
|  | 		resource.WithOSDescription(), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.EqualValues(t, map[string]string{ | ||||||
|  | 		"os.description": "Test", | ||||||
|  | 	}, toMap(res)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestWithOS(t *testing.T) { | ||||||
|  | 	mockRuntimeProviders() | ||||||
|  | 	t.Cleanup(restoreAttributesProviders) | ||||||
|  |  | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	res, err := resource.New(ctx, | ||||||
|  | 		resource.WithOS(), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.EqualValues(t, map[string]string{ | ||||||
|  | 		"os.type":        "linux", | ||||||
|  | 		"os.description": "Test", | ||||||
|  | 	}, toMap(res)) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										99
									
								
								sdk/resource/os_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								sdk/resource/os_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/sys/unix" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type unameProvider func(buf *unix.Utsname) (err error) | ||||||
|  |  | ||||||
|  | var defaultUnameProvider unameProvider = unix.Uname | ||||||
|  |  | ||||||
|  | var currentUnameProvider = defaultUnameProvider | ||||||
|  |  | ||||||
|  | func setDefaultUnameProvider() { | ||||||
|  | 	setUnameProvider(defaultUnameProvider) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func setUnameProvider(unameProvider unameProvider) { | ||||||
|  | 	currentUnameProvider = unameProvider | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // platformOSDescription returns a human readable OS version information string. | ||||||
|  | // The final string combines OS release information (where available) and the | ||||||
|  | // result of the `uname` system call. | ||||||
|  | func platformOSDescription() (string, error) { | ||||||
|  | 	uname, err := uname() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	osRelease := osRelease() | ||||||
|  | 	if osRelease != "" { | ||||||
|  | 		return fmt.Sprintf("%s (%s)", osRelease, uname), nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return uname, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // uname issues a uname(2) system call (or equivalent on systems which doesn't | ||||||
|  | // have one) and formats the output in a single string, similar to the output | ||||||
|  | // of the `uname` commandline program. The final string resembles the one | ||||||
|  | // obtained with a call to `uname -snrvm`. | ||||||
|  | func uname() (string, error) { | ||||||
|  | 	var utsName unix.Utsname | ||||||
|  |  | ||||||
|  | 	err := currentUnameProvider(&utsName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return fmt.Sprintf("%s %s %s %s %s", | ||||||
|  | 		charsToString(utsName.Sysname[:]), | ||||||
|  | 		charsToString(utsName.Nodename[:]), | ||||||
|  | 		charsToString(utsName.Release[:]), | ||||||
|  | 		charsToString(utsName.Version[:]), | ||||||
|  | 		charsToString(utsName.Machine[:]), | ||||||
|  | 	), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // charsToString converts a C-like null-terminated char array to a Go string. | ||||||
|  | func charsToString(charArray []byte) string { | ||||||
|  | 	if i := bytes.IndexByte(charArray, 0); i >= 0 { | ||||||
|  | 		charArray = charArray[:i] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return string(charArray) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getFirstAvailableFile returns an *os.File of the first available | ||||||
|  | // file from a list of candidate file paths. | ||||||
|  | func getFirstAvailableFile(candidates []string) (*os.File, error) { | ||||||
|  | 	for _, c := range candidates { | ||||||
|  | 		file, err := os.Open(c) | ||||||
|  | 		if err == nil { | ||||||
|  | 			return file, nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil, fmt.Errorf("no candidate file available: %v", candidates) | ||||||
|  | } | ||||||
							
								
								
									
										134
									
								
								sdk/resource/os_unix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								sdk/resource/os_unix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||||
|  |  | ||||||
|  | package resource_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  |  | ||||||
|  | 	"go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/sys/unix" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func fakeUnameProvider(buf *unix.Utsname) error { | ||||||
|  | 	copy(buf.Sysname[:], "Mock OS") | ||||||
|  | 	copy(buf.Nodename[:], "DESKTOP-PC") | ||||||
|  | 	copy(buf.Release[:], "5.0.0") | ||||||
|  | 	copy(buf.Version[:], "#1 SMP Thu May 6 12:34:56 UTC 2021") | ||||||
|  | 	copy(buf.Machine[:], "x86_64") | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func fakeUnameProviderWithError(buf *unix.Utsname) error { | ||||||
|  | 	return fmt.Errorf("Error invoking uname(2)") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestUname(t *testing.T) { | ||||||
|  | 	resource.SetUnameProvider(fakeUnameProvider) | ||||||
|  |  | ||||||
|  | 	uname, err := resource.Uname() | ||||||
|  |  | ||||||
|  | 	require.Equal(t, uname, "Mock OS DESKTOP-PC 5.0.0 #1 SMP Thu May 6 12:34:56 UTC 2021 x86_64") | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	resource.SetDefaultUnameProvider() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestUnameError(t *testing.T) { | ||||||
|  | 	resource.SetUnameProvider(fakeUnameProviderWithError) | ||||||
|  |  | ||||||
|  | 	uname, err := resource.Uname() | ||||||
|  |  | ||||||
|  | 	require.Empty(t, uname) | ||||||
|  | 	require.Error(t, err) | ||||||
|  |  | ||||||
|  | 	resource.SetDefaultUnameProvider() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCharsToString(t *testing.T) { | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name     string | ||||||
|  | 		Bytes    []byte | ||||||
|  | 		Expected string | ||||||
|  | 	}{ | ||||||
|  | 		{"Nil array", nil, ""}, | ||||||
|  | 		{"Empty array", []byte{}, ""}, | ||||||
|  | 		{"Empty string (null terminated)", []byte{0x00}, ""}, | ||||||
|  | 		{"Nonempty string (null terminated)", []byte{0x31, 0x32, 0x33, 0x00}, "123"}, | ||||||
|  | 		{"Nonempty string (non-null terminated)", []byte{0x31, 0x32, 0x33}, "123"}, | ||||||
|  | 		{"Nonempty string with values after null", []byte{0x31, 0x32, 0x33, 0x00, 0x34}, "123"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			result := resource.CharsToString(tc.Bytes) | ||||||
|  | 			require.EqualValues(t, tc.Expected, result) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestGetFirstAvailableFile(t *testing.T) { | ||||||
|  | 	tempDir := t.TempDir() | ||||||
|  |  | ||||||
|  | 	file1, _ := ioutil.TempFile(tempDir, "candidate_") | ||||||
|  | 	file2, _ := ioutil.TempFile(tempDir, "candidate_") | ||||||
|  |  | ||||||
|  | 	filename1, filename2 := file1.Name(), file2.Name() | ||||||
|  |  | ||||||
|  | 	tt := []struct { | ||||||
|  | 		Name             string | ||||||
|  | 		Candidates       []string | ||||||
|  | 		ExpectedFileName string | ||||||
|  | 		ExpectedErr      string | ||||||
|  | 	}{ | ||||||
|  | 		{"Gets first, skip second candidate", []string{filename1, filename2}, filename1, ""}, | ||||||
|  | 		{"Skips first, gets second candidate", []string{"does_not_exists", filename2}, filename2, ""}, | ||||||
|  | 		{"Skips first, gets second, ignores third candidate", []string{"does_not_exists", filename2, filename1}, filename2, ""}, | ||||||
|  | 		{"No candidates (empty slice)", []string{}, "", "no candidate file available: []"}, | ||||||
|  | 		{"No candidates (nil slice)", nil, "", "no candidate file available: []"}, | ||||||
|  | 		{"Single nonexisting candidate", []string{"does_not_exists"}, "", "no candidate file available: [does_not_exists]"}, | ||||||
|  | 		{"Multiple nonexisting candidates", []string{"does_not_exists", "this_either"}, "", "no candidate file available: [does_not_exists this_either]"}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tc := range tt { | ||||||
|  | 		tc := tc | ||||||
|  |  | ||||||
|  | 		t.Run(tc.Name, func(t *testing.T) { | ||||||
|  | 			file, err := resource.GetFirstAvailableFile(tc.Candidates) | ||||||
|  |  | ||||||
|  | 			filename := "" | ||||||
|  | 			if file != nil { | ||||||
|  | 				filename = file.Name() | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			errString := "" | ||||||
|  | 			if err != nil { | ||||||
|  | 				errString = err.Error() | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			require.Equal(t, tc.ExpectedFileName, filename) | ||||||
|  | 			require.Equal(t, tc.ExpectedErr, errString) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								sdk/resource/os_unsupported.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sdk/resource/os_unsupported.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | // Copyright The OpenTelemetry 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. | ||||||
|  |  | ||||||
|  | // +build !aix | ||||||
|  | // +build !darwin | ||||||
|  | // +build !dragonfly | ||||||
|  | // +build !freebsd | ||||||
|  | // +build !linux | ||||||
|  | // +build !netbsd | ||||||
|  | // +build !openbsd | ||||||
|  | // +build !solaris | ||||||
|  | // +build !windows | ||||||
|  | // +build !zos | ||||||
|  |  | ||||||
|  | package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | // platformOSDescription is a placeholder implementation for OSes | ||||||
|  | // for which this project currently doesn't support os.description | ||||||
|  | // attribute detection. See build tags declaration early on this file | ||||||
|  | // for a list of unsupported OSes. | ||||||
|  | func platformOSDescription() (string, error) { | ||||||
|  | 	return "<unknown>", nil | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								sdk/resource/os_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								sdk/resource/os_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource // import "go.opentelemetry.io/otel/sdk/resource" | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/sys/windows/registry" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // platformOSDescription returns a human readable OS version information string. | ||||||
|  | // It does so by querying registry values under the | ||||||
|  | // `SOFTWARE\Microsoft\Windows NT\CurrentVersion` key. The final string | ||||||
|  | // resembles the one displayed by the Version Reporter Applet (winver.exe). | ||||||
|  | func platformOSDescription() (string, error) { | ||||||
|  | 	k, err := registry.OpenKey( | ||||||
|  | 		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	defer k.Close() | ||||||
|  |  | ||||||
|  | 	var ( | ||||||
|  | 		productName               = readProductName(k) | ||||||
|  | 		displayVersion            = readDisplayVersion(k) | ||||||
|  | 		releaseID                 = readReleaseID(k) | ||||||
|  | 		currentMajorVersionNumber = readCurrentMajorVersionNumber(k) | ||||||
|  | 		currentMinorVersionNumber = readCurrentMinorVersionNumber(k) | ||||||
|  | 		currentBuildNumber        = readCurrentBuildNumber(k) | ||||||
|  | 		ubr                       = readUBR(k) | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	if displayVersion != "" { | ||||||
|  | 		displayVersion += " " | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return fmt.Sprintf("%s %s(%s) [Version %s.%s.%s.%s]", | ||||||
|  | 		productName, | ||||||
|  | 		displayVersion, | ||||||
|  | 		releaseID, | ||||||
|  | 		currentMajorVersionNumber, | ||||||
|  | 		currentMinorVersionNumber, | ||||||
|  | 		currentBuildNumber, | ||||||
|  | 		ubr, | ||||||
|  | 	), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getStringValue(name string, k registry.Key) string { | ||||||
|  | 	value, _, _ := k.GetStringValue(name) | ||||||
|  |  | ||||||
|  | 	return value | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getIntegerValue(name string, k registry.Key) uint64 { | ||||||
|  | 	value, _, _ := k.GetIntegerValue(name) | ||||||
|  |  | ||||||
|  | 	return value | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readProductName(k registry.Key) string { | ||||||
|  | 	return getStringValue("ProductName", k) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readDisplayVersion(k registry.Key) string { | ||||||
|  | 	return getStringValue("DisplayVersion", k) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readReleaseID(k registry.Key) string { | ||||||
|  | 	return getStringValue("ReleaseID", k) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readCurrentMajorVersionNumber(k registry.Key) string { | ||||||
|  | 	return strconv.FormatUint(getIntegerValue("CurrentMajorVersionNumber", k), 10) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readCurrentMinorVersionNumber(k registry.Key) string { | ||||||
|  | 	return strconv.FormatUint(getIntegerValue("CurrentMinorVersionNumber", k), 10) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readCurrentBuildNumber(k registry.Key) string { | ||||||
|  | 	return getStringValue("CurrentBuildNumber", k) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func readUBR(k registry.Key) string { | ||||||
|  | 	return strconv.FormatUint(getIntegerValue("UBR", k), 10) | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								sdk/resource/os_windows_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								sdk/resource/os_windows_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | // Copyright The OpenTelemetry 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 resource_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | 	"golang.org/x/sys/windows/registry" | ||||||
|  |  | ||||||
|  | 	"go.opentelemetry.io/otel/sdk/resource" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestPlatformOSDescription(t *testing.T) { | ||||||
|  | 	osDescription, err := resource.PlatformOSDescription() | ||||||
|  |  | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.Regexp(t, `^(\w+\s)+\(\d+\)\s\[Version\s\d+(\.\d+){3}\]$`, osDescription) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestReadRegistryValues(t *testing.T) { | ||||||
|  | 	k, err := registry.OpenKey( | ||||||
|  | 		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) | ||||||
|  |  | ||||||
|  | 	require.NoError(t, err, "should open Windows CurrentVersion registry key") | ||||||
|  |  | ||||||
|  | 	defer k.Close() | ||||||
|  |  | ||||||
|  | 	assert.NotEmpty(t, resource.ReadProductName(k), "should read ProductName") | ||||||
|  | 	assert.NotEmpty(t, resource.ReadReleaseID(k), "should read ReleaseID") | ||||||
|  | 	assert.NotEmpty(t, resource.ReadCurrentMajorVersionNumber(k), "should read CurrentMajorVersionNumber") | ||||||
|  | 	assert.NotEmpty(t, resource.ReadCurrentMinorVersionNumber(k), "should read CurrentMinorVersionNumber") | ||||||
|  | 	assert.NotEmpty(t, resource.ReadCurrentBuildNumber(k), "should read CurrentBuildNumber") | ||||||
|  | 	assert.NotEmpty(t, resource.ReadUBR(k), "should read UBR") | ||||||
|  | 	assert.NotPanics(t, func() { resource.ReadDisplayVersion(k) }, "should not panic when reading DisplayVersion") | ||||||
|  | } | ||||||
| @@ -97,10 +97,11 @@ func mockProcessAttributesProvidersWithErrors() { | |||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| func restoreProcessAttributesProviders() { | func restoreAttributesProviders() { | ||||||
| 	resource.SetDefaultOSProviders() | 	resource.SetDefaultOSProviders() | ||||||
| 	resource.SetDefaultRuntimeProviders() | 	resource.SetDefaultRuntimeProviders() | ||||||
| 	resource.SetDefaultUserProviders() | 	resource.SetDefaultUserProviders() | ||||||
|  | 	resource.SetDefaultOSDescriptionProvider() | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestWithProcessFuncs(t *testing.T) { | func TestWithProcessFuncs(t *testing.T) { | ||||||
| @@ -116,7 +117,7 @@ func TestWithProcessFuncs(t *testing.T) { | |||||||
| 	t.Run("WithRuntimeDescription", testWithProcessRuntimeDescription) | 	t.Run("WithRuntimeDescription", testWithProcessRuntimeDescription) | ||||||
| 	t.Run("WithProcess", testWithProcess) | 	t.Run("WithProcess", testWithProcess) | ||||||
|  |  | ||||||
| 	restoreProcessAttributesProviders() | 	restoreAttributesProviders() | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestWithProcessFuncsErrors(t *testing.T) { | func TestWithProcessFuncsErrors(t *testing.T) { | ||||||
| @@ -125,7 +126,7 @@ func TestWithProcessFuncsErrors(t *testing.T) { | |||||||
| 	t.Run("WithPID", testWithProcessExecutablePathError) | 	t.Run("WithPID", testWithProcessExecutablePathError) | ||||||
| 	t.Run("WithExecutableName", testWithProcessOwnerError) | 	t.Run("WithExecutableName", testWithProcessOwnerError) | ||||||
|  |  | ||||||
| 	restoreProcessAttributesProviders() | 	restoreAttributesProviders() | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestCommandArgs(t *testing.T) { | func TestCommandArgs(t *testing.T) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user