diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index 598bd8653bc..8057d9304de 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -145,7 +145,7 @@ go_library( "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ - "//vendor/github.com/sigma/go-inotify:go_default_library", + "//vendor/k8s.io/utils/inotify:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ "//pkg/windows/service:go_default_library", diff --git a/go.mod b/go.mod index 4efa6828b16..05de03fd92e 100644 --- a/go.mod +++ b/go.mod @@ -113,7 +113,7 @@ require ( github.com/robfig/cron v1.1.0 github.com/russross/blackfriday v1.5.2 github.com/seccomp/libseccomp-golang v0.9.1 // indirect - github.com/sigma/go-inotify v0.0.0-20181102212354-c87b6cf5033d + github.com/sigma/go-inotify v0.0.0-20181102212354-c87b6cf5033d // indirect github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect github.com/spf13/afero v1.2.2 github.com/spf13/cobra v0.0.4 diff --git a/vendor/BUILD b/vendor/BUILD index 971acacaaf5..b85d5df8907 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -470,6 +470,7 @@ filegroup( "//vendor/k8s.io/utils/buffer:all-srcs", "//vendor/k8s.io/utils/clock:all-srcs", "//vendor/k8s.io/utils/exec:all-srcs", + "//vendor/k8s.io/utils/inotify:all-srcs", "//vendor/k8s.io/utils/integer:all-srcs", "//vendor/k8s.io/utils/io:all-srcs", "//vendor/k8s.io/utils/keymutex:all-srcs", diff --git a/vendor/k8s.io/utils/inotify/BUILD b/vendor/k8s.io/utils/inotify/BUILD new file mode 100644 index 00000000000..c03fda77b74 --- /dev/null +++ b/vendor/k8s.io/utils/inotify/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["inotify_linux.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/utils/inotify", + importpath = "k8s.io/utils/inotify", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/utils/inotify/LICENSE b/vendor/k8s.io/utils/inotify/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/vendor/k8s.io/utils/inotify/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/k8s.io/utils/inotify/PATENTS b/vendor/k8s.io/utils/inotify/PATENTS new file mode 100644 index 00000000000..733099041f8 --- /dev/null +++ b/vendor/k8s.io/utils/inotify/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/k8s.io/utils/inotify/README.md b/vendor/k8s.io/utils/inotify/README.md new file mode 100644 index 00000000000..0c723a8d2b4 --- /dev/null +++ b/vendor/k8s.io/utils/inotify/README.md @@ -0,0 +1,5 @@ +This is a fork of golang.org/x/exp/inotify before it was deleted. + +Please use gopkg.in/fsnotify.v0 instead. + +For updates, see: https://fsnotify.org/ diff --git a/vendor/k8s.io/utils/inotify/inotify_linux.go b/vendor/k8s.io/utils/inotify/inotify_linux.go new file mode 100644 index 00000000000..04d0652b454 --- /dev/null +++ b/vendor/k8s.io/utils/inotify/inotify_linux.go @@ -0,0 +1,333 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package inotify implements a wrapper for the Linux inotify system. + +Example: + watcher, err := inotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + err = watcher.Watch("/tmp") + if err != nil { + log.Fatal(err) + } + for { + select { + case ev := <-watcher.Event: + log.Println("event:", ev) + case err := <-watcher.Error: + log.Println("error:", err) + } + } + +*/ +package inotify // import "k8s.io/utils/inotify" + +import ( + "errors" + "fmt" + "os" + "strings" + "sync" + "syscall" + "unsafe" +) + +// Event represents a notification +type Event struct { + Mask uint32 // Mask of events + Cookie uint32 // Unique cookie associating related events (for rename(2)) + Name string // File name (optional) +} + +type watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) +} + +// Watcher represents an inotify instance +type Watcher struct { + mu sync.Mutex + fd int // File descriptor (as returned by the inotify_init() syscall) + watches map[string]*watch // Map of inotify watches (key: path) + paths map[int]string // Map of watched paths (key: watch descriptor) + Error chan error // Errors are sent on this channel + Event chan *Event // Events are returned on this channel + done chan bool // Channel for sending a "quit message" to the reader goroutine + isClosed bool // Set to true when Close() is first called +} + +// NewWatcher creates and returns a new inotify instance using inotify_init(2) +func NewWatcher() (*Watcher, error) { + fd, errno := syscall.InotifyInit1(syscall.IN_CLOEXEC) + if fd == -1 { + return nil, os.NewSyscallError("inotify_init", errno) + } + w := &Watcher{ + fd: fd, + watches: make(map[string]*watch), + paths: make(map[int]string), + Event: make(chan *Event), + Error: make(chan error), + done: make(chan bool, 1), + } + + go w.readEvents() + return w, nil +} + +// Close closes an inotify watcher instance +// It sends a message to the reader goroutine to quit and removes all watches +// associated with the inotify instance +func (w *Watcher) Close() error { + if w.isClosed { + return nil + } + w.isClosed = true + + // Send "quit" message to the reader goroutine + w.done <- true + for path := range w.watches { + w.RemoveWatch(path) + } + + return nil +} + +// AddWatch adds path to the watched file set. +// The flags are interpreted as described in inotify_add_watch(2). +func (w *Watcher) AddWatch(path string, flags uint32) error { + if w.isClosed { + return errors.New("inotify instance already closed") + } + + watchEntry, found := w.watches[path] + if found { + watchEntry.flags |= flags + flags |= syscall.IN_MASK_ADD + } + + w.mu.Lock() // synchronize with readEvents goroutine + + wd, err := syscall.InotifyAddWatch(w.fd, path, flags) + if err != nil { + w.mu.Unlock() + return &os.PathError{ + Op: "inotify_add_watch", + Path: path, + Err: err, + } + } + + if !found { + w.watches[path] = &watch{wd: uint32(wd), flags: flags} + w.paths[wd] = path + } + w.mu.Unlock() + return nil +} + +// Watch adds path to the watched file set, watching all events. +func (w *Watcher) Watch(path string) error { + return w.AddWatch(path, InAllEvents) +} + +// RemoveWatch removes path from the watched file set. +func (w *Watcher) RemoveWatch(path string) error { + watch, ok := w.watches[path] + if !ok { + return fmt.Errorf("can't remove non-existent inotify watch for: %s", path) + } + success, errno := syscall.InotifyRmWatch(w.fd, watch.wd) + if success == -1 { + return os.NewSyscallError("inotify_rm_watch", errno) + } + delete(w.watches, path) + // Locking here to protect the read from paths in readEvents. + w.mu.Lock() + delete(w.paths, int(watch.wd)) + w.mu.Unlock() + return nil +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Event channel +func (w *Watcher) readEvents() { + var buf [syscall.SizeofInotifyEvent * 4096]byte + + for { + n, err := syscall.Read(w.fd, buf[:]) + // See if there is a message on the "done" channel + var done bool + select { + case done = <-w.done: + default: + } + + // If EOF or a "done" message is received + if n == 0 || done { + // The syscall.Close can be slow. Close + // w.Event first. + close(w.Event) + err := syscall.Close(w.fd) + if err != nil { + w.Error <- os.NewSyscallError("close", err) + } + close(w.Error) + return + } + if n < 0 { + w.Error <- os.NewSyscallError("read", err) + continue + } + if n < syscall.SizeofInotifyEvent { + w.Error <- errors.New("inotify: short read in readEvents()") + continue + } + + var offset uint32 + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + for offset <= uint32(n-syscall.SizeofInotifyEvent) { + // Point "raw" to the event in the buffer + raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset])) + event := new(Event) + event.Mask = uint32(raw.Mask) + event.Cookie = uint32(raw.Cookie) + nameLen := uint32(raw.Len) + // If the event happened to the watched directory or the watched file, the kernel + // doesn't append the filename to the event, but we would like to always fill the + // the "Name" field with a valid filename. We retrieve the path of the watch from + // the "paths" map. + w.mu.Lock() + name, ok := w.paths[int(raw.Wd)] + w.mu.Unlock() + if ok { + event.Name = name + if nameLen > 0 { + // Point "bytes" at the first byte of the filename + bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent])) + // The filename is padded with NUL bytes. TrimRight() gets rid of those. + event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + // Send the event on the events channel + w.Event <- event + } + // Move to the next event in the buffer + offset += syscall.SizeofInotifyEvent + nameLen + } + } +} + +// String formats the event e in the form +// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..." +func (e *Event) String() string { + var events string + + m := e.Mask + for _, b := range eventBits { + if m&b.Value == b.Value { + m &^= b.Value + events += "|" + b.Name + } + } + + if m != 0 { + events += fmt.Sprintf("|%#x", m) + } + if len(events) > 0 { + events = " == " + events[1:] + } + + return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events) +} + +const ( + // Options for inotify_init() are not exported + // IN_CLOEXEC uint32 = syscall.IN_CLOEXEC + // IN_NONBLOCK uint32 = syscall.IN_NONBLOCK + + // Options for AddWatch + + // InDontFollow : Don't dereference pathname if it is a symbolic link + InDontFollow uint32 = syscall.IN_DONT_FOLLOW + // InOneshot : Monitor the filesystem object corresponding to pathname for one event, then remove from watch list + InOneshot uint32 = syscall.IN_ONESHOT + // InOnlydir : Watch pathname only if it is a directory + InOnlydir uint32 = syscall.IN_ONLYDIR + + // The "IN_MASK_ADD" option is not exported, as AddWatch + // adds it automatically, if there is already a watch for the given path + // IN_MASK_ADD uint32 = syscall.IN_MASK_ADD + + // Events + + // InAccess : File was accessed + InAccess uint32 = syscall.IN_ACCESS + // InAllEvents : Bit mask for all notify events + InAllEvents uint32 = syscall.IN_ALL_EVENTS + // InAttrib : Metadata changed + InAttrib uint32 = syscall.IN_ATTRIB + // InClose : Equates to IN_CLOSE_WRITE | IN_CLOSE_NOWRITE + InClose uint32 = syscall.IN_CLOSE + // InCloseNowrite : File or directory not opened for writing was closed + InCloseNowrite uint32 = syscall.IN_CLOSE_NOWRITE + // InCloseWrite : File opened for writing was closed + InCloseWrite uint32 = syscall.IN_CLOSE_WRITE + // InCreate : File/directory created in watched directory + InCreate uint32 = syscall.IN_CREATE + // InDelete : File/directory deleted from watched directory + InDelete uint32 = syscall.IN_DELETE + // InDeleteSelf : Watched file/directory was itself deleted + InDeleteSelf uint32 = syscall.IN_DELETE_SELF + // InModify : File was modified + InModify uint32 = syscall.IN_MODIFY + // InMove : Equates to IN_MOVED_FROM | IN_MOVED_TO + InMove uint32 = syscall.IN_MOVE + // InMovedFrom : Generated for the directory containing the old filename when a file is renamed + InMovedFrom uint32 = syscall.IN_MOVED_FROM + // InMovedTo : Generated for the directory containing the new filename when a file is renamed + InMovedTo uint32 = syscall.IN_MOVED_TO + // InMoveSelf : Watched file/directory was itself moved + InMoveSelf uint32 = syscall.IN_MOVE_SELF + // InOpen : File or directory was opened + InOpen uint32 = syscall.IN_OPEN + + // Special events + + // InIsdir : Subject of this event is a directory + InIsdir uint32 = syscall.IN_ISDIR + // InIgnored : Watch was removed explicitly or automatically + InIgnored uint32 = syscall.IN_IGNORED + // InQOverflow : Event queue overflowed + InQOverflow uint32 = syscall.IN_Q_OVERFLOW + // InUnmount : Filesystem containing watched object was unmounted + InUnmount uint32 = syscall.IN_UNMOUNT +) + +var eventBits = []struct { + Value uint32 + Name string +}{ + {InAccess, "IN_ACCESS"}, + {InAttrib, "IN_ATTRIB"}, + {InClose, "IN_CLOSE"}, + {InCloseNowrite, "IN_CLOSE_NOWRITE"}, + {InCloseWrite, "IN_CLOSE_WRITE"}, + {InCreate, "IN_CREATE"}, + {InDelete, "IN_DELETE"}, + {InDeleteSelf, "IN_DELETE_SELF"}, + {InModify, "IN_MODIFY"}, + {InMove, "IN_MOVE"}, + {InMovedFrom, "IN_MOVED_FROM"}, + {InMovedTo, "IN_MOVED_TO"}, + {InMoveSelf, "IN_MOVE_SELF"}, + {InOpen, "IN_OPEN"}, + {InIsdir, "IN_ISDIR"}, + {InIgnored, "IN_IGNORED"}, + {InQOverflow, "IN_Q_OVERFLOW"}, + {InUnmount, "IN_UNMOUNT"}, +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 43980b487df..3d7b4dcc7d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1794,6 +1794,7 @@ k8s.io/utils/buffer k8s.io/utils/clock k8s.io/utils/exec k8s.io/utils/exec/testing +k8s.io/utils/inotify k8s.io/utils/integer k8s.io/utils/io k8s.io/utils/keymutex