go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/lr/collector.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package lr
     5  
     6  import (
     7  	"os"
     8  	"path"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/rs/zerolog/log"
    13  	"go.mondoo.com/cnquery/types"
    14  )
    15  
    16  // Collector provides helpers for go files inside a context
    17  type Collector struct {
    18  	path string
    19  	data types.StringToStrings
    20  }
    21  
    22  // NewCollector instantiates a collector to watch files in the context of a LR directory
    23  func NewCollector(lrFile string) *Collector {
    24  	base := path.Dir(lrFile)
    25  	if base == "" {
    26  		panic("Cannot find base folder from LR file in '" + lrFile + "'")
    27  	}
    28  	res := &Collector{
    29  		path: base,
    30  	}
    31  	err := res.collect()
    32  	if err != nil {
    33  		panic("failed to collect: " + err.Error())
    34  	}
    35  	return res
    36  }
    37  
    38  var regexMaps = map[string]*regexp.Regexp{
    39  	"init":   regexp.MustCompile(`func init(\S+)\([^)]+\) \([^,]+, \S+\.Resource, error\) {`),
    40  	"id":     regexp.MustCompile(`func \(\S+ \*(mql\S+)\) id\(\) \(string, error\)`),
    41  	"struct": regexp.MustCompile(`type (mql\S+Internal) struct `),
    42  }
    43  
    44  func (c *Collector) collect() error {
    45  	files, err := os.ReadDir(c.path)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	for i := range files {
    50  		file := files[i]
    51  		if file.IsDir() {
    52  			continue
    53  		}
    54  		if !strings.HasSuffix(file.Name(), ".go") {
    55  			continue
    56  		}
    57  
    58  		f := path.Join(c.path, file.Name())
    59  		res, err := os.ReadFile(f)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		for k, v := range regexMaps {
    65  			matches := v.FindAllSubmatch(res, -1)
    66  			for mi := range matches {
    67  				m := matches[mi]
    68  				if len(m) == 0 {
    69  					continue
    70  				}
    71  				log.Debug().Msg("found " + k + " in " + file.Name() + " for " + string(m[1]))
    72  				c.data.Store(k, string(m[1]))
    73  			}
    74  		}
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  // HasInit will verify if the given struct has a mondoo init function
    81  func (c *Collector) HasInit(interfaceName string) bool {
    82  	return c.data.Exist("init", interfaceName)
    83  }
    84  
    85  // HasID will verify if the given struct has a mondoo id function
    86  func (c *Collector) HasID(structname string) bool {
    87  	return c.data.Exist("id", structname)
    88  }
    89  
    90  // HasStruct will verify if the given struct is created (for embedding)
    91  func (c *Collector) HasStruct(structname string) bool {
    92  	return c.data.Exist("struct", structname)
    93  }