mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
132 lines
3.1 KiB
Go
132 lines
3.1 KiB
Go
package options
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/adrg/xdg"
|
|
|
|
"github.com/anchore/clio"
|
|
"github.com/anchore/go-homedir"
|
|
"github.com/anchore/syft/internal/cache"
|
|
"github.com/anchore/syft/internal/log"
|
|
)
|
|
|
|
// Cache provides configuration for the Syft caching behavior
|
|
type Cache struct {
|
|
Dir string `yaml:"dir" mapstructure:"dir"`
|
|
TTL string `yaml:"ttl" mapstructure:"ttl"`
|
|
}
|
|
|
|
func (c *Cache) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
|
descriptions.Add(&c.Dir, "root directory to cache any downloaded content; empty string will use an in-memory cache")
|
|
descriptions.Add(&c.TTL, "time to live for cached data; setting this to 0 will disable caching entirely")
|
|
}
|
|
|
|
func (c *Cache) PostLoad() error {
|
|
ttl, err := parseDuration(c.TTL)
|
|
if err != nil {
|
|
log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err)
|
|
ttl = defaultTTL()
|
|
}
|
|
// if TTL is <= 0, disable caching entirely
|
|
if ttl <= 0 {
|
|
cache.SetManager(nil)
|
|
return nil
|
|
}
|
|
// if dir == "" but we have a TTL, use an in-memory cache
|
|
if c.Dir == "" {
|
|
cache.SetManager(cache.NewInMemory(ttl))
|
|
return nil
|
|
}
|
|
dir, err := homedir.Expand(c.Dir)
|
|
if err != nil {
|
|
log.Warnf("unable to expand cache directory %s: %v", c.Dir, err)
|
|
cache.SetManager(cache.NewInMemory(ttl))
|
|
} else {
|
|
m, err := cache.NewFromDir(dir, ttl)
|
|
if err != nil {
|
|
log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err)
|
|
cache.SetManager(cache.NewInMemory(ttl))
|
|
} else {
|
|
cache.SetManager(m)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var _ interface {
|
|
clio.PostLoader
|
|
clio.FieldDescriber
|
|
} = (*Cache)(nil)
|
|
|
|
func DefaultCache() Cache {
|
|
return Cache{
|
|
Dir: defaultDir(),
|
|
TTL: durationToString(defaultTTL()),
|
|
}
|
|
}
|
|
|
|
func defaultTTL() time.Duration {
|
|
return 7 * 24 * time.Hour
|
|
}
|
|
|
|
func defaultDir() string {
|
|
var err error
|
|
cacheRoot := xdg.CacheHome
|
|
if cacheRoot == "" {
|
|
cacheRoot, err = homedir.Dir()
|
|
if err != nil {
|
|
cacheRoot = os.TempDir()
|
|
log.Debugf("unable to get stable cache directory due to: %v, defaulting cache to temp dir: %s", err, cacheRoot)
|
|
} else {
|
|
cacheRoot = filepath.Join(cacheRoot, ".cache")
|
|
}
|
|
}
|
|
|
|
return filepath.Join(cacheRoot, "syft")
|
|
}
|
|
|
|
func durationToString(duration time.Duration) string {
|
|
days := int64(duration / (24 * time.Hour))
|
|
remain := duration % (24 * time.Hour)
|
|
out := ""
|
|
if days > 0 {
|
|
out = fmt.Sprintf("%vd", days)
|
|
}
|
|
if remain != 0 {
|
|
out += remain.String()
|
|
}
|
|
if out == "" {
|
|
return "0"
|
|
}
|
|
return out
|
|
}
|
|
|
|
func parseDuration(duration string) (time.Duration, error) {
|
|
whitespace := regexp.MustCompile(`\s+`)
|
|
duration = strings.ToLower(whitespace.ReplaceAllString(duration, ""))
|
|
parts := strings.SplitN(duration, "d", 2)
|
|
var days time.Duration
|
|
var remain time.Duration
|
|
var err error
|
|
if len(parts) > 1 {
|
|
numDays, daysErr := strconv.Atoi(parts[0])
|
|
if daysErr != nil {
|
|
return 0, daysErr
|
|
}
|
|
days = time.Duration(numDays) * 24 * time.Hour
|
|
if len(parts[1]) > 0 {
|
|
remain, err = time.ParseDuration(parts[1])
|
|
}
|
|
} else {
|
|
remain, err = time.ParseDuration(duration)
|
|
}
|
|
return days + remain, err
|
|
}
|