Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split up util package into pkg/password, pkg/copy, pkg/version #1657

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions libnetwork/cni/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/containernetworking/cni/libcni"
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/common/pkg/version"
"github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -302,8 +302,8 @@ func (n *cniNetwork) NetworkInfo() types.NetworkInfo {
path := ""
packageVersion := ""
for _, p := range n.cniPluginDirs {
ver := cutil.PackageVersion(p)
if ver != cutil.UnknownPackage {
ver := version.Package(p)
if ver != version.UnknownPackage {
path = p
packageVersion = ver
break
Expand All @@ -317,8 +317,8 @@ func (n *cniNetwork) NetworkInfo() types.NetworkInfo {
}

dnsPath := filepath.Join(path, "dnsname")
dnsPackage := cutil.PackageVersion(dnsPath)
dnsProgram, err := cutil.ProgramVersionDnsname(dnsPath)
dnsPackage := version.Package(dnsPath)
dnsProgram, err := version.ProgramDnsname(dnsPath)
if err != nil {
logrus.Infof("Failed to get the dnsname plugin version: %v", err)
}
Expand Down
10 changes: 5 additions & 5 deletions libnetwork/netavark/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/common/pkg/version"
"github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -341,8 +341,8 @@ func (n *netavarkNetwork) DefaultInterfaceName() string {
// package version and program version.
func (n *netavarkNetwork) NetworkInfo() types.NetworkInfo {
path := n.netavarkBinary
packageVersion := cutil.PackageVersion(path)
programVersion, err := cutil.ProgramVersion(path)
packageVersion := version.Package(path)
programVersion, err := version.Program(path)
if err != nil {
logrus.Infof("Failed to get the netavark version: %v", err)
}
Expand All @@ -354,8 +354,8 @@ func (n *netavarkNetwork) NetworkInfo() types.NetworkInfo {
}

dnsPath := n.aardvarkBinary
dnsPackage := cutil.PackageVersion(dnsPath)
dnsProgram, err := cutil.ProgramVersion(dnsPath)
dnsPackage := version.Package(dnsPath)
dnsProgram, err := version.Program(dnsPath)
if err != nil {
logrus.Infof("Failed to get the aardvark version: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion libnetwork/util/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func createFilterFuncs(key string, filterValues []string) (types.FilterFunc, err
case "id":
// matches part of one id
return func(net types.Network) bool {
return util.FilterID(net.ID, filterValues)
return filters.FilterID(net.ID, filterValues)
}, nil

// TODO: add dns enabled, internal filter
Expand Down
4 changes: 2 additions & 2 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"path/filepath"
"strings"

"github.com/containers/common/pkg/util"
passwd "github.com/containers/common/pkg/password"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/pkg/docker/config"
Expand Down Expand Up @@ -269,7 +269,7 @@ func getUserAndPass(opts *LoginOptions, password, userFromAuthFile string) (user
}
if password == "" {
fmt.Fprint(opts.Stdout, "Password: ")
pass, err := util.ReadPassword(int(os.Stdin.Fd()))
pass, err := passwd.Read(int(os.Stdin.Fd()))
if err != nil {
return "", "", fmt.Errorf("reading password: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/util/copy.go → pkg/detach/copy.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package util
package detach

import (
"errors"
Expand All @@ -9,8 +9,8 @@ import (
// the user.
var ErrDetach = errors.New("detached from container")

// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
// Copy is similar to io.Copy but support a detach key sequence to break out.
func Copy(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
Expand Down
21 changes: 21 additions & 0 deletions pkg/filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"net/http"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/timetype"
)

Expand Down Expand Up @@ -134,3 +136,22 @@ func matchPattern(pattern string, value string) bool {
}
return false
}

// FilterID is a function used to compare an id against a set of ids, if the
// input is hex we check if the prefix matches. Otherwise we assume it is a
// regex and try to match that.
// see https://github.com/containers/podman/issues/18471 for why we do this
func FilterID(id string, filters []string) bool {
for _, want := range filters {
isRegex := types.NotHexRegex.MatchString(want)
if isRegex {
match, err := regexp.MatchString(want, id)
if err == nil && match {
return true
}
} else if strings.HasPrefix(id, strings.ToLower(want)) {
return true
}
}
return false
}
57 changes: 57 additions & 0 deletions pkg/password/password_supported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//go:build linux || darwin || freebsd
// +build linux darwin freebsd

package password

import (
"errors"
"os"
"os/signal"
"syscall"

terminal "golang.org/x/term"
)

var ErrInterrupt = errors.New("interrupted")

// Read reads a password from the terminal without echo.
func Read(fd int) ([]byte, error) {
// Store and restore the terminal status on interruptions to
// avoid that the terminal remains in the password state
// This is necessary as for https://github.com/golang/go/issues/31180

oldState, err := terminal.GetState(fd)
if err != nil {
return make([]byte, 0), err
}

type Buffer struct {
Buffer []byte
Error error
}
errorChannel := make(chan Buffer, 1)

// SIGINT and SIGTERM restore the terminal, otherwise the no-echo mode would remain intact
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
defer func() {
signal.Stop(interruptChannel)
close(interruptChannel)
}()
go func() {
for range interruptChannel {
if oldState != nil {
_ = terminal.Restore(fd, oldState)
}
errorChannel <- Buffer{Buffer: make([]byte, 0), Error: ErrInterrupt}
}
}()

go func() {
buf, err := terminal.ReadPassword(fd)
errorChannel <- Buffer{Buffer: buf, Error: err}
}()

buf := <-errorChannel
return buf.Buffer, buf.Error
}
21 changes: 21 additions & 0 deletions pkg/password/password_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build windows
// +build windows

package password

import (
terminal "golang.org/x/term"
)

// Read reads a password from the terminal.
func Read(fd int) ([]byte, error) {
oldState, err := terminal.GetState(fd)
if err != nil {
return make([]byte, 0), err
}
buf, err := terminal.ReadPassword(fd)
if oldState != nil {
_ = terminal.Restore(fd, oldState)
}
return buf, err
}
122 changes: 0 additions & 122 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
@@ -1,119 +1,16 @@
package util

import (
"bytes"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/containers/common/libnetwork/types"
"github.com/fsnotify/fsnotify"
"github.com/sirupsen/logrus"
)

const (
UnknownPackage = "Unknown"
)

var ErrInterrupt = errors.New("interrupted")

// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func queryPackageVersion(cmdArg ...string) string {
output := UnknownPackage
if 1 < len(cmdArg) {
cmd := exec.Command(cmdArg[0], cmdArg[1:]...)
if outp, err := cmd.Output(); err == nil {
output = string(outp)
deb := false
if cmdArg[0] == "/usr/bin/dlocate" {
// can return multiple matches
l := strings.Split(output, "\n")
output = l[0]
deb = true
} else if cmdArg[0] == "/usr/bin/dpkg" {
deb = true
}
if deb {
r := strings.Split(output, ": ")
queryFormat := `${Package}_${Version}_${Architecture}`
cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0])
if outp, err := cmd.Output(); err == nil {
output = string(outp)
}
}
}
if cmdArg[0] == "/sbin/apk" {
prefix := cmdArg[len(cmdArg)-1] + " is owned by "
output = strings.Replace(output, prefix, "", 1)
}
}
return strings.Trim(output, "\n")
}

// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func PackageVersion(program string) string { // program is full path
_, err := os.Stat(program)
if err != nil {
return UnknownPackage
}
packagers := [][]string{
{"/usr/bin/rpm", "-q", "-f"},
{"/usr/bin/dlocate", "-F"}, // Debian, Ubuntu (quick)
{"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu (slow)
{"/usr/bin/pacman", "-Qo"}, // Arch
{"/usr/bin/qfile", "-qv"}, // Gentoo (quick)
{"/usr/bin/equery", "b"}, // Gentoo (slow)
{"/sbin/apk", "info", "-W"}, // Alpine
{"/usr/local/sbin/pkg", "which", "-q"}, // FreeBSD
}

for _, cmd := range packagers {
cmd = append(cmd, program)
if out := queryPackageVersion(cmd...); out != UnknownPackage {
return out
}
}
return UnknownPackage
}

// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func ProgramVersion(program string) (string, error) {
return programVersion(program, false)
}

func ProgramVersionDnsname(program string) (string, error) {
return programVersion(program, true)
}

func programVersion(program string, dnsname bool) (string, error) {
cmd := exec.Command(program, "--version")
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

err := cmd.Run()
if err != nil {
return "", fmt.Errorf("`%v --version` failed: %v %v (%v)", program, stderr.String(), stdout.String(), err)
}

output := strings.TrimSuffix(stdout.String(), "\n")
// dnsname --version returns the information to stderr
if dnsname {
output = strings.TrimSuffix(stderr.String(), "\n")
}

return output, nil
}

// StringInSlice determines if a string is in a string slice, returns bool
func StringInSlice(s string, sl []string) bool {
for _, i := range sl {
Expand All @@ -135,25 +32,6 @@ func StringMatchRegexSlice(s string, re []string) bool {
return false
}

// FilterID is a function used to compare an id against a set of ids, if the
// input is hex we check if the prefix matches. Otherwise we assume it is a
// regex and try to match that.
// see https://github.com/containers/podman/issues/18471 for why we do this
func FilterID(id string, filters []string) bool {
for _, want := range filters {
isRegex := types.NotHexRegex.MatchString(want)
if isRegex {
match, err := regexp.MatchString(want, id)
if err == nil && match {
return true
}
} else if strings.HasPrefix(id, strings.ToLower(want)) {
return true
}
}
return false
}

// WaitForFile waits until a file has been created or the given timeout has occurred
func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, error) {
var inotifyEvents chan fsnotify.Event
Expand Down
Loading