// toLayers converts a path leading to one or multiple layers to Layer structs, // selecting the specified fields func toLayers(path *path.Path, selectedFields []string) ([]*Layer, error) { var layers []*Layer saveFields(path, selectedFields, []string{FieldLayerSuccessors, FieldLayerPackages, FieldLayerInstalledPackages, FieldLayerRemovedPackages}) it, _ := path.BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { tags := make(map[string]graph.Value) it.TagResults(tags) layer := Layer{Node: store.NameOf(it.Result())} for _, selectedField := range selectedFields { switch selectedField { case FieldLayerID: layer.ID = store.NameOf(tags[FieldLayerID]) case FieldLayerParent: layer.ParentNode = store.NameOf(tags[FieldLayerParent]) case FieldLayerSuccessors: var err error layer.SuccessorsNodes, err = toValues(cayley.StartPath(store, layer.Node).In(FieldLayerParent)) if err != nil { log.Errorf("could not get successors of layer %s: %s.", layer.Node, err.Error()) return nil, err } case FieldLayerOS: layer.OS = store.NameOf(tags[FieldLayerOS]) case FieldLayerPackages: var err error it, _ := cayley.StartPath(store, layer.Node).OutWithTags([]string{"predicate"}, FieldLayerInstalledPackages, FieldLayerRemovedPackages).BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { tags := make(map[string]graph.Value) it.TagResults(tags) predicate := store.NameOf(tags["predicate"]) if predicate == FieldLayerInstalledPackages { layer.InstalledPackagesNodes = append(layer.InstalledPackagesNodes, store.NameOf(it.Result())) } else if predicate == FieldLayerRemovedPackages { layer.RemovedPackagesNodes = append(layer.RemovedPackagesNodes, store.NameOf(it.Result())) } } if it.Err() != nil { log.Errorf("could not get installed/removed packages of layer %s: %s.", layer.Node, it.Err()) return nil, err } case FieldLayerEngineVersion: layer.EngineVersion, _ = strconv.Atoi(store.NameOf(tags[FieldLayerEngineVersion])) default: panic("unknown selectedField") } } layers = append(layers, &layer) } if it.Err() != nil { log.Errorf("failed query in toLayers: %s", it.Err()) return []*Layer{}, ErrBackendException } return layers, nil }
// toValues returns multiple values from a path // If the path does not lead to any value, an empty array is returned // If a database error occurs, an empty array and an error are returned func toValues(p *path.Path) ([]string, error) { var values []string it, _ := p.BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { if it.Result() != nil { values = append(values, store.NameOf(it.Result())) } } if it.Err() != nil { log.Errorf("failed query in toValues: %s", it.Err()) return []string{}, ErrBackendException } return values, nil }
// toValue returns a single value from a path // If the path does not lead to a value, an empty string is returned // If the path leads to multiple values or if a database error occurs, an empty string and an error are returned func toValue(p *path.Path) (string, error) { var value string it, _ := p.BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { if value != "" { log.Error("failed query in toValue: used on an iterator containing multiple values") return "", ErrInconsistent } if it.Result() != nil { value = store.NameOf(it.Result()) } } if it.Err() != nil { log.Errorf("failed query in toValue: %s", it.Err()) return "", ErrBackendException } return value, nil }
// toPackages converts a path leading to one or multiple packages to Package structs, selecting the specified fields func toPackages(path *path.Path, selectedFields []string) ([]*Package, error) { var packages []*Package var err error saveFields(path, selectedFields, []string{FieldPackagePreviousVersion}) it, _ := path.BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { tags := make(map[string]graph.Value) it.TagResults(tags) pkg := Package{Node: store.NameOf(it.Result())} for _, selectedField := range selectedFields { switch selectedField { case FieldPackageOS: pkg.OS = store.NameOf(tags[FieldPackageOS]) case FieldPackageName: pkg.Name = store.NameOf(tags[FieldPackageName]) case FieldPackageVersion: pkg.Version, err = types.NewVersion(store.NameOf(tags[FieldPackageVersion])) if err != nil { log.Warningf("could not parse version of package %s: %s", pkg.Node, err.Error()) } case FieldPackageNextVersion: pkg.NextVersionNode = store.NameOf(tags[FieldPackageNextVersion]) case FieldPackagePreviousVersion: pkg.PreviousVersionNode, err = toValue(cayley.StartPath(store, pkg.Node).In(FieldPackageNextVersion)) if err != nil { log.Warningf("could not get previousVersion on package %s: %s.", pkg.Node, err.Error()) return []*Package{}, ErrInconsistent } default: panic("unknown selectedField") } } packages = append(packages, &pkg) } if it.Err() != nil { log.Errorf("failed query in toPackages: %s", it.Err()) return []*Package{}, ErrBackendException } return packages, nil }
// toVulnerabilities converts a path leading to one or multiple vulnerabilities to Vulnerability structs, selecting the specified fields func toVulnerabilities(path *path.Path, selectedFields []string) ([]*Vulnerability, error) { var vulnerabilities []*Vulnerability saveFields(path, selectedFields, []string{FieldVulnerabilityFixedIn, FieldVulnerabilityCausedByPackage}) it, _ := path.BuildIterator().Optimize() defer it.Close() for cayley.RawNext(it) { tags := make(map[string]graph.Value) it.TagResults(tags) vulnerability := Vulnerability{Node: store.NameOf(it.Result())} for _, selectedField := range selectedFields { switch selectedField { case FieldVulnerabilityID: vulnerability.ID = store.NameOf(tags[FieldVulnerabilityID]) case FieldVulnerabilityLink: vulnerability.Link = store.NameOf(tags[FieldVulnerabilityLink]) case FieldVulnerabilityPriority: vulnerability.Priority = types.Priority(store.NameOf(tags[FieldVulnerabilityPriority])) case FieldVulnerabilityDescription: vulnerability.Description = store.NameOf(tags[FieldVulnerabilityDescription]) case FieldVulnerabilityFixedIn: var err error vulnerability.FixedInNodes, err = toValues(cayley.StartPath(store, vulnerability.Node).Out(FieldVulnerabilityFixedIn)) if err != nil { log.Errorf("could not get fixedIn on vulnerability %s: %s.", vulnerability.Node, err.Error()) return []*Vulnerability{}, err } case FieldVulnerabilityCausedByPackage: vulnerability.CausedByPackage = store.NameOf(tags[FieldVulnerabilityCausedByPackage]) default: panic("unknown selectedField") } } vulnerabilities = append(vulnerabilities, &vulnerability) } if it.Err() != nil { log.Errorf("failed query in toVulnerabilities: %s", it.Err()) return []*Vulnerability{}, ErrBackendException } return vulnerabilities, nil }