Merge pull request #30002 from dims/remove-pidof-dependency

Automatic merge from submit-queue

Remove kubelet dependency on pidof

Issue #26093 identified pidof as one of the dependencies of kublet
which could be worked around. In this PR, we just look at /proc
to construct the list of pids we need for a specified process
instead of running "pidof" executable

Related to #26093

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.kubernetes.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.kubernetes.io/reviews/kubernetes/kubernetes/30002)
<!-- Reviewable:end -->
pull/6/head
Kubernetes Submit Queue 2016-08-09 23:32:51 -07:00 committed by GitHub
commit 70d6d165d5
3 changed files with 64 additions and 18 deletions

View File

@ -22,10 +22,8 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"strconv"
"strings"
"sync"
"time"
@ -42,6 +40,7 @@ import (
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/procfs"
"k8s.io/kubernetes/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/sets"
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
@ -526,22 +525,7 @@ func getPidsForProcess(name, pidFile string) ([]int, error) {
runtime.HandleError(err)
}
}
out, err := exec.Command("pidof", name).Output()
if err != nil {
return []int{}, fmt.Errorf("failed to find pid of %q: %v", name, err)
}
// The output of pidof is a list of pids.
pids := []int{}
for _, pidStr := range strings.Split(strings.TrimSpace(string(out)), " ") {
pid, err := strconv.Atoi(pidStr)
if err != nil {
continue
}
pids = append(pids, pid)
}
return pids, nil
return procfs.PidOf(name), nil
}
// Ensures that the Docker daemon is in the desired container.

View File

@ -17,12 +17,17 @@ limitations under the License.
package procfs
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"unicode"
"github.com/golang/glog"
)
type ProcFS struct{}
@ -56,3 +61,46 @@ func (pfs *ProcFS) GetFullContainerName(pid int) (string, error) {
}
return containerNameFromProcCgroup(string(content))
}
func PidOf(name string) []int {
pids := []int{}
filepath.Walk("/proc", func(path string, info os.FileInfo, err error) error {
base := filepath.Base(path)
// Traverse only the directories we are interested in
if info.IsDir() && path != "/proc" {
// If the directory is not a number (i.e. not a PID), skip it
if _, err := strconv.Atoi(base); err != nil {
return filepath.SkipDir
}
}
if base != "cmdline" {
return nil
}
cmdline, err := ioutil.ReadFile(path)
if err != nil {
glog.V(4).Infof("Error reading file %s: %+v", path, err)
return nil
}
// The bytes we read have '\0' as a separator for the command line
parts := bytes.SplitN(cmdline, []byte{0}, 2)
if len(parts) == 0 {
return nil
}
// Split the command line itself we are interested in just the first part
exe := strings.FieldsFunc(string(parts[0]), func(c rune) bool {
return unicode.IsSpace(c) || c == ':'
})
if len(exe) == 0 {
return nil
}
// Check if the name of the executable is what we are looking for
if filepath.Base(exe[0]) == name {
dirname := filepath.Base(filepath.Dir(path))
// Grab the PID from the directory path
pid, _ := strconv.Atoi(dirname)
pids = append(pids, pid)
}
return nil
})
return pids
}

View File

@ -18,7 +18,12 @@ package procfs
import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
func verifyContainerName(procCgroupText, expectedName string, expectedErr bool, t *testing.T) {
@ -56,3 +61,12 @@ func TestContainerNameFromProcCgroup(t *testing.T) {
procCgroupInvalid := "devices:docker/kubelet\ncpuacct:pkg/kubectl"
verifyContainerName(procCgroupInvalid, "", true, t)
}
func TestPidOf(t *testing.T) {
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
t.Skipf("not supported on GOOS=%s", runtime.GOOS)
}
pids := PidOf(filepath.Base(os.Args[0]))
assert.NotZero(t, pids)
assert.Contains(t, pids, os.Getpid())
}