Needed for Kubernetes compatibility.
Kubernetes doesn't publish DNS records for pods. So the runtime can no longer assume that A/AAAA records exist for the host.
As a first step we need to be able to detect the hostname and kubernetes domain name. K8s is pretty good about populating `/etc/hosts` and `/etc/resolv.conf`, so we parse those when k8s is detected.
github.com/google/go-attestation v0.4.3
github.com/google/go-tpm v0.3.3 // indirect
github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad // indirect
- golang.org/x/crypto v0.23.0 // indirect
- golang.org/x/sys v0.20.0
+ golang.org/x/crypto v0.25.0 // indirect
+ golang.org/x/sys v0.22.0
)
require (
github.com/ThalesIgnite/crypto11 v1.2.5
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/distribution/distribution/v3 v3.0.0-20230621170613-87b280718d38
- github.com/eclipse/paho.mqtt.golang v1.4.2
+ github.com/eclipse/paho.mqtt.golang v1.5.0
github.com/go-kit/log v0.2.1
github.com/godbus/dbus/v5 v5.1.0
- github.com/gorilla/websocket v1.5.0
+ github.com/gorilla/websocket v1.5.3
github.com/hashicorp/golang-lru v0.5.4
github.com/keybase/go-keychain v0.0.0-20230523030712-b5615109f100
github.com/mdlayher/apcupsd v0.0.0-20230802135538-48f5030bcd58
go.fuhry.dev/grpc-quic v0.1.2
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d
golang.org/x/sync v0.7.0
- golang.org/x/term v0.20.0
+ golang.org/x/term v0.22.0
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
go.uber.org/mock v0.3.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
- golang.org/x/tools v0.21.0 // indirect
+ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
go.uber.org/atomic v1.11.0
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
- golang.org/x/net v0.25.0 // indirect
- golang.org/x/text v0.15.0
+ golang.org/x/net v0.27.0 // indirect
+ golang.org/x/text v0.16.0
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.34.1
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/eclipse/paho.mqtt.golang v1.4.2 h1:66wOzfUHSSI1zamx7jR6yMEI5EuHnT1G6rNA5PM12m4=
-github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA=
+github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
+github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
-github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
+golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
+golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
+golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
+golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
-golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
"github.com/miekg/dns"
"go.fuhry.dev/runtime/utils/fsutil"
+ "go.fuhry.dev/runtime/utils/hostname"
"go.fuhry.dev/runtime/utils/log"
)
Mask: net.CIDRMask(64, 128),
}
-func ResolveDualStack(hostname string) (string, string, error) {
+func ResolveDualStack(name string) (string, string, error) {
var msg *dns.Msg
var err error
}
})
- hostname = dns.Fqdn(hostname)
+ name = dns.Fqdn(name)
- if entry, ok := dnsCache.Get(hostname); ok {
+ if entry, ok := dnsCache.Get(name); ok {
if msg, ok = entry.(*dns.Msg); !ok {
return "", "", fmt.Errorf("lru cache is corrupt: expected entry to be *dns.Msg, got %T", entry)
}
- log.V(3).Debugf("cache hit for hostname %q: %+v", hostname, entry)
+ log.V(3).Debugf("cache hit for hostname %q: %+v", name, entry)
} else {
- msg, err = doDualStackQuery(hostname)
- if err != nil {
- return "", "", err
+ if name == hostname.Fqdn()+"." {
+ log.V(3).Debugf("requested name %q matches our own FQDN, checking /etc/hosts", name)
+ if nonlocal := queryHostsForNonlocalIPs(); nonlocal != nil {
+ msg = &dns.Msg{
+ Answer: nonlocal,
+ }
+ }
+ }
+ if msg == nil {
+ msg, err = doDualStackQuery(name)
+ if err != nil {
+ return "", "", err
+ }
}
- dnsCache.Add(hostname, msg)
+ dnsCache.Add(name, msg)
}
var (
if ip4 == "" && ip6 == "" {
return "", "", fmt.Errorf(
"did not receive any valid, non-loopback/local-scope answers for %q",
- hostname,
+ name,
)
}
},
}
}
+
+func queryHostsForNonlocalIPs() []dns.RR {
+ ips, _ := QueryHosts(hostname.Hostname())
+ ipsLong, _ := QueryHosts(hostname.Fqdn())
+ ips = append(ips, ipsLong...)
+ var nonlocal []dns.RR
+
+ if len(ips) > 0 {
+ for _, ip := range ips {
+ if ip4 := ip.To4(); ip4 != nil {
+ if !loopbackIPv4.Contains(ip4) && !autoPrivateIPv4.Contains(ip4) {
+ log.V(3).Debugf("found IPv4 in /etc/hosts: %s", ip4)
+ nonlocal = append(nonlocal, &dns.A{
+ A: ip4,
+ })
+ } else {
+ log.V(3).Debugf("rejecting loopback or auto-private IPv4 IP in /etc/hosts: %s", ip4)
+ }
+ } else {
+ if !ip.IsLoopback() && !localIPv6.Contains(ip) {
+ log.V(3).Debugf("found IPv6 in /etc/hosts: %s", ip)
+ nonlocal = append(nonlocal, &dns.AAAA{
+ AAAA: ip,
+ })
+ } else {
+ log.V(3).Debugf("rejecting loopback or link-local IPv6 IP in /etc/hosts: %s", ip)
+ }
+ }
+ }
+ }
+
+ return nonlocal
+}
--- /dev/null
+package dns
+
+import (
+ "fmt"
+ "net"
+ "os"
+ "regexp"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+type HostsEntry struct {
+ IP net.IP
+ HostNames []string
+}
+
+var spaceExp = regexp.MustCompile(`\s+`)
+var hashCommentExp = regexp.MustCompile(`#.*$`)
+
+var hosts []*HostsEntry
+var parseHostsOnce sync.Once
+
+func ParseHosts() (_ []*HostsEntry, err error) {
+ parseHostsOnce.Do(func() {
+ hosts, err = parseHosts()
+ })
+ if err != nil {
+ parseHostsOnce = sync.Once{}
+ return nil, err
+ }
+ return hosts, nil
+}
+
+func parseHosts() ([]*HostsEntry, error) {
+ hostsPath := "/etc/hosts"
+ if runtime.GOOS == "win32" {
+ hostsPath = fmt.Sprintf(`%s\system32\drivers\etc\hosts`, os.Getenv("SystemRoot"))
+ }
+
+ contents, err := os.ReadFile(hostsPath)
+ if err != nil {
+ return nil, err
+ }
+
+ lines := strings.Split(strings.ReplaceAll(string(contents), "\r\n", "\n"), "\n")
+
+ var entries []*HostsEntry
+ for _, line := range lines {
+ line = hashCommentExp.ReplaceAllLiteralString(line, "")
+ words := spaceExp.Split(line, -1)
+ if len(words) < 2 {
+ continue
+ }
+
+ ip := net.ParseIP(words[0])
+ if ip == nil {
+ continue
+ }
+
+ entry := &HostsEntry{
+ IP: ip,
+ HostNames: words[1:],
+ }
+
+ entries = append(entries, entry)
+ }
+
+ return entries, nil
+}
+
+func QueryHosts(name string) ([]net.IP, error) {
+ hosts, err := ParseHosts()
+ if err != nil {
+ return nil, err
+ }
+
+ name = strings.TrimSuffix(strings.ToLower(name), ".")
+ var ips []net.IP
+
+ for _, entry := range hosts {
+ for _, n := range entry.HostNames {
+ n = strings.ToLower(n)
+ if n == name || n == name+"." {
+ ips = append(ips, entry.IP)
+ }
+ }
+ }
+
+ return ips, nil
+}
--- /dev/null
+package hostname
+
+type ContainerType uint
+
+const (
+ ContainerUnknown ContainerType = iota
+ ContainerNone
+ ContainerSystemdNspawn
+ ContainerDocker
+ ContainerKubernetes
+)
+
+func (c ContainerType) String() string {
+ switch c {
+ case ContainerNone:
+ return "metal"
+ case ContainerSystemdNspawn:
+ return "systemd-nspawn"
+ case ContainerDocker:
+ return "docker"
+ case ContainerKubernetes:
+ return "kubernetes"
+ }
+ return "unknown"
+}
panic("fqdn is not implemented on your platform (" + runtime.GOOS + ")")
return ""
}
+
+func Containerization() ContainerType {
+ return ContainerNone
+}
import (
"fmt"
+ "os"
+ "regexp"
"strings"
"sync"
"syscall"
+
+ "go.fuhry.dev/runtime/utils/fsutil"
+ "go.fuhry.dev/runtime/utils/log"
)
type i8 = interface {
var utsname syscall.Utsname
var utsnameOnce sync.Once
+var spaceExp = regexp.MustCompile(`\s+`)
+var hashCommentExp = regexp.MustCompile(`#.*$`)
func Hostname() string {
return strings.Split(nodeName(), ".")[0]
}
}
+ if c := Containerization(); c == ContainerKubernetes {
+ if d := domainNameFromResolvConf(); d != "" {
+ return d
+ }
+ }
+
err := fmt.Errorf(
"could not determine domain name from (uname.Nodename=%v) (uname.Domainname=%v)",
int8ToString(uname.Nodename),
panic(err)
}
+func domainNameFromResolvConf() string {
+ contents, err := os.ReadFile("/etc/resolv.conf")
+ if err != nil {
+ return ""
+ }
+
+ lines := strings.Split(strings.ReplaceAll(string(contents), "\r\n", "\n"), "\n")
+
+ for _, line := range lines {
+ line = hashCommentExp.ReplaceAllLiteralString(line, "")
+ words := spaceExp.Split(line, -1)
+ if len(words) < 2 {
+ continue
+ }
+ if words[0] != "search" {
+ continue
+ }
+
+ shortestDomain := words[1]
+ for i := 1; i < len(words); i++ {
+ if len(words[i]) < len(shortestDomain) {
+ shortestDomain = words[i]
+ }
+ }
+
+ return shortestDomain
+ }
+
+ return ""
+}
+
func RegionName() string {
domain := DomainName()
return strings.Join([]string{Hostname(), DomainName()}, ".")
}
+func Containerization() ContainerType {
+ c := containerization()
+ log.Default().Infof("Detected container type: %s", c)
+
+ return c
+}
+
+func containerization() ContainerType {
+ if v := os.Getenv("KUBERNETES_SERVICE_HOST"); v != "" {
+ return ContainerKubernetes
+ }
+ if err := fsutil.FileExistsAndIsReadable("/.dockerenv"); err == nil {
+ return ContainerDocker
+ }
+ if c, err := os.ReadFile("/run/host/container-manager"); err == nil {
+ container := strings.Trim(string(c), "\r\n ")
+ switch container {
+ case "systemd-nspawn":
+ return ContainerSystemdNspawn
+ default:
+ return ContainerUnknown
+ }
+ }
+ return ContainerNone
+}
+
func uname() syscall.Utsname {
utsnameOnce.Do(func() {
err := syscall.Uname(&utsname)