Skip to content

Commit

Permalink
🧹 refactor python package
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-rock committed Feb 15, 2024
1 parent 04b47bb commit a6f66d1
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 209 deletions.
207 changes: 194 additions & 13 deletions providers/os/resources/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import (
"github.com/spf13/afero"
"go.mondoo.com/cnquery/v10/llx"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/util/convert"
"go.mondoo.com/cnquery/v10/providers/os/connection/shared"
"go.mondoo.com/cnquery/v10/providers/os/resources/python"
"go.mondoo.com/cnquery/v10/types"
)

type pythonDirectory struct {
Expand Down Expand Up @@ -68,12 +70,12 @@ func initPython(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[stri
return args, nil, nil
}

func (k *mqlPython) id() (string, error) {
return "python", nil
func (r *mqlPython) id() (string, error) {
return "python/" + r.Path.Data, nil
}

func (k *mqlPython) packages() ([]interface{}, error) {
allPyPkgDetails, err := k.getAllPackages()
func (r *mqlPython) packages() ([]interface{}, error) {
allPyPkgDetails, err := r.getAllPackages()
if err != nil {
return nil, err
}
Expand All @@ -85,7 +87,7 @@ func (k *mqlPython) packages() ([]interface{}, error) {
resp := []interface{}{}

for _, pyPkgDetails := range allPyPkgDetails {
res, err := pythonPackageDetailsWithDependenciesToResource(k.MqlRuntime, pyPkgDetails, allPyPkgDetails, pythonPackageResourceMap)
res, err := pythonPackageDetailsWithDependenciesToResource(r.MqlRuntime, pyPkgDetails, allPyPkgDetails, pythonPackageResourceMap)
if err != nil {
log.Error().Err(err).Msg("error while creating resource(s) for python package")
// we will keep trying to make resources even if a single one failed
Expand All @@ -97,8 +99,8 @@ func (k *mqlPython) packages() ([]interface{}, error) {
return resp, nil
}

func (k *mqlPython) toplevel() ([]interface{}, error) {
allPyPkgDetails, err := k.getAllPackages()
func (r *mqlPython) toplevel() ([]interface{}, error) {
allPyPkgDetails, err := r.getAllPackages()
if err != nil {
return nil, err
}
Expand All @@ -114,7 +116,7 @@ func (k *mqlPython) toplevel() ([]interface{}, error) {
continue
}

res, err := pythonPackageDetailsWithDependenciesToResource(k.MqlRuntime, pyPkgDetails, allPyPkgDetails, pythonPackageResourceMap)
res, err := pythonPackageDetailsWithDependenciesToResource(r.MqlRuntime, pyPkgDetails, allPyPkgDetails, pythonPackageResourceMap)
if err != nil {
log.Error().Err(err).Msg("error while creating resource(s) for python package")
// we will keep trying to make resources even if a single one failed
Expand All @@ -126,19 +128,19 @@ func (k *mqlPython) toplevel() ([]interface{}, error) {
return resp, nil
}

func (k *mqlPython) getAllPackages() ([]python.PackageDetails, error) {
func (r *mqlPython) getAllPackages() ([]python.PackageDetails, error) {
allResults := []python.PackageDetails{}

conn, ok := k.MqlRuntime.Connection.(shared.Connection)
conn, ok := r.MqlRuntime.Connection.(shared.Connection)
if !ok {
return nil, fmt.Errorf("provider is not an operating system provider")
}
afs := &afero.Afero{Fs: conn.FileSystem()}

if k.Path.Error != nil {
return nil, k.Path.Error
if r.Path.Error != nil {
return nil, r.Path.Error
}
pyPath := k.Path.Data
pyPath := r.Path.Data
if pyPath != "" {
// only search the specific path provided (if it was provided)
allResults = gatherPackages(afs, pyPath)
Expand Down Expand Up @@ -428,3 +430,182 @@ func darwinSearch(afs *afero.Afero) ([]python.PackageDetails, error) {
}
return allResults, nil
}

func newMqlPythonPackage(runtime *plugin.Runtime, ppd python.PackageDetails, dependencies []interface{}) (plugin.Resource, error) {
f, err := CreateResource(runtime, "file", map[string]*llx.RawData{
"path": llx.StringData(ppd.File),
})
if err != nil {
log.Error().Err(err).Msg("error while creating file resource for python package resource")
return nil, err
}

cpes := []interface{}{}
for i := range ppd.Cpes {
cpe, err := runtime.CreateSharedResource("cpe", map[string]*llx.RawData{
"uri": llx.StringData(ppd.Cpes[i]),
})
if err != nil {
return nil, err
}
cpes = append(cpes, cpe)
}

r, err := CreateResource(runtime, "python.package", map[string]*llx.RawData{
"id": llx.StringData(ppd.File),
"name": llx.StringData(ppd.Name),
"version": llx.StringData(ppd.Version),
"author": llx.StringData(ppd.Author),
"authorEmail": llx.StringData(ppd.AuthorEmail),
"summary": llx.StringData(ppd.Summary),
"license": llx.StringData(ppd.License),
"file": llx.ResourceData(f, f.MqlName()),
"dependencies": llx.ArrayData(dependencies, types.Any),
"purl": llx.StringData(ppd.Purl),
"cpes": llx.ArrayData(cpes, types.Resource("cpe")),
})
if err != nil {
log.Error().AnErr("err", err).Msg("error while creating MQL resource")
return nil, err
}
return r, nil
}

func (r *mqlPythonPackage) id() (string, error) {
return r.Id.Data, nil
}

func initPythonPackage(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) {
if len(args) > 1 {
return args, nil, nil
}
if x, ok := args["path"]; ok {
path, ok := x.Value.(string)
if !ok {
return nil, nil, errors.New("Wrong type for 'path' in python.package initialization, it must be a string")
}

file, err := CreateResource(runtime, "file", map[string]*llx.RawData{
"path": llx.StringData(path),
})
if err != nil {
return nil, nil, err
}
args["id"] = llx.StringData(path)
args["file"] = llx.ResourceData(file, "file")

delete(args, "path")
}
return args, nil, nil
}

func (r *mqlPythonPackage) name() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.Name.Data, nil
}

func (r *mqlPythonPackage) version() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.Version.Data, nil
}

func (r *mqlPythonPackage) license() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.License.Data, nil
}

func (r *mqlPythonPackage) author() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.Author.Data, nil
}

func (r *mqlPythonPackage) authorEmail() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.AuthorEmail.Data, nil
}

func (r *mqlPythonPackage) summary() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.Summary.Data, nil
}

func (r *mqlPythonPackage) purl() (string, error) {
err := r.populateData()
if err != nil {
return "", err
}
return r.Purl.Data, nil
}

func (r *mqlPythonPackage) cpes() ([]interface{}, error) {
err := r.populateData()
if err != nil {
return nil, err
}
return r.Cpes.Data, nil
}

func (r *mqlPythonPackage) dependencies() ([]interface{}, error) {
err := r.populateData()
if err != nil {
return nil, err
}
return r.Dependencies.Data, nil
}

func (r *mqlPythonPackage) populateData() error {
file := r.GetFile()
if file.Error != nil {
return file.Error
}

if file.Data == nil || file.Data.Path.Data == "" {
return fmt.Errorf("file path is empty")
}

pkg, err := python.ParseMIME(strings.NewReader(file.Data.Content.Data), file.Data.Path.Data)
if err != nil {
return fmt.Errorf("error parsing python package data: %s", err)
}

r.Name = plugin.TValue[string]{Data: pkg.Name, State: plugin.StateIsSet}
r.Version = plugin.TValue[string]{Data: pkg.Version, State: plugin.StateIsSet}
r.Author = plugin.TValue[string]{Data: pkg.Author, State: plugin.StateIsSet}
r.AuthorEmail = plugin.TValue[string]{Data: pkg.AuthorEmail, State: plugin.StateIsSet}
r.Summary = plugin.TValue[string]{Data: pkg.Summary, State: plugin.StateIsSet}
r.License = plugin.TValue[string]{Data: pkg.License, State: plugin.StateIsSet}
r.Dependencies = plugin.TValue[[]interface{}]{Data: convert.SliceAnyToInterface(pkg.Dependencies), State: plugin.StateIsSet}

cpes := []interface{}{}
for i := range pkg.Cpes {
cpe, err := r.MqlRuntime.CreateSharedResource("cpe", map[string]*llx.RawData{
"uri": llx.StringData(pkg.Cpes[i]),
})
if err != nil {
return err
}
cpes = append(cpes, cpe)
}

r.Cpes = plugin.TValue[[]interface{}]{Data: cpes, State: plugin.StateIsSet}
r.Purl = plugin.TValue[string]{Data: pkg.Purl, State: plugin.StateIsSet}
return nil
}
Loading

0 comments on commit a6f66d1

Please sign in to comment.