From: Dan Fuhry Date: Sat, 14 Mar 2026 23:11:19 +0000 (-0400) Subject: [utils/hostname] add CgroupInfoSelf and IsLikelyUserMachine, w/ tests X-Git-Url: https://go.fuhry.dev/?a=commitdiff_plain;h=759bd962178b3ef2cd2a993f5c253b91faee34d4;p=runtime.git [utils/hostname] add CgroupInfoSelf and IsLikelyUserMachine, w/ tests --- diff --git a/utils/hostname/BUILD.bazel b/utils/hostname/BUILD.bazel index 886070e..36f467d 100644 --- a/utils/hostname/BUILD.bazel +++ b/utils/hostname/BUILD.bazel @@ -1,4 +1,4 @@ -load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "hostname", @@ -12,17 +12,18 @@ go_library( ], importpath = "go.fuhry.dev/runtime/utils/hostname", visibility = ["//visibility:public"], - deps = select({ + deps = [ + "//utils/log", + ] + select({ "@rules_go//go/platform:aix": [ "//constants", ], "@rules_go//go/platform:android": [ + "//constants", "//utils/fsutil", - "//utils/log", ], "@rules_go//go/platform:darwin": [ "//constants", - "//utils/log", "@net_howett_plist//:plist", ], "@rules_go//go/platform:dragonfly": [ @@ -36,22 +37,20 @@ go_library( ], "@rules_go//go/platform:ios": [ "//constants", - "//utils/log", "@net_howett_plist//:plist", ], "@rules_go//go/platform:js": [ "//constants", ], "@rules_go//go/platform:linux": [ + "//constants", "//utils/fsutil", - "//utils/log", ], "@rules_go//go/platform:netbsd": [ "//constants", ], "@rules_go//go/platform:openbsd": [ "//constants", - "//utils/log", ], "@rules_go//go/platform:osx": [ "//constants", @@ -71,3 +70,10 @@ go_library( "//conditions:default": [], }), ) + +go_test( + name = "hostname_test", + srcs = ["hostname_test.go"], + embed = [":hostname"], + deps = ["@com_github_stretchr_testify//assert"], +) diff --git a/utils/hostname/hostname_common.go b/utils/hostname/hostname_common.go index 86e21dd..60a0d0f 100644 --- a/utils/hostname/hostname_common.go +++ b/utils/hostname/hostname_common.go @@ -1,7 +1,24 @@ package hostname +import ( + "errors" + "os" + "regexp" + "runtime" + "strings" + "sync" + + "go.fuhry.dev/runtime/utils/log" +) + type ContainerType uint +type CgroupInfo struct { + HierarchyID uint + ControllerList []string + Path string +} + const ( ContainerUnknown ContainerType = iota ContainerNone @@ -10,6 +27,13 @@ const ( ContainerKubernetes ) +var ( + ValidHostname = regexp.MustCompile(`^[A-Za-z0-9-]{1,64}$`) + ValidDomainName = regexp.MustCompile(`^[A-Za-z0-9-]{1,64}(\.[A-Za-z0-9-]{1,64}){0,5}$`) + + ErrCgroupsUnsupported = errors.New("cgroups are unsupported on "+runtime.GOOS) +) + func (c ContainerType) String() string { switch c { case ContainerNone: @@ -23,3 +47,33 @@ func (c ContainerType) String() string { } return "unknown" } + +var ( + isUserMachine bool + isUserMachineOnce sync.Once +) + +func IsLikelyUserMachine() bool { + isUserMachineOnce.Do(func() { + if cgroup, err := CgroupInfoSelf(); err == nil { + log.Default().V(1).Debugf("cgroup for current process: %v", cgroup) + } else { + log.Default().V(1).Debugf("error getting cgroup info: %v", err) + } + + isUserMachine = Containerization() == ContainerNone && + os.Geteuid() >= 500 && + (strings.HasPrefix(os.Getenv("HOME"), "/home/") || + strings.HasPrefix(os.Getenv("HOME"), "/Users/") || + runtime.GOOS == "win32" || + runtime.GOOS == "darwin") + + if isUserMachine { + log.Default().Info("Detected human-user environment") + } else { + log.Default().Info("Detected service/daemon environment") + } + }) + + return isUserMachine +} diff --git a/utils/hostname/hostname_generic.go b/utils/hostname/hostname_generic.go index 8796b22..6109d8e 100644 --- a/utils/hostname/hostname_generic.go +++ b/utils/hostname/hostname_generic.go @@ -12,3 +12,7 @@ func Fqdn() string { func Containerization() ContainerType { return ContainerNone } + +func CgroupInfoSelf() (*CgroupInfo, error) { + return nil, ErrCgroupsUnsupported +} diff --git a/utils/hostname/hostname_linux.go b/utils/hostname/hostname_linux.go index 50d0066..834a0fc 100644 --- a/utils/hostname/hostname_linux.go +++ b/utils/hostname/hostname_linux.go @@ -10,6 +10,7 @@ import ( "sync" "syscall" + "go.fuhry.dev/runtime/constants" "go.fuhry.dev/runtime/utils/fsutil" "go.fuhry.dev/runtime/utils/log" ) @@ -18,10 +19,12 @@ type i8 = interface { int8 | uint8 } -var utsname syscall.Utsname -var utsnameOnce sync.Once -var spaceExp = regexp.MustCompile(`\s+`) -var hashCommentExp = regexp.MustCompile(`#.*$`) +var ( + utsname syscall.Utsname + utsnameOnce sync.Once + spaceExp = regexp.MustCompile(`\s+`) + hashCommentExp = regexp.MustCompile(`#.*$`) +) func Hostname() string { return strings.Split(nodeName(), ".")[0] @@ -46,6 +49,8 @@ func DomainName() string { if d := domainNameFromResolvConf(); d != "" { return d } + } else if c == ContainerDocker { + return constants.DefaultHostDomain } err := fmt.Errorf( @@ -100,11 +105,18 @@ func Fqdn() string { return strings.Join([]string{Hostname(), DomainName()}, ".") } +var ( + containerType ContainerType + containerTypeOnce sync.Once +) + func Containerization() ContainerType { - c := containerization() - log.Default().Infof("Detected container type: %s", c) + containerTypeOnce.Do(func() { + containerType = containerization() + log.Default().Infof("Detected container type: %s", containerType) + }) - return c + return containerType } func containerization() ContainerType { @@ -154,3 +166,7 @@ func int8ToString[T i8](ba [65]T) string { return string(bytes) } + +func CgroupInfoSelf() (*CgroupInfo, error) { + return nil, ErrCgroupsUnsupported +} diff --git a/utils/hostname/hostname_macos.go b/utils/hostname/hostname_macos.go index 721e718..d78da7a 100644 --- a/utils/hostname/hostname_macos.go +++ b/utils/hostname/hostname_macos.go @@ -127,3 +127,7 @@ func fqdnFromDns() (string, error) { return "", errors.New("failed to lookup any hostname for 127.0.0.1 that does not resolve to just \"localhost\"") } + +func CgroupInfoSelf() (*CgroupInfo, error) { + return nil, ErrCgroupsUnsupported +} diff --git a/utils/hostname/hostname_openbsd.go b/utils/hostname/hostname_openbsd.go index 75125a4..8ee8ac7 100644 --- a/utils/hostname/hostname_openbsd.go +++ b/utils/hostname/hostname_openbsd.go @@ -74,3 +74,7 @@ func fqdnFromDns() (string, error) { return "", errors.New("failed to lookup any hostname for 127.0.0.1 that does not resolve to just \"localhost\"") } + +func CgroupInfoSelf() (*CgroupInfo, error) { + return nil, ErrCgroupsUnsupported +}