diff --git a/.changelog/236.txt b/.changelog/236.txt new file mode 100644 index 0000000..9d4ece1 --- /dev/null +++ b/.changelog/236.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +Allow to choose hostname and FQDN to be lowercased or not +``` diff --git a/providers/aix/host_aix_ppc64.go b/providers/aix/host_aix_ppc64.go index 9af09e5..9be0b04 100644 --- a/providers/aix/host_aix_ppc64.go +++ b/providers/aix/host_aix_ppc64.go @@ -34,9 +34,11 @@ import ( "errors" "fmt" "os" + "strings" "time" "github.com/elastic/go-sysinfo/internal/registry" + "github.com/elastic/go-sysinfo/providers" "github.com/elastic/go-sysinfo/providers/shared" "github.com/elastic/go-sysinfo/types" ) @@ -190,6 +192,10 @@ func (r *reader) hostname(h *host) { if r.addErr(err) { return } + + if providers.LowercaseHostname() { + v = strings.ToLower(v) + } h.info.Hostname = v } diff --git a/providers/darwin/host_darwin.go b/providers/darwin/host_darwin.go index 8b53eee..b3259b3 100644 --- a/providers/darwin/host_darwin.go +++ b/providers/darwin/host_darwin.go @@ -24,9 +24,11 @@ import ( "errors" "fmt" "os" + "strings" "time" "github.com/elastic/go-sysinfo/internal/registry" + "github.com/elastic/go-sysinfo/providers" "github.com/elastic/go-sysinfo/providers/shared" "github.com/elastic/go-sysinfo/types" ) @@ -225,6 +227,10 @@ func (r *reader) hostname(h *host) { if r.addErr(err) { return } + + if providers.LowercaseHostname() { + v = strings.ToLower(v) + } h.info.Hostname = v } diff --git a/providers/doc.go b/providers/doc.go new file mode 100644 index 0000000..9ec0afe --- /dev/null +++ b/providers/doc.go @@ -0,0 +1,30 @@ +// 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. + +// Package providers +// +// # Hostname Behavior +// +// Starting from version v1.11.0, the host provider started automatically +// lowercasing hostnames. This behavior was reverted in v1.14.1. +// +// To provide flexibility and allow users to control this behavior, the +// `LowercaseHostname` and `SetLowerHostname` functions were added. +// +// By default, hostnames are not lowercased. If you require hostnames to be +// lowercased, explicitly set this using `SetLowerHostname(true)`. +package providers diff --git a/providers/linux/host_linux.go b/providers/linux/host_linux.go index 24e72d0..152b77c 100644 --- a/providers/linux/host_linux.go +++ b/providers/linux/host_linux.go @@ -23,11 +23,13 @@ import ( "fmt" "os" "path/filepath" + "strings" "time" "github.com/prometheus/procfs" "github.com/elastic/go-sysinfo/internal/registry" + "github.com/elastic/go-sysinfo/providers" "github.com/elastic/go-sysinfo/providers/shared" "github.com/elastic/go-sysinfo/types" ) @@ -176,7 +178,8 @@ func newHost(fs procFS) (*host, error) { } type reader struct { - errs []error + errs []error + lowerHostname bool } func (r *reader) addErr(err error) bool { @@ -233,6 +236,10 @@ func (r *reader) hostname(h *host) { if r.addErr(err) { return } + + if providers.LowercaseHostname() { + v = strings.ToLower(v) + } h.info.Hostname = v } diff --git a/providers/lowerhostname.go b/providers/lowerhostname.go new file mode 100644 index 0000000..6612b10 --- /dev/null +++ b/providers/lowerhostname.go @@ -0,0 +1,34 @@ +// 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. + +package providers + +import "sync/atomic" + +var lowerHostname atomic.Bool + +// LowercaseHostname returns if the hostname should be lowercased or not. +func LowercaseHostname() bool { + return lowerHostname.Load() +} + +// SetLowerHostname instruct the host provider to lowercase the hostname. +// The LowercaseHostname and SetLowerHostname exist as a fix to allow the user +// to choose or not this behaviour introduced on v1.11.0 and reverted on v1.14.1. +func SetLowerHostname(lower bool) { + lowerHostname.Store(lower) +} diff --git a/providers/shared/fqdn.go b/providers/shared/fqdn.go index b8bb455..e257999 100644 --- a/providers/shared/fqdn.go +++ b/providers/shared/fqdn.go @@ -25,6 +25,8 @@ import ( "net" "os" "strings" + + "github.com/elastic/go-sysinfo/providers" ) // FQDNWithContext attempts to lookup the host's fully-qualified domain name and returns it. @@ -67,6 +69,10 @@ func fqdn(ctx context.Context, hostname string) (string, error) { if cname != "" { cname = strings.TrimSuffix(cname, ".") + if providers.LowercaseHostname() { + return strings.ToLower(cname), nil + } + // Go might lowercase the cname "for convenience". Therefore, if cname // is the same as hostname, return hostname as is. // See https://github.com/golang/go/blob/go1.22.5/src/net/hosts.go#L38 diff --git a/providers/shared/fqdn_test.go b/providers/shared/fqdn_test.go index ffddd5a..c5ac4a0 100644 --- a/providers/shared/fqdn_test.go +++ b/providers/shared/fqdn_test.go @@ -26,14 +26,22 @@ import ( "time" "github.com/stretchr/testify/require" + + "github.com/elastic/go-sysinfo/providers" ) func TestFQDN(t *testing.T) { + lowercaseHostname := providers.LowercaseHostname() + defer func() { + providers.SetLowerHostname(lowercaseHostname) + }() + tests := map[string]struct { - osHostname string - expectedFQDN string - expectedErrRegex string - timeout time.Duration + lowercaseHostname bool + osHostname string + expectedFQDN string + expectedErrRegex string + timeout time.Duration }{ // This test case depends on network, particularly DNS, // being available. If it starts to fail often enough @@ -59,6 +67,12 @@ func TestFQDN(t *testing.T) { expectedFQDN: "eLaSTic.co", expectedErrRegex: "", }, + "long_mixed_case_hostname_lowercaseHostname": { + lowercaseHostname: true, + osHostname: "eLaSTic.co", + expectedFQDN: "elastic.co", + expectedErrRegex: "", + }, "nonexistent_timeout": { osHostname: "foobarbaz", expectedFQDN: "", @@ -77,6 +91,7 @@ func TestFQDN(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() + providers.SetLowerHostname(test.lowercaseHostname) actualFQDN, err := fqdn(ctx, test.osHostname) require.Equal(t, test.expectedFQDN, actualFQDN) diff --git a/providers/windows/host_windows.go b/providers/windows/host_windows.go index ed94881..c90bced 100644 --- a/providers/windows/host_windows.go +++ b/providers/windows/host_windows.go @@ -28,9 +28,10 @@ import ( stdwindows "golang.org/x/sys/windows" - windows "github.com/elastic/go-windows" + "github.com/elastic/go-windows" "github.com/elastic/go-sysinfo/internal/registry" + "github.com/elastic/go-sysinfo/providers" "github.com/elastic/go-sysinfo/providers/shared" "github.com/elastic/go-sysinfo/types" ) @@ -161,6 +162,10 @@ func (r *reader) hostname(h *host) { if r.addErr(err) { return } + + if providers.LowercaseHostname() { + v = strings.ToLower(v) + } h.info.Hostname = v }