Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 645cfcc

Browse files
committed
Try to use local rpm binary to query rpmdb
With this commit the rpm differ first tries to execute local rpm to parse the image rpm database. In case of failure it fallbacks to running the image in a container to execute the rpm shipped within the image itself. Signed-off-by: David Cassany <[email protected]>
1 parent bca6c56 commit 645cfcc

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

differs/rpm_diff.go

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ limitations under the License.
1717
package differs
1818

1919
import (
20+
"bufio"
2021
"bytes"
2122
"context"
23+
"errors"
2224
"fmt"
2325
"math/rand"
2426
"os"
27+
"os/exec"
2528
"path/filepath"
2629
"strconv"
2730
"strings"
@@ -40,6 +43,11 @@ import (
4043
"github.com/sirupsen/logrus"
4144
)
4245

46+
//RPM command to extract packages from the rpm database
47+
var rpmCmd = []string{
48+
"rpm", "--nodigest", "--nosignature",
49+
"-qa", "--qf", "%{NAME}\t%{VERSION}\t%{SIZE}\n",
50+
}
4351
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
4452

4553
// daemonMutex is required to protect against other go-routines, as
@@ -87,7 +95,65 @@ func (a RPMAnalyzer) getPackages(image pkgutil.Image) (map[string]util.PackageIn
8795
}
8896
}
8997

90-
return rpmDataFromContainer(image)
98+
packages, err := rpmDataFromImageFS(image)
99+
if err != nil {
100+
logrus.Warn("Trying to run the RPM binary of the image in a container")
101+
return rpmDataFromContainer(image)
102+
}
103+
return packages, err
104+
}
105+
106+
// rpmDataFromImageFS runs a local rpm binary, if any, to query the image
107+
// rpmdb and returns a map of installed packages.
108+
func rpmDataFromImageFS(image pkgutil.Image) (map[string]util.PackageInfo, error) {
109+
packages := make(map[string]util.PackageInfo)
110+
// Check there is an executable rpm tool in host
111+
if err := exec.Command("rpm", "--version").Run(); err != nil {
112+
logrus.Warn("No RPM binary in host")
113+
return packages, err
114+
}
115+
dbPath, err := rpmDBPath(image.FSPath)
116+
if err != nil {
117+
logrus.Warnf("Couldn't find RPM database: %s", err.Error())
118+
return packages, err
119+
}
120+
cmdArgs := append([]string{"--root", image.FSPath, "--dbpath", dbPath}, rpmCmd[1:]...)
121+
out, err := exec.Command(rpmCmd[0], cmdArgs...).Output()
122+
if err != nil {
123+
logrus.Warnf("RPM call failed: %s", err.Error())
124+
return packages, err
125+
}
126+
output := strings.Split(string(out), "\n")
127+
return parsePackageData(output)
128+
}
129+
130+
// rpmDBPath tries to get the RPM database path from the /usr/lib/rpm/macros
131+
// file in the image rootfs.
132+
func rpmDBPath(rootFSPath string) (string, error) {
133+
rpmMacros, err := os.Open(filepath.Join(rootFSPath, "usr/lib/rpm/macros"))
134+
if err != nil {
135+
return "", err
136+
}
137+
defer rpmMacros.Close()
138+
139+
scanner := bufio.NewScanner(rpmMacros)
140+
for scanner.Scan() {
141+
line := strings.TrimSpace(scanner.Text())
142+
if strings.HasPrefix(line, "%_dbpath") {
143+
fields := strings.Fields(line)
144+
if len(fields) < 2 {
145+
break
146+
}
147+
out, err := exec.Command("rpm", "-E", fields[1]).Output()
148+
if err != nil {
149+
return "", err
150+
}
151+
dbPath := strings.TrimRight(string(out), "\r\n")
152+
_, err = os.Stat(filepath.Join(rootFSPath, dbPath))
153+
return dbPath, err
154+
}
155+
}
156+
return "", errors.New("Failed parsing macros file")
91157
}
92158

93159
// rpmDataFromContainer runs image in a container, queries the data of
@@ -114,7 +180,7 @@ func rpmDataFromContainer(image pkgutil.Image) (map[string]util.PackageInfo, err
114180
defer logrus.Infof("Removing image %s", imageName)
115181

116182
contConf := godocker.Config{
117-
Entrypoint: []string{"rpm", "--nodigest", "--nosignature", "-qa", "--qf", "%{NAME}\t%{VERSION}\t%{SIZE}\n"},
183+
Entrypoint: rpmCmd,
118184
Image: imageName,
119185
}
120186

0 commit comments

Comments
 (0)