Skip to content

Commit

Permalink
Use PotentialNamespace in ancestry
Browse files Browse the repository at this point in the history
If PotentialNamespace is available for given feature it is used instead
of detector namespace. Detector is empty in such a case.
  • Loading branch information
Allda committed Mar 14, 2019
1 parent 2c7838e commit f326b6f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 23 deletions.
17 changes: 14 additions & 3 deletions ancestry.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,20 @@ func (b *AncestryBuilder) createLayerIndexedFeature(namespace *layerIndexedNames

func (b *AncestryBuilder) lookupNamespace(feature *database.LayerFeature) (*layerIndexedNamespace, bool) {
matchedNamespaces := []*layerIndexedNamespace{}
for i, namespace := range b.namespaces {
if namespace.Namespace.VersionFormat == feature.VersionFormat {
matchedNamespaces = append(matchedNamespaces, &b.namespaces[i])
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])
}
}
}

Expand Down
36 changes: 24 additions & 12 deletions ancestry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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}
)
Expand Down Expand Up @@ -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,
Feature: f,
By: detector,
PotentialNamespace: ns,
})

return b
Expand All @@ -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) {
Expand Down Expand Up @@ -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,
},
}

Expand Down
21 changes: 14 additions & 7 deletions database/pgsql/ancestry/ancestry_feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -81,9 +81,14 @@ func FindAncestryFeatures(tx *sql.Tx, ancestryID int64, detectors detector.Detec
return nil, database.ErrInconsistent
}

nsDetector, ok := detectors.ByID[namespaceDetectorID]
if !ok {
return nil, database.ErrInconsistent
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{
Expand Down Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion database/pgsql/migrations/00001_initial_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit f326b6f

Please sign in to comment.