func detectFeatures(name string, data map[string][]byte, namespace *database.Namespace) (features []database.FeatureVersion, err error) { // TODO(Quentin-M): We need to pass the parent image DetectFeatures because it's possible that // some detectors would need it in order to produce the entire feature list (if they can only // detect a diff). Also, we should probably pass the detected namespace so detectors could // make their own decision. features, err = detectors.DetectFeatures(data) if err != nil { return } // Ensure that every feature has a Namespace associated, otherwise associate the detected // namespace. If there is no detected namespace, we'll throw an error. for i := 0; i < len(features); i++ { if features[i].Feature.Namespace.Name == "" { if namespace != nil { features[i].Feature.Namespace = *namespace } else { log.Warningf("layer %s: Layer's namespace is unknown but non-namespaced features have been detected", name) err = ErrUnsupported return } } } return }
func detectFeatureVersions(name string, data map[string][]byte, namespace *database.Namespace, parent *database.Layer) (features []database.FeatureVersion, err error) { // TODO(Quentin-M): We need to pass the parent image to DetectFeatures because it's possible that // some detectors would need it in order to produce the entire feature list (if they can only // detect a diff). Also, we should probably pass the detected namespace so detectors could // make their own decision. features, err = detectors.DetectFeatures(data) if err != nil { return } // If there are no FeatureVersions, use parent's FeatureVersions if possible. // TODO(Quentin-M): We eventually want to give the choice to each detectors to use none/some of // their parent's FeatureVersions. It would be useful for detectors that can't find their entire // result using one Layer. if len(features) == 0 && parent != nil { features = parent.Features return } // Build a map of the namespaces for each FeatureVersion in our parent layer. parentFeatureNamespaces := make(map[string]database.Namespace) if parent != nil { for _, parentFeature := range parent.Features { parentFeatureNamespaces[parentFeature.Feature.Name+":"+parentFeature.Version.String()] = parentFeature.Feature.Namespace } } // Ensure that each FeatureVersion has an associated Namespace. for i, feature := range features { if feature.Feature.Namespace.Name != "" { // There is a Namespace associated. continue } if parentFeatureNamespace, ok := parentFeatureNamespaces[feature.Feature.Name+":"+feature.Version.String()]; ok { // The FeatureVersion is present in the parent layer; associate with their Namespace. features[i].Feature.Namespace = parentFeatureNamespace continue } if namespace != nil { // The Namespace has been detected in this layer; associate it. features[i].Feature.Namespace = *namespace continue } log.Warningf("layer %s: Layer's namespace is unknown but non-namespaced features have been detected", name) err = ErrUnsupported return } return }