Documentation ¶
Overview ¶
Package util contains a collection of miscellaneous utility functions.
Index ¶
- Constants
- func AppendFile(name string, data []byte, perm os.FileMode) error
- func B64ToValue(str string) (interface{}, error)
- func Basename(p string) string
- func Bool(x interface{}) bool
- func BoolMapTrue(l []bool) bool
- func BoolMapValues(m map[string]bool) []bool
- func CloseAfter(ctx context.Context, d time.Duration) <-chan struct{}
- func Code(code string) string
- func CommonPathPrefix(paths ...string) string
- func ContextWithCloser(ctx context.Context, ch <-chan struct{}) (context.Context, context.CancelFunc)
- func CopyDiskContentsToFs(dstFs afero.Fs, src, dst string, force bool) error
- func CopyDiskToFs(dstFs afero.Fs, src, dst string, force bool) error
- func CopyDiskToFsAll(dstFs afero.Fs, src, dst string, force, all bool) error
- func CopyFs(srcFs, dstFs afero.Fs, src, dst string, force bool, all bool) error
- func CopyFsContents(srcFs afero.Fs, dstFs afero.Fs, src string, dst string, force bool) error
- func CopyFsContentsToDisk(srcFs afero.Fs, src, dst string, force bool) error
- func CopyFsToDisk(srcFs afero.Fs, src, dst string, force bool) error
- func CtxWithWg(ctx context.Context, wg *sync.WaitGroup) context.Context
- func DirParents(p string) []string
- func DirifyFileList(fileList []string, removeDirs bool) []string
- func Dirname(p string) string
- func ExecutablePath() (string, error)
- func ExpandHome(p string) (string, error)
- func FirstToUpper(str string) string
- func FlattenListWithSplit(input []string, split []string) []string
- func FsTree(fs afero.Fs, name string) (string, error)
- func GetFedoraDownloadURL(ctx context.Context) (string, error)
- func GetPhysicalEthernetDevices() ([]string, error)
- func HasPathPrefix(p, prefix string) bool
- func LatestFedoraVersion(ctx context.Context, arch string) (string, error)
- func LeftPad(s string, pad string, length int) string
- func MapSwap[M ~map[K]V, K, V comparable](m M) (map[V]K, error)
- func MissingMkdirs(input []string) ([]string, error)
- func NewRelPathFs(source afero.Fs, prefix string) afero.Fs
- func NumToAlpha(idx int) string
- func PathPrefixDelta(p, prefix string) int
- func PathSplit(p string) []string
- func PathSplitFullReversed(p string) []string
- func PriorityStrSliceSort(input []string, fn func(string) bool) []string
- func Rebase(path, base, root string) (string, error)
- func RemoveBasePath(path, base string) (string, error)
- func RemoveCommonFilePrefixes(paths []string) []string
- func RemovePathPrefix(s string) (string, error)
- func RemovePathSuffix(s string) (string, error)
- func ReverseStringList(in []string) []string
- func RightPad(s string, pad string, length int) string
- func SafePathClean(s string) string
- func SegmentedPathSplit(p string) []string
- func SessionBusPrivateUsable() (conn *dbus.Conn, err error)
- func SimpleCmd(ctx context.Context, name string, args []string, opts *SimpleCmdOpts) error
- func SortMapStringValuesByUInt64Keys(m map[uint64]string) []string
- func SortedStrSliceCompare(a, b []string) error
- func StrFilterElementsInList(filter []string, list []string) []string
- func StrInList(needle string, haystack []string) bool
- func StrInPathPrefixList(needle string, haystack []string) bool
- func StrListIntersection(list1 []string, list2 []string) []string
- func StrMapKeys(m map[string]string) []string
- func StrMapKeysUint64(m map[string]uint64) []string
- func StrMapValues(m map[string]string) []string
- func StrMapValuesUint64(m map[uint64]string) []string
- func StrRemoveDuplicatesInList(list []string) []string
- func SystemBusPrivateUsable() (conn *dbus.Conn, err error)
- func TestDir(suffix string) (string, error)
- func TestDirFull() (string, error)
- func TimeAfterOrBlock(t int) <-chan time.Time
- func TimeAfterOrBlockCtx(ctx context.Context, t int) <-chan struct{}
- func Uint(x interface{}) uint
- func Uint64KeyFromStrInMap(needle string, haystack map[uint64]string) (uint64, bool)
- func ValueToB64(value interface{}) (string, error)
- func WgFromCtx(ctx context.Context) *sync.WaitGroup
- type AferoFs
- type BlockedTimer
- type BoundedReadSemaphore
- type EasyAck
- type EasyAckOnce
- type EasyExit
- type EasyOnce
- type FedoraRelease
- type FileInfoDirEntry
- type Flock
- type LogWriter
- type PathSlice
- type RelPathFile
- type RelPathFs
- func (obj *RelPathFs) Chmod(name string, mode os.FileMode) (err error)
- func (obj *RelPathFs) Chown(name string, uid, gid int) (err error)
- func (obj *RelPathFs) Chtimes(name string, atime, mtime time.Time) (err error)
- func (obj *RelPathFs) Create(name string) (f afero.File, err error)
- func (obj *RelPathFs) LstatIfPossible(name string) (os.FileInfo, bool, error)
- func (obj *RelPathFs) Mkdir(name string, mode os.FileMode) (err error)
- func (obj *RelPathFs) MkdirAll(name string, mode os.FileMode) (err error)
- func (obj *RelPathFs) Name() string
- func (obj *RelPathFs) Open(name string) (f afero.File, err error)
- func (obj *RelPathFs) OpenFile(name string, flag int, mode os.FileMode) (f afero.File, err error)
- func (obj *RelPathFs) ReadlinkIfPossible(name string) (string, error)
- func (obj *RelPathFs) RealPath(name string) (string, error)
- func (obj *RelPathFs) Remove(name string) (err error)
- func (obj *RelPathFs) RemoveAll(name string) (err error)
- func (obj *RelPathFs) Rename(oldname, newname string) (err error)
- func (obj *RelPathFs) Stat(name string) (fi os.FileInfo, err error)
- func (obj *RelPathFs) SymlinkIfPossible(oldname, newname string) error
- type SimpleCmdOpts
- type SubscribedSignal
- type TLS
- type UInt64Slice
- type UnitData
Examples ¶
Constants ¶
const ( // FedoraDownloadURL is the default fedora releases and updates download // URL. If you try to use this, you will get redirected to a mirror near // you. FedoraDownloadURL = "https://download.fedoraproject.org/pub/fedora/linux/" // FedoraReleasesEndpointJSON is the location of the fedora release data // as specified in json format. FedoraReleasesEndpointJSON = "https://fedoraproject.org/releases.json" )
const (
// RelPathFsScheme returns a unique name for this type of filesystem.
RelPathFsScheme = "RelPathFs"
)
Variables ¶
This section is empty.
Functions ¶
func AppendFile ¶
AppendFile writes data to the named file, creating it if necessary. If it already exists, append this data to it. If the file does not exist, AppendFile creates it with permissions perm (before umask); otherwise AppendFile appends to it without changing permissions. Since AppendFile requires multiple system calls to complete, a failure mid-operation can leave the file in a partially written state. This is based on the golang stdlib os.WriteFile method.
func B64ToValue ¶
B64ToValue decodes a value from a base64 encoded string (after deserialization).
func Bool ¶
func Bool(x interface{}) bool
Bool returns the interface value if it is a bool, and otherwise it panics.
func BoolMapTrue ¶
BoolMapTrue returns true if everyone in the list is true.
func BoolMapValues ¶
BoolMapValues returns the sorted list of bool values in a map with string values.
func CloseAfter ¶
CloseAfter takes a duration, similarly to `time.After`, and returns a channel that closes when either the context is done, or the duration expires.
func Code ¶
Code takes a code block as a backtick enclosed `heredoc` and removes any common indentation from each line. This helps inline code as strings to be formatted nicely without unnecessary indentation. It also drops the very first line of code if it has zero length.
func CommonPathPrefix ¶
CommonPathPrefix returns the longest common prefix directory out of all the input paths! This is always a directory and thus ends with a slash, unless all of the paths are identical and are files, or if only one path is given in which case that is returned, or unless no paths are given in which case the empty string is returned. If any of your input paths are not absolute, and as such do not begin with a slash, then the behaviour is undefined.
func ContextWithCloser ¶
func ContextWithCloser(ctx context.Context, ch <-chan struct{}) (context.Context, context.CancelFunc)
ContextWithCloser wraps a context and returns a new one exactly like the other context.With* functions, except that it takes a channel as an alternate cancel signal. TODO: switch to interface{} instead of <-chan struct to allow any chan type.
func CopyDiskContentsToFs ¶
CopyDiskContentsToFs performs exactly as CopyFs, except that the src fs is our local disk os fs, and we don't keep the source dir name, we only copy the contents.
func CopyDiskToFs ¶
CopyDiskToFs performs exactly as CopyFs, except that the src fs is our local disk os fs.
func CopyDiskToFsAll ¶
CopyDiskToFsAll performs exactly as CopyDiskToFs, except that it allows you to specify the `all` argument which switches CopyFs to using MkdirAll instead of the regular Mkdir. TODO: This works around weird copying issues. POSIX is hard.
func CopyFs ¶
CopyFs copies a dir from the srcFs to a dir on the dstFs. It expects that the dst will be either empty, or that the force flag will be set to true. If the dst has a different set of contents in the same location, the behaviour is currently undefined. TODO: this should be made more rsync like and robust!
func CopyFsContents ¶
CopyFsContents copies a dir from the srcFs to a dir on the dstFs. It expects that the dst will be either empty, or that the force flag will be set to true. If the dst has a different set of contents in the same location, the behaviour is currently undefined. Notably, this does not copy the src dir itself, and only includes the contents. This is similar to `rsync dir/` vs. `rsync dir`. This function does the former, where as CopyFs does the latter. TODO: this should be made more rsync like and robust!
func CopyFsContentsToDisk ¶
CopyFsContentsToDisk performs exactly as CopyFs, except that the dst fs is our local disk os fs, and we don't keep the source dir name, we only copy the contents.
func CopyFsToDisk ¶
CopyFsToDisk performs exactly as CopyFs, except that the dst fs is our local disk os fs.
func CtxWithWg ¶
CtxWithWg takes a context and a wait group, and returns a new context that is embedded with the wait group. You must use WgFromCtx to extract it.
func DirParents ¶
DirParents returns a list of the parent directories in a given path. If you pass it an empty string, or a single slash, then you will get an empty list. If you pass it a malformed path, then you might get unexpected results.
func DirifyFileList ¶
DirifyFileList adds trailing slashes to any likely dirs in a package manager fileList if removeDirs is true, otherwise, don't keep the dirs in our output.
func ExecutablePath ¶
ExecutablePath returns the absolute path to this binary if it can find it.
func ExpandHome ¶
ExpandHome does an expansion of ~/ or ~james/ into user's home dir value. If the input path ends in a slash, the result does too.
func FirstToUpper ¶
FirstToUpper returns the string with the first character capitalized.
func FlattenListWithSplit ¶
FlattenListWithSplit flattens a list of input by splitting each element by any and all of the strings listed in the split array
func FsTree ¶
FsTree returns a string representation of the file system tree similar to the well-known `tree` command.
func GetFedoraDownloadURL ¶
GetFedoraDownloadURL gets an https base path of a mirror to use for downloading both the fedora release and updates. It is supposed to find something nearest to you. TODO: Do we need to specify version and arch to make sure mirror has those?
func GetPhysicalEthernetDevices ¶
GetPhysicalEthernetDevices returns a link of physical ethernet devices. This is a heuristic and I wish I knew the better way.
XXX: Patches welcome!
func HasPathPrefix ¶
HasPathPrefix tells us if a path string contain the given path prefix in it.
func LatestFedoraVersion ¶
LatestFedoraVersion returns the version number (as a string) of the latest fedora release known. This looks at a well-known endpoint to get the value. If you specify a non-empty arch, it will filter to that.
func LeftPad ¶
LeftPad adds multiples of the pad string to the left of the input string until it reaches a minimum length. If the padding string is not an integer multiple of the missing length to pad, then this will overshoot. It is better to overshoot than to undershoot because if you need a string of a precise length, then it's easier to truncate the result, rather than having to pad even more. Most scenarios pad with a single char meaning this is not even an issue.
func MapSwap ¶
func MapSwap[M ~map[K]V, K, V comparable](m M) (map[V]K, error)
MapSwap returns a new map with the keys and values interchanged. It errors if doing so would cause a loss of a value. This is a generic version.
func MissingMkdirs ¶
MissingMkdirs takes a list of paths, and returns a list of any missing paths that would be needed to avoid having to `mkdir -p` to prevent missing parent directory errors from happening. This adds paths all the way up to the root, but without including it, because it's implied. TODO: do we want to include the root? TODO: this could probably be implemented in a more efficient way...
func NewRelPathFs ¶
NewRelPathFs creates a new RelPathFs.
func NumToAlpha ¶
NumToAlpha returns a lower case string of letters representing a number. If you specify 0, you'll get `a`, 25 gives you `z`, and 26 gives you `aa` and so on...
func PathPrefixDelta ¶
PathPrefixDelta returns the delta of the path prefix, which tells you how many path tokens different the prefix is.
func PathSplit ¶
PathSplit splits a path into an array of tokens excluding any trailing empty tokens.
func PathSplitFullReversed ¶
PathSplitFullReversed returns the full list of "dependency" paths for a given path in reverse order.
func PriorityStrSliceSort ¶
PriorityStrSliceSort filters any elements matching fn to the end of the list. You can reverse the match result with a not to filter to the front instead! A copy of the list is returned, the original is not modified.
func Rebase ¶
Rebase takes an absolute base path (directory prefix) and removes it from an absolute path and then returns that path with a new root as an absolute path if root is an absolute dir, and as a relative path if root is a relative dir. Eg: Rebase("/usr/bin/foo", "/usr/", "/usr/local/") -> "/usr/local/bin/foo" Eg: Rebase("/var/lib/dir/file.conf", "/var/lib/", "") -> "dir/file.conf"
func RemoveBasePath ¶
RemoveBasePath removes an absolute base path (directory prefix) from an absolute path that is any file or directory. Eg: RemoveBasePath("/usr/bin/foo", "/usr/") -> "bin/foo" Eg: RemoveBasePath("/usr/bin/project/", "/usr/") -> "bin/project/".
func RemoveCommonFilePrefixes ¶
RemoveCommonFilePrefixes removes redundant file path prefixes that are under the tree of other files.
func RemovePathPrefix ¶
RemovePathPrefix takes an absolute path and removes the first chunk. It returns the remainder as an absolute path. This function is a bit of a hack, and could probably be re-written to support any kind of path, and return a relative path.
func RemovePathSuffix ¶
RemovePathSuffix takes an absolute path and removes the last chunk. It returns the remainder as an absolute path. This function is a bit of a hack, and could probably be re-written to support any kind of path, and return a relative path.
func ReverseStringList ¶
ReverseStringList reverses a list of strings.
func RightPad ¶
RightPad adds multiples of the pad string to the right of the input string until it reaches a minimum length. If the padding string is not an integer multiple of the missing length to pad, then this will overshoot. It is better to overshoot than to undershoot because if you need a string of a precise length, then it's easier to truncate the result, rather than having to pad even more. Most scenarios pad with a single char meaning this is not even an issue.
func SafePathClean ¶
SafePathClean does path.Clean, but it preserves any trailing slash if it was present in the initial path.
func SegmentedPathSplit ¶
SegmentedPathSplit splits an absolute path into chunks including their slash. This is similar to the PathSplit function, but the slashes are not lost here! TODO: There is likely a more efficient implementation of this function.
func SessionBusPrivateUsable ¶
func SessionBusPrivateUsable() (conn *dbus.Conn, err error)
SessionBusPrivateUsable makes using the private bus usable. TODO: should be upstream: https://github.com/godbus/dbus/issues/15
func SortMapStringValuesByUInt64Keys ¶
SortMapStringValuesByUInt64Keys builds a list of strings, sorted by the corresponding key that is associated with that value. TODO: add some tests
func SortedStrSliceCompare ¶
SortedStrSliceCompare takes two lists of strings and returns whether or not they are equivalent. It will return nil if both sets contain the same elements, regardless of order, and an error if they do not.
func StrFilterElementsInList ¶
StrFilterElementsInList removes any of the elements in filter, if they exist in the list.
func StrInPathPrefixList ¶
StrInPathPrefixList returns true if the needle is a PathPrefix in the haystack.
func StrListIntersection ¶
StrListIntersection removes any of the elements in filter, if they don't exist in the list. This is an in order intersection of two lists.
func StrMapKeys ¶
StrMapKeys return the sorted list of string keys in a map with string keys. NOTE: i thought it would be nice for this to use: map[string]interface{} but it turns out that's not allowed. I know we don't have generics, but come on!
func StrMapKeysUint64 ¶
StrMapKeysUint64 return the sorted list of string keys in a map with string keys but uint64 values.
func StrMapValues ¶
StrMapValues returns the sorted list of string values in a map with string values.
func StrMapValuesUint64 ¶
StrMapValuesUint64 return the sorted list of string values in a map with string values.
func StrRemoveDuplicatesInList ¶
StrRemoveDuplicatesInList removes any duplicate values in the list. This implementation is possibly sub-optimal (O(n^2)?) but preserves ordering.
func SystemBusPrivateUsable ¶
func SystemBusPrivateUsable() (conn *dbus.Conn, err error)
SystemBusPrivateUsable makes using the private bus usable. TODO: should be upstream: https://github.com/godbus/dbus/issues/15
func TestDir ¶
TestDir gets the absolute path to the test directory if it exists. If the dir does not exist, then this will error, but the path will still be returned. This is a utility function that is used in some tests.
func TestDirFull ¶
TestDirFull gets the full absolute path to a unique test directory if it exists. If the dir does not exist, then this will error, but the path will still be returned. This is a utility function that is used in some tests.
func TimeAfterOrBlock ¶
TimeAfterOrBlock is aspecial version of time.After that blocks when given a negative integer. When used in a case statement, the timer restarts on each select call to it.
func TimeAfterOrBlockCtx ¶
TimeAfterOrBlockCtx returns a channel that closes after a timeout. If you use a negative timeout, it will block forever. It can also unblock using context. Make sure to cancel the context when you're done, or you'll leak a goroutine.
func Uint ¶
func Uint(x interface{}) uint
Uint returns the interface value if it is a uint, and otherwise it panics.
func Uint64KeyFromStrInMap ¶
Uint64KeyFromStrInMap returns true if needle is found in haystack of keys that have uint64 type.
func ValueToB64 ¶
ValueToB64 encodes a value to a base64 encoded string (after serialization).
Types ¶
type AferoFs ¶
AferoFs is a simple wrapper to a file system to be used for standalone deploys. This is basically a pass-through so that we fulfill the same interface that the deploy mechanism uses. If you give it Scheme and Path fields it will use those to build the URI. NOTE: This struct is here, since I don't know where else to put it for now.
type BlockedTimer ¶
type BlockedTimer struct { // Duration specifies how long we should wait before we run (or print) // the function or message. The counter starts when that respective // function is run. For an easier method, specify the Seconds parameter // instead. Duration time.Duration // Seconds works exactly as Duration does, except it can be used as a // shorter method to accomplish the same thing. If this value is zero, // then Duration is used instead. Seconds int // contains filtered or unexported fields }
BlockedTimer is a helper facility for printing log messages when you have a possible deadlock. Alternatively, it can run an arbitrary function instead. It does this by starting a timer, and if that timer isn't cancelled soon enough, it executes the task. This is usually most useful before a select statement which should ordinarily unblock rather quickly. It's helpful to avoid unnecessary "waiting for select" log messages being constantly printed, but should those block for longer, you'd definitely like to know where to look first. This is safe for concurrent use. Multiple invocations of Printf or Run are permitted. They each have their own separate countdown timers, but are all cancelled when Cancel is run. It is safe to call Cancel multiple times. If Cancel is called before Printf or Run, then those will never run. A BlockedTimer must not be copied after first use.
func (*BlockedTimer) Cancel ¶
func (obj *BlockedTimer) Cancel()
Cancel cancels the execution of any Run or Printf functions. It is safe to call it multiple times. It is important to call this at least once (on defer for example) if you've used either Printf or Run, because otherwise you will leak goroutines.
func (*BlockedTimer) Printf ¶
func (obj *BlockedTimer) Printf(format string, v ...interface{})
Printf will print as expected when the timer expires if Cancel isn't run first. This can be used multiple times.
func (*BlockedTimer) Run ¶
func (obj *BlockedTimer) Run(f func())
Run will run the passed function as expected when the timer expires if Cancel isn't run first. This can be used multiple times.
type BoundedReadSemaphore ¶
type BoundedReadSemaphore struct {
// contains filtered or unexported fields
}
BoundedReadSemaphore is a mutex that allows multiple Lock operations to occur concurrently, as if they were read locks. The distinction is that for the first Lock operation to complete, the Start() channel state must be read. At this point subsequent Lock operations will succeed. The End state completes once the last paired Unlock operation is run. The cycle can be repeated without needing to re-initialize the struct. Each Lock or Unlock operation itself contains a call to Lock an internal mutex for accounting and implementation purposes.
This was previously named SharedMutex. We welcome alternate naming suggestions.
Example ¶
fmt.Printf("hello\n") defer fmt.Printf("goodbye\n") wg := &sync.WaitGroup{} defer wg.Wait() ch := make(chan struct{}) // close signal brs := NewBoundedReadSemaphore() wg.Add(1) go func() { defer wg.Done() brs.Lock() defer brs.Unlock() time.Sleep(100 * time.Millisecond) // delay for consistent print fmt.Printf("#1 is in the locked zone\n") time.Sleep(1 * time.Second) }() wg.Add(1) go func() { defer wg.Done() brs.Lock() defer brs.Unlock() time.Sleep(200 * time.Millisecond) // delay for consistent print fmt.Printf("#2 is in the locked zone\n") time.Sleep(2 * time.Second) }() wg.Add(1) go func() { defer wg.Done() brs.Lock() defer brs.Unlock() time.Sleep(300 * time.Millisecond) // delay for consistent print fmt.Printf("#3 is in the locked zone\n") time.Sleep(3 * time.Second) }() wg.Add(1) go func() { defer wg.Done() defer close(ch) // exit signal max := 2 // configure me for { if max == 0 { break } max-- time.Sleep(4 * time.Second) brs.Lock() time.Sleep(100 * time.Millisecond) // delay for consistent print fmt.Printf("#4 is in the locked zone\n") brs.Unlock() time.Sleep(100 * time.Millisecond) // delay for consistent print fmt.Printf("#4 is in the unlocked zone\n") } }() Loop: for { select { case <-ch: // exit signal break Loop case <-brs.Start(): // An empty value is received to start the locking. fmt.Printf("shared mutex start\n") } // subsequent Lock's that happen when at least one Lock is // already held are permitted... time.Sleep(1 * time.Second) // something happens here select { case <-brs.End(): // An empty values is received when the last Unlock happens. fmt.Printf("shared mutex end\n") } }
Output: hello shared mutex start #1 is in the locked zone #2 is in the locked zone #3 is in the locked zone shared mutex end shared mutex start #4 is in the locked zone shared mutex end #4 is in the unlocked zone shared mutex start #4 is in the locked zone shared mutex end #4 is in the unlocked zone goodbye
func NewBoundedReadSemaphore ¶
func NewBoundedReadSemaphore() *BoundedReadSemaphore
NewBoundedReadSemaphore creates an initialized object. This must be done before first use, as the empty struct is not a valid BoundedReadSemaphore.
func (*BoundedReadSemaphore) End ¶
func (obj *BoundedReadSemaphore) End() <-chan struct{}
End will return a single signal on this output channel to advise that we've returned to the "unlocked" state.
func (*BoundedReadSemaphore) Lock ¶
func (obj *BoundedReadSemaphore) Lock()
Lock asks for a lock on this mutex. After the first Lock call synchronizes, subsequent calls will succeed quickly. The first "synchronization" waits for the lock start signal, which is a receive on the Start channel.
func (*BoundedReadSemaphore) Start ¶
func (obj *BoundedReadSemaphore) Start() <-chan struct{}
Start will return a single signal on this output channel to advise that we've started the "locked" state.
func (*BoundedReadSemaphore) Unlock ¶
func (obj *BoundedReadSemaphore) Unlock()
Unlock unlocks from a previous Lock operation. If this call is the last paired unlock operation, it blocks until the End() signal is synchronized. If you unlock more times than you lock, then you will cause a panic.
type EasyAck ¶
type EasyAck struct {
// contains filtered or unexported fields
}
EasyAck is a wrapper to build ack functionality into a simple interface.
func NewEasyAck ¶
func NewEasyAck() *EasyAck
NewEasyAck builds the object. This must be called before use.
type EasyAckOnce ¶
type EasyAckOnce struct {
// contains filtered or unexported fields
}
EasyAckOnce is a wrapper to build ack functionality into a simple interface. It is safe because the Ack function can be called multiple times safely.
func NewEasyAckOnce ¶
func NewEasyAckOnce() *EasyAckOnce
NewEasyAckOnce builds the object. This must be called before use.
func (*EasyAckOnce) Ack ¶
func (obj *EasyAckOnce) Ack()
Ack sends the acknowledgment message. This can be called as many times as you like. Only the first Ack is meaningful. Subsequent Ack's are redundant. It is thread-safe.
func (*EasyAckOnce) Wait ¶
func (obj *EasyAckOnce) Wait() <-chan struct{}
Wait returns a channel that you can wait on for the ack message. The return channel closes on the first Ack it receives. Subsequent Ack's have no effect.
type EasyExit ¶
type EasyExit struct {
// contains filtered or unexported fields
}
EasyExit is a struct that helps you build a close switch and signal which can be called multiple times safely, and used as a signal many times in parallel. It can also provide a context, if you prefer to use that as a signal instead.
func (*EasyExit) Context ¶
Context returns a context that is canceled when the Done signal is triggered. This can be used in addition to or instead of the Signal method.
func (*EasyExit) Done ¶
Done triggers the exit signal. It associates an error condition with it too. This is thread-safe.
type EasyOnce ¶
type EasyOnce struct { Func func() // contains filtered or unexported fields }
EasyOnce is a wrapper for the sync.Once functionality which lets you define and register the associated `run once` function at declaration time. It may be copied at any time.
type FedoraRelease ¶
type FedoraRelease struct { Version string `json:"version"` Arch string `json:"arch"` Variant string `json:"variant"` }
FedoraRelease is a partial struct of the available data in the json releases file found. This was determined by inspection.
type FileInfoDirEntry ¶
FileInfoDirEntry provides an adapter from os.FileInfo to fs.DirEntry
func (FileInfoDirEntry) Info ¶
func (obj FileInfoDirEntry) Info() (fs.FileInfo, error)
Info returns the FileInfo for this DirEntry.
func (FileInfoDirEntry) Type ¶
func (obj FileInfoDirEntry) Type() fs.FileMode
Type returns the FileMode for this DirEntry.
type Flock ¶
type Flock struct { Path string // contains filtered or unexported fields }
Flock is a structure for building a lock file. This can be used to prevent a binary from running more than one copy at a time on a single machine.
Example ¶
lockFile := "/tmp/flock.lock" fmt.Printf("hello\n") defer fmt.Printf("goodbye\n") defer os.Remove(lockFile) m := NewFlock(lockFile) unlock, err := m.TryLock() if err != nil { fmt.Printf("err: %+v\n", err) return } if unlock == nil { fmt.Printf("already locked\n") return } fmt.Printf("locked...\n") time.Sleep(1 * time.Second) unlock() fmt.Printf("unlocked...\n")
Output: hello locked... unlocked... goodbye
func (*Flock) TryLock ¶
TryLock attempts to take the lock. If it errors, it means we couldn't build a lock today. If it returns (nil, nil) it means someone is already locked. If it returns a non-nil function, then you are now locked. Call that function to unlock. Note that it can error if it fails to unlock things.
type LogWriter ¶
LogWriter is a simple interface that wraps our logf interface. TODO: Logf should end in (n int, err error) like fmt.Printf does!
type PathSlice ¶
type PathSlice []string
PathSlice is a type used to implement sort.Interface on a slice of strings, where each string is a path. This allows you to call sort.Sort() on a list of paths, after casting the []string{} to this type. Paths will be sorted by depth in alphabetical order.
type RelPathFile ¶
RelPathFile represents a file node.
type RelPathFs ¶
type RelPathFs struct {
// contains filtered or unexported fields
}
RelPathFs removes a prefix from all operations to a given path within an Fs. The given file name to the operations on this Fs will have a prefix removed before calling the base Fs.
When initializing it with "/", a call to `/foo` turns into `foo`.
Note that it does not clean the error messages on return, so you may reveal the real path on errors.
func (*RelPathFs) Chtimes ¶
Chtimes changes the access and modification times of the named file, similar to the Unix utime() or utimes() functions. The underlying filesystem may truncate or round the values to a less precise time unit. If there is an error, it will be of type *PathError.
func (*RelPathFs) LstatIfPossible ¶
LstatIfPossible is for the lstater interface.
func (*RelPathFs) MkdirAll ¶
MkdirAll creates a directory named path, along with any necessary parents, and returns nil, or else returns an error. The permission bits perm are used for all directories that MkdirAll creates. If path is already a directory, MkdirAll does nothing and returns nil.
func (*RelPathFs) ReadlinkIfPossible ¶
ReadlinkIfPossible is for the weird Afero readlink API.
func (*RelPathFs) RemoveAll ¶
RemoveAll removes path and any children it contains. It removes everything it can but returns the first error it encounters. If the path does not exist, RemoveAll returns nil (no error).
func (*RelPathFs) SymlinkIfPossible ¶
SymlinkIfPossible is for the weird Afero symlink API.
type SimpleCmdOpts ¶
type SimpleCmdOpts struct { // Debug represents if we're running in debug mode or not. Debug bool // Logf is a logger which should be used. Logf func(format string, v ...interface{}) // LogOutput is the path to where we can append the stdout and stderr. LogOutput string }
SimpleCmdOpts is a list of extra things to pass into the SimpleCmd function.
type SubscribedSignal ¶
type SubscribedSignal struct {
// contains filtered or unexported fields
}
SubscribedSignal represents a synchronized read signal. It doesn't need to be instantiated before it can be used. It must not be copied after first use. It is equivalent to receiving a multicast signal from a closing channel, except that it must be acknowledged by every reader of the signal, and once this is done, it is reset and can be re-used. Readers must obtain a handle to the signal with the Subscribe method, and the signal is sent out with the Done method.
Example ¶
fmt.Println("hello") x := &SubscribedSignal{} wg := &sync.WaitGroup{} ready := &sync.WaitGroup{} // unit1 wg.Add(1) ready.Add(1) go func() { defer wg.Done() ch, ack := x.Subscribe() ready.Done() select { case <-ch: fmt.Println("got signal") } time.Sleep(1 * time.Second) // wait a bit for fun fmt.Println("(1) sending ack...") ack() // must call ack fmt.Println("done sending ack") }() // unit2 wg.Add(1) ready.Add(1) go func() { defer wg.Done() ch, ack := x.Subscribe() ready.Done() select { case <-ch: fmt.Println("got signal") } time.Sleep(2 * time.Second) // wait a bit for fun fmt.Println("(2) sending ack...") ack() // must call ack fmt.Println("done sending ack") }() // unit3 wg.Add(1) ready.Add(1) go func() { defer wg.Done() ch, ack := x.Subscribe() ready.Done() select { case <-ch: fmt.Println("got signal") } time.Sleep(3 * time.Second) // wait a bit for fun fmt.Println("(3) sending ack...") ack() // must call ack fmt.Println("done sending ack") }() ready.Wait() // wait for all subscribes fmt.Println("sending signal...") x.Send() // trigger! time.Sleep(1 * time.Second) // wait a bit so the next print doesn't race fmt.Println("done sending signal") wg.Wait() // wait for everyone to exit fmt.Println("exiting...")
Output: hello sending signal... got signal got signal got signal (1) sending ack... (2) sending ack... (3) sending ack... done sending ack done sending ack done sending ack done sending signal exiting...
func (*SubscribedSignal) Send ¶
func (obj *SubscribedSignal) Send()
Send is called if you want to multicast the signal to all subscribed parties. It will require all parties to acknowledge the receipt of the signal before it will unblock. Just before returning, it will reset the signal so that it can be called a subsequent time. This is thread safe and can be called multiple times in parallel because this call is protected by a mutex. The mutex also prevents simultaneous calls with the Subscribe method.
func (*SubscribedSignal) Subscribe ¶
func (obj *SubscribedSignal) Subscribe() (<-chan struct{}, func())
Subscribe is used by any reader of the signal. Once this function returns, it means that you're now ready to watch the signal. The signal can be watched as is done normally with any other ready channel. Once you have received the signal or when you are no longer interested in the signal you *must* call the cancel/ack function which is returned by this function on subscribe. If you do not, you will block the Send portion of this subscribed signal indefinitely. This is thread safe and can be called multiple times in parallel because this call is protected by a mutex. The mutex also prevents simultaneous calls with the Send method. the returned cancel/ack method must return before it's safe to call this method a subsequent time for a new signal. One important note: there is a possible race that *you* can cause if you race this Subscribe call, with the Send call. Make sure you run Subscribe and it returns *before* you run Send if you want to be sure to receive the next signal. This should be common sense but it is mentioned here to be helpful. They are protected by a lock, so they can't both run simultaneously.
type TLS ¶
type TLS struct { // Host is comma-separated hostnames and IPs to generate a certificate // for. Host string // ValidFrom is the creation date formatted as Jan 1 15:04:05 2011. ValidFrom string // ValidFor is the duration that certificate is valid for. ValidFor time.Duration // IsCA is Whether this cert should be its own Certificate Authority. IsCA bool // RsaBits is the size of RSA key to generate. Ignored if EcdsaCurve is // set. RsaBits int // EcdsaCurve is the ECDSA curve to use to generate a key. Valid values // are P224, P256 (recommended), P384, P521. EcdsaCurve string // Ed25519Key is true to generate an Ed25519 key. Ed25519Key bool // Organization is the name of the organization to store in the cert. Organization string }
TLS handles all of the TLS building.
type UInt64Slice ¶
type UInt64Slice []uint64
UInt64Slice attaches the methods of sort.Interface to []uint64, sorting in increasing order.
func (UInt64Slice) Len ¶
func (obj UInt64Slice) Len() int
Len returns the length of the slice of uint64's.
func (UInt64Slice) Less ¶
func (obj UInt64Slice) Less(i, j int) bool
Less returns the smaller element in the sort order.
func (UInt64Slice) Swap ¶
func (obj UInt64Slice) Swap(i, j int)
Swap swaps two elements in the slice.
type UnitData ¶
type UnitData struct { // Description field for the unit file. Description string // Documentation field for the unit file. Documentation string // After makes this happen after that target is ready. Usually you want // "network.target" or "systemd-networkd.service" here I think. After []string // Type is the type of service to run, such as "oneshot". Type string // ExecStart is the main command to run. ExecStart string // RestartSec is the number of seconds to wait between restarts. RestartSec string // Restart is the restart policy. Usually you want "always". Restart string // RemainAfterExit can be set to true to make it look like the service // is still active if it exits successfully. RemainAfterExit bool // StandardOutput specifies what happens with stdout. StandardOutput string // StandardError specifies what happens with stderr. StandardError string // WantedBy makes this a dependency of this target. Usually you want // "multi-user.target" here. WantedBy []string }
UnitData is the data struct used to build a systemd unit file. This isn't an exhaustive representation of what's possible, but is meant to handle most common cases. Alternatively we could have used the github.com/coreos/go-systemd/v22/unit library, but it didn't provide much value. More documentation on these fields can be seen at: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package arch is for utilities that deal with cpu architectures.
|
Package arch is for utilities that deal with cpu architectures. |
Package disjoint implements a "disjoint-set data structure", otherwise known as the "union–find data structure" which is commonly used for type unification, among other things.
|
Package disjoint implements a "disjoint-set data structure", otherwise known as the "union–find data structure" which is commonly used for type unification, among other things. |
Package distro is for utilities that deal with os/distro things.
|
Package distro is for utilities that deal with os/distro things. |
Package errwrap contains some error helpers.
|
Package errwrap contains some error helpers. |
Package password has some utility functions for dealing with misc passwords.
|
Package password has some utility functions for dealing with misc passwords. |
Package recwatch provides recursive file watching events via fsnotify.
|
Package recwatch provides recursive file watching events via fsnotify. |
Package safepath implements some types and methods for dealing with POSIX file paths safely.
|
Package safepath implements some types and methods for dealing with POSIX file paths safely. |
Package semaphore contains an implementation of a counting semaphore.
|
Package semaphore contains an implementation of a counting semaphore. |
Package socketset is in API for creating a select style netlink socket to receive events from the kernel.
|
Package socketset is in API for creating a select style netlink socket to receive events from the kernel. |