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,9 +211,20 @@ func (b *AncestryBuilder) createLayerIndexedFeature(namespace *layerIndexedNames
func (b *AncestryBuilder) lookupNamespace(feature *database.LayerFeature) (*layerIndexedNamespace, bool) { func (b *AncestryBuilder) lookupNamespace(feature *database.LayerFeature) (*layerIndexedNamespace, bool) {
matchedNamespaces := []*layerIndexedNamespace{} matchedNamespaces := []*layerIndexedNamespace{}
for i, namespace := range b.namespaces { if feature.PotentialNamespace.Name != "" {
if namespace.Namespace.VersionFormat == feature.VersionFormat { a := &layerIndexedNamespace{
matchedNamespaces = append(matchedNamespaces, &b.namespaces[i]) 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])
}
} }
} }

View File

@ -31,6 +31,7 @@ var (
aptsources = database.NewNamespaceDetector("apt-sources", "1.0") aptsources = database.NewNamespaceDetector("apt-sources", "1.0")
ubuntu = *database.NewNamespace("ubuntu:14.04", "dpkg") ubuntu = *database.NewNamespace("ubuntu:14.04", "dpkg")
ubuntu16 = *database.NewNamespace("ubuntu:16.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") debian = *database.NewNamespace("debian:7", "dpkg")
python2 = *database.NewNamespace("python:2", "pip") python2 = *database.NewNamespace("python:2", "pip")
sed = *database.NewSourcePackage("sed", "4.4-2", "dpkg") sed = *database.NewSourcePackage("sed", "4.4-2", "dpkg")
@ -39,6 +40,8 @@ var (
tar = *database.NewBinaryPackage("tar", "1.29b-2", "dpkg") tar = *database.NewBinaryPackage("tar", "1.29b-2", "dpkg")
scipy = *database.NewSourcePackage("scipy", "3.0.0", "pip") scipy = *database.NewSourcePackage("scipy", "3.0.0", "pip")
emptyNamespace = database.Namespace{}
detectors = []database.Detector{dpkg, osrelease, rpm} detectors = []database.Detector{dpkg, osrelease, rpm}
multinamespaceDetectors = []database.Detector{dpkg, osrelease, pip} multinamespaceDetectors = []database.Detector{dpkg, osrelease, pip}
) )
@ -97,10 +100,11 @@ func (b *layerBuilder) addNamespace(detector database.Detector, ns database.Name
return b 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{ b.layer.Features = append(b.layer.Features, database.LayerFeature{
Feature: f, Feature: f,
By: detector, By: detector,
PotentialNamespace: ns,
}) })
return b return b
@ -112,39 +116,43 @@ var testImage = []*database.Layer{
// ubuntu namespace // ubuntu namespace
newLayerBuilder("1").addNamespace(osrelease, ubuntu).layer, newLayerBuilder("1").addNamespace(osrelease, ubuntu).layer,
// install sed // install sed
newLayerBuilder("2").addFeature(dpkg, sed).layer, newLayerBuilder("2").addFeature(dpkg, sed, emptyNamespace).layer,
// install tar // install tar
newLayerBuilder("3").addFeature(dpkg, sed).addFeature(dpkg, tar).layer, newLayerBuilder("3").addFeature(dpkg, sed, emptyNamespace).addFeature(dpkg, tar, emptyNamespace).layer,
// remove tar // remove tar
newLayerBuilder("4").addFeature(dpkg, sed).layer, newLayerBuilder("4").addFeature(dpkg, sed, emptyNamespace).layer,
// upgrade ubuntu // upgrade ubuntu
newLayerBuilder("5").addNamespace(osrelease, ubuntu16).layer, newLayerBuilder("5").addNamespace(osrelease, ubuntu16).layer,
// no change to the detectable files // no change to the detectable files
newLayerBuilder("6").layer, newLayerBuilder("6").layer,
// change to the package installer database but no features are affected. // 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{ var invalidNamespace = []*database.Layer{
// add package without namespace, this indicates that the namespace detector // add package without namespace, this indicates that the namespace detector
// could not detect the namespace. // could not detect the namespace.
newLayerBuilder("0").addFeature(dpkg, sed).layer, newLayerBuilder("0").addFeature(dpkg, sed, emptyNamespace).layer,
} }
var noMatchingNamespace = []*database.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{ 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{ 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{ 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) { func TestAddLayer(t *testing.T) {
@ -262,6 +270,10 @@ func TestAddLayer(t *testing.T) {
title: "noMatchingNamespace", title: "noMatchingNamespace",
image: noMatchingNamespace, image: noMatchingNamespace,
expectedAncestry: *newAncestryBuilder(ancestryName([]string{"0"})).addDetectors(detectors...).addLayer("0", ancestryFeature(ubuntu, sed, osrelease, dpkg)).ancestry, 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() { for rows.Next() {
var ( var (
featureDetectorID int64 featureDetectorID int64
namespaceDetectorID int64 namespaceDetectorID sql.NullInt64
feature database.NamespacedFeature feature database.NamespacedFeature
// index is used to determine which layer the feature belongs to. // index is used to determine which layer the feature belongs to.
index sql.NullInt64 index sql.NullInt64
@ -81,9 +81,14 @@ func FindAncestryFeatures(tx *sql.Tx, ancestryID int64, detectors detector.Detec
return nil, database.ErrInconsistent return nil, database.ErrInconsistent
} }
nsDetector, ok := detectors.ByID[namespaceDetectorID] var nsDetector database.Detector
if !ok { if !namespaceDetectorID.Valid {
return nil, database.ErrInconsistent 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{ featureMap[index.Int64] = append(featureMap[index.Int64], database.AncestryFeature{
@ -120,9 +125,11 @@ func InsertAncestryFeatures(tx *sql.Tx, ancestryLayerID int64, layer database.An
return database.ErrMissingEntities return database.ErrMissingEntities
} }
namespaceDetectorID, ok := detectors.ByValue[layer.Features[index].NamespaceBy] var namespaceDetectorID sql.NullInt64
if !ok { var ok bool
return database.ErrMissingEntities namespaceDetectorID.Int64, ok = detectors.ByValue[layer.Features[index].NamespaceBy]
if ok {
namespaceDetectorID.Valid = true
} }
featureDetectorID, ok := detectors.ByValue[layer.Features[index].FeatureBy] 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, ancestry_layer_id INT NOT NULL REFERENCES ancestry_layer ON DELETE CASCADE,
namespaced_feature_id INT NOT NULL REFERENCES namespaced_feature 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, 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));`, UNIQUE (ancestry_layer_id, namespaced_feature_id));`,
`CREATE TABLE IF NOT EXISTS ancestry_detector( `CREATE TABLE IF NOT EXISTS ancestry_detector(