Use PotentialNamespace in ancestry

If PotentialNamespace is available for given feature it is used instead
of detector namespace. Detector is empty in such a case.
This commit is contained in:
Ales Raszka 2019-03-14 17:27:30 +01:00
parent 2c7838eac7
commit f326b6f664
4 changed files with 53 additions and 23 deletions

View File

@ -211,11 +211,22 @@ func (b *AncestryBuilder) createLayerIndexedFeature(namespace *layerIndexedNames
func (b *AncestryBuilder) lookupNamespace(feature *database.LayerFeature) (*layerIndexedNamespace, bool) {
matchedNamespaces := []*layerIndexedNamespace{}
if feature.PotentialNamespace.Name != "" {
a := &layerIndexedNamespace{
Namespace: database.LayerNamespace{
Namespace: feature.PotentialNamespace,
},
IntroducedIn: b.layerIndex,
}
matchedNamespaces = append(matchedNamespaces, a)
} else {
for i, namespace := range b.namespaces {
if namespace.Namespace.VersionFormat == feature.VersionFormat {
matchedNamespaces = append(matchedNamespaces, &b.namespaces[i])
}
}
}
if len(matchedNamespaces) == 1 {
return matchedNamespaces[0], true

View File

@ -31,6 +31,7 @@ var (
aptsources = database.NewNamespaceDetector("apt-sources", "1.0")
ubuntu = *database.NewNamespace("ubuntu:14.04", "dpkg")
ubuntu16 = *database.NewNamespace("ubuntu:16.04", "dpkg")
rhel7 = *database.NewNamespace("cpe:/o:redhat:enterprise_linux:7::computenode", "rpm")
debian = *database.NewNamespace("debian:7", "dpkg")
python2 = *database.NewNamespace("python:2", "pip")
sed = *database.NewSourcePackage("sed", "4.4-2", "dpkg")
@ -39,6 +40,8 @@ var (
tar = *database.NewBinaryPackage("tar", "1.29b-2", "dpkg")
scipy = *database.NewSourcePackage("scipy", "3.0.0", "pip")
emptyNamespace = database.Namespace{}
detectors = []database.Detector{dpkg, osrelease, rpm}
multinamespaceDetectors = []database.Detector{dpkg, osrelease, pip}
)
@ -97,10 +100,11 @@ func (b *layerBuilder) addNamespace(detector database.Detector, ns database.Name
return b
}
func (b *layerBuilder) addFeature(detector database.Detector, f database.Feature) *layerBuilder {
func (b *layerBuilder) addFeature(detector database.Detector, f database.Feature, ns database.Namespace) *layerBuilder {
b.layer.Features = append(b.layer.Features, database.LayerFeature{
Feature: f,
By: detector,
PotentialNamespace: ns,
})
return b
@ -112,39 +116,43 @@ var testImage = []*database.Layer{
// ubuntu namespace
newLayerBuilder("1").addNamespace(osrelease, ubuntu).layer,
// install sed
newLayerBuilder("2").addFeature(dpkg, sed).layer,
newLayerBuilder("2").addFeature(dpkg, sed, emptyNamespace).layer,
// install tar
newLayerBuilder("3").addFeature(dpkg, sed).addFeature(dpkg, tar).layer,
newLayerBuilder("3").addFeature(dpkg, sed, emptyNamespace).addFeature(dpkg, tar, emptyNamespace).layer,
// remove tar
newLayerBuilder("4").addFeature(dpkg, sed).layer,
newLayerBuilder("4").addFeature(dpkg, sed, emptyNamespace).layer,
// upgrade ubuntu
newLayerBuilder("5").addNamespace(osrelease, ubuntu16).layer,
// no change to the detectable files
newLayerBuilder("6").layer,
// change to the package installer database but no features are affected.
newLayerBuilder("7").addFeature(dpkg, sed).layer,
newLayerBuilder("7").addFeature(dpkg, sed, emptyNamespace).layer,
}
var invalidNamespace = []*database.Layer{
// add package without namespace, this indicates that the namespace detector
// could not detect the namespace.
newLayerBuilder("0").addFeature(dpkg, sed).layer,
newLayerBuilder("0").addFeature(dpkg, sed, emptyNamespace).layer,
}
var noMatchingNamespace = []*database.Layer{
newLayerBuilder("0").addFeature(rpm, sedByRPM).addFeature(dpkg, sed).addNamespace(osrelease, ubuntu).layer,
newLayerBuilder("0").addFeature(rpm, sedByRPM, emptyNamespace).addFeature(dpkg, sed, emptyNamespace).addNamespace(osrelease, ubuntu).layer,
}
var multiplePackagesOnFirstLayer = []*database.Layer{
newLayerBuilder("0").addFeature(dpkg, sed).addFeature(dpkg, tar).addFeature(dpkg, sedBin).addNamespace(osrelease, ubuntu16).layer,
newLayerBuilder("0").addFeature(dpkg, sed, emptyNamespace).addFeature(dpkg, tar, emptyNamespace).addFeature(dpkg, sedBin, emptyNamespace).addNamespace(osrelease, ubuntu16).layer,
}
var twoNamespaceDetectorsWithSameResult = []*database.Layer{
newLayerBuilderWithoutDetector("0").addDetectors(dpkg, aptsources, osrelease).addFeature(dpkg, sed).addNamespace(aptsources, ubuntu).addNamespace(osrelease, ubuntu).layer,
newLayerBuilderWithoutDetector("0").addDetectors(dpkg, aptsources, osrelease).addFeature(dpkg, sed, emptyNamespace).addNamespace(aptsources, ubuntu).addNamespace(osrelease, ubuntu).layer,
}
var sameVersionFormatDiffName = []*database.Layer{
newLayerBuilder("0").addFeature(dpkg, sed).addNamespace(aptsources, ubuntu).addNamespace(osrelease, debian).layer,
newLayerBuilder("0").addFeature(dpkg, sed, emptyNamespace).addNamespace(aptsources, ubuntu).addNamespace(osrelease, debian).layer,
}
var potentialFeatureNamespace = []*database.Layer{
newLayerBuilder("0").addFeature(rpm, sed, rhel7).layer,
}
func TestAddLayer(t *testing.T) {
@ -262,6 +270,10 @@ func TestAddLayer(t *testing.T) {
title: "noMatchingNamespace",
image: noMatchingNamespace,
expectedAncestry: *newAncestryBuilder(ancestryName([]string{"0"})).addDetectors(detectors...).addLayer("0", ancestryFeature(ubuntu, sed, osrelease, dpkg)).ancestry,
}, {
title: "featureWithPotentialNamespace",
image: potentialFeatureNamespace,
expectedAncestry: *newAncestryBuilder(ancestryName([]string{"0"})).addDetectors(detectors...).addLayer("0", ancestryFeature(rhel7, sed, database.Detector{}, rpm)).ancestry,
},
}

View File

@ -50,7 +50,7 @@ func FindAncestryFeatures(tx *sql.Tx, ancestryID int64, detectors detector.Detec
for rows.Next() {
var (
featureDetectorID int64
namespaceDetectorID int64
namespaceDetectorID sql.NullInt64
feature database.NamespacedFeature
// index is used to determine which layer the feature belongs to.
index sql.NullInt64
@ -81,10 +81,15 @@ func FindAncestryFeatures(tx *sql.Tx, ancestryID int64, detectors detector.Detec
return nil, database.ErrInconsistent
}
nsDetector, ok := detectors.ByID[namespaceDetectorID]
var nsDetector database.Detector
if !namespaceDetectorID.Valid {
nsDetector = database.Detector{}
} else {
nsDetector, ok = detectors.ByID[namespaceDetectorID.Int64]
if !ok {
return nil, database.ErrInconsistent
}
}
featureMap[index.Int64] = append(featureMap[index.Int64], database.AncestryFeature{
NamespacedFeature: feature,
@ -120,9 +125,11 @@ func InsertAncestryFeatures(tx *sql.Tx, ancestryLayerID int64, layer database.An
return database.ErrMissingEntities
}
namespaceDetectorID, ok := detectors.ByValue[layer.Features[index].NamespaceBy]
if !ok {
return database.ErrMissingEntities
var namespaceDetectorID sql.NullInt64
var ok bool
namespaceDetectorID.Int64, ok = detectors.ByValue[layer.Features[index].NamespaceBy]
if ok {
namespaceDetectorID.Valid = true
}
featureDetectorID, ok := detectors.ByValue[layer.Features[index].FeatureBy]

View File

@ -127,7 +127,7 @@ var (
ancestry_layer_id INT NOT NULL REFERENCES ancestry_layer ON DELETE CASCADE,
namespaced_feature_id INT NOT NULL REFERENCES namespaced_feature ON DELETE CASCADE,
feature_detector_id INT NOT NULL REFERENCES detector ON DELETE CASCADE,
namespace_detector_id INT NOT NULL REFERENCES detector ON DELETE CASCADE,
namespace_detector_id INT REFERENCES detector ON DELETE CASCADE,
UNIQUE (ancestry_layer_id, namespaced_feature_id));`,
`CREATE TABLE IF NOT EXISTS ancestry_detector(