mirror of https://github.com/minio/minio.git
Add support for DCOS host detection, improve Docker detection. (#4525)
isDocker was currently reading from `/proc/cgroup` file. But this file alone is rather not conclusive evidence. Docker internally has `.dockerenv` as a special file which we should use instead. Fixes #4456
This commit is contained in:
parent
6f4862659f
commit
b8463a738c
|
@ -138,11 +138,11 @@ func newApp(name string) *cli.App {
|
|||
|
||||
// Main main for minio server.
|
||||
func Main(args []string) {
|
||||
name := filepath.Base(args[0])
|
||||
app := newApp(name)
|
||||
// Set the minio app name.
|
||||
appName := filepath.Base(args[0])
|
||||
|
||||
// Run the app - exit on error.
|
||||
if err := app.Run(args); err != nil {
|
||||
if err := newApp(appName).Run(args); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -98,26 +97,41 @@ func GetCurrentReleaseTime() (releaseTime time.Time, err error) {
|
|||
return getCurrentReleaseTime(Version, os.Args[0])
|
||||
}
|
||||
|
||||
func isDocker(cgroupFile string) (bool, error) {
|
||||
cgroup, err := ioutil.ReadFile(cgroupFile)
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
// Check if we are indeed inside docker.
|
||||
// https://github.com/moby/moby/blob/master/daemon/initlayer/setup_unix.go#L25
|
||||
//
|
||||
// "/.dockerenv": "file",
|
||||
//
|
||||
func isDocker(dockerEnvFile string) (ok bool, err error) {
|
||||
_, err = os.Stat(dockerEnvFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
return bytes.Contains(cgroup, []byte("docker")), err
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// IsDocker - returns if the environment minio is running
|
||||
// is docker or not.
|
||||
func IsDocker() bool {
|
||||
found, err := isDocker("/proc/self/cgroup")
|
||||
fatalIf(err, "Error in docker check.")
|
||||
found, err := isDocker("/.dockerenv")
|
||||
// We don't need to fail for this check, log
|
||||
// an error and return false.
|
||||
errorIf(err, "Error in docker check.")
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
// IsKubernetes returns if the environment minio is
|
||||
// running is kubernetes or not.
|
||||
// IsDCOS returns true if minio is running in DCOS.
|
||||
func IsDCOS() bool {
|
||||
// http://mesos.apache.org/documentation/latest/docker-containerizer/
|
||||
// Mesos docker containerizer sets this value
|
||||
return os.Getenv("MESOS_CONTAINER_NAME") != ""
|
||||
}
|
||||
|
||||
// IsKubernetes returns true if minio is running in kubernetes.
|
||||
func IsKubernetes() bool {
|
||||
// Kubernetes env used to validate if we are
|
||||
// indeed running inside a kubernetes pod
|
||||
|
@ -139,7 +153,7 @@ func IsSourceBuild() bool {
|
|||
// DO NOT CHANGE USER AGENT STYLE.
|
||||
// The style should be
|
||||
//
|
||||
// Minio (<OS>; <ARCH>[; kubernetes][; docker][; source]) Minio/<VERSION> Minio/<RELEASE-TAG> Minio/<COMMIT-ID>
|
||||
// Minio (<OS>; <ARCH>[; dcos][; kubernetes][; docker][; source]) Minio/<VERSION> Minio/<RELEASE-TAG> Minio/<COMMIT-ID> [Minio/univers-<PACKAGE_NAME>]
|
||||
//
|
||||
// For any change here should be discussed by openning an issue at https://github.com/minio/minio/issues.
|
||||
func getUserAgent(mode string) string {
|
||||
|
@ -147,6 +161,9 @@ func getUserAgent(mode string) string {
|
|||
if mode != "" {
|
||||
userAgent += "; " + mode
|
||||
}
|
||||
if IsDCOS() {
|
||||
userAgent += "; dcos"
|
||||
}
|
||||
if IsKubernetes() {
|
||||
userAgent += "; kubernetes"
|
||||
}
|
||||
|
@ -156,8 +173,15 @@ func getUserAgent(mode string) string {
|
|||
if IsSourceBuild() {
|
||||
userAgent += "; source"
|
||||
}
|
||||
userAgent += ") " + " Minio/" + Version + " Minio/" + ReleaseTag + " Minio/" + CommitID
|
||||
|
||||
userAgent += ") Minio/" + Version + " Minio/" + ReleaseTag + " Minio/" + CommitID
|
||||
if IsDCOS() {
|
||||
universePkgVersion := os.Getenv("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION")
|
||||
// On DC/OS environment try to the get universe package version.
|
||||
if universePkgVersion != "" {
|
||||
userAgent += " Minio/" + "universe-" + universePkgVersion
|
||||
}
|
||||
}
|
||||
return userAgent
|
||||
}
|
||||
|
||||
|
@ -241,10 +265,21 @@ func getLatestReleaseTime(timeout time.Duration, mode string) (releaseTime time.
|
|||
return parseReleaseData(data)
|
||||
}
|
||||
|
||||
// Kubernetes deploy doc link.
|
||||
const kubernetesDeploymentDoc = "https://docs.minio.io/docs/deploy-minio-on-kubernetes"
|
||||
const (
|
||||
// Kubernetes deployment doc link.
|
||||
kubernetesDeploymentDoc = "https://docs.minio.io/docs/deploy-minio-on-kubernetes"
|
||||
|
||||
// Mesos deployment doc link.
|
||||
mesosDeploymentDoc = "https://docs.minio.io/docs/deploy-minio-on-dc-os"
|
||||
)
|
||||
|
||||
func getDownloadURL(buildDate time.Time) (downloadURL string) {
|
||||
// Check if we are in DCOS environment, return
|
||||
// deployment guide for update procedures.
|
||||
if IsDCOS() {
|
||||
return mesosDeploymentDoc
|
||||
}
|
||||
|
||||
// Check if we are in kubernetes environment, return
|
||||
// deployment guide for update procedures.
|
||||
if IsKubernetes() {
|
||||
|
|
|
@ -44,12 +44,18 @@ func TestDownloadURL(t *testing.T) {
|
|||
}
|
||||
|
||||
os.Setenv("KUBERNETES_SERVICE_HOST", "10.11.148.5")
|
||||
defer os.Unsetenv("KUBERNETES_SERVICE_HOST")
|
||||
|
||||
durl = getDownloadURL(minioVersion1)
|
||||
if durl != kubernetesDeploymentDoc {
|
||||
t.Errorf("Expected %s, got %s", kubernetesDeploymentDoc, durl)
|
||||
}
|
||||
os.Unsetenv("KUBERNETES_SERVICE_HOST")
|
||||
|
||||
os.Setenv("MESOS_CONTAINER_NAME", "mesos-1111")
|
||||
durl = getDownloadURL(minioVersion1)
|
||||
if durl != mesosDeploymentDoc {
|
||||
t.Errorf("Expected %s, got %s", mesosDeploymentDoc, durl)
|
||||
}
|
||||
os.Unsetenv("MESOS_CONTAINER_NAME")
|
||||
}
|
||||
|
||||
func TestGetCurrentReleaseTime(t *testing.T) {
|
||||
|
@ -158,6 +164,63 @@ func TestGetCurrentReleaseTime(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests user agent string.
|
||||
func TestUserAgent(t *testing.T) {
|
||||
testCases := []struct {
|
||||
envName string
|
||||
envValue string
|
||||
mode string
|
||||
expectedStr string
|
||||
}{
|
||||
{
|
||||
envName: "",
|
||||
envValue: "",
|
||||
mode: globalMinioModeFS,
|
||||
expectedStr: fmt.Sprintf("Minio (%s; %s; %s; source) Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeFS),
|
||||
},
|
||||
{
|
||||
envName: "MESOS_CONTAINER_NAME",
|
||||
envValue: "mesos-11111",
|
||||
mode: globalMinioModeXL,
|
||||
expectedStr: fmt.Sprintf("Minio (%s; %s; %s; %s; source) Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET Minio/universe-%s", runtime.GOOS, runtime.GOARCH, globalMinioModeXL, "dcos", "mesos-1111"),
|
||||
},
|
||||
{
|
||||
envName: "KUBERNETES_SERVICE_HOST",
|
||||
envValue: "10.11.148.5",
|
||||
mode: globalMinioModeXL,
|
||||
expectedStr: fmt.Sprintf("Minio (%s; %s; %s; %s; source) Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET Minio/DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeXL, "kubernetes"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
os.Setenv(testCase.envName, testCase.envValue)
|
||||
if testCase.envName == "MESOS_CONTAINER_NAME" {
|
||||
os.Setenv("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION", "mesos-1111")
|
||||
}
|
||||
str := getUserAgent(testCase.mode)
|
||||
if str != testCase.expectedStr {
|
||||
t.Errorf("Test %d: expected: %s, got: %s", i+1, testCase.expectedStr, str)
|
||||
}
|
||||
os.Unsetenv("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION")
|
||||
os.Unsetenv(testCase.envName)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests if the environment we are running is in DCOS.
|
||||
func TestIsDCOS(t *testing.T) {
|
||||
os.Setenv("MESOS_CONTAINER_NAME", "mesos-1111")
|
||||
dcos := IsDCOS()
|
||||
if !dcos {
|
||||
t.Fatalf("Expected %t, got %t", true, dcos)
|
||||
}
|
||||
|
||||
os.Unsetenv("MESOS_CONTAINER_NAME")
|
||||
dcos = IsDCOS()
|
||||
if dcos {
|
||||
t.Fatalf("Expected %t, got %t", false, dcos)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests if the environment we are running is in kubernetes.
|
||||
func TestIsKubernetes(t *testing.T) {
|
||||
os.Setenv("KUBERNETES_SERVICE_HOST", "10.11.148.5")
|
||||
|
@ -188,36 +251,8 @@ func TestIsDocker(t *testing.T) {
|
|||
return tmpfile.Name()
|
||||
}
|
||||
|
||||
filename1 := createTempFile(`11:pids:/user.slice/user-1000.slice/user@1000.service
|
||||
10:blkio:/
|
||||
9:hugetlb:/
|
||||
8:perf_event:/
|
||||
7:cpuset:/
|
||||
6:devices:/user.slice
|
||||
5:net_cls,net_prio:/
|
||||
4:cpu,cpuacct:/
|
||||
3:memory:/user/bala/0
|
||||
2:freezer:/user/bala/0
|
||||
1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
|
||||
`)
|
||||
defer os.Remove(filename1)
|
||||
|
||||
filename2 := createTempFile(`14:name=systemd:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
13:pids:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
12:hugetlb:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
11:net_prio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
10:perf_event:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
9:net_cls:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
8:freezer:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
7:devices:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
6:memory:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
5:blkio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
4:cpuacct:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
3:cpu:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
2:cpuset:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||
1:name=openrc:/docker
|
||||
`)
|
||||
defer os.Remove(filename2)
|
||||
filename := createTempFile("")
|
||||
defer os.Remove(filename)
|
||||
|
||||
testCases := []struct {
|
||||
filename string
|
||||
|
@ -226,8 +261,7 @@ func TestIsDocker(t *testing.T) {
|
|||
}{
|
||||
{"", false, nil},
|
||||
{"/tmp/non-existing-file", false, nil},
|
||||
{filename1, false, nil},
|
||||
{filename2, true, nil},
|
||||
{filename, true, nil},
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
|
@ -235,7 +269,7 @@ func TestIsDocker(t *testing.T) {
|
|||
filename string
|
||||
expectedResult bool
|
||||
expectedErr error
|
||||
}{"/proc/1/cwd", false, fmt.Errorf("open /proc/1/cwd: permission denied")})
|
||||
}{"/proc/1/cwd", false, errors.New("stat /proc/1/cwd: permission denied")})
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
|
Loading…
Reference in New Issue