Repository: elastic/go-sysinfo
Pull request #153 (2023-02-25 01:46:50)

Bump golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/golang/net/commits/v0.7.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/net&package-manager=go_modules&previous-version=0.0.0-20220722155237-a158d28d115b&new-version=0.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language
- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language
- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language
- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/elastic/go-sysinfo/network/alerts).

</details>

elasticmachine: 
## :green_heart: Build Succeeded


<!-- BUILD BADGES-->
> _the below badges are clickable and redirect to their specific view in the CI or DOCS_
[![Pipeline View](https://img.shields.io/badge/pipeline-pipeline%20-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-153/detail/PR-153/1//pipeline) [![Test View](https://img.shields.io/badge/test-test-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-153/detail/PR-153/1//tests) [![Changes](https://img.shields.io/badge/changes-changes-green)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-153/detail/PR-153/1//changes) [![Artifacts](https://img.shields.io/badge/artifacts-artifacts-yellow)](https://beats-ci.elastic.co/blue/organizations/jenkins/Library%2Fgo-sysinfo-mbp%2FPR-153/detail/PR-153/1//artifacts) [![preview](https://img.shields.io/badge/docs-preview-yellowgreen)](http://go-sysinfo_153.docs-preview.app.elstc.co/diff)  [![preview](https://img.shields.io/badge/elastic-observability-blue)](https://ci-stats.elastic.co/app/apm/services/beats-ci/transactions/view?rangeFrom=2023-02-25T01:37:05.138Z&rangeTo=2023-02-25T01:57:05.138Z&transactionName=BUILD+Library%2Fgo-sysinfo-mbp%2FPR-%7Bnumber%7D&transactionType=job&latencyAggregationType=avg&traceId=0f360c527379f62af553c88aef42e4c2&transactionId=769acd05eb6d4a39)

<!-- BUILD SUMMARY-->
<details><summary>Expand to view the summary</summary>
<p>

#### Build stats




* Start Time: 2023-02-25T01:47:05.138+0000


* Duration: 8 min 59 sec




#### Test stats :test_tube:

| Test         | Results                         |
| ------------ | :-----------------------------: |
| Failed       | 0  |
| Passed       | 256  |
| Skipped      | 4 |
| Total        | 260   |


</p>
</details>

<!-- TEST RESULTS IF ANY-->


<!-- STEPS ERRORS IF ANY -->















</p>
</details>

<!--COMMENT_GENERATED_WITH_ID_comment.id-->

Patch:
diff --git a/go.mod b/go.mod
index fe11aba..c3a08f2 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901
 	github.com/prometheus/procfs v0.8.0
 	github.com/stretchr/testify v1.7.0
-	golang.org/x/sys v0.1.0
+	golang.org/x/sys v0.5.0
 	howett.net/plist v0.0.0-20181124034731-591f970eefbb
 )
 
@@ -27,7 +27,7 @@ require (
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/sirupsen/logrus v1.9.0 // indirect
 	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
-	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+	golang.org/x/net v0.7.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/tools v0.1.12 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
diff --git a/go.sum b/go.sum
index 7a2f58c..01e7d03 100644
--- a/go.sum
+++ b/go.sum
@@ -62,8 +62,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -72,8 +72,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 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/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
diff --git a/providers/darwin/host_darwin.go b/providers/darwin/host_darwin.go
index 5add2fd..a3a45b6 100644
--- a/providers/darwin/host_darwin.go
+++ b/providers/darwin/host_darwin.go
@@ -139,6 +139,10 @@ func (h *host) Memory() (*types.HostMemoryInfo, error) {
 	return &mem, nil
 }
 
+func (h *host) FQDN() (string, error) {
+	return shared.FQDN()
+}
+
 func (h *host) LoadAverage() (*types.LoadAverageInfo, error) {
 	load, err := getLoadAverage()
 	if err != nil {
@@ -160,7 +164,6 @@ func newHost() (*host, error) {
 	r.architecture(h)
 	r.bootTime(h)
 	r.hostname(h)
-	r.fqdn(h)
 	r.network(h)
 	r.kernelVersion(h)
 	r.os(h)
@@ -214,14 +217,6 @@ func (r *reader) hostname(h *host) {
 	h.info.Hostname = v
 }
 
-func (r *reader) fqdn(h *host) {
-	v, err := shared.FQDN()
-	if r.addErr(err) {
-		return
-	}
-
-	h.info.FQDN = v
-}
 func (r *reader) network(h *host) {
 	ips, macs, err := shared.Network()
 	if r.addErr(err) {
diff --git a/providers/linux/host_linux.go b/providers/linux/host_linux.go
index 7361559..c7dffce 100644
--- a/providers/linux/host_linux.go
+++ b/providers/linux/host_linux.go
@@ -72,6 +72,10 @@ func (h *host) Memory() (*types.HostMemoryInfo, error) {
 	return parseMemInfo(content)
 }
 
+func (h *host) FQDN() (string, error) {
+	return shared.FQDN()
+}
+
 // VMStat reports data from /proc/vmstat on linux.
 func (h *host) VMStat() (*types.VMStatInfo, error) {
 	content, err := ioutil.ReadFile(h.procFS.path("vmstat"))
@@ -149,7 +153,6 @@ func newHost(fs procFS) (*host, error) {
 	r.bootTime(h)
 	r.containerized(h)
 	r.hostname(h)
-	r.fqdn(h)
 	r.network(h)
 	r.kernelVersion(h)
 	r.os(h)
@@ -212,15 +215,6 @@ func (r *reader) hostname(h *host) {
 	h.info.Hostname = v
 }
 
-func (r *reader) fqdn(h *host) {
-	v, err := shared.FQDN()
-	if r.addErr(err) {
-		return
-	}
-
-	h.info.FQDN = v
-}
-
 func (r *reader) network(h *host) {
 	ips, macs, err := shared.Network()
 	if r.addErr(err) {
diff --git a/providers/shared/fqdn.go b/providers/shared/fqdn.go
index 387fda7..c4dabd1 100644
--- a/providers/shared/fqdn.go
+++ b/providers/shared/fqdn.go
@@ -26,12 +26,30 @@ import (
 	"strings"
 )
 
+// FQDN attempts to lookup the host's fully-qualified domain name and returns it.
+// It does so using the following algorithm:
+//
+//  1. It gets the hostname from the OS. If this step fails, it returns an error.
+//
+//  2. It tries to perform a CNAME DNS lookup for the hostname. If this succeeds, it
+//     returns the CNAME (after trimming any trailing period) as the FQDN.
+//
+//  3. It tries to perform an IP lookup for the hostname. If this succeeds, it tries
+//     to perform a reverse DNS lookup on the returned IPs and returns the first
+//     successful result (after trimming any trailing period) as the FQDN.
+//
+//  4. If steps 2 and 3 both fail, an empty string is returned as the FQDN along with
+//     errors from those steps.
 func FQDN() (string, error) {
 	hostname, err := os.Hostname()
 	if err != nil {
 		return "", fmt.Errorf("could not get hostname to look for FQDN: %w", err)
 	}
 
+	return fqdn(hostname)
+}
+
+func fqdn(hostname string) (string, error) {
 	var errs error
 	cname, err := net.LookupCNAME(hostname)
 	if err != nil {
diff --git a/providers/windows/host_windows.go b/providers/windows/host_windows.go
index 015f37e..604c84d 100644
--- a/providers/windows/host_windows.go
+++ b/providers/windows/host_windows.go
@@ -84,13 +84,21 @@ func (h *host) Memory() (*types.HostMemoryInfo, error) {
 	}, nil
 }
 
+func (h *host) FQDN() (string, error) {
+	fqdn, err := getComputerNameEx(stdwindows.ComputerNamePhysicalDnsFullyQualified)
+	if err != nil {
+		return "", fmt.Errorf("could not get windows FQDN: %s", err)
+	}
+
+	return strings.TrimSuffix(fqdn, "."), nil
+}
+
 func newHost() (*host, error) {
 	h := &host{}
 	r := &reader{}
 	r.architecture(h)
 	r.bootTime(h)
 	r.hostname(h)
-	r.fqdn(h)
 	r.network(h)
 	r.kernelVersion(h)
 	r.os(h)
@@ -144,17 +152,6 @@ func (r *reader) hostname(h *host) {
 	h.info.Hostname = v
 }
 
-func (r *reader) fqdn(h *host) {
-	fqdn, err := getComputerNameEx(
-		stdwindows.ComputerNamePhysicalDnsFullyQualified)
-	if err != nil {
-		r.addErr(fmt.Errorf("could not get windows FQDN: %s", err))
-		return
-	}
-
-	h.info.FQDN = strings.TrimSuffix(fqdn, ".")
-}
-
 func getComputerNameEx(name uint32) (string, error) {
 	size := uint32(64)
 
diff --git a/types/host.go b/types/host.go
index ee8a07b..2d8f0fd 100644
--- a/types/host.go
+++ b/types/host.go
@@ -26,6 +26,7 @@ type Host interface {
 	CPUTimer
 	Info() HostInfo
 	Memory() (*HostMemoryInfo, error)
+	FQDN() (string, error)
 }
 
 // NetworkCounters represents network stats from /proc/net
@@ -67,14 +68,13 @@ type HostInfo struct {
 	BootTime          time.Time `json:"boot_time"`               // Host boot time.
 	Containerized     *bool     `json:"containerized,omitempty"` // Is the process containerized.
 	Hostname          string    `json:"name"`                    // Hostname
-	FQDN              string    `json:"fqdn"`
-	IPs               []string  `json:"ip,omitempty"`        // List of all IPs.
-	KernelVersion     string    `json:"kernel_version"`      // Kernel version.
-	MACs              []string  `json:"mac"`                 // List of MAC addresses.
-	OS                *OSInfo   `json:"os"`                  // OS information.
-	Timezone          string    `json:"timezone"`            // System timezone.
-	TimezoneOffsetSec int       `json:"timezone_offset_sec"` // Timezone offset (seconds from UTC).
-	UniqueID          string    `json:"id,omitempty"`        // Unique ID of the host (optional).
+	IPs               []string  `json:"ip,omitempty"`            // List of all IPs.
+	KernelVersion     string    `json:"kernel_version"`          // Kernel version.
+	MACs              []string  `json:"mac"`                     // List of MAC addresses.
+	OS                *OSInfo   `json:"os"`                      // OS information.
+	Timezone          string    `json:"timezone"`                // System timezone.
+	TimezoneOffsetSec int       `json:"timezone_offset_sec"`     // Timezone offset (seconds from UTC).
+	UniqueID          string    `json:"id,omitempty"`            // Unique ID of the host (optional).
 }
 
 // Uptime returns the system uptime


Test patch:
diff --git a/providers/linux/host_fqdn_integration_docker_linux_test.go b/providers/linux/host_fqdn_integration_docker_linux_test.go
index 135f2d6..cbb25c9 100644
--- a/providers/linux/host_fqdn_integration_docker_linux_test.go
+++ b/providers/linux/host_fqdn_integration_docker_linux_test.go
@@ -22,6 +22,8 @@ package linux
 import (
 	"fmt"
 	"testing"
+
+	"github.com/stretchr/testify/require"
 )
 
 func TestHost_FQDN_set(t *testing.T) {
@@ -30,9 +32,10 @@ func TestHost_FQDN_set(t *testing.T) {
 		t.Fatal(fmt.Errorf("could not get host information: %w", err))
 	}
 
-	got := host.Info()
-	if got.FQDN != wantFQDN {
-		t.Errorf("got FQDN %q, want: %q", got.FQDN, wantFQDN)
+	gotFQDN, err := host.FQDN()
+	require.NoError(t, err)
+	if gotFQDN != wantFQDN {
+		t.Errorf("got FQDN %q, want: %q", gotFQDN, wantFQDN)
 	}
 }
 
@@ -42,8 +45,10 @@ func TestHost_FQDN_not_set(t *testing.T) {
 		t.Fatal(fmt.Errorf("could not get host information: %w", err))
 	}
 
-	got := host.Info()
-	if got.Hostname != got.FQDN {
-		t.Errorf("name and FQDN should be the same but hostname: %s, FQDN %s", got.Hostname, got.FQDN)
+	gotFQDN, err := host.FQDN()
+	require.NoError(t, err)
+	hostname := host.Info().Hostname
+	if gotFQDN != hostname {
+		t.Errorf("name and FQDN should be the same but hostname: %s, FQDN %s", hostname, gotFQDN)
 	}
 }
diff --git a/providers/shared/fqdn_test.go b/providers/shared/fqdn_test.go
new file mode 100644
index 0000000..23a9450
--- /dev/null
+++ b/providers/shared/fqdn_test.go
@@ -0,0 +1,78 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you 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.
+
+//go:build linux || darwin
+
+package shared
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestFQDN(t *testing.T) {
+	tests := map[string]struct {
+		osHostname       string
+		expectedFQDN     string
+		expectedErrRegex string
+	}{
+		// This test case depends on network, particularly DNS,
+		// being available.  If it starts to fail often enough
+		// due to occasional network/DNS unavailability, we should
+		// probably just delete this test case.
+		"long_real_hostname": {
+			osHostname:       "elastic.co",
+			expectedFQDN:     "elastic.co",
+			expectedErrRegex: "",
+		},
+		"long_nonexistent_hostname": {
+			osHostname:       "foo.bar.elastic.co",
+			expectedFQDN:     "",
+			expectedErrRegex: makeErrorRegex("foo.bar.elastic.co"),
+		},
+		"short_nonexistent_hostname": {
+			osHostname:       "foobarbaz",
+			expectedFQDN:     "",
+			expectedErrRegex: makeErrorRegex("foobarbaz"),
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			actualFQDN, err := fqdn(test.osHostname)
+			require.Equal(t, test.expectedFQDN, actualFQDN)
+
+			if test.expectedErrRegex == "" {
+				require.Nil(t, err)
+			} else {
+				require.Regexp(t, test.expectedErrRegex, err.Error())
+			}
+		})
+	}
+}
+
+func makeErrorRegex(osHostname string) string {
+	return fmt.Sprintf(
+		"could not get FQDN, all methods failed: "+
+			"failed looking up CNAME: lookup %s.*: "+
+			"failed looking up IP: lookup %s.*",
+		osHostname,
+		osHostname,
+	)
+}